/** * Permission Templates API client — reusable permission presets. * * Backend: /api/v1/permission-templates (list, create, update, delete, * apply). Templates define default sharing rules; applying them creates * entity_permissions entries automatically. * Permissions: templates:read (list) / templates:write (everything else). */ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { apiGet, apiPost, apiPut, apiDelete } from '@/api/client'; export type TemplateLevel = 'read' | 'write' | 'admin' | 'delete'; export interface ShareEntry { principal_type?: string; principal_id?: string; level?: string; } export interface PermissionTemplate { id: string; name: string; entity_type: string; trigger_condition: Record | null; auto_share_with: ShareEntry[] | null; level: TemplateLevel; tenant_id: string; created_at: string | null; updated_at: string | null; } export interface TemplateListResponse { items: PermissionTemplate[]; total: number; } export interface TemplateCreatePayload { name: string; entity_type: string; level?: TemplateLevel; trigger_condition?: Record | null; auto_share_with?: ShareEntry[] | null; } export type TemplateUpdatePayload = Partial; export interface TemplateApplyPayload { entity_type: string; entity_id: string; template_id?: string | null; } export interface TemplateApplyResponse { applied: Array>; count: number; } // ─── Query hooks ───────────────────────────────────────────── export function usePermissionTemplates(entityType?: string) { const qs = entityType ? `?entity_type=${encodeURIComponent(entityType)}` : ''; return useQuery({ queryKey: ['permission-templates', entityType ?? null], queryFn: () => apiGet(`/permission-templates${qs}`), }); } // ─── Mutation hooks ────────────────────────────────────────── function useInvalidateTemplates() { const qc = useQueryClient(); return () => { qc.invalidateQueries({ queryKey: ['permission-templates'] }); }; } export function useCreatePermissionTemplate() { const invalidate = useInvalidateTemplates(); return useMutation({ mutationFn: (data) => apiPost('/permission-templates', data), onSuccess: invalidate, }); } export function useUpdatePermissionTemplate() { const invalidate = useInvalidateTemplates(); return useMutation< PermissionTemplate, Error, { templateId: string; payload: TemplateUpdatePayload } >({ mutationFn: ({ templateId, payload }) => apiPut(`/permission-templates/${templateId}`, payload), onSuccess: invalidate, }); } export function useDeletePermissionTemplate() { const invalidate = useInvalidateTemplates(); return useMutation({ mutationFn: (templateId) => apiDelete(`/permission-templates/${templateId}`), onSuccess: invalidate, }); } export function useApplyPermissionTemplate() { return useMutation({ mutationFn: (data) => apiPost('/permission-templates/apply', data), }); }