Add limited backoffice role template actions
This commit is contained in:
@@ -1,21 +1,136 @@
|
||||
<script setup>
|
||||
import EditableTableColumn from "@/components/displays/buttons/EditableTableColumn.vue";
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import Swal from "sweetalert2";
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
defineProps(['objects']);
|
||||
import { ref } from 'vue';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { usePaginatedListInstance } from "@/components/pagination/paginatedList.vue";
|
||||
const { loadList } = usePaginatedListInstance();
|
||||
import { SessionUser } from "@/components/session/token/SessionUser.vue";
|
||||
import ActionSettingsWheelButton from "@/components/displays/buttons/ActionSettingsWheelButton.vue";
|
||||
import ActionSettingsWheelItem from "@/components/displays/buttons/ActionSettingsWheelItem.vue";
|
||||
import ActionSettingsWheelItemLabel from "@/components/displays/buttons/ActionSettingsWheelItemLabel.vue";
|
||||
|
||||
const redirect = (path) => {
|
||||
window.location = path;
|
||||
}
|
||||
|
||||
const limitedBackofficeTemplates = ref([]);
|
||||
const templatesLoading = ref(false);
|
||||
const templatesLoadError = ref(false);
|
||||
const applyingTemplateKey = ref("");
|
||||
|
||||
const canApplyLimitedBackofficeTemplates = computed(() => SessionUser.hasPermission("add_role_permission"));
|
||||
|
||||
const loadLimitedBackofficeTemplates = async () => {
|
||||
if (!canApplyLimitedBackofficeTemplates.value || templatesLoading.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
templatesLoading.value = true;
|
||||
templatesLoadError.value = false;
|
||||
try {
|
||||
const templates = await SessionUser.objects.roles.functions.getLimitedBackofficePermissionTemplates();
|
||||
limitedBackofficeTemplates.value = Array.isArray(templates) ? templates : [];
|
||||
} catch (error) {
|
||||
console.error("Failed to load limited backoffice permission templates", error);
|
||||
templatesLoadError.value = true;
|
||||
} finally {
|
||||
templatesLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const templateTranslation = (template, field) => {
|
||||
const key = `templates.limited_backoffice.roles.${template?.key}.${field}`;
|
||||
const translated = t(key);
|
||||
return translated === key ? template?.[field] || template?.key || "" : translated;
|
||||
};
|
||||
|
||||
const templateLabel = (template) => templateTranslation(template, "label");
|
||||
|
||||
const rolePermissions = (role) => (Array.isArray(role?.permissions) ? role.permissions : []);
|
||||
const templatePermissions = (template) => (Array.isArray(template?.permissions) ? template.permissions : []);
|
||||
|
||||
const missingTemplatePermissions = (role, template) => {
|
||||
const currentPermissions = new Set(rolePermissions(role));
|
||||
return templatePermissions(template).filter((permission) => permission && !currentPermissions.has(permission));
|
||||
};
|
||||
|
||||
const roleTemplateActionKey = (role, template) => `${role?.id}:${template?.key}`;
|
||||
const isApplyingTemplate = (role, template) => applyingTemplateKey.value === roleTemplateActionKey(role, template);
|
||||
const isTemplateActionDisabled = (role, template) =>
|
||||
templatesLoading.value || Boolean(applyingTemplateKey.value) || missingTemplatePermissions(role, template).length === 0;
|
||||
|
||||
const applyLimitedBackofficeTemplate = async (role, template) => {
|
||||
const missingPermissions = missingTemplatePermissions(role, template);
|
||||
const label = templateLabel(template);
|
||||
|
||||
if (missingPermissions.length === 0) {
|
||||
await Swal.fire({
|
||||
icon: "success",
|
||||
title: t("roles.templates.up_to_date_title"),
|
||||
text: t("roles.templates.up_to_date_text", { role: role.name, template: label }),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const confirmation = await Swal.fire({
|
||||
icon: "question",
|
||||
title: t("roles.templates.confirm_title"),
|
||||
text: t("roles.templates.confirm_text", {
|
||||
count: missingPermissions.length,
|
||||
role: role.name,
|
||||
template: label,
|
||||
}),
|
||||
showCancelButton: true,
|
||||
confirmButtonText: t("roles.templates.confirm_button"),
|
||||
cancelButtonText: t("common.cancel"),
|
||||
});
|
||||
|
||||
if (!confirmation.isConfirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
applyingTemplateKey.value = roleTemplateActionKey(role, template);
|
||||
try {
|
||||
const results = await Promise.allSettled(
|
||||
missingPermissions.map((permission) =>
|
||||
SessionUser.objects.roles.functions.permissions.add(role.id, permission)
|
||||
)
|
||||
);
|
||||
const failed = results.filter((result) => result.status === "rejected");
|
||||
|
||||
if (failed.length > 0) {
|
||||
throw failed[0].reason;
|
||||
}
|
||||
|
||||
await Swal.fire({
|
||||
icon: "success",
|
||||
title: t("roles.templates.success_title"),
|
||||
text: t("roles.templates.success_text", {
|
||||
count: missingPermissions.length,
|
||||
role: role.name,
|
||||
template: label,
|
||||
}),
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Failed to apply limited backoffice permission template", error);
|
||||
await Swal.fire({
|
||||
icon: "error",
|
||||
title: t("roles.templates.error_title"),
|
||||
text: t("roles.templates.error_text", { role: role.name, template: label }),
|
||||
});
|
||||
} finally {
|
||||
applyingTemplateKey.value = "";
|
||||
await loadList();
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(loadLimitedBackofficeTemplates);
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -66,6 +181,46 @@ const redirect = (path) => {
|
||||
icon="fas fa-clone"
|
||||
:click-action="() => SessionUser.objects.roles.functions.cloneObject(object.id).then(() => loadList())"
|
||||
></ActionSettingsWheelItem>
|
||||
|
||||
<div
|
||||
v-if="canApplyLimitedBackofficeTemplates"
|
||||
class="role-limited-backoffice-template-actions"
|
||||
:data-testid="`role-limited-backoffice-template-actions-${object.id}`"
|
||||
>
|
||||
<ActionSettingsWheelItemLabel
|
||||
:label="$t('roles.templates.section')"
|
||||
icon="fas fa-id-badge"
|
||||
></ActionSettingsWheelItemLabel>
|
||||
<ActionSettingsWheelItem
|
||||
v-if="templatesLoading"
|
||||
:label="$t('roles.templates.loading')"
|
||||
icon="fas fa-spinner"
|
||||
disabled
|
||||
></ActionSettingsWheelItem>
|
||||
<ActionSettingsWheelItem
|
||||
v-else-if="templatesLoadError"
|
||||
:label="$t('roles.templates.load_error')"
|
||||
icon="fas fa-sync-alt"
|
||||
:click-action="loadLimitedBackofficeTemplates"
|
||||
></ActionSettingsWheelItem>
|
||||
<ActionSettingsWheelItem
|
||||
v-else-if="limitedBackofficeTemplates.length === 0"
|
||||
:label="$t('roles.templates.unavailable')"
|
||||
icon="fas fa-ban"
|
||||
disabled
|
||||
></ActionSettingsWheelItem>
|
||||
<template v-else>
|
||||
<ActionSettingsWheelItem
|
||||
v-for="template in limitedBackofficeTemplates"
|
||||
:key="template.key"
|
||||
:label="$t('roles.templates.apply', { template: templateLabel(template) })"
|
||||
:icon="isApplyingTemplate(object, template) ? 'fas fa-spinner' : 'fas fa-id-badge'"
|
||||
:disabled="isTemplateActionDisabled(object, template)"
|
||||
:test-id="`role-template-${object.id}-${template.key}`"
|
||||
:click-action="() => applyLimitedBackofficeTemplate(object, template)"
|
||||
></ActionSettingsWheelItem>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</ActionSettingsWheelButton>
|
||||
</div>
|
||||
@@ -85,4 +240,4 @@ const redirect = (path) => {
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script>
|
||||
import Swal from "sweetalert2";
|
||||
import { authenticatedRequest } from "@/components/session/authenticatedRequest.vue";
|
||||
import { ObjectsGlobal } from "@/components/session/token/SessionUser/Objects/ObjectsGlobal.vue";
|
||||
import { SessionUser } from "@/components/session/token/SessionUser.vue";
|
||||
@@ -123,6 +122,10 @@ export const Roles = {
|
||||
id: id
|
||||
});
|
||||
},
|
||||
getLimitedBackofficePermissionTemplates: async () => {
|
||||
const response = await authenticatedRequest("/roles/limited-backoffice-permission-templates", "GET");
|
||||
return response?.data?.data ?? response?.data ?? [];
|
||||
},
|
||||
permissions: {
|
||||
add: async (roleId, permissionId) => {
|
||||
return authenticatedRequest("/roles/permissions", "POST", {
|
||||
@@ -161,4 +164,4 @@ export const Roles = {
|
||||
);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@@ -5048,6 +5048,22 @@
|
||||
"title": "Tilladelser for rolle {id}",
|
||||
"title_with_name": "Tilladelser for {name}"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "Anvend {template}-skabelon",
|
||||
"confirm_button": "Anvend skabelon",
|
||||
"confirm_text": "Tilfoej {count} manglende tilladelser fra {template} til {role}?",
|
||||
"confirm_title": "Anvend tilladelsesskabelon?",
|
||||
"error_text": "En eller flere tilladelser fra {template} kunne ikke tilfoejes til {role}. Rollelisten blev genindlaest.",
|
||||
"error_title": "Kunne ikke anvende skabelon",
|
||||
"load_error": "Kunne ikke indlaese skabeloner. Proev igen",
|
||||
"loading": "Indlaeser skabeloner...",
|
||||
"section": "Begraenset backoffice-skabeloner",
|
||||
"success_text": "Tilfoejede {count} tilladelser fra {template} til {role}.",
|
||||
"success_title": "Skabelon anvendt",
|
||||
"unavailable": "Ingen skabeloner er tilgaengelige.",
|
||||
"up_to_date_text": "{role} har allerede alle tilladelser i {template}.",
|
||||
"up_to_date_title": "Rollen er opdateret"
|
||||
},
|
||||
"subtitle": "@.capitalize:{'words.generated.brugerroller'}"
|
||||
},
|
||||
"self_wash": {
|
||||
|
||||
@@ -5159,6 +5159,22 @@
|
||||
"title": "Berechtigungen fuer Rolle {id}",
|
||||
"title_with_name": "Berechtigungen fuer {name}"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "{template}-Vorlage anwenden",
|
||||
"confirm_button": "Vorlage anwenden",
|
||||
"confirm_text": "{count} fehlende Berechtigungen aus {template} zu {role} hinzufuegen?",
|
||||
"confirm_title": "Berechtigungsvorlage anwenden?",
|
||||
"error_text": "Eine oder mehrere Berechtigungen aus {template} konnten {role} nicht hinzugefuegt werden. Die Rollenliste wurde neu geladen.",
|
||||
"error_title": "Vorlage konnte nicht angewendet werden",
|
||||
"load_error": "Vorlagen konnten nicht geladen werden. Erneut versuchen",
|
||||
"loading": "Vorlagen werden geladen...",
|
||||
"section": "Limited-Backoffice-Vorlagen",
|
||||
"success_text": "{count} Berechtigungen aus {template} zu {role} hinzugefuegt.",
|
||||
"success_title": "Vorlage angewendet",
|
||||
"unavailable": "Keine Vorlagen verfuegbar.",
|
||||
"up_to_date_text": "{role} hat bereits alle Berechtigungen in {template}.",
|
||||
"up_to_date_title": "Rolle ist aktuell"
|
||||
},
|
||||
"subtitle": "Benutzerrollen"
|
||||
},
|
||||
"self_wash": {
|
||||
|
||||
@@ -4880,6 +4880,22 @@
|
||||
"title": "Role {id} permissions",
|
||||
"title_with_name": "{name} permissions"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "Apply {template} template",
|
||||
"confirm_button": "Apply template",
|
||||
"confirm_text": "Add {count} missing permissions from {template} to {role}?",
|
||||
"confirm_title": "Apply permission template?",
|
||||
"error_text": "One or more permissions from {template} could not be added to {role}. The role list was reloaded.",
|
||||
"error_title": "Could not apply template",
|
||||
"load_error": "Could not load templates. Try again",
|
||||
"loading": "Loading templates...",
|
||||
"section": "Limited backoffice templates",
|
||||
"success_text": "Added {count} permissions from {template} to {role}.",
|
||||
"success_title": "Template applied",
|
||||
"unavailable": "No templates are available.",
|
||||
"up_to_date_text": "{role} already has every permission in {template}.",
|
||||
"up_to_date_title": "Role is up to date"
|
||||
},
|
||||
"subtitle": "@.capitalize:{'words.generated.user'} @:{'words.generated.roles'}"
|
||||
},
|
||||
"self_wash": {
|
||||
|
||||
@@ -4373,6 +4373,22 @@
|
||||
"title": "@:{'templates.generated.compat.roles.permissions.title'}",
|
||||
"title_with_name": "@:{'templates.generated.compat.roles.permissions.title_with_name'}"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "@:{'templates.generated.compat.roles.templates.apply'}",
|
||||
"confirm_button": "@:{'templates.generated.compat.roles.templates.confirm_button'}",
|
||||
"confirm_text": "@:{'templates.generated.compat.roles.templates.confirm_text'}",
|
||||
"confirm_title": "@:{'templates.generated.compat.roles.templates.confirm_title'}",
|
||||
"error_text": "@:{'templates.generated.compat.roles.templates.error_text'}",
|
||||
"error_title": "@:{'templates.generated.compat.roles.templates.error_title'}",
|
||||
"load_error": "@:{'templates.generated.compat.roles.templates.load_error'}",
|
||||
"loading": "@:{'templates.generated.compat.roles.templates.loading'}",
|
||||
"section": "@:{'templates.generated.compat.roles.templates.section'}",
|
||||
"success_text": "@:{'templates.generated.compat.roles.templates.success_text'}",
|
||||
"success_title": "@:{'templates.generated.compat.roles.templates.success_title'}",
|
||||
"unavailable": "@:{'templates.generated.compat.roles.templates.unavailable'}",
|
||||
"up_to_date_text": "@:{'templates.generated.compat.roles.templates.up_to_date_text'}",
|
||||
"up_to_date_title": "@:{'templates.generated.compat.roles.templates.up_to_date_title'}"
|
||||
},
|
||||
"subtitle": "@:{'templates.generated.compat.roles.subtitle'}",
|
||||
"title": "@:{'templates.generated.compat.common.roles'}"
|
||||
},
|
||||
|
||||
@@ -5162,6 +5162,22 @@
|
||||
"title": "Tillatelser for rolle {id}",
|
||||
"title_with_name": "Tillatelser for {name}"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "Bruk {template}-mal",
|
||||
"confirm_button": "Bruk mal",
|
||||
"confirm_text": "Legg til {count} manglende tillatelser fra {template} til {role}?",
|
||||
"confirm_title": "Bruke tillatelsesmal?",
|
||||
"error_text": "En eller flere tillatelser fra {template} kunne ikke legges til i {role}. Rollelisten ble lastet inn pa nytt.",
|
||||
"error_title": "Kunne ikke bruke mal",
|
||||
"load_error": "Kunne ikke laste maler. Prov igjen",
|
||||
"loading": "Laster maler...",
|
||||
"section": "Begrenset backoffice-maler",
|
||||
"success_text": "La til {count} tillatelser fra {template} i {role}.",
|
||||
"success_title": "Mal brukt",
|
||||
"unavailable": "Ingen maler er tilgjengelige.",
|
||||
"up_to_date_text": "{role} har allerede alle tillatelser i {template}.",
|
||||
"up_to_date_title": "Rollen er oppdatert"
|
||||
},
|
||||
"subtitle": "@.capitalize:{'words.generated.user'} roles"
|
||||
},
|
||||
"self_wash": {
|
||||
|
||||
@@ -5212,6 +5212,22 @@
|
||||
"title": "Behorigheter for roll {id}",
|
||||
"title_with_name": "Behorigheter for {name}"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "Anvand mallen {template}",
|
||||
"confirm_button": "Anvand mall",
|
||||
"confirm_text": "Lagg till {count} saknade behorigheter fran {template} till {role}?",
|
||||
"confirm_title": "Anvanda behorighetsmall?",
|
||||
"error_text": "En eller flera behorigheter fran {template} kunde inte laggas till i {role}. Rolllistan laddades om.",
|
||||
"error_title": "Kunde inte anvanda mall",
|
||||
"load_error": "Kunde inte ladda mallar. Forsok igen",
|
||||
"loading": "Laddar mallar...",
|
||||
"section": "Begransade backoffice-mallar",
|
||||
"success_text": "Lade till {count} behorigheter fran {template} i {role}.",
|
||||
"success_title": "Mall anvand",
|
||||
"unavailable": "Inga mallar ar tillgangliga.",
|
||||
"up_to_date_text": "{role} har redan alla behorigheter i {template}.",
|
||||
"up_to_date_title": "Rollen ar uppdaterad"
|
||||
},
|
||||
"subtitle": "@.capitalize:{'words.generated.user'} @:{'words.generated.roles'}"
|
||||
},
|
||||
"self_wash": {
|
||||
|
||||
@@ -91,6 +91,22 @@
|
||||
"subtitle": "Rolletilladelser",
|
||||
"title": "Tilladelser for rolle {id}",
|
||||
"title_with_name": "Tilladelser for {name}"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "Anvend {template}-skabelon",
|
||||
"confirm_button": "Anvend skabelon",
|
||||
"confirm_text": "Tilfoej {count} manglende tilladelser fra {template} til {role}?",
|
||||
"confirm_title": "Anvend tilladelsesskabelon?",
|
||||
"error_text": "En eller flere tilladelser fra {template} kunne ikke tilfoejes til {role}. Rollelisten blev genindlaest.",
|
||||
"error_title": "Kunne ikke anvende skabelon",
|
||||
"load_error": "Kunne ikke indlaese skabeloner. Proev igen",
|
||||
"loading": "Indlaeser skabeloner...",
|
||||
"section": "Begraenset backoffice-skabeloner",
|
||||
"success_text": "Tilfoejede {count} tilladelser fra {template} til {role}.",
|
||||
"success_title": "Skabelon anvendt",
|
||||
"unavailable": "Ingen skabeloner er tilgaengelige.",
|
||||
"up_to_date_text": "{role} har allerede alle tilladelser i {template}.",
|
||||
"up_to_date_title": "Rollen er opdateret"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,22 @@
|
||||
"subtitle": "Rollenberechtigungen",
|
||||
"title": "Berechtigungen fuer Rolle {id}",
|
||||
"title_with_name": "Berechtigungen fuer {name}"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "{template}-Vorlage anwenden",
|
||||
"confirm_button": "Vorlage anwenden",
|
||||
"confirm_text": "{count} fehlende Berechtigungen aus {template} zu {role} hinzufuegen?",
|
||||
"confirm_title": "Berechtigungsvorlage anwenden?",
|
||||
"error_text": "Eine oder mehrere Berechtigungen aus {template} konnten {role} nicht hinzugefuegt werden. Die Rollenliste wurde neu geladen.",
|
||||
"error_title": "Vorlage konnte nicht angewendet werden",
|
||||
"load_error": "Vorlagen konnten nicht geladen werden. Erneut versuchen",
|
||||
"loading": "Vorlagen werden geladen...",
|
||||
"section": "Limited-Backoffice-Vorlagen",
|
||||
"success_text": "{count} Berechtigungen aus {template} zu {role} hinzugefuegt.",
|
||||
"success_title": "Vorlage angewendet",
|
||||
"unavailable": "Keine Vorlagen verfuegbar.",
|
||||
"up_to_date_text": "{role} hat bereits alle Berechtigungen in {template}.",
|
||||
"up_to_date_title": "Rolle ist aktuell"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,22 @@
|
||||
"subtitle": "Role permissions",
|
||||
"title": "Role {id} permissions",
|
||||
"title_with_name": "{name} permissions"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "Apply {template} template",
|
||||
"confirm_button": "Apply template",
|
||||
"confirm_text": "Add {count} missing permissions from {template} to {role}?",
|
||||
"confirm_title": "Apply permission template?",
|
||||
"error_text": "One or more permissions from {template} could not be added to {role}. The role list was reloaded.",
|
||||
"error_title": "Could not apply template",
|
||||
"load_error": "Could not load templates. Try again",
|
||||
"loading": "Loading templates...",
|
||||
"section": "Limited backoffice templates",
|
||||
"success_text": "Added {count} permissions from {template} to {role}.",
|
||||
"success_title": "Template applied",
|
||||
"unavailable": "No templates are available.",
|
||||
"up_to_date_text": "{role} already has every permission in {template}.",
|
||||
"up_to_date_title": "Role is up to date"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,22 @@
|
||||
"title": "@:{'phrases.compat.roles.permissions.title'}",
|
||||
"title_with_name": "@:{'phrases.compat.roles.permissions.title_with_name'}"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "@:{'phrases.compat.roles.templates.apply'}",
|
||||
"confirm_button": "@:{'phrases.compat.roles.templates.confirm_button'}",
|
||||
"confirm_text": "@:{'phrases.compat.roles.templates.confirm_text'}",
|
||||
"confirm_title": "@:{'phrases.compat.roles.templates.confirm_title'}",
|
||||
"error_text": "@:{'phrases.compat.roles.templates.error_text'}",
|
||||
"error_title": "@:{'phrases.compat.roles.templates.error_title'}",
|
||||
"load_error": "@:{'phrases.compat.roles.templates.load_error'}",
|
||||
"loading": "@:{'phrases.compat.roles.templates.loading'}",
|
||||
"section": "@:{'phrases.compat.roles.templates.section'}",
|
||||
"success_text": "@:{'phrases.compat.roles.templates.success_text'}",
|
||||
"success_title": "@:{'phrases.compat.roles.templates.success_title'}",
|
||||
"unavailable": "@:{'phrases.compat.roles.templates.unavailable'}",
|
||||
"up_to_date_text": "@:{'phrases.compat.roles.templates.up_to_date_text'}",
|
||||
"up_to_date_title": "@:{'phrases.compat.roles.templates.up_to_date_title'}"
|
||||
},
|
||||
"subtitle": "@:{'phrases.compat.roles.subtitle'}",
|
||||
"title": "@:{'phrases.compat.common.roles'}"
|
||||
}
|
||||
|
||||
@@ -91,6 +91,22 @@
|
||||
"subtitle": "Rolletillatelser",
|
||||
"title": "Tillatelser for rolle {id}",
|
||||
"title_with_name": "Tillatelser for {name}"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "Bruk {template}-mal",
|
||||
"confirm_button": "Bruk mal",
|
||||
"confirm_text": "Legg til {count} manglende tillatelser fra {template} til {role}?",
|
||||
"confirm_title": "Bruke tillatelsesmal?",
|
||||
"error_text": "En eller flere tillatelser fra {template} kunne ikke legges til i {role}. Rollelisten ble lastet inn pa nytt.",
|
||||
"error_title": "Kunne ikke bruke mal",
|
||||
"load_error": "Kunne ikke laste maler. Prov igjen",
|
||||
"loading": "Laster maler...",
|
||||
"section": "Begrenset backoffice-maler",
|
||||
"success_text": "La til {count} tillatelser fra {template} i {role}.",
|
||||
"success_title": "Mal brukt",
|
||||
"unavailable": "Ingen maler er tilgjengelige.",
|
||||
"up_to_date_text": "{role} har allerede alle tillatelser i {template}.",
|
||||
"up_to_date_title": "Rollen er oppdatert"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,22 @@
|
||||
"subtitle": "Rollbehorigheter",
|
||||
"title": "Behorigheter for roll {id}",
|
||||
"title_with_name": "Behorigheter for {name}"
|
||||
},
|
||||
"templates": {
|
||||
"apply": "Anvand mallen {template}",
|
||||
"confirm_button": "Anvand mall",
|
||||
"confirm_text": "Lagg till {count} saknade behorigheter fran {template} till {role}?",
|
||||
"confirm_title": "Anvanda behorighetsmall?",
|
||||
"error_text": "En eller flera behorigheter fran {template} kunde inte laggas till i {role}. Rolllistan laddades om.",
|
||||
"error_title": "Kunde inte anvanda mall",
|
||||
"load_error": "Kunde inte ladda mallar. Forsok igen",
|
||||
"loading": "Laddar mallar...",
|
||||
"section": "Begransade backoffice-mallar",
|
||||
"success_text": "Lade till {count} behorigheter fran {template} i {role}.",
|
||||
"success_title": "Mall anvand",
|
||||
"unavailable": "Inga mallar ar tillgangliga.",
|
||||
"up_to_date_text": "{role} har redan alla behorigheter i {template}.",
|
||||
"up_to_date_title": "Rollen ar uppdaterad"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,11 +43,46 @@ const departments = [
|
||||
},
|
||||
];
|
||||
|
||||
const roleTemplatePermissions = [
|
||||
"user",
|
||||
"permissions_list_own",
|
||||
"list_departments",
|
||||
"list_orders",
|
||||
"fetch_order",
|
||||
"statistics_orders_new",
|
||||
];
|
||||
|
||||
const limitedBackofficePermissionTemplates = [
|
||||
{
|
||||
key: "viewer",
|
||||
label: "Deactivated",
|
||||
description: "Keeps the employee registered without order, booking, or management permissions.",
|
||||
permissions: ["user", "permissions_list_own"],
|
||||
},
|
||||
{
|
||||
key: "cashier",
|
||||
label: "Cashier",
|
||||
description: "Can work with POS orders for assigned departments.",
|
||||
permissions: roleTemplatePermissions,
|
||||
},
|
||||
];
|
||||
|
||||
type PermissionCall = {
|
||||
action: "add" | "remove";
|
||||
permission: string;
|
||||
};
|
||||
|
||||
const roleListEnvelope = (rows: Array<Record<string, unknown>>) => ({
|
||||
data: rows,
|
||||
meta: {
|
||||
pagination: {
|
||||
page: 1,
|
||||
per_page: 100,
|
||||
total: rows.length,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const openGroupTab = async (page: Page, label: RegExp) => {
|
||||
await page.locator(".tabs").getByText(label).click();
|
||||
};
|
||||
@@ -147,6 +182,107 @@ const bootRolePermissionsPage = async (page: Page, routeOptions = {}) => {
|
||||
};
|
||||
|
||||
test.describe("Superuser role permissions", () => {
|
||||
test("applies limited backoffice templates from the role action wheel in add-only mode", async ({ page }) => {
|
||||
const role = {
|
||||
id: 2,
|
||||
name: "Operations manager",
|
||||
description: "Can manage operations.",
|
||||
created_at: "2026-07-06T08:00:00.000Z",
|
||||
permissions: ["user", "list_orders"],
|
||||
};
|
||||
const calls: PermissionCall[] = [];
|
||||
|
||||
await page.addInitScript(() => {
|
||||
window.localStorage.setItem("locale", "en");
|
||||
});
|
||||
await seedAuthenticatedState(page, "superuser-roles-template-token");
|
||||
await mockApi(page, {
|
||||
authenticated: true,
|
||||
permissions: ["superuser", "user", "list_roles", "add_role_permission"],
|
||||
sessionData: {
|
||||
group_id: 1,
|
||||
},
|
||||
});
|
||||
|
||||
await page.route(apiPathPattern("/roles/limited-backoffice-permission-templates"), async (route: Route) => {
|
||||
await route.fulfill(json({ data: limitedBackofficePermissionTemplates }));
|
||||
});
|
||||
|
||||
await page.route(apiPathPattern("/roles"), async (route: Route) => {
|
||||
await route.fulfill(json(roleListEnvelope([role])));
|
||||
});
|
||||
|
||||
await page.route(apiPathPattern("/roles/permissions"), async (route: Route) => {
|
||||
const body = route.request().postDataJSON();
|
||||
const permission = String(body.permission_id || "");
|
||||
calls.push({ action: "add", permission });
|
||||
if (!role.permissions.includes(permission)) {
|
||||
role.permissions = [...role.permissions, permission];
|
||||
}
|
||||
await route.fulfill(json({ data: role }));
|
||||
});
|
||||
|
||||
await page.goto("/superuser/roles", { waitUntil: "domcontentloaded" });
|
||||
await expect(page.getByRole("row", { name: /Operations manager/ })).toBeVisible();
|
||||
|
||||
const row = page.getByRole("row", { name: /Operations manager/ });
|
||||
await row.locator(".action-settings-wheel-trigger").click();
|
||||
await expect(page.getByTestId("role-limited-backoffice-template-actions-2")).toBeVisible();
|
||||
await page.getByTestId("role-template-2-cashier").click();
|
||||
|
||||
await expect(page.getByText("Apply permission template?")).toBeVisible();
|
||||
await page.getByRole("button", { name: "Apply template" }).click();
|
||||
|
||||
await expect
|
||||
.poll(() => calls.map((call) => call.permission))
|
||||
.toEqual(["permissions_list_own", "list_departments", "fetch_order", "statistics_orders_new"]);
|
||||
await expect(page.getByText("Template applied")).toBeVisible();
|
||||
});
|
||||
|
||||
test("disables limited backoffice template actions when a role is already up to date", async ({ page }) => {
|
||||
const role = {
|
||||
id: 3,
|
||||
name: "Cashier role",
|
||||
description: "Current cashier permissions.",
|
||||
created_at: "2026-07-06T08:00:00.000Z",
|
||||
permissions: [...roleTemplatePermissions],
|
||||
};
|
||||
const calls: PermissionCall[] = [];
|
||||
|
||||
await page.addInitScript(() => {
|
||||
window.localStorage.setItem("locale", "en");
|
||||
});
|
||||
await seedAuthenticatedState(page, "superuser-roles-template-up-to-date-token");
|
||||
await mockApi(page, {
|
||||
authenticated: true,
|
||||
permissions: ["superuser", "user", "list_roles", "add_role_permission"],
|
||||
sessionData: {
|
||||
group_id: 1,
|
||||
},
|
||||
});
|
||||
|
||||
await page.route(apiPathPattern("/roles/limited-backoffice-permission-templates"), async (route: Route) => {
|
||||
await route.fulfill(json({ data: limitedBackofficePermissionTemplates }));
|
||||
});
|
||||
|
||||
await page.route(apiPathPattern("/roles"), async (route: Route) => {
|
||||
await route.fulfill(json(roleListEnvelope([role])));
|
||||
});
|
||||
|
||||
await page.route(apiPathPattern("/roles/permissions"), async (route: Route) => {
|
||||
calls.push({ action: "add", permission: String(route.request().postDataJSON().permission_id || "") });
|
||||
await route.fulfill(json({ data: role }));
|
||||
});
|
||||
|
||||
await page.goto("/superuser/roles", { waitUntil: "domcontentloaded" });
|
||||
const row = page.getByRole("row", { name: /Cashier role/ });
|
||||
await expect(row).toBeVisible();
|
||||
await row.locator(".action-settings-wheel-trigger").click();
|
||||
|
||||
await expect(page.getByTestId("role-template-3-cashier")).toBeDisabled();
|
||||
expect(calls).toEqual([]);
|
||||
});
|
||||
|
||||
test("@smoke @pr loads grouped permissions, searches, and toggles without a blank page", async ({ page }) => {
|
||||
const { calls } = await bootRolePermissionsPage(page);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user