bcc6b45515
Implements #23 per ADR-0002. - Discord authorization code grant (identify + guilds.members.read), form-encoded token exchange - Guild membership gate via the single-guild endpoint; optional DISCORD_REQUIRED_ROLE (empty default) - Owner Discord ID is the only identity allowed to sign in - Sessions are DB rows with opaque random ids; cookie carries only the id; expiry enforced; delete = revoke - HMAC session signing, derived key, and WEB_PASSWORD removed; no replacement signing secret - Login rate limiting preserved on the callback - Full flow tested through the real router against a local Discord stub (DISCORD_API_BASE) - Env: DISCORD_CLIENT_ID/_CLIENT_SECRET/_GUILD_ID/_REQUIRED_ROLE/_API_BASE/_REDIRECT_URI; docs updated go test ./... passes. Reviewed-on: #31 Co-authored-by: Sulthan Zaki <sultankiki05@gmail.com> Co-committed-by: Sulthan Zaki <sultankiki05@gmail.com>
12 lines
528 B
SQL
12 lines
528 B
SQL
-- One row per browser session. The id is an opaque random value the cookie
|
|
-- carries verbatim; a request is authenticated by looking the row up, and
|
|
-- deleting the row is how a session is revoked. Expired rows are removed
|
|
-- lazily on lookup and swept by the next login, so nothing runs a background
|
|
-- cleanup.
|
|
CREATE TABLE sessions (
|
|
id text PRIMARY KEY,
|
|
reader_id bigint NOT NULL REFERENCES readers (id) ON DELETE CASCADE,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
expires_at timestamptz NOT NULL
|
|
);
|