Files
OverCooked-Installer/s-migrations/000001_s1_s3.up.sql
T

82 lines
5.2 KiB
SQL

CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE TABLE users (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
username text NOT NULL,
username_normalized text NOT NULL UNIQUE,
email text NOT NULL,
email_normalized text NOT NULL UNIQUE,
role text NOT NULL DEFAULT 'user' CHECK (role IN ('user','admin')),
status text NOT NULL DEFAULT 'active' CHECK (status IN ('active','disabled','deleted')),
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz
);
CREATE TABLE credentials (
user_id uuid PRIMARY KEY REFERENCES users(id),
password_hash text NOT NULL,
password_changed_at timestamptz NOT NULL DEFAULT now(),
created_at timestamptz NOT NULL DEFAULT now()
);
CREATE TABLE memberships (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(), user_id uuid NOT NULL REFERENCES users(id),
status text NOT NULL CHECK (status IN ('active','expired','revoked')),
starts_at timestamptz NOT NULL, ends_at timestamptz NOT NULL,
source text NOT NULL, created_at timestamptz NOT NULL DEFAULT now(),
CHECK (ends_at > starts_at)
);
CREATE INDEX memberships_active_user_idx ON memberships(user_id, ends_at DESC) WHERE status = 'active';
CREATE TABLE refresh_token_families (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(), user_id uuid NOT NULL REFERENCES users(id),
revoked_at timestamptz, created_at timestamptz NOT NULL DEFAULT now()
);
CREATE TABLE refresh_tokens (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(), family_id uuid NOT NULL REFERENCES refresh_token_families(id),
token_hash bytea NOT NULL UNIQUE, expires_at timestamptz NOT NULL, consumed_at timestamptz,
replaced_by uuid, created_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX refresh_tokens_family_idx ON refresh_tokens(family_id);
CREATE TABLE card_batches (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(), name text NOT NULL, card_type text NOT NULL CHECK (card_type IN ('registration','renewal')),
duration_days integer NOT NULL CHECK (duration_days > 0), created_by uuid REFERENCES users(id),
revoked_at timestamptz, created_at timestamptz NOT NULL DEFAULT now()
);
CREATE TABLE cards (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(), batch_id uuid NOT NULL REFERENCES card_batches(id),
code_hash bytea NOT NULL UNIQUE, remaining_uses integer NOT NULL DEFAULT 1 CHECK (remaining_uses >= 0),
status text NOT NULL DEFAULT 'active' CHECK (status IN ('active','revoked','exhausted')),
expires_at timestamptz, created_at timestamptz NOT NULL DEFAULT now()
);
CREATE TABLE card_usages (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(), card_id uuid NOT NULL REFERENCES cards(id), user_id uuid NOT NULL REFERENCES users(id),
used_at timestamptz NOT NULL DEFAULT now(), UNIQUE(card_id, user_id)
);
CREATE INDEX card_usages_user_idx ON card_usages(user_id, used_at DESC);
CREATE TABLE audit_events (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY, actor_user_id uuid REFERENCES users(id), action text NOT NULL,
target_type text NOT NULL, target_id text NOT NULL, detail jsonb NOT NULL DEFAULT '{}'::jsonb, created_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX audit_events_target_idx ON audit_events(target_type, target_id, created_at DESC);
CREATE TABLE policy_rules (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(), subject_type text NOT NULL CHECK (subject_type IN ('global','membership','user')),
subject_id uuid, priority integer NOT NULL DEFAULT 0, enabled boolean NOT NULL DEFAULT true,
max_devices integer, max_online integer, max_playbacks integer, max_device_playbacks integer, max_bitrate_kbps integer,
downloads_allowed boolean, proxy_allowed boolean, transcode_allowed boolean, library_id text,
allowed_cidrs text[] NOT NULL DEFAULT '{}', countries text[] NOT NULL DEFAULT '{}', regions text[] NOT NULL DEFAULT '{}',
asns bigint[] NOT NULL DEFAULT '{}', carriers text[] NOT NULL DEFAULT '{}', route_id text, created_at timestamptz NOT NULL DEFAULT now(),
CHECK ((subject_type = 'global' AND subject_id IS NULL) OR (subject_type <> 'global' AND subject_id IS NOT NULL))
);
CREATE INDEX policy_rules_subject_idx ON policy_rules(subject_type, subject_id, priority DESC) WHERE enabled;
CREATE TABLE devices (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(), user_id uuid NOT NULL REFERENCES users(id), fingerprint_hash bytea NOT NULL,
first_seen_at timestamptz NOT NULL DEFAULT now(), last_seen_at timestamptz NOT NULL DEFAULT now(), revoked_at timestamptz,
UNIQUE(user_id, fingerprint_hash)
);
CREATE TABLE playback_sessions (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(), user_id uuid NOT NULL REFERENCES users(id), device_id uuid REFERENCES devices(id),
e_session_id text NOT NULL UNIQUE, library_id text NOT NULL, route_id text, state text NOT NULL CHECK (state IN ('reserved','active','released','expired')),
lease_token_hash bytea NOT NULL UNIQUE, expires_at timestamptz NOT NULL, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), released_at timestamptz
);
CREATE INDEX playback_sessions_active_user_idx ON playback_sessions(user_id, expires_at) WHERE state IN ('reserved','active');
CREATE INDEX playback_sessions_active_device_idx ON playback_sessions(device_id, expires_at) WHERE state IN ('reserved','active');