fix(PROJ-34): Mandanten-Retention ist Opt-in — kein globaler Lock für Mandanten

storage.Save(): retention_days eines Mandanten muss explizit > 0 sein.
Globale config greift nie automatisch auf Mandanten-Mails.
Mails ohne Mandant: globale config als Fallback (unveraendert).
Frontend: Hinweis und Labels klargestellt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
sysops
2026-03-31 10:50:54 +02:00
parent 4aadf7a4d2
commit ebc9e278ea
2 changed files with 18 additions and 22 deletions
+9 -16
View File
@@ -63,17 +63,11 @@ async function triggerPurge(): Promise<number> {
return data.deleted ?? 0;
}
function retentionLabel(days: number, globalDays: number): React.ReactNode {
function retentionLabel(days: number): React.ReactNode {
if (days === 0) {
return globalDays > 0 ? (
<span className="text-muted-foreground text-sm">
Global ({globalDays} Tage)
</span>
) : (
<Badge variant="secondary">Kein Lock</Badge>
);
return <Badge variant="secondary">Kein Lock (manuell setzen)</Badge>;
}
return <Badge>{days} Tage</Badge>;
return <Badge>{days} Tage ({(days / 365).toFixed(1)} Jahre)</Badge>;
}
export function RetentionTab() {
@@ -137,8 +131,6 @@ export function RetentionTab() {
}
};
const globalDays = data?.global_retention_days ?? 0;
return (
<div className="mt-4 space-y-4">
{/* Global Policy */}
@@ -149,15 +141,16 @@ export function RetentionTab() {
<CardContent className="space-y-3">
<div className="flex items-center gap-3">
<span className="text-sm font-medium">Globale Aufbewahrungsfrist:</span>
{globalDays > 0 ? (
<Badge>{globalDays} Tage ({Math.round(globalDays / 365)} Jahre)</Badge>
{(data?.global_retention_days ?? 0) > 0 ? (
<Badge>{data!.global_retention_days} Tage ({Math.round(data!.global_retention_days / 365)} Jahre)</Badge>
) : (
<Badge variant="secondary">Kein globaler Lock (config.yml)</Badge>
)}
</div>
<p className="text-sm text-muted-foreground">
Die globale Frist wird in <code className="text-xs bg-muted px-1 rounded">config.yml storage.retention_days</code> konfiguriert.
Mandanten-spezifische Einstellungen überschreiben diese, wenn gesetzt.
Die globale Frist gilt nur für Mails ohne Mandant-Zuordnung (Systemkonten).
<strong className="text-foreground"> Für Mandanten greift ausschließlich die individuelle Einstellung</strong>
solange ein Mandant keine eigene Frist gesetzt hat (0 Tage), werden seine Mails nie automatisch gelöscht.
</p>
<Button
variant="destructive"
@@ -191,7 +184,7 @@ export function RetentionTab() {
{(data?.tenants ?? []).map((t) => (
<TableRow key={t.id}>
<TableCell className="font-medium">{t.name}</TableCell>
<TableCell>{retentionLabel(t.retention_days, globalDays)}</TableCell>
<TableCell>{retentionLabel(t.retention_days)}</TableCell>
<TableCell>
<Button size="sm" variant="outline" onClick={() => handleEditOpen(t)}>
Bearbeiten