Skip to content

Add account deletion, data export and a retention sweep - #279

Merged
PianoNic merged 3 commits into
mainfrom
feature/274_AccountDeletion
Sep 9, 2026
Merged

Add account deletion, data export and a retention sweep#279
PianoNic merged 3 commits into
mainfrom
feature/274_AccountDeletion

Conversation

@PianoNic

@PianoNic PianoNic commented Sep 9, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds IAccountPurger, one service that erases everything stored about a user: school users and their grades, absences, agenda entries, semester reports, subject grades, documents and class memberships, plus the account row. The per-user deletions are a single named list of purge steps, so a new user-scoped table is a two-line addition.
  • Student document blobs are removed from S3 through IDocumentStorage.DeleteAsync after the database transaction commits; a missing or unreachable object is logged and counted, never fatal.
  • Teacher rows linked to the account are unlinked rather than deleted - they are school-owned master data referenced by classes, which is what DeleteBehavior.SetNull on the FK already says.
  • DELETE /api/auth/me purges the caller's data and then deletes the Keycloak user through the admin REST API using a service-account client (Oidc:AdminClientId / Oidc:AdminClientSecret). Unconfigured, or any failure against Keycloak, logs a warning and leaves local deletion successful.
  • GET /api/auth/me/export returns everything stored about the caller as schuly-export.json.
  • Retention sweep as a hosted service: first pass five minutes after startup, then daily. Drops cached school data for school users whose LeaveDate is older than Retention:MonthsAfterLeave (6), and accounts with no authenticated request for Retention:MonthsInactive (12). Both, and Retention:Enabled, are configurable; it reuses the same purge code.
  • "Inactive" is defined by a new nullable ApplicationUser.LastSeenAt, stamped from the JWT validation pipeline at most once an hour, falling back to CreatedAt for accounts predating the column. The sweep never touches identity-provider users, so a swept account can sign in again and resync.
  • Purge logging carries a hashed user id and row counts only, no personal data.
  • Plugin vault entries are left alone and the reason is recorded in code: a VaultEntry is keyed by plugin namespace and an opaque key, with no user dimension to match on.

Closes #274

Adds IAccountPurger as the single place that erases everything stored about
a user, a self-service DELETE and export endpoint on /api/auth/me, and a
daily retention sweep that reuses the same purge code.
@PianoNic PianoNic added the feature New feature label Sep 9, 2026
@PianoNic
PianoNic merged commit e98f8ab into main Sep 9, 2026
@PianoNic
PianoNic deleted the feature/274_AccountDeletion branch September 9, 2026 18:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Account deletion, data export and retention job

1 participant