105 lines
5.0 KiB
SQL
105 lines
5.0 KiB
SQL
CREATE TABLE IF NOT EXISTS plugin_user_policies (
|
|
user_id uuid PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
|
|
is_disabled boolean NOT NULL DEFAULT false,
|
|
is_administrator boolean NOT NULL DEFAULT false,
|
|
allow_video_playback boolean NOT NULL DEFAULT true,
|
|
allow_audio_playback boolean NOT NULL DEFAULT true,
|
|
allow_content_downloading boolean NOT NULL DEFAULT false,
|
|
enable_remote_access boolean NOT NULL DEFAULT true,
|
|
enabled_library_ids text[] NOT NULL DEFAULT '{}',
|
|
blocked_library_ids text[] NOT NULL DEFAULT '{}',
|
|
max_concurrent_streams integer NOT NULL DEFAULT 0 CHECK (max_concurrent_streams >= 0),
|
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
ALTER TABLE playback_decisions
|
|
ADD COLUMN IF NOT EXISTS media_type text NOT NULL DEFAULT '' CHECK (media_type IN ('','video','audio'));
|
|
ALTER TABLE playback_sessions
|
|
ADD COLUMN IF NOT EXISTS media_type text NOT NULL DEFAULT '' CHECK (media_type IN ('','video','audio'));
|
|
CREATE INDEX IF NOT EXISTS playback_sessions_plugin_report_idx ON playback_sessions(created_at DESC,user_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS user_group_media_policies (
|
|
group_id uuid PRIMARY KEY REFERENCES user_groups(id) ON DELETE CASCADE,
|
|
enabled_library_ids text[] NOT NULL DEFAULT '{}',
|
|
blocked_library_ids text[] NOT NULL DEFAULT '{}',
|
|
updated_by uuid REFERENCES users(id),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
CHECK (cardinality(enabled_library_ids) <= 500),
|
|
CHECK (cardinality(blocked_library_ids) <= 500)
|
|
);
|
|
|
|
ALTER TABLE invite_codes
|
|
ADD COLUMN IF NOT EXISTS owner_reward_points integer NOT NULL DEFAULT 0 CHECK (owner_reward_points >= 0),
|
|
ADD COLUMN IF NOT EXISTS owner_reward_membership_days integer NOT NULL DEFAULT 0 CHECK (owner_reward_membership_days >= 0),
|
|
ADD COLUMN IF NOT EXISTS redeemer_reward_points integer NOT NULL DEFAULT 0 CHECK (redeemer_reward_points >= 0),
|
|
ADD COLUMN IF NOT EXISTS redeemer_reward_membership_days integer NOT NULL DEFAULT 0 CHECK (redeemer_reward_membership_days >= 0);
|
|
|
|
CREATE TABLE IF NOT EXISTS invite_redemptions (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
invite_id uuid NOT NULL REFERENCES invite_codes(id) ON DELETE CASCADE,
|
|
redeemed_by_user_id uuid NOT NULL REFERENCES users(id),
|
|
idempotency_key text NOT NULL CHECK (char_length(idempotency_key) BETWEEN 1 AND 256),
|
|
owner_reward_points integer NOT NULL DEFAULT 0,
|
|
owner_reward_membership_days integer NOT NULL DEFAULT 0,
|
|
redeemer_reward_points integer NOT NULL DEFAULT 0,
|
|
redeemer_reward_membership_days integer NOT NULL DEFAULT 0,
|
|
redeemed_at timestamptz NOT NULL DEFAULT now(),
|
|
UNIQUE (invite_id, redeemed_by_user_id),
|
|
UNIQUE (invite_id, idempotency_key)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS invite_redemptions_user_time_idx ON invite_redemptions(redeemed_by_user_id,redeemed_at DESC);
|
|
|
|
INSERT INTO membership_plans(code,name,duration_days,max_playbacks,max_devices,max_bitrate_kbps,price_points,self_service,enabled)
|
|
VALUES('points-7d','7 天会员',7,1,3,0,30,true,true)
|
|
ON CONFLICT(code) DO NOTHING;
|
|
|
|
ALTER TABLE point_ledger DROP CONSTRAINT IF EXISTS point_ledger_source_type_check;
|
|
ALTER TABLE point_ledger ADD CONSTRAINT point_ledger_source_type_check CHECK (source_type IN (
|
|
'manual','playback_session','media_feedback','redemption','daily_checkin',
|
|
'membership_purchase','telegram_red_packet','invite_reward'
|
|
));
|
|
|
|
CREATE TABLE IF NOT EXISTS plugin_telegram_contexts (
|
|
token_hash bytea PRIMARY KEY,
|
|
plugin_id text NOT NULL,
|
|
tenant_id text NOT NULL,
|
|
telegram_user_id bigint NOT NULL,
|
|
chat_id bigint NOT NULL,
|
|
telegram_username text NOT NULL DEFAULT '',
|
|
expires_at timestamptz NOT NULL,
|
|
consumed_at timestamptz,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
CHECK (expires_at > created_at)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS plugin_telegram_contexts_expiry_idx ON plugin_telegram_contexts(expires_at) WHERE consumed_at IS NULL;
|
|
|
|
CREATE TABLE IF NOT EXISTS plugin_telegram_sends (
|
|
plugin_id text NOT NULL,
|
|
tenant_id text NOT NULL,
|
|
action text NOT NULL CHECK (action IN ('send_photo','send_document')),
|
|
idempotency_key text NOT NULL CHECK (char_length(idempotency_key) BETWEEN 1 AND 256),
|
|
status text NOT NULL DEFAULT 'pending' CHECK (status IN ('pending','sent')),
|
|
message_id bigint NOT NULL DEFAULT 0,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
PRIMARY KEY (plugin_id,tenant_id,action,idempotency_key)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS plugin_telegram_sends_pending_idx ON plugin_telegram_sends(updated_at) WHERE status='pending';
|
|
|
|
CREATE TABLE IF NOT EXISTS plugin_audit_records (
|
|
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
plugin_id text NOT NULL,
|
|
plugin_version text NOT NULL,
|
|
tenant_id text NOT NULL,
|
|
actor_type text NOT NULL,
|
|
actor_id text NOT NULL,
|
|
action text NOT NULL,
|
|
target_type text NOT NULL,
|
|
target_id text NOT NULL DEFAULT '',
|
|
request_id text NOT NULL DEFAULT '',
|
|
trace_id text NOT NULL DEFAULT '',
|
|
result text NOT NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
CREATE INDEX IF NOT EXISTS plugin_audit_records_plugin_time_idx ON plugin_audit_records(plugin_id,tenant_id,created_at DESC,id DESC);
|