Files
leocrm/frontend/src/api/permissionTemplates.ts
T

112 lines
3.4 KiB
TypeScript
Raw Normal View History

/**
* 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<string, unknown> | 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<string, unknown> | null;
auto_share_with?: ShareEntry[] | null;
}
export type TemplateUpdatePayload = Partial<TemplateCreatePayload>;
export interface TemplateApplyPayload {
entity_type: string;
entity_id: string;
template_id?: string | null;
}
export interface TemplateApplyResponse {
applied: Array<Record<string, unknown>>;
count: number;
}
// ─── Query hooks ─────────────────────────────────────────────
export function usePermissionTemplates(entityType?: string) {
const qs = entityType ? `?entity_type=${encodeURIComponent(entityType)}` : '';
return useQuery<TemplateListResponse>({
queryKey: ['permission-templates', entityType ?? null],
queryFn: () => apiGet<TemplateListResponse>(`/permission-templates${qs}`),
});
}
// ─── Mutation hooks ──────────────────────────────────────────
function useInvalidateTemplates() {
const qc = useQueryClient();
return () => {
qc.invalidateQueries({ queryKey: ['permission-templates'] });
};
}
export function useCreatePermissionTemplate() {
const invalidate = useInvalidateTemplates();
return useMutation<PermissionTemplate, Error, TemplateCreatePayload>({
mutationFn: (data) => apiPost<PermissionTemplate>('/permission-templates', data),
onSuccess: invalidate,
});
}
export function useUpdatePermissionTemplate() {
const invalidate = useInvalidateTemplates();
return useMutation<
PermissionTemplate,
Error,
{ templateId: string; payload: TemplateUpdatePayload }
>({
mutationFn: ({ templateId, payload }) =>
apiPut<PermissionTemplate>(`/permission-templates/${templateId}`, payload),
onSuccess: invalidate,
});
}
export function useDeletePermissionTemplate() {
const invalidate = useInvalidateTemplates();
return useMutation<void, Error, string>({
mutationFn: (templateId) => apiDelete(`/permission-templates/${templateId}`),
onSuccess: invalidate,
});
}
export function useApplyPermissionTemplate() {
return useMutation<TemplateApplyResponse, Error, TemplateApplyPayload>({
mutationFn: (data) => apiPost<TemplateApplyResponse>('/permission-templates/apply', data),
});
}