Playwright Tests / test (push) Canceled after 0s
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>
5.4 KiB
5.4 KiB
status, date, applyTo, supersededBy
| status | date | applyTo | supersededBy | |||||
|---|---|---|---|---|---|---|---|---|
| Superseded | 2026-09-09 |
|
0015-split-admin-user-management-module.md |
0014 — Admin user management: folded into the admin module, dual auth axis, password always emailed
Context
An operator needs to see the list of non-deleted intranet user accounts (name + email), and
per account reset the password, change the email address, and view/change group assignments.
The database layer for this already existed (fis_admin_getUserAccountList,
fis_admin_getUserGroupList, fis_admin_setUserAccount, fis_admin_resetUserPassword,
fis_admin_addGroupMember/remGroupMember) but was completely unwired from any controller.
Those procs gate on a different authorization mechanism than the rest of the app: a
per-user intranet_admin setting read via fis_admin_getUserAuth(@authaccount) > 1, entirely
independent of the fis_getModuleAuth/fis_module_auth mechanism the rest of the app
(including the existing Admin module, see
0011) uses.
Decision
- Fold user management into the existing
adminmodule (fn=admin) rather than create a new top-level module. Newidcases (users,userpwdreset,useremail,usergroups,usergroupset) sit inDo_Process_Adminalongside the system-status diagnostics, behind the samefds_sys > 4server-side gate as the rest of that module. - Known, accepted gap: two independent authorization axes.
fds_sys > 4controls whether the endpoints are reachable at all; the underlyingfis_admin_*SQL objects separately require the caller'sintranet_adminsetting to be> 1(fis_admin_getUserAuth). An account withfds_sys > 4but nointranet_adminsetting will reach these endpoints but get empty result sets / no-op writes from SQL — not an error, just silently nothing. Operational consequence: any account meant to do user management must be provisioned with bothfds_sys > 4andintranet_admin >= 2(viafis_useraccounts_settings). This was a deliberate simplicity trade-off (see Alternatives) rather than unifying the two permission systems. - Password reset always emails the result; never displays it. The ribbon's "Passwort
zurücksetzen" action lets the admin either type a specific new password or leave the field
blank to auto-generate one (
fis_admin_resetUserPasswordgained an optional@newpasswordparameter for this). Either way, the resulting plaintext password is sent only to the target user's stored email address viaIComService(respecting theFuchs:Email:OverrideRecipientdev safety net) — the admin never sees it on screen. - Change email reuses
fis_admin_setUserAccount(prefilling the other fields from the existing row,@password = NULLso the update path leaves the password untouched) instead of adding a narrower proc — itsWHEN MATCHEDbranch never touchespassword_enc, and its existing duplicate-emailTHROW 60001is mapped to an HTTP 409 in the controller. - New
fis_admin_getUserGroupMembershipfunction returns every group plus amemberbit for one target user (mirrorsfis_admin_getUserGroupList's auth-gate style) — needed for the per-user group checkbox dialog; toggling a checkbox callsfis_admin_addGroupMember/remGroupMemberimmediately (no separate save step, consistent with the rest of the module's ribbon actions). - Per the exception-user-notification rule,
a failed password reset, a failed reset-email delivery, or a target with no usable email all
call
IEventService.UserIssueAsyncso the admin is never left believing an operation succeeded silently.
Consequences
- Deploying/onboarding an admin for user management is now a two-step provisioning task
(
fds_sysandintranet_admin), not obvious from the UI — document this whenever granting the permission. fis_admin_resetUserPassword's signature changed (added optional@newpassword) and its result set gained anewpasswordcolumn; it was previously unwired from any caller, so this is a safe in-place change.- The Admin module's frontend now mixes two concerns (system diagnostics + user management) under one ribbon/menu entry; if user management grows substantially, revisit splitting it into its own module (see Alternatives).
Alternatives considered
- Unify the two authorization axes (e.g. make
fis_admin_*procs checkfis_getModuleAuthinstead offis_admin_getUserAuth, or vice versa). Rejected for this change — it would touch every existingfis_admin_*proc/function (all already gate onfis_admin_getUserAuth) for a feature that only needed to wire up what already existed; revisit if a real conflict surfaces in practice. - New standalone top-level module (
fn=usr) with its own menu button and its ownfis_admin_getUserAuth-based gate. Rejected per explicit user direction — folding into the existing Administration module was preferred over a second admin-ish menu entry. - Show the new/reset password on screen instead of emailing it. Rejected per explicit user direction — the password must only ever reach the user's own inbox, never be visible to the admin performing the reset.