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:
Cursor Agent 2026-09-08 19:08:46 +00:00
parent d9aeee1073
commit 2f7f121121
No known key found for this signature in database

View file

@ -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();