265 lines
12 KiB
SQL
265 lines
12 KiB
SQL
DO $$ BEGIN
|
|
CREATE TYPE "public"."push_delivery_status" AS ENUM('pending', 'accepted_by_push_service', 'failed', 'invalid_subscription', 'expired');
|
|
EXCEPTION
|
|
WHEN duplicate_object THEN null;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
DO $$ BEGIN
|
|
CREATE TYPE "public"."user_role" AS ENUM('admin', 'user');
|
|
EXCEPTION
|
|
WHEN duplicate_object THEN null;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
CREATE TABLE IF NOT EXISTS "api_token_topics" (
|
|
"token_id" uuid NOT NULL,
|
|
"topic_id" uuid NOT NULL,
|
|
CONSTRAINT "api_token_topics_token_id_topic_id_pk" PRIMARY KEY("token_id","topic_id")
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE IF NOT EXISTS "api_tokens" (
|
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
"name" text NOT NULL,
|
|
"token_hash" text NOT NULL,
|
|
"token_prefix" text NOT NULL,
|
|
"allowed_source" text,
|
|
"allowed_cidrs" text[],
|
|
"expires_at" timestamp with time zone,
|
|
"revoked_at" timestamp with time zone,
|
|
"created_by" uuid,
|
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
"last_used_at" timestamp with time zone,
|
|
"usage_count" bigint DEFAULT 0 NOT NULL
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE IF NOT EXISTS "audit_log" (
|
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
"actor_user_id" uuid,
|
|
"actor_token_id" uuid,
|
|
"action" text NOT NULL,
|
|
"target_type" text,
|
|
"target_id" text,
|
|
"metadata" jsonb,
|
|
"ip_address" "inet",
|
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE IF NOT EXISTS "notifications" (
|
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
"topic_id" uuid NOT NULL,
|
|
"source" text NOT NULL,
|
|
"title" text NOT NULL,
|
|
"message" text NOT NULL,
|
|
"external_url" text,
|
|
"image_url" text,
|
|
"attachment_filename" text,
|
|
"attachment_content_type" text,
|
|
"attachment_size_bytes" bigint,
|
|
"deduplication_key" text,
|
|
"occurrence_count" integer DEFAULT 1 NOT NULL,
|
|
"raw_priority" text,
|
|
"sender_token_id" uuid,
|
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE IF NOT EXISTS "push_delivery_attempts" (
|
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
"notification_id" uuid NOT NULL,
|
|
"push_subscription_id" uuid NOT NULL,
|
|
"status" "push_delivery_status" NOT NULL,
|
|
"http_status" integer,
|
|
"error_message" text,
|
|
"retry_count" integer DEFAULT 0 NOT NULL,
|
|
"attempted_at" timestamp with time zone DEFAULT now() NOT NULL
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE IF NOT EXISTS "push_subscriptions" (
|
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
"user_id" uuid NOT NULL,
|
|
"endpoint" text NOT NULL,
|
|
"p256dh" text NOT NULL,
|
|
"auth" text NOT NULL,
|
|
"user_agent" text,
|
|
"device_label" text,
|
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
"last_seen_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
"disabled_at" timestamp with time zone
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE IF NOT EXISTS "system_settings" (
|
|
"key" text PRIMARY KEY NOT NULL,
|
|
"value" jsonb NOT NULL,
|
|
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE IF NOT EXISTS "topic_members" (
|
|
"topic_id" uuid NOT NULL,
|
|
"user_id" uuid NOT NULL,
|
|
CONSTRAINT "topic_members_topic_id_user_id_pk" PRIMARY KEY("topic_id","user_id")
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE IF NOT EXISTS "topics" (
|
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
"slug" text NOT NULL,
|
|
"display_name" text NOT NULL,
|
|
"description" text,
|
|
"icon" text,
|
|
"accent_color" text,
|
|
"retention_days" integer,
|
|
"restricted" boolean DEFAULT false NOT NULL,
|
|
"created_by" uuid,
|
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
"archived_at" timestamp with time zone
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE IF NOT EXISTS "user_notification_state" (
|
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
"user_id" uuid NOT NULL,
|
|
"notification_id" uuid NOT NULL,
|
|
"read" boolean DEFAULT false NOT NULL,
|
|
"read_at" timestamp with time zone,
|
|
"starred" boolean DEFAULT false NOT NULL,
|
|
"starred_at" timestamp with time zone
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE IF NOT EXISTS "user_topic_subscriptions" (
|
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
"user_id" uuid NOT NULL,
|
|
"topic_id" uuid NOT NULL,
|
|
"push_enabled" boolean DEFAULT true NOT NULL,
|
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE IF NOT EXISTS "users" (
|
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
"email" text NOT NULL,
|
|
"display_name" text NOT NULL,
|
|
"avatar_url" text,
|
|
"role" "user_role" DEFAULT 'user' NOT NULL,
|
|
"auth_subject" text NOT NULL,
|
|
"auth_issuer" text,
|
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
"last_login_at" timestamp with time zone
|
|
);
|
|
--> statement-breakpoint
|
|
DO $$ BEGIN
|
|
ALTER TABLE "api_token_topics" ADD CONSTRAINT "api_token_topics_token_id_api_tokens_id_fk" FOREIGN KEY ("token_id") REFERENCES "public"."api_tokens"("id") ON DELETE cascade ON UPDATE no action;
|
|
EXCEPTION
|
|
WHEN duplicate_object THEN null;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
DO $$ BEGIN
|
|
ALTER TABLE "api_token_topics" ADD CONSTRAINT "api_token_topics_topic_id_topics_id_fk" FOREIGN KEY ("topic_id") REFERENCES "public"."topics"("id") ON DELETE cascade ON UPDATE no action;
|
|
EXCEPTION
|
|
WHEN duplicate_object THEN null;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
DO $$ BEGIN
|
|
ALTER TABLE "api_tokens" ADD CONSTRAINT "api_tokens_created_by_users_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;
|
|
EXCEPTION
|
|
WHEN duplicate_object THEN null;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
DO $$ BEGIN
|
|
ALTER TABLE "audit_log" ADD CONSTRAINT "audit_log_actor_user_id_users_id_fk" FOREIGN KEY ("actor_user_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;
|
|
EXCEPTION
|
|
WHEN duplicate_object THEN null;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
DO $$ BEGIN
|
|
ALTER TABLE "audit_log" ADD CONSTRAINT "audit_log_actor_token_id_api_tokens_id_fk" FOREIGN KEY ("actor_token_id") REFERENCES "public"."api_tokens"("id") ON DELETE set null ON UPDATE no action;
|
|
EXCEPTION
|
|
WHEN duplicate_object THEN null;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
DO $$ BEGIN
|
|
ALTER TABLE "notifications" ADD CONSTRAINT "notifications_topic_id_topics_id_fk" FOREIGN KEY ("topic_id") REFERENCES "public"."topics"("id") ON DELETE cascade ON UPDATE no action;
|
|
EXCEPTION
|
|
WHEN duplicate_object THEN null;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
DO $$ BEGIN
|
|
ALTER TABLE "notifications" ADD CONSTRAINT "notifications_sender_token_id_api_tokens_id_fk" FOREIGN KEY ("sender_token_id") REFERENCES "public"."api_tokens"("id") ON DELETE set null ON UPDATE no action;
|
|
EXCEPTION
|
|
WHEN duplicate_object THEN null;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
DO $$ BEGIN
|
|
ALTER TABLE "push_delivery_attempts" ADD CONSTRAINT "push_delivery_attempts_notification_id_notifications_id_fk" FOREIGN KEY ("notification_id") REFERENCES "public"."notifications"("id") ON DELETE cascade ON UPDATE no action;
|
|
EXCEPTION
|
|
WHEN duplicate_object THEN null;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
DO $$ BEGIN
|
|
ALTER TABLE "push_delivery_attempts" ADD CONSTRAINT "push_delivery_attempts_push_subscription_id_push_subscriptions_id_fk" FOREIGN KEY ("push_subscription_id") REFERENCES "public"."push_subscriptions"("id") ON DELETE cascade ON UPDATE no action;
|
|
EXCEPTION
|
|
WHEN duplicate_object THEN null;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
DO $$ BEGIN
|
|
ALTER TABLE "push_subscriptions" ADD CONSTRAINT "push_subscriptions_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;
|
|
EXCEPTION
|
|
WHEN duplicate_object THEN null;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
DO $$ BEGIN
|
|
ALTER TABLE "topic_members" ADD CONSTRAINT "topic_members_topic_id_topics_id_fk" FOREIGN KEY ("topic_id") REFERENCES "public"."topics"("id") ON DELETE cascade ON UPDATE no action;
|
|
EXCEPTION
|
|
WHEN duplicate_object THEN null;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
DO $$ BEGIN
|
|
ALTER TABLE "topic_members" ADD CONSTRAINT "topic_members_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;
|
|
EXCEPTION
|
|
WHEN duplicate_object THEN null;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
DO $$ BEGIN
|
|
ALTER TABLE "topics" ADD CONSTRAINT "topics_created_by_users_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;
|
|
EXCEPTION
|
|
WHEN duplicate_object THEN null;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
DO $$ BEGIN
|
|
ALTER TABLE "user_notification_state" ADD CONSTRAINT "user_notification_state_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;
|
|
EXCEPTION
|
|
WHEN duplicate_object THEN null;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
DO $$ BEGIN
|
|
ALTER TABLE "user_notification_state" ADD CONSTRAINT "user_notification_state_notification_id_notifications_id_fk" FOREIGN KEY ("notification_id") REFERENCES "public"."notifications"("id") ON DELETE cascade ON UPDATE no action;
|
|
EXCEPTION
|
|
WHEN duplicate_object THEN null;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
DO $$ BEGIN
|
|
ALTER TABLE "user_topic_subscriptions" ADD CONSTRAINT "user_topic_subscriptions_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;
|
|
EXCEPTION
|
|
WHEN duplicate_object THEN null;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
DO $$ BEGIN
|
|
ALTER TABLE "user_topic_subscriptions" ADD CONSTRAINT "user_topic_subscriptions_topic_id_topics_id_fk" FOREIGN KEY ("topic_id") REFERENCES "public"."topics"("id") ON DELETE cascade ON UPDATE no action;
|
|
EXCEPTION
|
|
WHEN duplicate_object THEN null;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "api_tokens_token_hash_key" ON "api_tokens" USING btree ("token_hash");--> statement-breakpoint
|
|
CREATE INDEX IF NOT EXISTS "audit_log_created_idx" ON "audit_log" USING btree ("created_at");--> statement-breakpoint
|
|
CREATE INDEX IF NOT EXISTS "audit_log_action_idx" ON "audit_log" USING btree ("action");--> statement-breakpoint
|
|
CREATE INDEX IF NOT EXISTS "notifications_topic_created_idx" ON "notifications" USING btree ("topic_id","created_at");--> statement-breakpoint
|
|
CREATE INDEX IF NOT EXISTS "notifications_dedup_idx" ON "notifications" USING btree ("deduplication_key","topic_id","created_at");--> statement-breakpoint
|
|
CREATE INDEX IF NOT EXISTS "notifications_created_idx" ON "notifications" USING btree ("created_at");--> statement-breakpoint
|
|
CREATE INDEX IF NOT EXISTS "push_delivery_attempts_notification_idx" ON "push_delivery_attempts" USING btree ("notification_id");--> statement-breakpoint
|
|
CREATE INDEX IF NOT EXISTS "push_delivery_attempts_subscription_idx" ON "push_delivery_attempts" USING btree ("push_subscription_id","attempted_at");--> statement-breakpoint
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "push_subscriptions_endpoint_key" ON "push_subscriptions" USING btree ("endpoint");--> statement-breakpoint
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "topics_slug_key" ON "topics" USING btree ("slug");--> statement-breakpoint
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "user_notification_state_user_notification_key" ON "user_notification_state" USING btree ("user_id","notification_id");--> statement-breakpoint
|
|
CREATE INDEX IF NOT EXISTS "user_notification_state_user_read_idx" ON "user_notification_state" USING btree ("user_id","read");--> statement-breakpoint
|
|
CREATE INDEX IF NOT EXISTS "user_notification_state_user_starred_idx" ON "user_notification_state" USING btree ("user_id","starred");--> statement-breakpoint
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "user_topic_subscriptions_user_topic_key" ON "user_topic_subscriptions" USING btree ("user_id","topic_id");--> statement-breakpoint
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "users_email_key" ON "users" USING btree ("email");--> statement-breakpoint
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "users_issuer_subject_key" ON "users" USING btree ("auth_issuer","auth_subject"); |