Dienstkonto-Kennzeichen in der Benutzerverwaltung setzbar machen

Nachgezogen: Das Feld isServiceAccount lag in der Datenbank, war aber nirgends
setzbar - weder im Formular noch ueber die API. Der Betreiber haette es nicht
aktivieren koennen, damit waere die R182-Einstufung wirkungslos geblieben.

Jetzt Ankreuzfeld "Dienstkonto" im Benutzerformular mit Erklaerung im
Klartext, Feld in der Mass-Assignment-Whitelist (gilt damit auch beim Anlegen),
im Service-Typ und in allen drei select-Bloecken, damit es beim Bearbeiten
vorbelegt wird.

Verifiziert: Whitelist laesst das Feld durch und blockt Fremdfelder weiterhin,
Wert ueber Prisma lesbar, tsc und vite build gruen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-24 10:09:28 +02:00
co-authored by Claude Opus 5
parent 910c94daa1
commit b696980793
4 changed files with 42 additions and 0 deletions
+4
View File
@@ -44,6 +44,7 @@ export async function getAllUsers(filters: UserFilters) {
firstName: true,
lastName: true,
isActive: true,
isServiceAccount: true,
customerId: true,
whatsappNumber: true,
telegramUsername: true,
@@ -97,6 +98,7 @@ export async function getUserById(id: number) {
firstName: true,
lastName: true,
isActive: true,
isServiceAccount: true,
customerId: true,
whatsappNumber: true,
telegramUsername: true,
@@ -170,6 +172,7 @@ export async function createUser(data: {
firstName: true,
lastName: true,
isActive: true,
isServiceAccount: true,
customerId: true,
roles: {
include: { role: true },
@@ -198,6 +201,7 @@ export async function updateUser(
firstName?: string;
lastName?: string;
isActive?: boolean;
isServiceAccount?: boolean;
roleIds?: number[];
customerId?: number;
hasDeveloperAccess?: boolean;
+4
View File
@@ -640,6 +640,10 @@ const USER_UPDATABLE_FIELDS = [
'firstName',
'lastName',
'isActive',
// Kennzeichnet planmaessig arbeitende Konten (z. B. das Gegenbuch). Ihre
// Anmeldungen werden als Routine statt CRITICAL gefuehrt, dafuer wacht der
// Heartbeat-Monitor ueber ihr AUSBLEIBEN (Pentest R182/R183).
'isServiceAccount',
'whatsappNumber',
'telegramUsername',
'signalNumber',
+14
View File
@@ -97,6 +97,20 @@ isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung
## ✅ Erledigt
- [x] **🖱️ Dienstkonto-Kennzeichen in der Benutzerverwaltung** (2026-08-24)
- Nachgezogen: Das Feld `isServiceAccount` lag zwar in der Datenbank, war
aber **nirgends setzbar** weder im Formular noch ueber die API. Der
Betreiber haette es nicht aktivieren koennen, damit waere die
R182-Einstufung wirkungslos geblieben.
- Jetzt: Ankreuzfeld „Dienstkonto“ im Benutzerformular unter den
zusaetzlichen Berechtigungen, mit Erklaerung im Klartext (planmaessige
Anmeldungen als Routine, dafuer Meldung bei AUSBLEIBEN). Feld in der
Whitelist (`USER_UPDATABLE_FIELDS`, damit auch beim Anlegen), im
Service-Typ und in allen drei `select`-Bloecken, damit es beim Bearbeiten
vorbelegt wird.
- Verifiziert: Whitelist laesst das Feld durch und blockt Fremdfelder
weiterhin; Wert ueber Prisma lesbar; `tsc` und `vite build` gruen.
- [x] **🚨 Retention-Governance + Heartbeat-Wachhund (Pentest R183, R182-Rest)** (2026-08-24)
- **R183-01 (HIGH)** Die geladene Waffe war ungegatet, der Abzug gegatet:
`PUT /retention-policies/{id}` nahm `retentionDays: 0` **ohne
+20
View File
@@ -247,6 +247,7 @@ function UserModal({
isActive: true,
hasDeveloperAccess: false,
hasGdprAccess: false,
isServiceAccount: false,
whatsappNumber: '',
telegramUsername: '',
signalNumber: '',
@@ -267,6 +268,7 @@ function UserModal({
isActive: (user as any).isActive ?? true,
hasDeveloperAccess: (user as any).hasDeveloperAccess ?? false,
hasGdprAccess: (user as any).hasGdprAccess ?? false,
isServiceAccount: (user as any).isServiceAccount ?? false,
whatsappNumber: (user as any).whatsappNumber || '',
telegramUsername: (user as any).telegramUsername || '',
signalNumber: (user as any).signalNumber || '',
@@ -324,6 +326,7 @@ function UserModal({
isActive: formData.isActive,
hasDeveloperAccess: formData.hasDeveloperAccess,
hasGdprAccess: formData.hasGdprAccess,
isServiceAccount: formData.isServiceAccount,
whatsappNumber: formData.whatsappNumber || undefined,
telegramUsername: formData.telegramUsername || undefined,
signalNumber: formData.signalNumber || undefined,
@@ -359,6 +362,7 @@ function UserModal({
roleIds: formData.roleIds,
hasDeveloperAccess: formData.hasDeveloperAccess,
hasGdprAccess: formData.hasGdprAccess,
isServiceAccount: formData.isServiceAccount,
whatsappNumber: formData.whatsappNumber || undefined,
telegramUsername: formData.telegramUsername || undefined,
signalNumber: formData.signalNumber || undefined,
@@ -487,6 +491,22 @@ function UserModal({
</div>
<label className="block text-sm font-medium text-gray-700 mt-4 mb-2">Zusätzliche Berechtigungen</label>
<div className="space-y-2">
<label className="flex items-start gap-2">
<input
type="checkbox"
checked={formData.isServiceAccount}
onChange={(e) => setFormData({ ...formData, isServiceAccount: e.target.checked })}
className="mt-1 rounded border-blue-300 text-blue-600 focus:ring-blue-500"
/>
<span>
<span className="font-medium">Dienstkonto</span>
<span className="block text-sm text-gray-500">
Für Konten, die sich planmäßig und regelmäßig anmelden etwa das Gegenbuch.
Ihre Anmeldungen erscheinen im Audit-Log als Routine statt als kritisches
Ereignis. Dafür wird gemeldet, wenn ein solches Konto <em>ausbleibt</em>.
</span>
</span>
</label>
<label className="flex items-center gap-2">
<input
type="checkbox"