mirror of
https://origin.cursor.com/mrdevmx/panels.git
synced 2026-10-09 14:33: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>
67 lines
1.9 KiB
TypeScript
67 lines
1.9 KiB
TypeScript
const ROUTE_PERMISSIONS: Record<string, string> = {
|
|
"/": "reports.view",
|
|
"/proyectos": "projects.view",
|
|
"/obras": "projects.view",
|
|
"/presupuesto": "budget.view",
|
|
"/programa-obra": "work_program.view",
|
|
"/control-presupuesto": "cost_control.view",
|
|
"/gastos": "expenses.view",
|
|
"/almacen": "warehouse.view",
|
|
"/kanban": "kanban.view",
|
|
"/padron": "workers.view",
|
|
"/gafetes": "documents.view",
|
|
"/nomina": "payroll.view",
|
|
"/configuracion": "settings.view",
|
|
"/usuarios": "users.view",
|
|
};
|
|
|
|
export default defineNuxtRouteMiddleware(async (to) => {
|
|
if (to.path === "/login") return;
|
|
const { user, fetchMe } = useAuth();
|
|
const { api } = useApi();
|
|
try {
|
|
if (!user.value) {
|
|
await Promise.race([
|
|
fetchMe(),
|
|
new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), 4000)),
|
|
]);
|
|
}
|
|
} catch {
|
|
user.value = null;
|
|
}
|
|
if (!user.value) return navigateTo("/login");
|
|
|
|
if (user.value.role_code === "platform_admin" && user.value.realm === "platform") {
|
|
user.value = null;
|
|
try {
|
|
await api("/v1/auth/logout", { method: "POST" });
|
|
} catch {
|
|
/* ignore */
|
|
}
|
|
if (import.meta.client) {
|
|
window.location.href = "http://localhost:3001/login";
|
|
return abortNavigation();
|
|
}
|
|
return navigateTo("/login");
|
|
}
|
|
|
|
if (user.value.must_change_password && to.path !== "/cambiar-password") {
|
|
return navigateTo("/cambiar-password");
|
|
}
|
|
if (!user.value.must_change_password && to.path === "/cambiar-password") {
|
|
return navigateTo("/");
|
|
}
|
|
|
|
const perms = usePermissions();
|
|
const userScope = useScope();
|
|
if (!perms.loaded.value) await perms.load();
|
|
if (!userScope.loaded.value) await userScope.load();
|
|
|
|
const required = Object.entries(ROUTE_PERMISSIONS).find(([path]) =>
|
|
path === "/" ? to.path === "/" : to.path === path || to.path.startsWith(`${path}/`),
|
|
)?.[1];
|
|
|
|
if (required && !perms.can(required)) {
|
|
return navigateTo("/");
|
|
}
|
|
});
|