feat: add database schema and SQLx migrations
- 5 reversible migrations: extensions/enums, tables, indexes, views, config seed - Tables: event, user, session, upload, hashtag, upload_hashtag, comment, comment_hashtag, like, export_job, config - Views: v_feed (uploads with like/comment counts), v_hashtag_counts - Indexes optimised for feed queries, session lookup, hashtag filtering - Config table seeded with default rate limits and quotas - db.rs module: PgPool creation with auto-migration on startup - docker-compose.override.yml: expose db port 5432 for local dev - Fix crate names: async_zip, tower_governor (underscore, not hyphen) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
112
backend/migrations/002_tables.up.sql
Normal file
112
backend/migrations/002_tables.up.sql
Normal file
@@ -0,0 +1,112 @@
|
||||
-- event
|
||||
CREATE TABLE event (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
slug TEXT NOT NULL UNIQUE,
|
||||
name TEXT NOT NULL,
|
||||
cover_image_path TEXT,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
uploads_locked_at TIMESTAMPTZ,
|
||||
export_released_at TIMESTAMPTZ,
|
||||
export_zip_ready BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
export_html_ready BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- user
|
||||
CREATE TABLE "user" (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
event_id UUID NOT NULL REFERENCES event(id) ON DELETE CASCADE,
|
||||
display_name TEXT NOT NULL,
|
||||
role user_role NOT NULL DEFAULT 'guest',
|
||||
is_banned BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
uploads_hidden BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
recovery_pin_hash TEXT NOT NULL,
|
||||
total_upload_bytes BIGINT NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- session
|
||||
CREATE TABLE session (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
|
||||
token_hash TEXT NOT NULL UNIQUE,
|
||||
expires_at TIMESTAMPTZ NOT NULL,
|
||||
last_seen_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- upload
|
||||
CREATE TABLE upload (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
event_id UUID NOT NULL REFERENCES event(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES "user"(id),
|
||||
original_path TEXT NOT NULL,
|
||||
preview_path TEXT,
|
||||
thumbnail_path TEXT,
|
||||
mime_type TEXT NOT NULL,
|
||||
original_size_bytes BIGINT NOT NULL,
|
||||
caption TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
-- hashtag
|
||||
CREATE TABLE hashtag (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
event_id UUID NOT NULL REFERENCES event(id) ON DELETE CASCADE,
|
||||
tag TEXT NOT NULL,
|
||||
UNIQUE (event_id, tag)
|
||||
);
|
||||
|
||||
-- upload_hashtag (junction)
|
||||
CREATE TABLE upload_hashtag (
|
||||
upload_id UUID NOT NULL REFERENCES upload(id) ON DELETE CASCADE,
|
||||
hashtag_id UUID NOT NULL REFERENCES hashtag(id) ON DELETE CASCADE,
|
||||
PRIMARY KEY (upload_id, hashtag_id)
|
||||
);
|
||||
|
||||
-- comment
|
||||
CREATE TABLE comment (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
upload_id UUID NOT NULL REFERENCES upload(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES "user"(id),
|
||||
body TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
-- comment_hashtag (junction)
|
||||
CREATE TABLE comment_hashtag (
|
||||
comment_id UUID NOT NULL REFERENCES comment(id) ON DELETE CASCADE,
|
||||
hashtag_id UUID NOT NULL REFERENCES hashtag(id) ON DELETE CASCADE,
|
||||
PRIMARY KEY (comment_id, hashtag_id)
|
||||
);
|
||||
|
||||
-- like
|
||||
CREATE TABLE "like" (
|
||||
upload_id UUID NOT NULL REFERENCES upload(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
PRIMARY KEY (upload_id, user_id)
|
||||
);
|
||||
|
||||
-- export_job
|
||||
CREATE TABLE export_job (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
event_id UUID NOT NULL REFERENCES event(id) ON DELETE CASCADE,
|
||||
type export_type NOT NULL,
|
||||
status export_status NOT NULL DEFAULT 'pending',
|
||||
progress_pct SMALLINT NOT NULL DEFAULT 0 CHECK (progress_pct BETWEEN 0 AND 100),
|
||||
file_path TEXT,
|
||||
error_message TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
completed_at TIMESTAMPTZ,
|
||||
UNIQUE (event_id, type)
|
||||
);
|
||||
|
||||
-- config (admin-configurable runtime settings)
|
||||
CREATE TABLE config (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
Reference in New Issue
Block a user