diff --git a/frontend/src/api/projectPermissions.ts b/frontend/src/api/projectPermissions.ts index 4d887b4a..c663c680 100644 --- a/frontend/src/api/projectPermissions.ts +++ b/frontend/src/api/projectPermissions.ts @@ -1,8 +1,47 @@ -import { apiGet, apiPut } from "./axios"; -import type { ProjectRolePermissionsResponse, ProjectRolePermissionsUpdate } from "../types/api"; +import { apiGet, apiPut, apiPost } from "./axios"; +import type { + ProjectRolePermissionsResponse, + ProjectRolePermissionsUpdate, + ApiEndpointPermissionsResponse, + ApiEndpointPermissionsUpdate, + PermissionMetricsResponse, + CacheStatsResponse, + AlertsResponse, + HealthResponse, +} from "../types/api"; +// 模块级权限(现有) export const fetchProjectRolePermissions = (studyId: string) => apiGet(`/api/v1/studies/${studyId}/permissions/`); export const updateProjectRolePermissions = (studyId: string, payload: ProjectRolePermissionsUpdate) => apiPut(`/api/v1/studies/${studyId}/permissions/`, payload); + +// 接口级权限(新增) +export const fetchApiEndpointPermissions = (studyId: string) => + apiGet(`/api/v1/studies/${studyId}/api-permissions`); + +export const updateApiEndpointPermissions = (studyId: string, payload: ApiEndpointPermissionsUpdate) => + apiPut(`/api/v1/studies/${studyId}/api-permissions`, payload); + +// 权限系统监控API(新增) +export const fetchPermissionMetrics = () => + apiGet(`/api/v1/permission-monitoring/metrics`); + +export const fetchCacheStats = () => + apiGet(`/api/v1/permission-monitoring/cache-stats`); + +export const fetchPermissionAlerts = (level?: string, limit?: number) => + apiGet(`/api/v1/permission-monitoring/alerts`, { + params: { level, limit }, + }); + +export const fetchPermissionHealth = () => + apiGet(`/api/v1/permission-monitoring/health`); + +export const resetPermissionMetrics = () => + apiPost(`/api/v1/permission-monitoring/reset-metrics`); + +export const clearPermissionAlerts = () => + apiPost(`/api/v1/permission-monitoring/clear-alerts`); + diff --git a/frontend/src/components/ApiEndpointPermissions.vue b/frontend/src/components/ApiEndpointPermissions.vue new file mode 100644 index 00000000..d7ac2c18 --- /dev/null +++ b/frontend/src/components/ApiEndpointPermissions.vue @@ -0,0 +1,222 @@ + + + + + diff --git a/frontend/src/components/PermissionMonitoring.vue b/frontend/src/components/PermissionMonitoring.vue new file mode 100644 index 00000000..6bd71e24 --- /dev/null +++ b/frontend/src/components/PermissionMonitoring.vue @@ -0,0 +1,351 @@ + + + + + diff --git a/frontend/src/components/ProjectPermissionsModule.vue b/frontend/src/components/ProjectPermissionsModule.vue new file mode 100644 index 00000000..44503020 --- /dev/null +++ b/frontend/src/components/ProjectPermissionsModule.vue @@ -0,0 +1,95 @@ + + + + + diff --git a/frontend/src/locales/zh-CN.ts b/frontend/src/locales/zh-CN.ts index 14e9901b..e579fae4 100644 --- a/frontend/src/locales/zh-CN.ts +++ b/frontend/src/locales/zh-CN.ts @@ -1150,5 +1150,42 @@ export const TEXT = { SITE: "中心", DERIVED: "派生", }, + permissionManagement: { + title: "权限管理", + moduleLevel: "模块级权限", + apiLevel: "接口级权限", + monitoring: "权限监控", + refreshMetrics: "刷新指标", + save: "保存", + search: "搜索端点", + filterModule: "筛选模块", + filterMethod: "筛选方法", + endpoint: "端点", + module: "模块", + method: "方法", + role: "角色", + allowed: "允许", + denied: "拒绝", + healthStatus: "系统健康状态", + healthScore: "健康分数", + healthy: "健康", + degraded: "降级", + unhealthy: "不健康", + issues: "发现的问题", + totalChecks: "总检查次数", + avgResponseTime: "平均响应时间", + allowRate: "允许率", + errorRate: "错误率", + cacheEfficiency: "缓存效率", + cacheHitRate: "缓存命中率", + cacheItems: "缓存项目数", + cacheInvalidations: "缓存失效次数", + recentAlerts: "最近告警", + time: "时间", + level: "级别", + type: "类型", + message: "消息", + noAlerts: "暂无告警", + }, }, } as const; diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index 8a8ff458..f13a172a 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -20,6 +20,7 @@ import ProjectMembers from "../views/admin/ProjectMembers.vue"; import AdminSites from "../views/admin/Sites.vue"; import ProjectDetail from "../views/admin/ProjectDetail.vue"; import ProjectPermissions from "../views/admin/ProjectPermissions.vue"; +import ApiPermissions from "../views/admin/ApiPermissions.vue"; import ProfileSettings from "../views/ProfileSettings.vue"; import ProjectOverview from "../views/ia/ProjectOverview.vue"; import ProjectMilestones from "../views/ia/ProjectMilestones.vue"; @@ -447,6 +448,12 @@ const routes: RouteRecordRaw[] = [ component: ProjectPermissions, meta: { title: "权限管理", adminProjectPermission: { module: "project_members", action: "write" } }, }, + { + path: "projects/:id/api-permissions", + name: "AdminApiPermissions", + component: ApiPermissions, + meta: { title: "接口级权限管理", adminProjectPermission: { module: "project_members", action: "write" } }, + }, { path: "projects/:projectId/sites", name: "AdminSites", diff --git a/frontend/src/types/api.ts b/frontend/src/types/api.ts index c2fe1e6b..941340e6 100644 --- a/frontend/src/types/api.ts +++ b/frontend/src/types/api.ts @@ -152,3 +152,78 @@ export interface ProjectRolePermissionsResponse { export interface ProjectRolePermissionsUpdate { roles: ProjectPermissionMatrix; } + +// 接口级权限 +export interface ApiEndpointPermissionsResponse { + [role: string]: { + [endpoint_key: string]: { + allowed: boolean; + }; + }; +} + +export interface ApiEndpointPermissionsUpdate { + [role: string]: { + [endpoint_key: string]: boolean; + }; +} + +// 监控指标 +export interface PermissionCheckMetrics { + total_checks: number; + allowed_checks: number; + denied_checks: number; + total_time: number; + min_time: number; + max_time: number; + avg_time: number; + allow_rate: number; + deny_rate: number; + error_rate: number; + errors: number; +} + +export interface CacheMetrics { + total_accesses: number; + cache_hits: number; + cache_misses: number; + cache_invalidations: number; + hit_rate: number; + miss_rate: number; +} + +export interface PermissionMetricsResponse { + check_metrics: PermissionCheckMetrics; + cache_metrics: CacheMetrics; + uptime_seconds: number; +} + +export interface CacheStatsResponse { + cache_items: { + project_permissions_count: number; + member_role_count: number; + total_count: number; + }; + cache_metrics: CacheMetrics; +} + +export interface Alert { + timestamp: number; + level: "info" | "warning" | "error"; + type: string; + message: string; + data: Record; +} + +export interface AlertsResponse { + total: number; + alerts: Alert[]; +} + +export interface HealthResponse { + status: "healthy" | "degraded" | "unhealthy"; + health_score: number; + issues: string[]; + metrics: PermissionMetricsResponse; + cache_stats: CacheStatsResponse; +} diff --git a/frontend/src/views/admin/ApiPermissions.vue b/frontend/src/views/admin/ApiPermissions.vue new file mode 100644 index 00000000..df7f367a --- /dev/null +++ b/frontend/src/views/admin/ApiPermissions.vue @@ -0,0 +1,279 @@ + + + + +