feat(backend): give every Bookmark an owner (Reader table) (#22)
A readers table appears, keyed by Discord user ID and carrying the SHA-256 of the owner's userscript token (the global API token today). Startup seeds exactly one Reader from OWNER_DISCORD_ID, idempotently, and a run-once migration (0004, version-table-gated) attaches existing bookmarks to it before reshaping: the surrogate key column is dropped and bookmarks are keyed (reader_id, site, series_id) with an FK to readers ON DELETE CASCADE, so a duplicate bookmark for one Reader and Series is impossible at the database level. Every store read and write is now scoped to the reader it names; handlers act as the seeded owner while the global token remains the only credential. Authentication and the wire format are untouched: the flat JSON still carries key/site/series_id, with key derived on read. OWNER_DISCORD_ID is a new required env var (compose + docs updated).
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
-- Attach every pre-existing bookmark to the owner reader, seeded between the
|
||||
-- two migrate passes (Store.Open). The oldest reader is the owner by
|
||||
-- construction: only the seed creates readers, and it runs once per database.
|
||||
-- Run-once via the version table, like every migration.
|
||||
UPDATE bookmarks SET reader_id = (SELECT id FROM readers ORDER BY id LIMIT 1);
|
||||
|
||||
-- Ownership lands structurally: reader_id becomes part of the key, so a
|
||||
-- bookmark is one Reader's progress on one Series and a duplicate for the
|
||||
-- same pair is impossible at the database level. Deleting a Reader takes
|
||||
-- their bookmarks with them. The old text key is gone — the wire "key" is
|
||||
-- derived as site:series_id on read, and nothing references the column.
|
||||
-- Dropping it drops the primary key it carried; the composite key replaces
|
||||
-- it, and the FK index the series constraint needs is created automatically.
|
||||
ALTER TABLE bookmarks
|
||||
ALTER COLUMN reader_id SET NOT NULL,
|
||||
DROP COLUMN key,
|
||||
ADD PRIMARY KEY (reader_id, site, series_id),
|
||||
ADD CONSTRAINT bookmarks_reader_fk
|
||||
FOREIGN KEY (reader_id) REFERENCES readers (id) ON DELETE CASCADE;
|
||||
Reference in New Issue
Block a user