Files
Sauci/apps/api/drizzle/0004_chat.sql
jjbrunton 006761d3b0 feat(backend): add standalone data plane
Replace the Supabase application data plane with the Node/PostgreSQL API, migrate mobile, admin, web, and MCP callers, add controlled cutover tooling, and define hardened Dokploy infrastructure.
2026-08-28 14:42:11 +01:00

86 lines
3.8 KiB
SQL

CREATE TABLE IF NOT EXISTS "messages" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
"match_id" uuid NOT NULL REFERENCES "matches"("id") ON DELETE CASCADE,
"user_id" uuid NOT NULL REFERENCES "profiles"("id") ON DELETE CASCADE,
"content" text,
"created_at" timestamptz NOT NULL DEFAULT now(),
"read_at" timestamptz,
"delivered_at" timestamptz,
"deleted_at" timestamptz,
"media_path" text,
"media_type" text CHECK ("media_type" IS NULL OR "media_type" IN ('image', 'video')),
"media_expires_at" timestamptz,
"media_expired" boolean NOT NULL DEFAULT false,
"media_viewed_at" timestamptz,
"version" integer NOT NULL DEFAULT 1,
"encrypted_content" text,
"encryption_iv" text,
"keys_metadata" jsonb,
"moderation_status" text,
"flag_reason" text,
"category" text,
CONSTRAINT "messages_content_or_media" CHECK (
"content" IS NOT NULL OR "media_path" IS NOT NULL OR "encrypted_content" IS NOT NULL
)
);
--> statement-breakpoint
ALTER TABLE "messages"
ADD COLUMN IF NOT EXISTS "delivered_at" timestamptz,
ADD COLUMN IF NOT EXISTS "deleted_at" timestamptz,
ADD COLUMN IF NOT EXISTS "media_path" text,
ADD COLUMN IF NOT EXISTS "media_type" text,
ADD COLUMN IF NOT EXISTS "media_expires_at" timestamptz,
ADD COLUMN IF NOT EXISTS "media_expired" boolean NOT NULL DEFAULT false,
ADD COLUMN IF NOT EXISTS "media_viewed_at" timestamptz,
ADD COLUMN IF NOT EXISTS "version" integer NOT NULL DEFAULT 1,
ADD COLUMN IF NOT EXISTS "encrypted_content" text,
ADD COLUMN IF NOT EXISTS "encryption_iv" text,
ADD COLUMN IF NOT EXISTS "keys_metadata" jsonb,
ADD COLUMN IF NOT EXISTS "moderation_status" text,
ADD COLUMN IF NOT EXISTS "flag_reason" text,
ADD COLUMN IF NOT EXISTS "category" text;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "messages" ADD CONSTRAINT "messages_media_type_check"
CHECK ("media_type" IS NULL OR "media_type" IN ('image', 'video'));
EXCEPTION WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "messages" ADD CONSTRAINT "messages_content_or_media"
CHECK ("content" IS NOT NULL OR "media_path" IS NOT NULL OR "encrypted_content" IS NOT NULL);
EXCEPTION WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
CREATE INDEX IF NOT EXISTS "messages_match_created_idx" ON "messages" ("match_id", "created_at" DESC);
--> statement-breakpoint
CREATE INDEX IF NOT EXISTS "messages_unread_idx" ON "messages" ("match_id", "user_id") WHERE "read_at" IS NULL;
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "message_deletions" (
"message_id" uuid NOT NULL REFERENCES "messages"("id") ON DELETE CASCADE,
"user_id" uuid NOT NULL REFERENCES "profiles"("id") ON DELETE CASCADE,
"deleted_at" timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY ("message_id", "user_id")
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "message_reports" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
"message_id" uuid NOT NULL REFERENCES "messages"("id") ON DELETE CASCADE,
"reporter_id" uuid NOT NULL REFERENCES "profiles"("id") ON DELETE CASCADE,
"reason" text NOT NULL CHECK ("reason" IN ('harassment', 'spam', 'inappropriate_content', 'other')),
"status" text NOT NULL DEFAULT 'pending' CHECK ("status" IN ('pending', 'reviewed', 'dismissed')),
"created_at" timestamptz NOT NULL DEFAULT now(),
UNIQUE ("message_id", "reporter_id")
);
--> statement-breakpoint
CREATE INDEX IF NOT EXISTS "message_reports_status_idx" ON "message_reports" ("status", "created_at" DESC);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "chat_typing_states" (
"match_id" uuid NOT NULL REFERENCES "matches"("id") ON DELETE CASCADE,
"user_id" uuid NOT NULL REFERENCES "profiles"("id") ON DELETE CASCADE,
"expires_at" timestamptz NOT NULL,
PRIMARY KEY ("match_id", "user_id")
);
--> statement-breakpoint
CREATE INDEX IF NOT EXISTS "chat_typing_expires_idx" ON "chat_typing_states" ("expires_at");