feat: add RBAC hooks and permission-gated components
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
15
ui/src/components/DeploymentStatusBadge.tsx
Normal file
15
ui/src/components/DeploymentStatusBadge.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Badge } from '@cameleer/design-system';
|
||||
|
||||
// Badge color values: 'primary' | 'success' | 'warning' | 'error' | 'running' | 'auto'
|
||||
const STATUS_COLORS: Record<string, 'primary' | 'success' | 'warning' | 'error' | 'running' | 'auto'> = {
|
||||
BUILDING: 'warning',
|
||||
STARTING: 'warning',
|
||||
RUNNING: 'running',
|
||||
FAILED: 'error',
|
||||
STOPPED: 'auto',
|
||||
};
|
||||
|
||||
export function DeploymentStatusBadge({ status }: { status: string }) {
|
||||
const color = STATUS_COLORS[status] ?? 'auto';
|
||||
return <Badge label={status} color={color} />;
|
||||
}
|
||||
13
ui/src/components/RequirePermission.tsx
Normal file
13
ui/src/components/RequirePermission.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { usePermissions } from '../hooks/usePermissions';
|
||||
|
||||
interface Props {
|
||||
permission: string;
|
||||
children: React.ReactNode;
|
||||
fallback?: React.ReactNode;
|
||||
}
|
||||
|
||||
export function RequirePermission({ permission, children, fallback }: Props) {
|
||||
const { has } = usePermissions();
|
||||
if (!has(permission)) return fallback ? <>{fallback}</> : null;
|
||||
return <>{children}</>;
|
||||
}
|
||||
27
ui/src/hooks/usePermissions.ts
Normal file
27
ui/src/hooks/usePermissions.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { useAuthStore } from '../auth/auth-store';
|
||||
|
||||
const ROLE_PERMISSIONS: Record<string, string[]> = {
|
||||
OWNER: ['tenant:manage', 'billing:manage', 'team:manage', 'apps:manage', 'apps:deploy', 'secrets:manage', 'observe:read', 'observe:debug', 'settings:manage'],
|
||||
ADMIN: ['team:manage', 'apps:manage', 'apps:deploy', 'secrets:manage', 'observe:read', 'observe:debug', 'settings:manage'],
|
||||
DEVELOPER: ['apps:deploy', 'secrets:manage', 'observe:read', 'observe:debug'],
|
||||
VIEWER: ['observe:read'],
|
||||
};
|
||||
|
||||
export function usePermissions() {
|
||||
const roles = useAuthStore((s) => s.roles);
|
||||
|
||||
const permissions = new Set<string>();
|
||||
for (const role of roles) {
|
||||
const perms = ROLE_PERMISSIONS[role];
|
||||
if (perms) perms.forEach((p) => permissions.add(p));
|
||||
}
|
||||
|
||||
return {
|
||||
has: (permission: string) => permissions.has(permission),
|
||||
canManageApps: permissions.has('apps:manage'),
|
||||
canDeploy: permissions.has('apps:deploy'),
|
||||
canManageTenant: permissions.has('tenant:manage'),
|
||||
canViewObservability: permissions.has('observe:read'),
|
||||
roles,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user