Public Access
feat(account): let users delete their account
DELETE /api/users/me with the password sets users.deleted_at, ends all logins and frees the Steam ID. A nightly job removes users flagged 30 days ago, Core first, and prunes Core orphans. Dry run by default.
This commit is contained in:
1 parent
a1763addce
commit
7dc2fb613e
33 files changed
+1115
-11
No files matched your search
@@ -38,6 +38,12 @@ To Be Played is split into three repositories:
|
||||
10 minutes, `typ=public-profile`) that Core accepts for the public library data only. Its `profileStats` claim
|
||||
names the stat groups the user chose to show there (none by default). The ticket is not a login:
|
||||
both services reject every token with a `typ` claim on normal endpoints.
|
||||
- **Delete my account** with the password (5 wrong tries per 15 minutes, then `429`). It only sets
|
||||
`users.deleted_at` and revokes every refresh token: from then on no login, no refresh, no public profile, no Steam
|
||||
link, not in the landing stats. Email and display name stay taken; the Steam ID is freed, so an undo needs a
|
||||
new Steam link. A nightly job (04:15, Europe/Berlin) removes
|
||||
users flagged 30 days ago, in Core first and then in Auth. It calls Core's `/internal/accounts/*` with a
|
||||
**service token** (EdDSA JWT, 60 s, `typ=service`). `app.account-cleanup.dry-run` (default `true`) only logs.
|
||||
|
||||
## API
|
||||
|
||||
@@ -51,6 +57,7 @@ To Be Played is split into three repositories:
|
||||
| `PUT` | `/api/users/settings` | access token |
|
||||
| `POST` | `/api/users/steam-link` | access token, returns Steam's login URL and sets the binding cookie |
|
||||
| `DELETE` | `/api/users/steam-link` | access token, removes the Steam ID and sets a new access cookie |
|
||||
| `DELETE` | `/api/users/me` (`{password}`; `204` and both cookies cleared, `403 INVALID_PASSWORD`, `429`) | access token |
|
||||
| `GET` | `/api/steam-link/callback` | public, Steam's redirect back; binding cookie; redirects to the frontend settings |
|
||||
| `PUT` | `/api/users/settings/appearance` | access token |
|
||||
| `PUT` | `/api/users/settings/profile-stats` (`{groups}`: `PILE`, `TOP_GAMES`, `TASTE`, `HABITS`, `FINISHED`, `TREND`; `204`) | access token |
|
||||
@@ -82,6 +89,8 @@ layers:
|
||||
|
||||
`profile` and `stats` only read data. They have no entities and use `JdbcTemplate` queries in a `repo` package.
|
||||
`version` has only an `api` package: `GET /api/version` answers the commit and build time of the running image.
|
||||
`account` (delete and nightly cleanup) sets the flag with `JdbcTemplate` in a `repo` package too, and calls Core
|
||||
through `CoreAccountService`.
|
||||
|
||||
ArchUnit enforces these rules in `src/test/java/auth_service/architecture/ArchitectureTest.java`, so a layer
|
||||
violation fails the build. It also keeps the modules independent of each other and free of cycles. Test base
|
||||
@@ -135,6 +144,27 @@ sequenceDiagram
|
||||
once. `SteamOpenIdService` checks mode, endpoint, `return_to` and the signed fields, then asks Steam.
|
||||
`UserService.linkVerifiedSteamId` stores the ID and takes it from an account that only typed it in.
|
||||
|
||||
### Delete account flow
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant B as Browser (Frontend)
|
||||
participant A as Auth
|
||||
participant C as Core
|
||||
B->>A: DELETE /api/users/me {password}
|
||||
A->>A: users.deleted_at = now, revoke refresh tokens
|
||||
A->>C: POST /internal/accounts/deleted (service token)
|
||||
A-->>B: 204, both cookies cleared
|
||||
Note over A,C: nightly 04:15
|
||||
A->>C: PUT /internal/accounts/deleted (all flagged users)
|
||||
A->>C: POST /internal/accounts/purge (flagged 30+ days)
|
||||
A->>A: DELETE users (only when Core answered and no dry run)
|
||||
A->>C: POST /internal/accounts/prune (all user ids)
|
||||
```
|
||||
|
||||
A failed call to Core does not fail the delete: the next night sends the whole flagged set again. Undo within 30
|
||||
days is `UPDATE users SET deleted_at = NULL` (see the Deployment README).
|
||||
|
||||
## Run locally
|
||||
|
||||
Needs Java 25 and Docker.
|
||||
|
||||
Reference in new issue
Block a user