feat(auth): add role/permission management (backend + frontend)

- RoleService: CRUD, assign_permissions, get_role_permissions
- PermissionService: list all tenant permissions
- Role handlers: 8 endpoints with RBAC permission checks
- Frontend Roles page: table, create/edit modal, permission assignment
- Frontend Roles API: full CRUD + permission operations
- Routes registered in AuthModule protected_routes
This commit is contained in:
iven
2026-04-11 03:46:54 +08:00
parent 4a03a639a6
commit 6fd0288e7c
9 changed files with 946 additions and 2 deletions

73
apps/web/src/api/roles.ts Normal file
View File

@@ -0,0 +1,73 @@
import client from './client';
import type { PaginatedResponse } from './users';
export interface RoleInfo {
id: string;
name: string;
code: string;
description?: string;
is_system: boolean;
}
export interface PermissionInfo {
id: string;
code: string;
name: string;
resource: string;
action: string;
description?: string;
}
export interface CreateRoleRequest {
name: string;
code: string;
description?: string;
}
export interface UpdateRoleRequest {
name?: string;
description?: string;
}
export async function listRoles(page = 1, pageSize = 20) {
const { data } = await client.get<{ success: boolean; data: PaginatedResponse<RoleInfo> }>(
'/roles',
{ params: { page, page_size: pageSize } },
);
return data.data;
}
export async function getRole(id: string) {
const { data } = await client.get<{ success: boolean; data: RoleInfo }>(`/roles/${id}`);
return data.data;
}
export async function createRole(req: CreateRoleRequest) {
const { data } = await client.post<{ success: boolean; data: RoleInfo }>('/roles', req);
return data.data;
}
export async function updateRole(id: string, req: UpdateRoleRequest) {
const { data } = await client.put<{ success: boolean; data: RoleInfo }>(`/roles/${id}`, req);
return data.data;
}
export async function deleteRole(id: string) {
await client.delete(`/roles/${id}`);
}
export async function assignPermissions(roleId: string, permissionIds: string[]) {
await client.post(`/roles/${roleId}/permissions`, { permission_ids: permissionIds });
}
export async function getRolePermissions(roleId: string) {
const { data } = await client.get<{ success: boolean; data: PermissionInfo[] }>(
`/roles/${roleId}/permissions`,
);
return data.data;
}
export async function listPermissions() {
const { data } = await client.get<{ success: boolean; data: PermissionInfo[] }>('/permissions');
return data.data;
}