mirror of
https://origin.cursor.com/mrdevmx/panels.git
synced 2026-10-09 15:33:17 +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">
|
<FormField label="Plantilla">
|
||||||
<Select v-model="roleForm.template" :options="templateOptions" option-label="label" option-value="value" class="w-full" />
|
<Select v-model="roleForm.template" :options="templateOptions" option-label="label" option-value="value" class="w-full" />
|
||||||
</FormField>
|
</FormField>
|
||||||
<FormField label="Código">
|
|
||||||
<InputText v-model="roleForm.code" class="w-full" />
|
|
||||||
</FormField>
|
|
||||||
<FormField label="Etiqueta">
|
<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>
|
</FormField>
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
|
|
@ -184,10 +181,11 @@ const userForm = reactive({
|
||||||
|
|
||||||
const roleForm = reactive({
|
const roleForm = reactive({
|
||||||
template: "operativo",
|
template: "operativo",
|
||||||
code: "",
|
|
||||||
label: "",
|
label: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const RESERVED_ROLE_CODES = new Set(["tenant_admin", "platform_admin", "user", "operativo"]);
|
||||||
|
|
||||||
const templateOptions = [
|
const templateOptions = [
|
||||||
{ label: "Administrador operativo", value: "admin_operativo" },
|
{ label: "Administrador operativo", value: "admin_operativo" },
|
||||||
{ label: "Supervisor de obra", value: "supervisor_obra" },
|
{ 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() {
|
function openNewRole() {
|
||||||
roleForm.template = "operativo";
|
roleForm.template = "operativo";
|
||||||
roleForm.code = "";
|
roleForm.label = templateOptions.find((o) => o.value === "operativo")?.label ?? "";
|
||||||
roleForm.label = "";
|
|
||||||
showRoleDialog.value = true;
|
showRoleDialog.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveRole() {
|
async function saveRole() {
|
||||||
saving.value = true;
|
saving.value = true;
|
||||||
try {
|
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", {
|
await api("/v1/iam/roles", {
|
||||||
method: "POST",
|
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 });
|
toast.add({ severity: "success", summary: "Rol creado", life: 2500 });
|
||||||
showRoleDialog.value = false;
|
showRoleDialog.value = false;
|
||||||
|
|
@ -510,6 +542,14 @@ function syncChrome() {
|
||||||
|
|
||||||
watch([selectedUser, selectedRole, treeKey], 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 () => {
|
onMounted(async () => {
|
||||||
if (!treeKey.value) treeKey.value = "users-active";
|
if (!treeKey.value) treeKey.value = "users-active";
|
||||||
await load();
|
await load();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue