Files
Fuchs_Intranet/Fuchs/Docs/Decisions/0015-split-admin-user-management-module.md
T
StefanandClaude Sonnet 5 076290cbeb
Playwright Tests / test (push) Canceled after 0s
Split Admin module into Status and User Management under one sidemenu dropdown
Splits fn=admin into two independent modules: the original status
dashboard stays at fn=admin, user management moves to a new fn=usr
(IntranetController.AdminUsers.cs, fis.usr.js). Both are now reached
through a single "Administration" sidemenu dropdown (Systemüberwachung /
Benutzerverwaltung) gated by one shared fds_sys > 4 check, per ADR 0015
(supersedes 0014's "fold into one module" choice).

Also fixes the password-reset validation to check only a plain 6-char
minimum instead of silently also requiring ValidatePassword's default
2-uppercase/2-lowercase/2-digit composition, which contradicted the
"mind. 6 Zeichen" message shown to the admin.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 12:09:44 +02:00

83 lines
5.5 KiB
Markdown

---
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.