--- status: Accepted date: 2026-09-09 applyTo: - "Fuchs/Controllers/IntranetController.Admin.cs" - "Fuchs/Controllers/IntranetController.AdminUsers.cs" - "Fuchs/js/intranet/modules/fis.admin*.js" - "Fuchs/js/intranet/modules/fis.usr*.js" - "Fuchs/js/intranet/modules/fis.usr.scss" - "Fuchs/js/intranet/fis_main_menu.js" - "Fuchs_Database/dbo/Functions/fis_admin_*.sql" - "Fuchs_Database/dbo/Stored Procedures/fis_admin_*.sql" supersededBy: "" --- # 0015 — Split Admin into separate "Status" (`admin`) and "User Management" (`usr`) modules, under one "Administration" sidemenu dropdown ## Context [0014](0014-admin-user-management.md) folded user management into the existing `admin` module (one sidemenu button, one `fn`) to avoid provisioning a second admin-ish permission. In practice this meant one button opened two unrelated things — infrastructure diagnostics and user account administration. The user asked for these to be split into two distinct buttons, grouped under a single "Administration" sidemenu entry (an `ocmsmenu` dropdown, not two flat top-level buttons). This decision supersedes 0014's "fold into admin" choice; the parts of 0014 that are about SQL-layer behavior (dual auth axis, password-reset email, group-toggle semantics) are unaffected and still apply, just under `fn=usr` instead of `fn=admin`. ## Decision - **Two independent modules, exposed as a single "Administration" dropdown in the sidemenu** with two entries — Benutzerverwaltung and Systemüberwachung — using `ocmsmenu`'s existing nested-item support (`itm: [...]` on a menu entry renders it as a Bootstrap dropdown; see `oci_main.js#$ocms.menu`, `subm`/`subi`). Both modules stay gated by the same `fds_sys > 4` server-side check (`AdminMinAuthExclusive`/`GetSystemAdminAuthAsync`, both defined once in `IntranetController.Admin.cs` and shared by both dispatchers): - `fn=admin` — unchanged status/diagnostics dashboard (`Do_Process_Admin`, `fis.admin.js`), reached via the "Systemüberwachung" dropdown entry. - `fn=usr` — new user-management module (`Do_Process_AdminUsers` in the new `IntranetController.AdminUsers.cs`, `fis.usr.js`/`fis.usr_txt_de.js`/`fis.usr.scss`), built as a self-contained list+ribbon module (Banking's `iMn`/`eM` pattern) rather than a card embedded in the dashboard, reached via the "Benutzerverwaltung" dropdown entry. - **The still-true dual-authorization caveat from 0014 carries over unchanged, just renamed**: `fds_sys > 4` gates the `usr` module's endpoints; the `fis_admin_*` SQL objects they call separately require the caller's `intranet_admin` setting to be `> 1` (`fis_admin_getUserAuth`). An account needs both to actually manage users. `Fuchs/Docs/Concepts/admin-user-management.md` now carries this note (split out of `admin-system-status.md`). - `id` values shortened now that the module name itself says "usr" (no more redundant `user` prefix): `users`→`list`, `userpwdreset`→`pwdreset`, `useremail`→`email`, `usergroups`→`groups`, `usergroupset`→`groupset`. Endpoints move from `/do/admin/*` to `/do/usr/*` accordingly. - One shared client-side auth check gates the whole dropdown: `fis_main_menu.js#addAdminMenuButtonsIfAuthorized` (renamed from `addAdminMenuIfAuthorized`) calls `$fis.getAuth('fds_sys')` once and, if authorized, pushes a **single** parent menu entry (`id: 'm_admin_grp'`, label `$t.m_admin` = "Administration", no `fnc` of its own) whose `itm` array holds the two real entries (`fnc: 'init:usr'` / `fnc: 'init:admin'`). The parent has no navigation behavior — clicking it only opens/closes the dropdown; the two children navigate. Idempotency is checked on the parent id alone. ## Consequences - Two bundle pairs now exist for what was one (`fis.admin.de.js`/`.min.css` and `fis.usr.de.js`/`.min.css`, both registered in `bdlconfig.json`) — a small duplication of the lazy-load/auth-check plumbing, acceptable for the clarity of separate concerns. - The in-module header text for the dashboard module changed from "Administration" to "Systemüberwachung" (`fis.admin_txt_de.js#$adt.mdl`) so it no longer collides with the parent dropdown's "Administration" label once both are visible on screen at once. - Any future admin-only feature should default to its own module, added as a new entry under the same "Administration" dropdown (or its own dropdown, if unrelated), unless it's genuinely part of the status dashboard's diagnostics — the original "fold everything into one Admin button" instinct from 0014 didn't hold up once a second real feature existed. - `IntranetController.BuildPasswordResetEmail`/`NotifyAdminUserActionFailedAsync` moved to `IntranetController.AdminUsers.cs`; `Fuchs.Tests/AdminUserManagementTests.cs` needed no change since it calls them through the (unchanged) `IntranetController` type. ## Alternatives considered - **Two flat top-level sidemenu buttons (no shared "Administration" parent).** Rejected per explicit user direction — the request was specifically for both to live "within Administration" in the sidemenu, i.e. a single grouping entry with two children. - **Keep one module, add an internal tab/sub-nav for user management.** Rejected — a client-side tab within one `fn` would still route through one `fn` auth check per the frontend's per-`fn` auth-caching design (`fis_main.js#$ocms.init`), the same limitation 0014 already ran into when this was one module with two unrelated concerns; splitting into two real modules under a shared menu dropdown gets a clean navigation grouping without that limitation.