mirror of
https://origin.cursor.com/mrdevmx/panels.git
synced 2026-10-09 14:13:18 +00:00
IAM: auto-generate role code from label when creating roles
Remove the manual Código field from the new-role dialog. Prefill label from the selected template and derive a unique slug code on save. Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
This commit is contained in:
parent
d9aeee1073
commit
2f7f121121
1 changed files with 49 additions and 9 deletions
|
|
@ -113,11 +113,8 @@
|
|||
<FormField label="Plantilla">
|
||||
<Select v-model="roleForm.template" :options="templateOptions" option-label="label" option-value="value" class="w-full" />
|
||||
</FormField>
|
||||
<FormField label="Código">
|
||||
<InputText v-model="roleForm.code" class="w-full" />
|
||||
</FormField>
|
||||
<FormField label="Etiqueta">
|
||||
<InputText v-model="roleForm.label" class="w-full" />
|
||||
<InputText v-model="roleForm.label" class="w-full" placeholder="Nombre visible del rol" />
|
||||
</FormField>
|
||||
</div>
|
||||
<template #footer>
|
||||
|
|
@ -184,10 +181,11 @@ const userForm = reactive({
|
|||
|
||||
const roleForm = reactive({
|
||||
template: "operativo",
|
||||
code: "",
|
||||
label: "",
|
||||
});
|
||||
|
||||
const RESERVED_ROLE_CODES = new Set(["tenant_admin", "platform_admin", "user", "operativo"]);
|
||||
|
||||
const templateOptions = [
|
||||
{ label: "Administrador operativo", value: "admin_operativo" },
|
||||
{ label: "Supervisor de obra", value: "supervisor_obra" },
|
||||
|
|
@ -384,20 +382,54 @@ async function resetAccess() {
|
|||
}
|
||||
}
|
||||
|
||||
function slugRoleCode(text: string): string {
|
||||
let s = text
|
||||
.normalize("NFD")
|
||||
.replace(/\p{M}/gu, "")
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]+/g, "_")
|
||||
.replace(/^_+|_+$/g, "")
|
||||
.replace(/_+/g, "_");
|
||||
if (!s || !/^[a-z]/.test(s)) s = `rol_${s || "nuevo"}`;
|
||||
return s.slice(0, 64);
|
||||
}
|
||||
|
||||
function uniqueRoleCode(base: string): string {
|
||||
const taken = new Set(roles.value.map((r) => r.code));
|
||||
let code = base;
|
||||
let n = 2;
|
||||
while (taken.has(code) || RESERVED_ROLE_CODES.has(code)) {
|
||||
const suffix = `_${n}`;
|
||||
code = `${base.slice(0, Math.max(1, 64 - suffix.length))}${suffix}`;
|
||||
n++;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
function roleCodeFromForm(): string {
|
||||
const label = roleForm.label.trim();
|
||||
const base = slugRoleCode(label || roleForm.template);
|
||||
return uniqueRoleCode(base);
|
||||
}
|
||||
|
||||
function openNewRole() {
|
||||
roleForm.template = "operativo";
|
||||
roleForm.code = "";
|
||||
roleForm.label = "";
|
||||
roleForm.label = templateOptions.find((o) => o.value === "operativo")?.label ?? "";
|
||||
showRoleDialog.value = true;
|
||||
}
|
||||
|
||||
async function saveRole() {
|
||||
saving.value = true;
|
||||
try {
|
||||
const code = (roleForm.code || roleForm.template).trim().toLowerCase();
|
||||
const label = roleForm.label.trim();
|
||||
if (!label) {
|
||||
toast.add({ severity: "warn", summary: "Indique la etiqueta del rol", life: 3000 });
|
||||
return;
|
||||
}
|
||||
const code = roleCodeFromForm();
|
||||
await api("/v1/iam/roles", {
|
||||
method: "POST",
|
||||
json: { code, label: roleForm.label || code, template: roleForm.template },
|
||||
json: { code, label, template: roleForm.template },
|
||||
});
|
||||
toast.add({ severity: "success", summary: "Rol creado", life: 2500 });
|
||||
showRoleDialog.value = false;
|
||||
|
|
@ -510,6 +542,14 @@ function syncChrome() {
|
|||
|
||||
watch([selectedUser, selectedRole, treeKey], syncChrome);
|
||||
|
||||
watch(
|
||||
() => roleForm.template,
|
||||
(tpl) => {
|
||||
const opt = templateOptions.find((o) => o.value === tpl);
|
||||
if (opt) roleForm.label = opt.label;
|
||||
},
|
||||
);
|
||||
|
||||
onMounted(async () => {
|
||||
if (!treeKey.value) treeKey.value = "users-active";
|
||||
await load();
|
||||
|
|
|
|||
Loading…
Reference in a new issue