Public Access
feat(account): Steam ID and blocked state from Auth (V25)
A blocked user gets no sync and leaves the landing stats. A new or removed Steam ID stops the nightly sync of the old one. No token check in Core: the token lives until it expires.
This commit is contained in:
1 parent
3512159b41
commit
504c935b27
15 files changed
+312
-20
No files matched your search
@@ -129,6 +129,7 @@ method calling another service's method that needs more.
|
||||
| `GET` | `/api/public/profiles/library` | profile ticket |
|
||||
| `GET` | `/api/stats/public` | public |
|
||||
| `POST`, `PUT` | `/internal/accounts/deleted` (`{userIds}`; POST adds, PUT replaces the whole set; `204`) | service token |
|
||||
| `POST`, `PUT` | `/internal/accounts/states` (`{accounts: [{userId, steamId, blocked}]}`; POST updates, PUT replaces the whole set; `204`) | service token |
|
||||
| `POST` | `/internal/accounts/purge` (`{userIds}`), `/internal/accounts/prune` (`{knownUserIds}`, not empty) | service token |
|
||||
| `GET` | `/api/version` (`{commit, builtAt}` of the running image, from the CI build; `dev` locally) | public |
|
||||
|
||||
@@ -173,9 +174,9 @@ flowchart LR
|
||||
Igdb -->|"OAuth token"| Twitch["Twitch"]
|
||||
Speedrun --> SpeedrunApi["speedrun.com API"]
|
||||
LibRepo --> Db[("PostgreSQL tbp_core")]
|
||||
Stats -->|"listed_user_game, deleted_user"| Db
|
||||
Stats -->|"listed_user_game, deleted_user, blocked_user"| Db
|
||||
Auth -->|"service token<br/>/internal/accounts"| Account
|
||||
Account -->|"per-user rows, deleted_user"| Db
|
||||
Account -->|"per-user rows, deleted_user, blocked_user, user_seen_at"| Db
|
||||
```
|
||||
|
||||
| Module | Content |
|
||||
@@ -183,15 +184,16 @@ flowchart LR
|
||||
| `library` | Sync, backlog, manual games, imports, playtime history, wishlist, achievements, public profile data |
|
||||
| `stats` | Public numbers for the landing page |
|
||||
| `version` | `GET /api/version`: commit and build time of the running image |
|
||||
| `account` | Deleted accounts, driven by Auth: tombstones in `deleted_user`, purge and orphan prune of the per-user rows |
|
||||
| `account` | Driven by Auth: tombstones in `deleted_user`, purge and orphan prune of the per-user rows; blocks in `blocked_user`, Steam ID changes stop the nightly sync |
|
||||
| `steam_adapter` | Steam Web API client, availability check of Steam CDN pictures |
|
||||
| `igdb_adapter` | IGDB client (Twitch OAuth): time to beat, game tags for moods, release years, game search |
|
||||
| `speedrun_adapter` | speedrun.com client: game search by name, verified runs |
|
||||
|
||||
**One shared schema.** All modules use one database `tbp_core`, and some read or write another module's tables in
|
||||
SQL, which ArchUnit cannot see: `stats` reads `listed_user_game`, `steam_game` and `deleted_user`; `account` deletes
|
||||
the per-user rows of the library tables (`AccountCleanupRepository`; a new library table with `user_id` goes into
|
||||
its list); `library` reads `deleted_user`. A module that moves to its own service takes these reads along as calls.
|
||||
SQL, which ArchUnit cannot see: `stats` reads `listed_user_game`, `steam_game`, `deleted_user` and `blocked_user`; `account`
|
||||
deletes the per-user rows of the library tables (`AccountCleanupRepository`; a new library table with `user_id` goes
|
||||
into its list) and writes `user_seen_at` and `last_synced_at` of `user_steam_sync` (`AccountStateRepository`); `library`
|
||||
reads `deleted_user` and `blocked_user`. A module that moves to its own service takes these reads along as calls.
|
||||
The listed rule ("still owned, not hidden") is `UserGameRepository.LISTED` for JPQL and the view
|
||||
`listed_user_game` for native SQL; V24 says what a migration of `user_game` must do with the view.
|
||||
|
||||
@@ -222,7 +224,7 @@ Inside a module: `api` (controllers, DTOs), `service` (business logic), `domain`
|
||||
dates finished games by the unlock of their ending achievement
|
||||
(`FinishedEstimateService`, `user_game.finished_at_estimate`).
|
||||
3. `LibrarySyncWorker` runs on the background pool. `user_steam_sync` lets only one run per user start, and none for
|
||||
a user in `deleted_user`.
|
||||
a user in `deleted_user` or `blocked_user`.
|
||||
4. The worker loads the wishlist and the owned games from Steam. It updates `steam_game` and `user_game`, adds
|
||||
the playtime growth of the day to `user_game_playtime_day`, and soft-deletes Steam games the user no longer
|
||||
owns. The growth counts at most Steam's playtime of the last two weeks, so a game seen for the first time brings
|
||||
@@ -310,6 +312,16 @@ flagged set (`PUT`), then `purge` for users flagged 30 days ago (only tombstoned
|
||||
user ids, which removes the rows of users Auth does not know (refused for more than
|
||||
`app.account-cleanup.max-orphans`, default 5). `app.account-cleanup.dry-run` (default `true`) only counts the rows.
|
||||
|
||||
### Blocked users and Steam ID changes
|
||||
|
||||
Auth sends a user's state (`POST /internal/accounts/states`) after a Steam link, an unlink, a Steam ID another account
|
||||
took by a verified link, a block and an unblock; its nightly job sends every user (`PUT`). A blocked user is in
|
||||
`blocked_user`: no nightly sync, no new sync run, not in the landing stats. The access token still works in Core until
|
||||
it expires (max 15 min). A new Steam ID or no Steam ID takes the user out of the nightly sync; the next visit syncs
|
||||
the ID of the token (Core's copy changes only then, so that sync sees the change and drops the old account's games). A visit with an access token that still has the old ID (max 15 min) can sync it once
|
||||
more and put the user back on the nightly list; the nightly `PUT` at 04:15 takes the user off again, so at most one
|
||||
nightly sync (23:55) runs with the old ID. Unblock and the nightly `PUT` lift the block.
|
||||
|
||||
### Manual games next to Steam games
|
||||
|
||||
A game the user adds by hand comes from IGDB (`ManualGameService`). Steam games and manual games share
|
||||
|
||||
Reference in new issue
Block a user