diff --git a/README.md b/README.md index be309e8..51b411a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # GovOPlaN Admin + +**Repository type:** module (platform). + + `govoplan-admin` owns generic system administration API and WebUI contributions during the GovOPlaN module split. diff --git a/package.json b/package.json index f46ff84..c18388c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@govoplan/admin-webui", - "version": "0.1.7", + "version": "0.1.8", "private": true, "type": "module", "main": "webui/src/index.ts", @@ -18,7 +18,7 @@ "LICENSE" ], "peerDependencies": { - "@govoplan/core-webui": "^0.1.7", + "@govoplan/core-webui": "^0.1.8", "lucide-react": "^1.23.0", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/pyproject.toml b/pyproject.toml index 385b899..b916d4e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,14 +4,14 @@ build-backend = "setuptools.build_meta" [project] name = "govoplan-admin" -version = "0.1.7" +version = "0.1.8" description = "GovOPlaN generic administration module." readme = "README.md" requires-python = ">=3.12" authors = [{ name = "GovOPlaN" }] dependencies = [ - "govoplan-core>=0.1.7", - "govoplan-access>=0.1.7", + "govoplan-core>=0.1.8", + "govoplan-access>=0.1.8", ] [tool.setuptools.packages.find] diff --git a/src/govoplan_admin/backend/manifest.py b/src/govoplan_admin/backend/manifest.py index c94362c..9b64f19 100644 --- a/src/govoplan_admin/backend/manifest.py +++ b/src/govoplan_admin/backend/manifest.py @@ -17,7 +17,7 @@ def _route_factory(context: ModuleContext): manifest = ModuleManifest( id="admin", name="Admin", - version="0.1.7", + version="0.1.8", required_capabilities=(CAPABILITY_AUTH_PRINCIPAL_RESOLVER, CAPABILITY_AUTH_PERMISSION_EVALUATOR), route_factory=_route_factory, migration_spec=MigrationSpec(module_id="admin", metadata=Base.metadata), diff --git a/webui/package.json b/webui/package.json index e9173c0..108bdd2 100644 --- a/webui/package.json +++ b/webui/package.json @@ -1,6 +1,6 @@ { "name": "@govoplan/admin-webui", - "version": "0.1.7", + "version": "0.1.8", "private": true, "type": "module", "main": "src/index.ts", @@ -13,7 +13,7 @@ } }, "peerDependencies": { - "@govoplan/core-webui": "^0.1.7", + "@govoplan/core-webui": "^0.1.8", "lucide-react": "^1.23.0", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/webui/src/features/admin/GovernanceTemplatesPanel.tsx b/webui/src/features/admin/GovernanceTemplatesPanel.tsx index a7bd16d..f1c4772 100644 --- a/webui/src/features/admin/GovernanceTemplatesPanel.tsx +++ b/webui/src/features/admin/GovernanceTemplatesPanel.tsx @@ -19,7 +19,7 @@ import { type PermissionItem, type TenantAdminItem } from "../../api/admin"; -import { AdminIconButton, AdminPageLayout, AdminSelectionList, adminErrorMessage, joinLabels, i18nMessage, useUnsavedDraftGuard } from "@govoplan/core-webui"; +import { AdminIconButton, AdminPageLayout, AdminSelectionList, adminErrorMessage, i18nMessage, useUnsavedDraftGuard } from "@govoplan/core-webui"; const emptyDraft = { slug: "", @@ -54,6 +54,7 @@ export default function GovernanceTemplatesPanel({ const [error, setError] = useState(""); const [success, setSuccess] = useState(""); const dirty = editing !== null && draftKey(draft) !== savedDraftKey; + const permissionsByScope = useMemo(() => new Map(permissions.map((permission) => [permission.scope, permission])), [permissions]); useUnsavedDraftGuard({ dirty, @@ -238,7 +239,7 @@ export default function GovernanceTemplatesPanel({ setViewing(null)} className="admin-dialog admin-dialog-wide" footer={ setViewing(null)}>i18n:govoplan-admin.close.bbfa773e}> - {viewing && i18n:govoplan-admin.kind.e00ac23f{viewing.kind}i18n:govoplan-admin.slug.094da9b9{viewing.slug}i18n:govoplan-admin.status.bae7d5be{viewing.is_active ? "i18n:govoplan-admin.active.a733b809" : "i18n:govoplan-admin.inactive.09af574c"}i18n:govoplan-admin.tenants.1f7ae776{viewing.assignments.length || "i18n:govoplan-admin.none.6eef6648"}i18n:govoplan-admin.description.55f8ebc8{viewing.description || "—"}i18n:govoplan-admin.permissions.d06d5557{viewing.permissions.length ? joinLabels(viewing.permissions.map((name) => ({ name }))) : "—"}} + {viewing && i18n:govoplan-admin.kind.e00ac23f{viewing.kind}i18n:govoplan-admin.slug.094da9b9{viewing.slug}i18n:govoplan-admin.status.bae7d5be{viewing.is_active ? "i18n:govoplan-admin.active.a733b809" : "i18n:govoplan-admin.inactive.09af574c"}i18n:govoplan-admin.tenants.1f7ae776{viewing.assignments.length || "i18n:govoplan-admin.none.6eef6648"}i18n:govoplan-admin.description.55f8ebc8{viewing.description || "—"}i18n:govoplan-admin.permissions.d06d5557{viewing.permissions.length ? : "—"}} setDeleting(null)} onConfirm={() => void remove()} /> @@ -249,3 +250,31 @@ export default function GovernanceTemplatesPanel({ function draftKey(draft: typeof emptyDraft): string { return JSON.stringify(draft); } + +function PermissionDetails({ scopes, permissionsByScope }: {scopes: string[];permissionsByScope: ReadonlyMap;}) { + const groups = groupPermissionScopes(scopes, permissionsByScope); + return ( + + {groups.map((group) => + {group.module} + + {group.permissions.map((permission) => + {permission.label} + {permission.scope} + )} + + )} + ); +} + +function groupPermissionScopes(scopes: string[], permissionsByScope: ReadonlyMap) { + const groups = new Map(); + for (const scope of [...scopes].sort()) { + const moduleId = scope.split(":", 1)[0] || "other"; + const permission = permissionsByScope.get(scope); + const group = groups.get(moduleId) ?? []; + group.push({ scope, label: permission?.label || scope }); + groups.set(moduleId, group); + } + return [...groups.entries()].map(([module, permissions]) => ({ module, permissions })); +} diff --git a/webui/src/i18n/generatedTranslations.ts b/webui/src/i18n/generatedTranslations.ts index dbf8a43..1439a02 100644 --- a/webui/src/i18n/generatedTranslations.ts +++ b/webui/src/i18n/generatedTranslations.ts @@ -14,7 +14,7 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.after.695c89be": "After:", "i18n:govoplan-admin.add_group_template.b74d8f0f": "Add group template", "i18n:govoplan-admin.add_plan_item.fa55f028": "Add plan item", - "i18n:govoplan-admin.add_tenant_role.fcd904ea": "Add tenant role", + "i18n:govoplan-admin.add_tenant_role.fcd904ea": "Add role template", "i18n:govoplan-admin.admin.4e7afebc": "Admin", "i18n:govoplan-admin.administration.b8be3d12": "Administration", "i18n:govoplan-admin.platform_administration": "Platform administration", @@ -75,7 +75,7 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.create_group_template.72407248": "Create group template", "i18n:govoplan-admin.create_request_and_apply.da79e153": "Create request and apply", "i18n:govoplan-admin.create_suspend_and_govern_tenant_spaces.77992a39": "Create, suspend and govern tenant spaces.", - "i18n:govoplan-admin.create_tenant_role.f58db104": "Create tenant role", + "i18n:govoplan-admin.create_tenant_role.f58db104": "Create role template", "i18n:govoplan-admin.created.0c78dab1": "Created:", "i18n:govoplan-admin.created.accf40c8": "Created", "i18n:govoplan-admin.current_window.73e25c9f": "Current window:", @@ -100,7 +100,7 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.defaults_for_newly_created_tenants.9d0f4ccd": "Defaults for newly created tenants", "i18n:govoplan-admin.delete_group_template.8745d842": "Delete group template", "i18n:govoplan-admin.delete_template.399bf72a": "Delete template", - "i18n:govoplan-admin.delete_tenant_role.4efa0813": "Delete tenant role", + "i18n:govoplan-admin.delete_tenant_role.4efa0813": "Delete role template", "i18n:govoplan-admin.delete_value_removal_is_blocked_while_a_material.d4eba73d": "Delete {value0}? Removal is blocked while a materialized tenant definition still has members or assignments.", "i18n:govoplan-admin.delete_value.4d18989e": "Delete {value0}", "i18n:govoplan-admin.dependencies.9f4f78d1": "Dependencies:", @@ -115,7 +115,7 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.dry_run_change_request_created_value_enable_main.49826d07": "Dry-run change request created: {value0}. Enable maintenance mode, then apply the request.", "i18n:govoplan-admin.dry_run.3d14659c": "Dry-run", "i18n:govoplan-admin.edit_group_template.9bc72d21": "Edit group template", - "i18n:govoplan-admin.edit_tenant_role.c15a260d": "Edit tenant role", + "i18n:govoplan-admin.edit_tenant_role.c15a260d": "Edit role template", "i18n:govoplan-admin.edit_value.fad75899": "Edit {value0}", "i18n:govoplan-admin.enable_maintenance_mode.75f98d57": "Enable maintenance mode", "i18n:govoplan-admin.enabled_modules.3c38e9ff": "Enabled modules:", @@ -302,7 +302,7 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.save_plan.842dc280": "Save plan", "i18n:govoplan-admin.save_settings.913aba9f": "Save settings", "i18n:govoplan-admin.save_template.0885fab2": "Save template", - "i18n:govoplan-admin.save_tenant_role.8fc0d37d": "Save tenant role", + "i18n:govoplan-admin.save_tenant_role.8fc0d37d": "Save role template", "i18n:govoplan-admin.save_the_install_plan_before_queueing_a_daemon_r.3ba00691": "Save the install plan before queueing a daemon request.", "i18n:govoplan-admin.saved.c0ae8f6e": "Saved", "i18n:govoplan-admin.saving.56a2285c": "Saving…", @@ -347,9 +347,9 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.tenant_locale_and_tenant_specific_settings.ac49c83b": "Tenant locale and tenant-specific settings.", "i18n:govoplan-admin.tenant_memberships_and_inherited_roles.16eda9f6": "Tenant memberships and inherited roles.", "i18n:govoplan-admin.tenant_permission_bundles_and_system_managed_rol.bb563bea": "Tenant permission bundles and system-managed role copies.", - "i18n:govoplan-admin.tenant_permissions.246294bc": "Tenant permissions", - "i18n:govoplan-admin.tenant_role.6b53115d": "Tenant role", - "i18n:govoplan-admin.tenant_roles.51aca82d": "Tenant roles", + "i18n:govoplan-admin.tenant_permissions.246294bc": "Permissions", + "i18n:govoplan-admin.tenant_role.6b53115d": "Role template", + "i18n:govoplan-admin.tenant_roles.51aca82d": "Role templates", "i18n:govoplan-admin.tenant_users.cb800b38": "Tenant users", "i18n:govoplan-admin.tenants.1f7ae776": "Tenants", "i18n:govoplan-admin.these_settings_are_enforced_by_the_backend_centr.8112ed6f": "These settings are enforced by the backend. Central groups and tenant roles remain available even when local creation is disabled.", @@ -403,7 +403,7 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.after.695c89be": "Nach:", "i18n:govoplan-admin.add_group_template.b74d8f0f": "Add group template", "i18n:govoplan-admin.add_plan_item.fa55f028": "Add plan item", - "i18n:govoplan-admin.add_tenant_role.fcd904ea": "Add tenant role", + "i18n:govoplan-admin.add_tenant_role.fcd904ea": "Rollenvorlage hinzufügen", "i18n:govoplan-admin.admin.4e7afebc": "Administration", "i18n:govoplan-admin.administration.b8be3d12": "Administration", "i18n:govoplan-admin.platform_administration": "Plattformadministration", @@ -464,7 +464,7 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.create_group_template.72407248": "Create group template", "i18n:govoplan-admin.create_request_and_apply.da79e153": "Create request and apply", "i18n:govoplan-admin.create_suspend_and_govern_tenant_spaces.77992a39": "Create, suspend and govern tenant spaces.", - "i18n:govoplan-admin.create_tenant_role.f58db104": "Create tenant role", + "i18n:govoplan-admin.create_tenant_role.f58db104": "Rollenvorlage erstellen", "i18n:govoplan-admin.created.0c78dab1": "Created:", "i18n:govoplan-admin.created.accf40c8": "Erstellt", "i18n:govoplan-admin.current_window.73e25c9f": "Aktuelles Fenster:", @@ -489,7 +489,7 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.defaults_for_newly_created_tenants.9d0f4ccd": "Standards für neu erstellte Mandanten", "i18n:govoplan-admin.delete_group_template.8745d842": "Delete group template", "i18n:govoplan-admin.delete_template.399bf72a": "Delete template", - "i18n:govoplan-admin.delete_tenant_role.4efa0813": "Delete tenant role", + "i18n:govoplan-admin.delete_tenant_role.4efa0813": "Rollenvorlage löschen", "i18n:govoplan-admin.delete_value_removal_is_blocked_while_a_material.d4eba73d": "Delete {value0}? Removal is blocked while a materialized tenant definition still has members or assignments.", "i18n:govoplan-admin.delete_value.4d18989e": "Delete {value0}", "i18n:govoplan-admin.dependencies.9f4f78d1": "Abhaengigkeiten:", @@ -504,7 +504,7 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.dry_run_change_request_created_value_enable_main.49826d07": "Dry-run change request created: {value0}. Enable maintenance mode, then apply the request.", "i18n:govoplan-admin.dry_run.3d14659c": "Dry-run", "i18n:govoplan-admin.edit_group_template.9bc72d21": "Edit group template", - "i18n:govoplan-admin.edit_tenant_role.c15a260d": "Edit tenant role", + "i18n:govoplan-admin.edit_tenant_role.c15a260d": "Rollenvorlage bearbeiten", "i18n:govoplan-admin.edit_value.fad75899": "Edit {value0}", "i18n:govoplan-admin.enable_maintenance_mode.75f98d57": "Enable maintenance mode", "i18n:govoplan-admin.enabled_modules.3c38e9ff": "Aktive Module:", @@ -691,7 +691,7 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.save_plan.842dc280": "Save plan", "i18n:govoplan-admin.save_settings.913aba9f": "Einstellungen speichern", "i18n:govoplan-admin.save_template.0885fab2": "Save template", - "i18n:govoplan-admin.save_tenant_role.8fc0d37d": "Save tenant role", + "i18n:govoplan-admin.save_tenant_role.8fc0d37d": "Rollenvorlage speichern", "i18n:govoplan-admin.save_the_install_plan_before_queueing_a_daemon_r.3ba00691": "Speichern Sie den Installationsplan, bevor eine Daemon-Anfrage eingereiht wird.", "i18n:govoplan-admin.saved.c0ae8f6e": "Gespeichert", "i18n:govoplan-admin.saving.56a2285c": "Saving…", @@ -736,9 +736,9 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.tenant_locale_and_tenant_specific_settings.ac49c83b": "Tenant locale and tenant-specific settings.", "i18n:govoplan-admin.tenant_memberships_and_inherited_roles.16eda9f6": "Tenant memberships and inherited roles.", "i18n:govoplan-admin.tenant_permission_bundles_and_system_managed_rol.bb563bea": "Tenant permission bundles and system-managed role copies.", - "i18n:govoplan-admin.tenant_permissions.246294bc": "Tenant permissions", - "i18n:govoplan-admin.tenant_role.6b53115d": "Tenant role", - "i18n:govoplan-admin.tenant_roles.51aca82d": "Mandantenrollen", + "i18n:govoplan-admin.tenant_permissions.246294bc": "Berechtigungen", + "i18n:govoplan-admin.tenant_role.6b53115d": "Rollenvorlage", + "i18n:govoplan-admin.tenant_roles.51aca82d": "Rollenvorlagen", "i18n:govoplan-admin.tenant_users.cb800b38": "Mandantenbenutzer", "i18n:govoplan-admin.tenants.1f7ae776": "Mandanten", "i18n:govoplan-admin.these_settings_are_enforced_by_the_backend_centr.8112ed6f": "Diese Einstellungen werden vom Backend erzwungen. Zentrale Gruppen und Mandantenrollen bleiben verfügbar, auch wenn lokale Erstellung deaktiviert ist.",
{permission.scope}