Files
Stefan 8a0ebeeb1e Add German localization and styling for administration module
- 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.
2026-07-16 14:59:14 +02:00

6.0 KiB

status, lastUpdated, applyTo, relatedDecisions
status lastUpdated applyTo relatedDecisions
Active 2026-07-16
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
Fuchs/js/intranet/fis_main_menu.js
0011-admin-module-system-status.md

Admin / System-Status module

Summary

The Admin module gives a privileged operator a live, in-app view of the running deployment's configuration and health, plus a test-email tool. It answers "which host am I on, can this instance reach SQL Server / Key Vault / Blob Storage / the MFR ERP, how is email wired up (including the OverrideRecipient redirect), and does sending actually work". Access is restricted to users whose fds_sys module authorization is greater than 4.

How it works

Authorization (two layers)

  1. Menu visibility — at page load fis_main_menu.js#addAdminMenuIfAuthorized calls $fis.getAuth('fds_sys'); only when the level is > 4 does it push the init:admin button into $ocms.ocmsmenu and re-render #mainmenu. Users below the threshold never see the button and never fetch the module script.
  2. Server-side gate — every /do/admin/* endpoint resolves fis_getModuleAuth('fds_sys', authuser) and returns 401 unless it is > 4. The only exception is admin/auth, which returns { manage: 0 } for unauthorized users so the frontend can cleanly decline to render. This is defense in depth: hiding the button is not a security control on its own.

Request flow

click "Administration"  → $ocms.init('admin')
  POST /do/admin/auth   → { manage, level }         (manage>0 ⇒ authorized)
  load /web/fis.admin.de.js + /web/fis.admin.css
  $ocms.admin.init2()   → init3() renders the page
    POST /do/admin/status → { info, probes }         full snapshot + all probes
  per-card "Aktualisieren" → POST /do/admin/probe/<component> → { probe }
  "Test-E-Mail senden"     → POST /do/admin/testmail (to/subject/body) → { result }

Backend (ISystemStatusService / SystemStatusService, scoped)

  • GetInfo() — passive snapshot, no network calls: host (machine/OS/framework/environment/ test-deployment/uptime), database (server/catalog/login parsed from the connection string — never the password), email (mailer enabled/base-url/account/server-id/token-present + OverrideRecipient), blob (enabled/configured/containers), MFR (host/creds-present/sync), Key Vault (vault-uri/app-prefix/managed-secret-count/client-registered).
  • Probes (database, keyvault, blob, mfr) each return a SystemProbeResult (status = ok/error/disabled/unconfigured, ok, message, detail, durationMs, optional metrics). They never throw — failures are captured in the result. database runs SELECT @@SERVERNAME, DB_NAME(), SUSER_SNAME(); keyvault reads the first managed secret via the DI SecretClient; blob calls IBlobStorageService.CheckConnectivityAsync (account-info request plus a per-container blob count for the invoice/reminder containers, surfaced as metrics and totalled in the message); mfr calls IMfrClientFactory.Create().GetEntities(). The generic metrics (label/value pairs) is how a probe reports extra facts for display — the blob probe uses it for the file counts.
  • SendTestEmailAsync(to, subject, body) HTML-encodes the body and sends via IComService, so the Fuchs:Email:OverrideRecipient redirect applies exactly as for any other mail; the result reports the requested recipient and, when active, the override target.
  • Every probe emits the fuchs.systemstatus.probes counter tagged by component + status and an systemstatus.probe activity span.

Startup-checks widget (non-refreshable)

StartupSelfTestService runs the boot self-test once (Key Vault / Database / MFR / PDF-license / mailer, gated by Fuchs:StartupChecks:*). It now also writes its outcome to the singleton StartupCheckReporter, which GetInfo() returns as StartupChecks. The Admin page renders it as a single non-refreshable card (there is no per-check retry — the live connectivity probes above cover on-demand re-testing; the startup card is a historical record of the boot run). When the self-test is disabled (Enabled=false, the appsettings default) or has not completed, the card shows a "nicht ausgeführt" note. Each item shows OK / Fehler / übersprungen (a disabled check reports enabled=false).

Frontend (fis.admin.js + fis.admin_txt_de.js + fis.admin.scss)

Standard lazy-loaded module (same contract as inv/rep/bam). Renders a system card plus a responsive grid of status cards; connectivity cards carry a colored status pill and a per-card refresh button, the email card carries the test-email dialog. The topbar has an "Alle prüfen" button that reloads the whole snapshot. Admin responses are serialized camelCase (the DTOs are PascalCase) so the JS reads probe.status, info.database.server, etc.

Key files

  • Fuchs/Controllers/IntranetController.Admin.csDo_Process_Admin dispatch + auth gate + camelCase JSON helper.
  • Fuchs/Services/ISystemStatusService.cs, SystemStatusService.cs, SystemStatusModels.cs — diagnostics service + DTOs.
  • Fuchs/Services/StartupCheckReport.cs (StartupCheckReporter singleton) + StartupSelfTestService.cs — boot self-test result captured for the non-refreshable widget.
  • Fuchs/Services/IBlobStorageService.cs / AzureBlobStorageService.csCheckConnectivityAsync + BlobConnectivity.
  • Fuchs/js/intranet/modules/fis.admin*.js, fis.admin.scss — the module, texts, styles (bundled via bdlconfig.json).
  • Fuchs/js/intranet/fis_main_menu.js (addAdminMenuIfAuthorized) + fis_main_go.js — conditional menu button.
  • Fuchs.Tests/SystemStatusServiceTests.cs — service tests.