import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { adminFetch } from './admin-api'; // ── Types ────────────────────────────────────────────────────────────── export interface RoleSummary { id: string; name: string; scope: string; } export interface GroupSummary { id: string; name: string; parentGroupId: string | null; } export interface UserSummary { userId: string; displayName: string; } export interface UserDetail { userId: string; provider: string; email: string; displayName: string; createdAt: string; directRoles: RoleSummary[]; directGroups: GroupSummary[]; effectiveRoles: RoleSummary[]; effectiveGroups: GroupSummary[]; } export interface RoleDetail { id: string; name: string; description: string; scope: string; system: boolean; createdAt: string; assignedGroups: GroupSummary[]; directUsers: UserSummary[]; effectivePrincipals: UserSummary[]; } export interface GroupDetail { id: string; name: string; parentGroupId: string | null; createdAt: string; directRoles: RoleSummary[]; effectiveRoles: RoleSummary[]; members: UserSummary[]; childGroups: GroupSummary[]; } export interface CreateUserRequest { username: string; displayName?: string; email?: string; password?: string; } export interface UpdateUserRequest { displayName?: string; email?: string; } export interface CreateRoleRequest { name: string; description?: string; scope?: string; } export interface UpdateRoleRequest { name: string; description?: string; scope?: string; } export interface CreateGroupRequest { name: string; parentGroupId?: string | null; } export interface UpdateGroupRequest { name: string; parentGroupId?: string | null; } // ── Stats Hook ─────────────────────────────────────────────────────── export interface RbacStats { userCount: number; activeUserCount: number; groupCount: number; maxGroupDepth: number; roleCount: number; } export function useRbacStats() { return useQuery({ queryKey: ['admin', 'rbac', 'stats'], queryFn: () => adminFetch('/rbac/stats'), }); } // ── User Query Hooks ─────────────────────────────────────────────────── export function useUsers() { return useQuery({ queryKey: ['admin', 'users'], queryFn: () => adminFetch('/users'), }); } export function useUser(userId: string | null) { return useQuery({ queryKey: ['admin', 'users', userId], queryFn: () => adminFetch(`/users/${userId}`), enabled: !!userId, }); } // ── Role Query Hooks ─────────────────────────────────────────────────── export function useRoles() { return useQuery({ queryKey: ['admin', 'roles'], queryFn: () => adminFetch('/roles'), }); } export function useRole(roleId: string | null) { return useQuery({ queryKey: ['admin', 'roles', roleId], queryFn: () => adminFetch(`/roles/${roleId}`), enabled: !!roleId, }); } // ── Group Query Hooks ────────────────────────────────────────────────── export function useGroups() { return useQuery({ queryKey: ['admin', 'groups'], queryFn: () => adminFetch('/groups'), }); } export function useGroup(groupId: string | null) { return useQuery({ queryKey: ['admin', 'groups', groupId], queryFn: () => adminFetch(`/groups/${groupId}`), enabled: !!groupId, }); } // ── User Mutation Hooks ──────────────────────────────────────────────── export function useCreateUser() { const qc = useQueryClient(); return useMutation({ mutationFn: (req: CreateUserRequest) => adminFetch('/users', { method: 'POST', body: JSON.stringify(req), }), onSuccess: () => { qc.invalidateQueries({ queryKey: ['admin', 'users'] }); }, }); } export function useUpdateUser() { const qc = useQueryClient(); return useMutation({ mutationFn: ({ userId, ...req }: UpdateUserRequest & { userId: string }) => adminFetch(`/users/${userId}`, { method: 'PUT', body: JSON.stringify(req), }), onSuccess: () => { qc.invalidateQueries({ queryKey: ['admin', 'users'] }); }, }); } export function useDeleteUser() { const qc = useQueryClient(); return useMutation({ mutationFn: (userId: string) => adminFetch(`/users/${userId}`, { method: 'DELETE' }), onSuccess: () => { qc.invalidateQueries({ queryKey: ['admin', 'users'] }); }, }); } export function useAssignRoleToUser() { const qc = useQueryClient(); return useMutation({ mutationFn: ({ userId, roleId }: { userId: string; roleId: string }) => adminFetch(`/users/${userId}/roles/${roleId}`, { method: 'POST' }), onSuccess: () => { qc.invalidateQueries({ queryKey: ['admin', 'users'] }); qc.invalidateQueries({ queryKey: ['admin', 'roles'] }); }, }); } export function useRemoveRoleFromUser() { const qc = useQueryClient(); return useMutation({ mutationFn: ({ userId, roleId }: { userId: string; roleId: string }) => adminFetch(`/users/${userId}/roles/${roleId}`, { method: 'DELETE' }), onSuccess: () => { qc.invalidateQueries({ queryKey: ['admin', 'users'] }); qc.invalidateQueries({ queryKey: ['admin', 'roles'] }); }, }); } export function useAddUserToGroup() { const qc = useQueryClient(); return useMutation({ mutationFn: ({ userId, groupId }: { userId: string; groupId: string }) => adminFetch(`/users/${userId}/groups/${groupId}`, { method: 'POST' }), onSuccess: () => { qc.invalidateQueries({ queryKey: ['admin', 'users'] }); qc.invalidateQueries({ queryKey: ['admin', 'groups'] }); }, }); } export function useRemoveUserFromGroup() { const qc = useQueryClient(); return useMutation({ mutationFn: ({ userId, groupId }: { userId: string; groupId: string }) => adminFetch(`/users/${userId}/groups/${groupId}`, { method: 'DELETE' }), onSuccess: () => { qc.invalidateQueries({ queryKey: ['admin', 'users'] }); qc.invalidateQueries({ queryKey: ['admin', 'groups'] }); }, }); } // ── Role Mutation Hooks ──────────────────────────────────────────────── export function useCreateRole() { const qc = useQueryClient(); return useMutation({ mutationFn: (req: CreateRoleRequest) => adminFetch<{ id: string }>('/roles', { method: 'POST', body: JSON.stringify(req), }), onSuccess: () => { qc.invalidateQueries({ queryKey: ['admin', 'roles'] }); }, }); } export function useUpdateRole() { const qc = useQueryClient(); return useMutation({ mutationFn: ({ id, ...req }: UpdateRoleRequest & { id: string }) => adminFetch(`/roles/${id}`, { method: 'PUT', body: JSON.stringify(req), }), onSuccess: () => { qc.invalidateQueries({ queryKey: ['admin', 'roles'] }); }, }); } export function useDeleteRole() { const qc = useQueryClient(); return useMutation({ mutationFn: (id: string) => adminFetch(`/roles/${id}`, { method: 'DELETE' }), onSuccess: () => { qc.invalidateQueries({ queryKey: ['admin', 'roles'] }); }, }); } // ── Group Mutation Hooks ─────────────────────────────────────────────── export function useCreateGroup() { const qc = useQueryClient(); return useMutation({ mutationFn: (req: CreateGroupRequest) => adminFetch<{ id: string }>('/groups', { method: 'POST', body: JSON.stringify(req), }), onSuccess: () => { qc.invalidateQueries({ queryKey: ['admin', 'groups'] }); }, }); } export function useUpdateGroup() { const qc = useQueryClient(); return useMutation({ mutationFn: ({ id, ...req }: UpdateGroupRequest & { id: string }) => adminFetch(`/groups/${id}`, { method: 'PUT', body: JSON.stringify(req), }), onSuccess: () => { qc.invalidateQueries({ queryKey: ['admin', 'groups'] }); }, }); } export function useDeleteGroup() { const qc = useQueryClient(); return useMutation({ mutationFn: (id: string) => adminFetch(`/groups/${id}`, { method: 'DELETE' }), onSuccess: () => { qc.invalidateQueries({ queryKey: ['admin', 'groups'] }); }, }); } export function useAssignRoleToGroup() { const qc = useQueryClient(); return useMutation({ mutationFn: ({ groupId, roleId }: { groupId: string; roleId: string }) => adminFetch(`/groups/${groupId}/roles/${roleId}`, { method: 'POST' }), onSuccess: () => { qc.invalidateQueries({ queryKey: ['admin', 'groups'] }); qc.invalidateQueries({ queryKey: ['admin', 'roles'] }); }, }); } export function useRemoveRoleFromGroup() { const qc = useQueryClient(); return useMutation({ mutationFn: ({ groupId, roleId }: { groupId: string; roleId: string }) => adminFetch(`/groups/${groupId}/roles/${roleId}`, { method: 'DELETE' }), onSuccess: () => { qc.invalidateQueries({ queryKey: ['admin', 'groups'] }); qc.invalidateQueries({ queryKey: ['admin', 'roles'] }); }, }); }