-- Phase 9: application services, and the parts of the admin API that keep -- state of their own — registration tokens, server notice rooms, media -- quotas and the audit log. -- Registration tokens made through the admin API. The tokens in the config -- file are not here: they have no use count or expiry to keep. -- -- uses_allowed is NULL for a token that may be used any number of times. -- completed counts the registrations that spent it; a registration takes -- its use when the account is created, not when the stage is passed, so an -- abandoned sign-up costs nothing. CREATE TABLE IF NOT EXISTS admin_registration_tokens ( token TEXT NOT NULL PRIMARY KEY, uses_allowed BIGINT, completed BIGINT NOT NULL DEFAULT 0, -- 0 means the token never expires. expires_at_ms BIGINT NOT NULL DEFAULT 0, created_at_ms BIGINT NOT NULL ); -- The room each user gets their server notices in. One per user: a second -- notice goes into the same room, and a user who left it is invited back. CREATE TABLE IF NOT EXISTS admin_server_notice_rooms ( localpart TEXT NOT NULL PRIMARY KEY, room_id TEXT NOT NULL ); -- A user's media quota, where the admin API set one. Users without a row -- get media.max_user_storage_bytes. max_bytes 0 is no limit, the same as -- the config value. CREATE TABLE IF NOT EXISTS media_quotas ( user_id TEXT NOT NULL PRIMARY KEY, max_bytes BIGINT NOT NULL ); -- Usage is summed over a user's uploads, so it wants an index that starts -- with the uploader. CREATE INDEX IF NOT EXISTS media_repository_user_idx ON media_repository (user_id, media_origin); -- The audit log: one row per change made through the admin API. id is -- handed out by admin_sequences inside the writing transaction, for the -- reason the roomserver's stream positions are (0003): no engine-specific -- autoincrement, and no gaps. CREATE TABLE IF NOT EXISTS admin_sequences ( name TEXT NOT NULL PRIMARY KEY, value BIGINT NOT NULL ); INSERT INTO admin_sequences (name, value) VALUES ('audit', 0) ON CONFLICT (name) DO NOTHING; CREATE TABLE IF NOT EXISTS admin_audit_log ( id BIGINT NOT NULL PRIMARY KEY, ts_ms BIGINT NOT NULL, -- The admin who made the change, as a full user ID. actor TEXT NOT NULL, -- What was done, e.g. "user.deactivate"; see docs/admin-api.md. action TEXT NOT NULL, -- What it was done to: a user ID, a room ID, a token. Empty for a -- server-wide change. target TEXT NOT NULL DEFAULT '', details_json TEXT NOT NULL DEFAULT '{}' ); CREATE INDEX IF NOT EXISTS admin_audit_log_actor_idx ON admin_audit_log (actor, id); CREATE INDEX IF NOT EXISTS admin_audit_log_action_idx ON admin_audit_log (action, id); -- Where each application service is in the event stream. -- -- stream_pos is the last stream position whose events have been delivered -- (or found to be of no interest). txn_to is non-zero while a transaction -- is in flight: it is the top of the events in it, and txn_id its ID, so -- that after a restart the same transaction — same ID, same events — is -- sent again rather than a new one that overlaps it. An application -- service deduplicates by transaction ID, and only a retry that is -- identical can be deduplicated. CREATE TABLE IF NOT EXISTS appservice_state ( as_id TEXT NOT NULL PRIMARY KEY, stream_pos BIGINT NOT NULL, txn_id BIGINT NOT NULL DEFAULT 0, txn_to BIGINT NOT NULL DEFAULT 0 );