Prüfung / Lint, Typen, Tests (push) Canceled after 0s
Prüfung / Images bauen (pdf) (push) Canceled after 0s
Prüfung / Images bauen (web) (push) Canceled after 0s
Prüfung / Images bauen (worker) (push) Canceled after 0s
Images / bauen (pdf, docker/pdf.Dockerfile) (push) Canceled after 0s
Images / bauen (web, docker/web.Dockerfile) (push) Canceled after 0s
Images / bauen (worker, docker/worker.Dockerfile) (push) Canceled after 0s
375 Vorkommen in 210 Dateien. Betrifft Kommentare, Oberflaechentexte und die README; an keiner Stelle Bedeutung, nur Zeichensetzung.
114 lines
4.0 KiB
TypeScript
114 lines
4.0 KiB
TypeScript
import type { EffectivePermissions, Permission } from '@/lib/auth/permissions'
|
|
import type { WriteCheck } from '@/lib/access/caseWrite'
|
|
|
|
/**
|
|
* Schreibgrenzen für Personalakten und Dokumente.
|
|
*
|
|
* Dieselbe Bauform wie `caseWrite.ts`: reine Funktionen, die auch dann greifen,
|
|
* wenn die Oberfläche einen Knopf versehentlich stehen lässt. Jede Server
|
|
* Action ruft sie auf, nicht nur die, die den Knopf zeichnet.
|
|
*/
|
|
|
|
/** Status, in denen ein Dokument nicht mehr verändert wird. */
|
|
export const READ_ONLY_DOCUMENT_STATUS = ['RETRACTED'] as const
|
|
|
|
function requirePermission(p: EffectivePermissions, permission: Permission): WriteCheck {
|
|
if (p.isAdmin || p.permissions.has(permission)) return { ok: true }
|
|
return { ok: false, reason: 'no-permission', permission }
|
|
}
|
|
|
|
/**
|
|
* Darf dieser Nutzer eine Personalakte mit dieser Klassifizierung anlegen oder
|
|
* auf diese Stufe heben? Wie bei der Fallakte: nie über der eigenen Stufe.
|
|
*/
|
|
export function canWritePersonnel(
|
|
p: EffectivePermissions,
|
|
classification: number,
|
|
): WriteCheck {
|
|
const permitted = requirePermission(p, 'personnel.edit')
|
|
if (!permitted.ok) return permitted
|
|
if (classification > p.clearanceLevel && !p.isAdmin) {
|
|
return { ok: false, reason: 'clearance-too-low', required: classification }
|
|
}
|
|
return { ok: true }
|
|
}
|
|
|
|
/**
|
|
* Darf dieser Nutzer ein Dokument mit dieser Klassifizierung anlegen?
|
|
*
|
|
* Der Besitzer ist vorher schon durch die Sichtbarkeitsprüfung gelaufen - was
|
|
* man nicht sieht, kann man nicht bestücken.
|
|
*/
|
|
export function canCreateDocument(
|
|
p: EffectivePermissions,
|
|
classification: number,
|
|
): WriteCheck {
|
|
const permitted = requirePermission(p, 'document.create')
|
|
if (!permitted.ok) return permitted
|
|
if (classification > p.clearanceLevel) {
|
|
return { ok: false, reason: 'clearance-too-low', required: classification }
|
|
}
|
|
return { ok: true }
|
|
}
|
|
|
|
/**
|
|
* Darf dieser Nutzer dieses Dokument ändern?
|
|
*
|
|
* Ein zurückgezogenes Dokument ist endgültig schreibgeschützt, auch für
|
|
* Admins: es steht als Grabstein und darf nicht nachträglich zu etwas anderem
|
|
* werden. Ein ausgefertigtes Dokument zu ändern setzt dasselbe Recht voraus,
|
|
* das die Ausfertigung erlaubt hat.
|
|
*/
|
|
export function canEditDocument(
|
|
p: EffectivePermissions,
|
|
target: { status: string; classification: number },
|
|
): WriteCheck {
|
|
if ((READ_ONLY_DOCUMENT_STATUS as readonly string[]).includes(target.status)) {
|
|
return { ok: false, reason: 'read-only', status: target.status }
|
|
}
|
|
|
|
const permitted = requirePermission(p, 'document.edit')
|
|
if (!permitted.ok) return permitted
|
|
|
|
if (target.classification > p.clearanceLevel && !p.isAdmin) {
|
|
return { ok: false, reason: 'clearance-too-low', required: target.classification }
|
|
}
|
|
|
|
if (target.status === 'FINAL') {
|
|
const final = requirePermission(p, 'document.finalize')
|
|
if (!final.ok) return { ok: false, reason: 'closed' }
|
|
}
|
|
|
|
return { ok: true }
|
|
}
|
|
|
|
/** Ausfertigen: aus einem Entwurf wird ein gültiges Dokument. */
|
|
export function canFinalizeDocument(
|
|
p: EffectivePermissions,
|
|
target: { status: string; classification: number },
|
|
): WriteCheck {
|
|
if (target.status !== 'DRAFT') return { ok: false, reason: 'read-only', status: target.status }
|
|
const permitted = requirePermission(p, 'document.finalize')
|
|
if (!permitted.ok) return permitted
|
|
if (target.classification > p.clearanceLevel && !p.isAdmin) {
|
|
return { ok: false, reason: 'clearance-too-low', required: target.classification }
|
|
}
|
|
return { ok: true }
|
|
}
|
|
|
|
/** Zurückziehen. Löschen gibt es nicht, der Grabstein bleibt stehen. */
|
|
export function canRetractDocument(
|
|
p: EffectivePermissions,
|
|
target: { status: string; classification: number },
|
|
): WriteCheck {
|
|
if (target.status === 'RETRACTED') {
|
|
return { ok: false, reason: 'read-only', status: target.status }
|
|
}
|
|
const permitted = requirePermission(p, 'document.retract')
|
|
if (!permitted.ok) return permitted
|
|
if (target.classification > p.clearanceLevel && !p.isAdmin) {
|
|
return { ok: false, reason: 'clearance-too-low', required: target.classification }
|
|
}
|
|
return { ok: true }
|
|
}
|