feat(PROJ-20): GoBD-konforme Nutzer-Löschung mit IMAP-Cleanup und Warn-Dialog

- imap/store.go: DeleteByOwner() – löscht alle IMAP-Konten eines Nutzers
- api/server.go: handleDeleteUser lädt Nutzername vor Löschung, ruft DeleteByOwner, schreibt erweitertes Audit-Log (username, role, IMAP-Count, GoBD-Hinweis)
- admin/page.tsx: confirm() ersetzt durch Dialog mit GoBD-Hinweis, Deaktivieren-Option (empfohlen) und endgültigem Löschen (destruktiv)
- features/PROJ-20-nutzer-loeschung.md: Feature-Spec angelegt
- features/INDEX.md: PROJ-20 eingetragen, Next ID → PROJ-21

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
sysops
2026-03-17 13:44:32 +01:00
parent 2900e53753
commit e46b68b63f
5 changed files with 214 additions and 10 deletions
+10
View File
@@ -238,6 +238,16 @@ func (s *Store) Delete(ctx context.Context, id int64) error {
return nil
}
// DeleteByOwner removes all IMAP accounts belonging to the given username.
// Returns the number of accounts deleted.
func (s *Store) DeleteByOwner(ctx context.Context, username string) (int, error) {
tag, err := s.pool.Exec(ctx, `DELETE FROM imap_accounts WHERE owner = $1`, username)
if err != nil {
return 0, fmt.Errorf("imap store: delete by owner: %w", err)
}
return int(tag.RowsAffected()), nil
}
// UpdateExcluded sets the list of excluded folders for an account.
func (s *Store) UpdateExcluded(ctx context.Context, id int64, excluded []string) error {
_, err := s.pool.Exec(ctx, `UPDATE imap_accounts SET excluded_folders = $1 WHERE id = $2`, excluded, id)