mirror of
https://origin.cursor.com/mrdevmx/panels.git
synced 2026-10-09 20:43:17 +00:00
- Add IAM v2 auth with role_id, is_owner, status checks, and API key without tenant_admin bypass - Enforce CRUD permissions and project/warehouse scope across API routes - Rewrite usuarios.vue with ribbon, tree, user/role management, and permission matrix - Add dynamic menu, route guards, usePermissions/useScope composables - Apply role templates on create; filter project docs by category; hide cost tab without permission - Add iam_test unit tests; update bootstrap and SaaS tenant admin to use role_id Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
39 lines
1.1 KiB
TypeScript
39 lines
1.1 KiB
TypeScript
export function usePermissions() {
|
|
const permissions = useState<string[]>("user-permissions", () => []);
|
|
const isOwner = useState("user-permissions-owner", () => false);
|
|
const loaded = useState("user-permissions-loaded", () => false);
|
|
const { api } = useApi();
|
|
|
|
async function load() {
|
|
try {
|
|
const r = await api<{
|
|
permissions?: string[];
|
|
is_owner?: boolean;
|
|
}>("/v1/me/permissions");
|
|
permissions.value = r.permissions ?? [];
|
|
isOwner.value = Boolean(r.is_owner);
|
|
loaded.value = true;
|
|
} catch {
|
|
permissions.value = [];
|
|
isOwner.value = false;
|
|
loaded.value = true;
|
|
}
|
|
}
|
|
|
|
function can(code: string): boolean {
|
|
if (isOwner.value) return true;
|
|
return permissions.value.includes(code);
|
|
}
|
|
|
|
function canAny(...codes: string[]): boolean {
|
|
return codes.some((c) => can(c));
|
|
}
|
|
|
|
function canModuleView(module: string): boolean {
|
|
return can(`${module}.view`) || canAny(
|
|
...permissions.value.filter((p) => p.startsWith(`${module}.`) && p.endsWith(".view")),
|
|
);
|
|
}
|
|
|
|
return { permissions, isOwner, loaded, load, can, canAny, canModuleView };
|
|
}
|