feat(api, web): enhance agent management and linting capabilities
- Added a new linting command for OpenAPI specifications in the package.json, improving code quality checks. - Updated frontend documentation to clarify component usage and structure, including detailed descriptions for `SettingsShell` and `Auth callback`. - Refactored agent-related API routes to streamline control-plane functionalities, consolidating multiple routes for better organization. - Improved error handling in the API to provide more informative responses for validation errors, enhancing user feedback during interactions. These changes enhance the overall development experience and improve the management of agents within the application.
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { putSettingsBodySchema } from './contracts.js'
|
||||
|
||||
describe('putSettingsBodySchema', () => {
|
||||
it('accepts whitelisted keys', () => {
|
||||
const parsed = putSettingsBodySchema.parse({
|
||||
enroll_seed: 'x',
|
||||
show_quick_actions: 'true',
|
||||
})
|
||||
expect(parsed.show_quick_actions).toBe('true')
|
||||
})
|
||||
|
||||
it('rejects unknown keys', () => {
|
||||
expect(() =>
|
||||
putSettingsBodySchema.parse({ evil_key: 'nope' }),
|
||||
).toThrow()
|
||||
})
|
||||
})
|
||||
@@ -320,6 +320,29 @@ export const evobgpCommunitySchema = z.object({
|
||||
title: z.string().nullable().optional(),
|
||||
})
|
||||
|
||||
/** Whitelist keys for PUT /api/v1/settings. */
|
||||
export const SETTINGS_KEYS = [
|
||||
'enroll_seed',
|
||||
'evobgp_api_url',
|
||||
'evobgp_api_token',
|
||||
'agent_sync_interval_sec',
|
||||
'show_quick_actions',
|
||||
] as const
|
||||
|
||||
export const putSettingsBodySchema = z
|
||||
.record(z.string(), z.string())
|
||||
.superRefine((obj, ctx) => {
|
||||
for (const key of Object.keys(obj)) {
|
||||
if (!(SETTINGS_KEYS as readonly string[]).includes(key)) {
|
||||
ctx.addIssue({
|
||||
code: 'custom',
|
||||
message: `Unknown settings key: ${key}`,
|
||||
path: [key],
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export type Agent = z.infer<typeof agentSchema>
|
||||
export type IpList = z.infer<typeof ipListSchema>
|
||||
export type PolicyRule = z.infer<typeof policyRuleSchema>
|
||||
@@ -331,3 +354,4 @@ export type DashboardStats = z.infer<typeof dashboardStatsSchema>
|
||||
export type InstallLink = z.infer<typeof installLinkSchema>
|
||||
export type EvobgpCommunity = z.infer<typeof evobgpCommunitySchema>
|
||||
export type DefaultAction = z.infer<typeof defaultActionSchema>
|
||||
export type PutSettingsBody = z.infer<typeof putSettingsBodySchema>
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { permissionForRequest } from '@evofw/shared'
|
||||
|
||||
describe('permissionForRequest', () => {
|
||||
it('maps install-links to agents permissions', () => {
|
||||
expect(permissionForRequest('GET', '/api/v1/install-links')).toBe(
|
||||
'fw:agents:read',
|
||||
)
|
||||
expect(permissionForRequest('POST', '/api/v1/install-links')).toBe(
|
||||
'fw:agents:write',
|
||||
)
|
||||
})
|
||||
|
||||
it('maps integrations to lists read / settings admin', () => {
|
||||
expect(
|
||||
permissionForRequest('GET', '/api/v1/integrations/evobgp/communities'),
|
||||
).toBe('fw:lists:read')
|
||||
expect(
|
||||
permissionForRequest('POST', '/api/v1/integrations/evobgp/refresh'),
|
||||
).toBe('fw:settings:admin')
|
||||
})
|
||||
})
|
||||
@@ -29,7 +29,7 @@ export function permissionForRequest(
|
||||
const m = method.toUpperCase()
|
||||
const write = m !== 'GET' && m !== 'HEAD' && m !== 'OPTIONS'
|
||||
|
||||
if (path.startsWith('/api/v1/agents')) {
|
||||
if (path.startsWith('/api/v1/agents') || path.startsWith('/api/v1/install-links')) {
|
||||
return write ? 'fw:agents:write' : 'fw:agents:read'
|
||||
}
|
||||
if (path.startsWith('/api/v1/lists')) {
|
||||
@@ -45,6 +45,9 @@ export function permissionForRequest(
|
||||
if (path.startsWith('/api/v1/stats') || path.startsWith('/api/v1/dashboard')) {
|
||||
return 'fw:stats:read'
|
||||
}
|
||||
if (path.startsWith('/api/v1/integrations')) {
|
||||
return write ? 'fw:settings:admin' : 'fw:lists:read'
|
||||
}
|
||||
if (path.startsWith('/api/v1/settings') || path.startsWith('/api/v1/install-context')) {
|
||||
return write ? 'fw:settings:admin' : 'fw:settings:read'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user