- Introduced new JavaScript file `fis.admin_txt_de.js` for German translations of administration-related terms and messages. - Created `fis.admin.css` for styling the administration interface, including layout, cards, and buttons. - Added `fis.admin.de.js` for the main functionality of the administration module, implementing features such as system status checks and email testing. - Minified version of the German JavaScript file created as `fis.admin.de.min.js`. - Minified CSS file created as `fis.admin.min.css` for optimized loading.
68 lines
4.0 KiB
Markdown
68 lines
4.0 KiB
Markdown
---
|
|
status: Accepted
|
|
date: 2026-07-16
|
|
applyTo:
|
|
- "Fuchs/Controllers/IntranetController.Admin.cs"
|
|
- "Fuchs/Services/SystemStatusService.cs"
|
|
- "Fuchs/Services/ISystemStatusService.cs"
|
|
- "Fuchs/Services/SystemStatusModels.cs"
|
|
- "Fuchs/js/intranet/modules/fis.admin*.js"
|
|
- "Fuchs/js/intranet/modules/fis.admin.scss"
|
|
supersededBy: ""
|
|
---
|
|
|
|
# 0011 — Admin module gated on `fds_sys` > 4
|
|
|
|
## Context
|
|
Operators needed an in-app view of the running deployment's health: which host it
|
|
runs on, whether SQL Server / Azure Key Vault / Azure Blob Storage / the MFR ERP are
|
|
reachable, how the email service is configured (including the dev/test
|
|
`Fuchs:Email:OverrideRecipient` redirect), and a way to send a test email. The
|
|
`StartupSelfTestService` already probes most of these once at startup and writes the
|
|
result to the log — but that is invisible to a logged-in operator and cannot be re-run
|
|
on demand. This is privileged, infrastructure-revealing information (server names,
|
|
account names, connectivity state) that must not be exposed to ordinary users.
|
|
|
|
## Decision
|
|
- Add an **Admin** module (`admin`) alongside the existing invoice/reminder/report/banking
|
|
modules, following the same frontend module contract (`init:admin` → `admin/auth`
|
|
returns `{ manage }` → lazy-load `/web/fis.admin.de.js` + `/web/fis.admin.css` →
|
|
`init2()`).
|
|
- Access is gated on the caller's **`fds_sys` module authorization being strictly greater
|
|
than 4** (`fis_getModuleAuth('fds_sys', authuser) > 4`). The menu button is only rendered,
|
|
and the module script only fetched, for such users; **every** Admin data endpoint
|
|
additionally re-checks the level server-side (defense in depth) and returns 401 otherwise.
|
|
`admin/auth` is the sole endpoint that answers for unauthorized users too (it returns
|
|
`manage: 0`), so the frontend can decide whether to render the module at all.
|
|
- Backend diagnostics live in a new DI-registered `ISystemStatusService` (scoped). It exposes
|
|
a passive `GetInfo()` snapshot and live, never-throwing connectivity probes
|
|
(`database`, `keyvault`, `blob`, `mfr`) plus `SendTestEmailAsync`. The test email goes
|
|
through the normal `IComService` pipeline, so the `OverrideRecipient` safety net applies
|
|
exactly as for any other outbound mail.
|
|
- The service never returns secrets — only presence flags and non-sensitive values
|
|
(server/catalog/login name, storage account name, error text). Responses are serialized
|
|
camelCase to match the frontend's lowercase convention.
|
|
|
|
## Consequences
|
|
- `fds_sys` is now a security-relevant authorization key: granting it a value > 4 exposes
|
|
infrastructure status and the ability to send test emails. Provision it deliberately.
|
|
- `SystemStatusService` is intentionally **separate** from `StartupSelfTestService` rather
|
|
than a shared refactor: the startup service's probe methods are `protected virtual` and its
|
|
tests override them, so folding both onto one probe surface would have broken that contract.
|
|
The two therefore duplicate a little probe logic (Key Vault secret read, MFR `GetEntities`,
|
|
SQL `SELECT`); keep them behaviourally aligned when either changes.
|
|
- New probes (or new status facts) belong in `SystemStatusService` behind the same
|
|
`SystemProbeResult` / `SystemInfoSnapshot` shapes; add the component id to
|
|
`SystemStatusService.Components` and a card in `fis.admin.js`.
|
|
- Blob connectivity is checked via a new `IBlobStorageService.CheckConnectivityAsync`
|
|
(account-info request); it too never throws.
|
|
|
|
## Alternatives considered
|
|
- **Reuse `StartupSelfTestService` directly.** Rejected — see Consequences; its virtual/overridden
|
|
probe surface is owned by its tests, and it is a one-shot `BackgroundService`, not a
|
|
request-scoped query service.
|
|
- **Gate only in the frontend (hide the menu button).** Rejected — the endpoints would still be
|
|
reachable by crafting the POST. Server-side enforcement on every endpoint is required.
|
|
- **A separate `fds_admin`/new module-auth key.** Rejected — `fds_sys` already models
|
|
system-level privilege; reusing it avoids a parallel permission to provision.
|