Closes #27. Guild membership is now the whole gate. `discordCallback` checks membership (and `DISCORD_REQUIRED_ROLE` when set), then `Store.EnsureReader` creates the Reader on first sight and returns the same row on every later login. The refusal returns before `EnsureReader`, so a turned-away sign-in leaves no row behind. `OWNER_DISCORD_ID` still seeds the owner, but only as the administrator — it no longer gates login. The cutover grace path goes with it: `API_TOKEN`, `API_TOKEN_GRACE_UNTIL` and the legacy branch in `httpmw.ResolveReader` are deleted, so a credential authenticates exactly one Reader or nothing. `userscript.Handler` drops its re-derivation too — the resolved path segment is already the credential. New surfaces: an empty library offers both install links (behind the tab-specific empty states, so "No favourites yet" still wins), and the owner alone gets a Readers panel with `POST /readers/{id}/revoke`. The owner's own row is not revocable — 404, not a self-logout. Isolation is asserted from both directions for read, modify and delete, and the shared-series invariant is pinned: two Readers on one series produce one series row, two independent progresses, one poll per due cycle, and one Reader's delete leaves the other's bookmark and the poll intact. Verified: `go test ./...` green; live smoke against a throwaway Postgres — empty-library state in both colour branches, roster rendering, a real revoke through the panel (target 401s next request, owner untouched), owner self-revoke refused 404, per-Reader `/u/<cred>` and bearer auth both 200 with 404 for an unknown credential. Reviewed-on: #36 Co-authored-by: Sulthan Zaki <sultankiki05@gmail.com> Co-committed-by: Sulthan Zaki <sultankiki05@gmail.com>
This commit was merged in pull request #36.
This commit is contained in:
+10
-15
@@ -6,17 +6,10 @@
|
||||
# openssl rand -hex 32
|
||||
TOKEN_KEY=changeme-generate-a-long-random-token
|
||||
|
||||
# Retired global credential, kept only during the cutover window so
|
||||
# already-installed scripts keep working. Remove both it and
|
||||
# API_TOKEN_GRACE_UNTIL once the window has passed and every device has
|
||||
# reinstalled through the web UI.
|
||||
# API_TOKEN=
|
||||
# Moment the retired credential stops resolving to the owner (YYYY-MM-DD or
|
||||
# RFC3339). Enforced in code on every request; unset means it is already dead.
|
||||
# API_TOKEN_GRACE_UNTIL=2026-08-22
|
||||
|
||||
# The owner's Discord user ID — the one Reader every bookmark belongs to
|
||||
# (seeded at startup). Discord snowflake, e.g. 1046923170000000000.
|
||||
# The owner's Discord user ID — seeded at startup as the first Reader, the
|
||||
# administrator (the only one who can revoke another Reader's sessions), and
|
||||
# the owner of every bookmark that predates registration. Discord snowflake,
|
||||
# e.g. 1046923170000000000.
|
||||
OWNER_DISCORD_ID=changeme-your-discord-user-id
|
||||
|
||||
# Comma-separated origins allowed to call the API (CORS). Both Asura domains
|
||||
@@ -42,10 +35,12 @@ POSTGRES_PASSWORD=changeme-generate-a-long-random-password
|
||||
# TRAEFIK_CERTRESOLVER=le
|
||||
|
||||
# --- Web UI (Discord OAuth) ---
|
||||
# Sign-in is a Discord authorization code grant (ADR-0002): the owner signs in
|
||||
# with Discord, and guild membership gates access. Create the application at
|
||||
# https://discord.com/developers/applications and register the exact callback
|
||||
# URL ($BOOKMARK_WEB_HOST/auth/discord/callback) as an OAuth2 redirect.
|
||||
# Sign-in is a Discord authorization code grant (ADR-0002), and it is also
|
||||
# registration: any member of the configured guild becomes a Reader on their
|
||||
# first successful login, with their own empty library. Create the application
|
||||
# at https://discord.com/developers/applications and register the exact
|
||||
# callback URL ($BOOKMARK_WEB_HOST/auth/discord/callback) as an OAuth2
|
||||
# redirect.
|
||||
DISCORD_CLIENT_ID=
|
||||
DISCORD_CLIENT_SECRET=
|
||||
# The guild whose membership gates sign-in (Developer Mode -> right-click the
|
||||
|
||||
Reference in New Issue
Block a user