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)
This commit is contained in:
2026-08-04 18:50:28 +02:00
parent 09abb2b323
commit 90dc3981d5
3 changed files with 195 additions and 10 deletions
@@ -71,6 +71,21 @@ export function AdminSidebar() {
</svg> </svg>
), ),
}, },
{
label: t('admin.groups'),
href: '/admin/groups',
show: true,
icon: (
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<line x1="8" x2="21" y1="6" y2="6" />
<line x1="8" x2="21" y1="12" y2="12" />
<line x1="8" x2="21" y1="18" y2="18" />
<line x1="3" x2="3.01" y1="6" y2="6" />
<line x1="3" x2="3.01" y1="12" y2="12" />
<line x1="3" x2="3.01" y1="18" y2="18" />
</svg>
),
},
]; ];
return ( return (
+90 -5
View File
@@ -75,7 +75,8 @@
"tenants": "Mandanten", "tenants": "Mandanten",
"modules": "Module", "modules": "Module",
"ldap": "LDAP", "ldap": "LDAP",
"smtp": "SMTP" "smtp": "SMTP",
"groups": "Gruppen"
}, },
"role": { "role": {
"SUPER_ADMIN": "Super-Admin", "SUPER_ADMIN": "Super-Admin",
@@ -264,7 +265,21 @@
"status": "Status", "status": "Status",
"actions": "Aktionen", "actions": "Aktionen",
"password": "Passwort", "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": { "tenants": {
"title": "Mandantenverwaltung", "title": "Mandantenverwaltung",
@@ -353,6 +368,52 @@
"skipped": "uebersprungen", "skipped": "uebersprungen",
"errors": "Fehler" "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": { "adminModules": {
@@ -367,7 +428,24 @@
"noModules": "Keine Module verfuegbar", "noModules": "Keine Module verfuegbar",
"activateSuccess": "Modul erfolgreich aktiviert", "activateSuccess": "Modul erfolgreich aktiviert",
"deactivateSuccess": "Modul erfolgreich deaktiviert", "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": { "theme": {
"light": "Hell", "light": "Hell",
@@ -387,7 +465,12 @@
"backToCategory": "Zurueck zur Kategorie", "backToCategory": "Zurueck zur Kategorie",
"allModules": "Module", "allModules": "Module",
"allModulesDescription": "Verfuegbare Module fuer Ihren Mandanten", "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": { "domaincheck": {
"title": "Domaincheck", "title": "Domaincheck",
@@ -521,7 +604,9 @@
"detailVersion": "Version {version}", "detailVersion": "Version {version}",
"detailStatusActive": "Aktiviert fuer diesen Mandanten", "detailStatusActive": "Aktiviert fuer diesen Mandanten",
"detailStatusInactive": "Nicht aktiviert", "detailStatusInactive": "Nicht aktiviert",
"accessDenied": "Zugriff verweigert" "accessDenied": "Zugriff verweigert",
"statusNoAccess": "Kein Zugriff",
"toastNoAccess": "Kein Zugriff auf dieses Modul — wende dich an deinen Administrator."
}, },
"certManager": { "certManager": {
"title": "Zertifikat-Manager", "title": "Zertifikat-Manager",
+90 -5
View File
@@ -75,7 +75,8 @@
"tenants": "Tenants", "tenants": "Tenants",
"modules": "Modules", "modules": "Modules",
"ldap": "LDAP", "ldap": "LDAP",
"smtp": "SMTP" "smtp": "SMTP",
"groups": "Groups"
}, },
"role": { "role": {
"SUPER_ADMIN": "Super Admin", "SUPER_ADMIN": "Super Admin",
@@ -264,7 +265,21 @@
"status": "Status", "status": "Status",
"actions": "Actions", "actions": "Actions",
"password": "Password", "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": { "tenants": {
"title": "Tenant Management", "title": "Tenant Management",
@@ -353,6 +368,52 @@
"skipped": "skipped", "skipped": "skipped",
"errors": "errors" "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": { "adminModules": {
@@ -367,7 +428,24 @@
"noModules": "No modules available", "noModules": "No modules available",
"activateSuccess": "Module activated successfully", "activateSuccess": "Module activated successfully",
"deactivateSuccess": "Module deactivated 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": { "theme": {
"light": "Light", "light": "Light",
@@ -387,7 +465,12 @@
"backToCategory": "Back to category", "backToCategory": "Back to category",
"allModules": "Modules", "allModules": "Modules",
"allModulesDescription": "Available modules for your tenant", "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": { "domaincheck": {
"title": "Domain Check", "title": "Domain Check",
@@ -521,7 +604,9 @@
"detailVersion": "Version {version}", "detailVersion": "Version {version}",
"detailStatusActive": "Activated for this tenant", "detailStatusActive": "Activated for this tenant",
"detailStatusInactive": "Not activated", "detailStatusInactive": "Not activated",
"accessDenied": "Access denied" "accessDenied": "Access denied",
"statusNoAccess": "No Access",
"toastNoAccess": "No access to this module — please contact your administrator."
}, },
"certManager": { "certManager": {
"title": "Certificate Manager", "title": "Certificate Manager",