From 90dc3981d5fab23db811f020bc742803b3c4bcf2 Mon Sep 17 00:00:00 2001 From: Schalli Date: Tue, 4 Aug 2026 18:50:28 +0200 Subject: [PATCH] feat(15-06): phase-wide i18n keys + sixth admin nav entry for groups - de.json/en.json: admin.groups.* (incl. ldapBind, members, deleteConfirm, grants sub-namespaces), admin.users.grants.*, adminModules.grantsLink + grants.* + activationDialog.*, modules.accessDenied.*, marketplace statusNoAccess/toastNoAccess, header.admin.groups -- covers this plan's /admin/groups surface plus the Wave 4 surfaces (permission matrix, user-detail grants, activation dialog, 403 page, marketplace badge) so 15-07/15-08 can run in parallel without touching the translation files - admin-sidebar.tsx: sixth nav entry "Gruppen" -> /admin/groups with a roster/list icon (Lucide list glyph, distinct from the users icon) --- .../src/components/admin/admin-sidebar.tsx | 15 +++ apps/web/src/messages/de.json | 95 ++++++++++++++++++- apps/web/src/messages/en.json | 95 ++++++++++++++++++- 3 files changed, 195 insertions(+), 10 deletions(-) diff --git a/apps/web/src/components/admin/admin-sidebar.tsx b/apps/web/src/components/admin/admin-sidebar.tsx index e471b71..81e0119 100644 --- a/apps/web/src/components/admin/admin-sidebar.tsx +++ b/apps/web/src/components/admin/admin-sidebar.tsx @@ -71,6 +71,21 @@ export function AdminSidebar() { ), }, + { + label: t('admin.groups'), + href: '/admin/groups', + show: true, + icon: ( + + + + + + + + + ), + }, ]; return ( diff --git a/apps/web/src/messages/de.json b/apps/web/src/messages/de.json index 79fa2c2..661ac00 100644 --- a/apps/web/src/messages/de.json +++ b/apps/web/src/messages/de.json @@ -75,7 +75,8 @@ "tenants": "Mandanten", "modules": "Module", "ldap": "LDAP", - "smtp": "SMTP" + "smtp": "SMTP", + "groups": "Gruppen" }, "role": { "SUPER_ADMIN": "Super-Admin", @@ -264,7 +265,21 @@ "status": "Status", "actions": "Aktionen", "password": "Passwort", - "noUsers": "Keine Benutzer gefunden" + "noUsers": "Keine Benutzer gefunden", + "grants": { + "detailsButton": "Details", + "modalTitle": "{username} — Zugriff", + "groupsSection": "Gruppenmitgliedschaften", + "noGroups": "Dieser Benutzer ist keiner Gruppe zugeordnet.", + "accessSection": "Modul-Zugriff", + "moduleColumn": "Modul", + "viaGroupsColumn": "Über Gruppe(n)", + "directColumn": "Direkt", + "noInheritance": "–", + "noActiveModules": "Für diesen Mandanten sind keine Module aktiviert.", + "directCheckboxLabel": "{module} direkt für {user} {granted, select, true {freigeben} other {entziehen}}", + "saveError": "Freigabe konnte nicht gespeichert werden. Bitte erneut versuchen." + } }, "tenants": { "title": "Mandantenverwaltung", @@ -353,6 +368,52 @@ "skipped": "uebersprungen", "errors": "Fehler" } + }, + "groups": { + "title": "Gruppen", + "create": "Gruppe erstellen", + "edit": "Gruppe bearbeiten", + "delete": "Gruppe löschen", + "noGroups": "Keine Gruppen vorhanden", + "noGroupsBody": "Lege deine erste Gruppe an, um Modulzugriff gezielt zu vergeben.", + "name": "Name", + "ldapBinding": "AD-Bindung", + "boundBadge": "AD-gebunden", + "manualBadge": "Manuell", + "defaultGroup": "Standardgruppe", + "setDefault": "Als Standardgruppe festlegen", + "isDefault": "Standardgruppe", + "memberCount": "Mitglieder", + "actions": "Aktionen", + "membersButton": "Mitglieder", + "saveError": "Gruppe konnte nicht gespeichert werden. Bitte erneut versuchen.", + "deleteError": "Gruppe konnte nicht gelöscht werden. Bitte erneut versuchen.", + "ldapBind": { + "hint": "Wähle eine AD-Gruppe aus der Liste, um die Mitgliedschaft automatisch zu synchronisieren.", + "bound": "Gebunden an: {ldapDn}", + "unbind": "Bindung entfernen", + "searchPlaceholder": "AD-Gruppen durchsuchen...", + "discoverError": "AD-Gruppen konnten nicht geladen werden. Bitte erneut versuchen.", + "noResults": "Keine AD-Gruppen gefunden." + }, + "members": { + "title": "Mitglieder", + "remove": "Mitglied entfernen", + "ldapManaged": "Wird über AD-Sync verwaltet", + "sourceManual": "Manuell", + "sourceLdap": "LDAP", + "addTitle": "Mitglied hinzufügen", + "searchPlaceholder": "Benutzer suchen...", + "noMembers": "Keine Mitglieder vorhanden.", + "addError": "Mitglied konnte nicht hinzugefügt werden. Bitte erneut versuchen." + }, + "deleteConfirm": { + "title": "Gruppe löschen", + "body": "Diese Gruppe hat {memberCount} Mitglieder und {grantCount} Modul-Freigaben. Betroffene Benutzer verlieren den Zugriff, sofern sie ihn nicht anderweitig haben. Diese Aktion kann nicht rückgängig gemacht werden." + }, + "grants": { + "matrixCheckboxLabel": "{module} für Gruppe {group} {granted, select, true {freigeben} other {entziehen}}" + } } }, "adminModules": { @@ -367,7 +428,24 @@ "noModules": "Keine Module verfuegbar", "activateSuccess": "Modul erfolgreich aktiviert", "deactivateSuccess": "Modul erfolgreich deaktiviert", - "error": "Fehler bei der Modulverwaltung" + "error": "Fehler bei der Modulverwaltung", + "grantsLink": "Freigaben-Matrix", + "grants": { + "title": "Freigaben-Matrix", + "searchPlaceholder": "Module oder Gruppen durchsuchen...", + "emptyModules": "Es sind noch keine Module für diesen Mandanten aktiviert. Aktiviere zuerst ein Modul unter Module.", + "emptyModulesLink": "Zu Module", + "adminNote": "ADMIN und SUPER_ADMIN haben immer Zugriff auf alle aktiven Module — diese Matrix betrifft nur die Rolle USER.", + "saveError": "Freigabe konnte nicht gespeichert werden. Bitte erneut versuchen." + }, + "activationDialog": { + "title": "Modul aktivieren: {module}", + "body": "Soll die Standardgruppe sofort Zugriff auf dieses Modul erhalten, oder möchtest du die Freigaben separat konfigurieren?", + "grantNow": "Sofort freigeben", + "configureLater": "Später konfigurieren", + "cancel": "Abbrechen", + "noDefaultGroupHint": "Keine Standardgruppe markiert — lege zuerst eine unter Gruppen fest oder konfiguriere die Freigabe manuell." + } }, "theme": { "light": "Hell", @@ -387,7 +465,12 @@ "backToCategory": "Zurueck zur Kategorie", "allModules": "Module", "allModulesDescription": "Verfuegbare Module fuer Ihren Mandanten", - "noActiveModules": "Keine Module aktiviert. Bitten Sie Ihren Administrator, Module zu aktivieren." + "noActiveModules": "Keine Module aktiviert. Bitten Sie Ihren Administrator, Module zu aktivieren.", + "accessDenied": { + "title": "Kein Zugriff auf dieses Modul", + "body": "Du hast für dieses Modul keine Freigabe. Wende dich an deinen Administrator.", + "backToDashboard": "Zur Startseite" + } }, "domaincheck": { "title": "Domaincheck", @@ -521,7 +604,9 @@ "detailVersion": "Version {version}", "detailStatusActive": "Aktiviert fuer diesen Mandanten", "detailStatusInactive": "Nicht aktiviert", - "accessDenied": "Zugriff verweigert" + "accessDenied": "Zugriff verweigert", + "statusNoAccess": "Kein Zugriff", + "toastNoAccess": "Kein Zugriff auf dieses Modul — wende dich an deinen Administrator." }, "certManager": { "title": "Zertifikat-Manager", diff --git a/apps/web/src/messages/en.json b/apps/web/src/messages/en.json index 4d2c85a..e01702a 100644 --- a/apps/web/src/messages/en.json +++ b/apps/web/src/messages/en.json @@ -75,7 +75,8 @@ "tenants": "Tenants", "modules": "Modules", "ldap": "LDAP", - "smtp": "SMTP" + "smtp": "SMTP", + "groups": "Groups" }, "role": { "SUPER_ADMIN": "Super Admin", @@ -264,7 +265,21 @@ "status": "Status", "actions": "Actions", "password": "Password", - "noUsers": "No users found" + "noUsers": "No users found", + "grants": { + "detailsButton": "Details", + "modalTitle": "{username} — Access", + "groupsSection": "Group Memberships", + "noGroups": "This user is not a member of any group.", + "accessSection": "Module Access", + "moduleColumn": "Module", + "viaGroupsColumn": "Via Group(s)", + "directColumn": "Direct", + "noInheritance": "–", + "noActiveModules": "No modules are activated for this tenant.", + "directCheckboxLabel": "{granted, select, true {Grant} other {Revoke}} {module} directly for {user}", + "saveError": "Could not save grant. Please try again." + } }, "tenants": { "title": "Tenant Management", @@ -353,6 +368,52 @@ "skipped": "skipped", "errors": "errors" } + }, + "groups": { + "title": "Groups", + "create": "Create Group", + "edit": "Edit Group", + "delete": "Delete Group", + "noGroups": "No groups yet", + "noGroupsBody": "Create your first group to grant module access selectively.", + "name": "Name", + "ldapBinding": "AD Binding", + "boundBadge": "AD-bound", + "manualBadge": "Manual", + "defaultGroup": "Default Group", + "setDefault": "Set as default group", + "isDefault": "Default group", + "memberCount": "Members", + "actions": "Actions", + "membersButton": "Members", + "saveError": "Could not save group. Please try again.", + "deleteError": "Could not delete group. Please try again.", + "ldapBind": { + "hint": "Choose an AD group from the list to sync membership automatically.", + "bound": "Bound to: {ldapDn}", + "unbind": "Remove binding", + "searchPlaceholder": "Search AD groups...", + "discoverError": "Could not load AD groups. Please try again.", + "noResults": "No AD groups found." + }, + "members": { + "title": "Members", + "remove": "Remove member", + "ldapManaged": "Managed via AD sync", + "sourceManual": "Manual", + "sourceLdap": "LDAP", + "addTitle": "Add member", + "searchPlaceholder": "Search users...", + "noMembers": "No members yet.", + "addError": "Could not add member. Please try again." + }, + "deleteConfirm": { + "title": "Delete Group", + "body": "This group has {memberCount} members and {grantCount} module grants. Affected users will lose access unless they have it another way. This action cannot be undone." + }, + "grants": { + "matrixCheckboxLabel": "{granted, select, true {Grant} other {Revoke}} {module} for group {group}" + } } }, "adminModules": { @@ -367,7 +428,24 @@ "noModules": "No modules available", "activateSuccess": "Module activated successfully", "deactivateSuccess": "Module deactivated successfully", - "error": "Error managing module" + "error": "Error managing module", + "grantsLink": "Grants Matrix", + "grants": { + "title": "Grants Matrix", + "searchPlaceholder": "Search modules or groups...", + "emptyModules": "No modules are activated for this tenant yet. Activate a module under Modules first.", + "emptyModulesLink": "Go to Modules", + "adminNote": "ADMIN and SUPER_ADMIN always have access to all active modules — this matrix only applies to the USER role.", + "saveError": "Could not save grant. Please try again." + }, + "activationDialog": { + "title": "Activate Module: {module}", + "body": "Should the default group get immediate access to this module, or would you rather configure grants separately?", + "grantNow": "Grant Now", + "configureLater": "Configure Later", + "cancel": "Cancel", + "noDefaultGroupHint": "No default group marked — set one under Groups first or configure access manually." + } }, "theme": { "light": "Light", @@ -387,7 +465,12 @@ "backToCategory": "Back to category", "allModules": "Modules", "allModulesDescription": "Available modules for your tenant", - "noActiveModules": "No modules activated. Ask your administrator to enable modules." + "noActiveModules": "No modules activated. Ask your administrator to enable modules.", + "accessDenied": { + "title": "No Access to This Module", + "body": "You do not have access to this module. Please contact your administrator.", + "backToDashboard": "Back to Dashboard" + } }, "domaincheck": { "title": "Domain Check", @@ -521,7 +604,9 @@ "detailVersion": "Version {version}", "detailStatusActive": "Activated for this tenant", "detailStatusInactive": "Not activated", - "accessDenied": "Access denied" + "accessDenied": "Access denied", + "statusNoAccess": "No Access", + "toastNoAccess": "No access to this module — please contact your administrator." }, "certManager": { "title": "Certificate Manager",