// Sharing by link. The author makes a link; whoever follows it, signed in, // accepts, and the resource joins their library as a share (a row in // user_resource_shares, exactly as before). Only the hash of the token is // stored, so a database read does not hand out working links; a link can be // given an expiry and withdrawn. exports.up = pgm => pgm.sql(` CREATE TABLE IF NOT EXISTS user_resource_share_links ( id SERIAL PRIMARY KEY, resource_id INTEGER NOT NULL REFERENCES user_resources(id) ON DELETE CASCADE, token_hash TEXT NOT NULL UNIQUE, created_by INTEGER REFERENCES users(id) ON DELETE SET NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), expires_at TIMESTAMPTZ, revoked_at TIMESTAMPTZ, accepted_count INTEGER NOT NULL DEFAULT 0 ); CREATE INDEX IF NOT EXISTS idx_resource_share_links_resource ON user_resource_share_links (resource_id); `); exports.down = pgm => pgm.sql(` DROP TABLE IF EXISTS user_resource_share_links; `);