diff --git a/backend/services/identity-service/prisma/migrations/.gitkeep b/backend/services/identity-service/prisma/migrations/.gitkeep deleted file mode 100644 index b87434af..00000000 --- a/backend/services/identity-service/prisma/migrations/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -# Prisma migrations will be stored here diff --git a/backend/services/identity-service/prisma/migrations/20241204000000_init/migration.sql b/backend/services/identity-service/prisma/migrations/20241204000000_init/migration.sql new file mode 100644 index 00000000..20f391e1 --- /dev/null +++ b/backend/services/identity-service/prisma/migrations/20241204000000_init/migration.sql @@ -0,0 +1,317 @@ +-- CreateTable +CREATE TABLE "user_accounts" ( + "user_id" BIGSERIAL NOT NULL, + "account_sequence" BIGINT NOT NULL, + "phone_number" VARCHAR(20), + "nickname" VARCHAR(100) NOT NULL, + "avatar_url" VARCHAR(500), + "inviter_sequence" BIGINT, + "referral_code" VARCHAR(10) NOT NULL, + "province_code" VARCHAR(10) NOT NULL, + "city_code" VARCHAR(10) NOT NULL, + "address" VARCHAR(500), + "kyc_status" VARCHAR(20) NOT NULL DEFAULT 'NOT_VERIFIED', + "real_name" VARCHAR(100), + "id_card_number" VARCHAR(20), + "id_card_front_url" VARCHAR(500), + "id_card_back_url" VARCHAR(500), + "kyc_verified_at" TIMESTAMP(3), + "status" VARCHAR(20) NOT NULL DEFAULT 'ACTIVE', + "registered_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "last_login_at" TIMESTAMP(3), + "updated_at" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "user_accounts_pkey" PRIMARY KEY ("user_id") +); + +-- CreateTable +CREATE TABLE "user_devices" ( + "id" BIGSERIAL NOT NULL, + "user_id" BIGINT NOT NULL, + "device_id" VARCHAR(100) NOT NULL, + "device_name" VARCHAR(100), + "added_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "last_active_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "user_devices_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "wallet_addresses" ( + "address_id" BIGSERIAL NOT NULL, + "user_id" BIGINT NOT NULL, + "chain_type" VARCHAR(20) NOT NULL, + "address" VARCHAR(100) NOT NULL, + "public_key" VARCHAR(130) NOT NULL, + "address_digest" VARCHAR(66) NOT NULL, + "mpc_signature_r" VARCHAR(66) NOT NULL, + "mpc_signature_s" VARCHAR(66) NOT NULL, + "mpc_signature_v" INTEGER NOT NULL, + "status" VARCHAR(20) NOT NULL DEFAULT 'ACTIVE', + "bound_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "wallet_addresses_pkey" PRIMARY KEY ("address_id") +); + +-- CreateTable +CREATE TABLE "account_sequence_generator" ( + "id" INTEGER NOT NULL DEFAULT 1, + "current_sequence" BIGINT NOT NULL DEFAULT 0, + "updated_at" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "account_sequence_generator_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "user_events" ( + "event_id" BIGSERIAL NOT NULL, + "event_type" VARCHAR(50) NOT NULL, + "aggregate_id" VARCHAR(100) NOT NULL, + "aggregate_type" VARCHAR(50) NOT NULL, + "event_data" JSONB NOT NULL, + "user_id" BIGINT, + "occurred_at" TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "version" INTEGER NOT NULL DEFAULT 1, + + CONSTRAINT "user_events_pkey" PRIMARY KEY ("event_id") +); + +-- CreateTable +CREATE TABLE "device_tokens" ( + "id" BIGSERIAL NOT NULL, + "user_id" BIGINT NOT NULL, + "device_id" VARCHAR(100) NOT NULL, + "refresh_token_hash" VARCHAR(64) NOT NULL, + "expires_at" TIMESTAMP(3) NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "revoked_at" TIMESTAMP(3), + + CONSTRAINT "device_tokens_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "dead_letter_events" ( + "id" BIGSERIAL NOT NULL, + "topic" VARCHAR(100) NOT NULL, + "event_id" VARCHAR(100) NOT NULL, + "event_type" VARCHAR(50) NOT NULL, + "aggregate_id" VARCHAR(100) NOT NULL, + "aggregate_type" VARCHAR(50) NOT NULL, + "payload" JSONB, + "error_message" TEXT NOT NULL, + "error_stack" TEXT, + "retry_count" INTEGER NOT NULL DEFAULT 0, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "processed_at" TIMESTAMP(3), + + CONSTRAINT "dead_letter_events_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "sms_codes" ( + "id" BIGSERIAL NOT NULL, + "phone_number" VARCHAR(20) NOT NULL, + "code" VARCHAR(10) NOT NULL, + "purpose" VARCHAR(50) NOT NULL, + "expires_at" TIMESTAMP(3) NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "used_at" TIMESTAMP(3), + + CONSTRAINT "sms_codes_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "mpc_key_shares" ( + "share_id" BIGSERIAL NOT NULL, + "user_id" BIGINT NOT NULL, + "public_key" VARCHAR(130) NOT NULL, + "party_index" INTEGER NOT NULL, + "threshold" INTEGER NOT NULL DEFAULT 2, + "total_parties" INTEGER NOT NULL DEFAULT 3, + "encrypted_share_data" TEXT NOT NULL, + "status" VARCHAR(20) NOT NULL DEFAULT 'ACTIVE', + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "rotated_at" TIMESTAMP(3), + + CONSTRAINT "mpc_key_shares_pkey" PRIMARY KEY ("share_id") +); + +-- CreateTable +CREATE TABLE "mpc_sessions" ( + "session_id" VARCHAR(50) NOT NULL, + "session_type" VARCHAR(20) NOT NULL, + "user_id" BIGINT, + "public_key" VARCHAR(130), + "status" VARCHAR(20) NOT NULL DEFAULT 'PENDING', + "error_message" TEXT, + "message_hash" VARCHAR(66), + "signature_r" VARCHAR(66), + "signature_s" VARCHAR(66), + "signature_v" INTEGER, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "completed_at" TIMESTAMP(3), + + CONSTRAINT "mpc_sessions_pkey" PRIMARY KEY ("session_id") +); + +-- CreateTable +CREATE TABLE "referral_links" ( + "link_id" BIGSERIAL NOT NULL, + "user_id" BIGINT NOT NULL, + "referral_code" VARCHAR(10) NOT NULL, + "short_code" VARCHAR(10) NOT NULL, + "channel" VARCHAR(50), + "campaign_id" VARCHAR(50), + "click_count" INTEGER NOT NULL DEFAULT 0, + "register_count" INTEGER NOT NULL DEFAULT 0, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "expires_at" TIMESTAMP(3), + + CONSTRAINT "referral_links_pkey" PRIMARY KEY ("link_id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "user_accounts_account_sequence_key" ON "user_accounts"("account_sequence"); + +-- CreateIndex +CREATE UNIQUE INDEX "user_accounts_phone_number_key" ON "user_accounts"("phone_number"); + +-- CreateIndex +CREATE UNIQUE INDEX "user_accounts_referral_code_key" ON "user_accounts"("referral_code"); + +-- CreateIndex +CREATE INDEX "idx_phone" ON "user_accounts"("phone_number"); + +-- CreateIndex +CREATE INDEX "idx_sequence" ON "user_accounts"("account_sequence"); + +-- CreateIndex +CREATE INDEX "idx_referral_code" ON "user_accounts"("referral_code"); + +-- CreateIndex +CREATE INDEX "idx_inviter" ON "user_accounts"("inviter_sequence"); + +-- CreateIndex +CREATE INDEX "idx_province_city" ON "user_accounts"("province_code", "city_code"); + +-- CreateIndex +CREATE INDEX "idx_kyc_status" ON "user_accounts"("kyc_status"); + +-- CreateIndex +CREATE INDEX "idx_status" ON "user_accounts"("status"); + +-- CreateIndex +CREATE INDEX "idx_device" ON "user_devices"("device_id"); + +-- CreateIndex +CREATE INDEX "idx_user" ON "user_devices"("user_id"); + +-- CreateIndex +CREATE INDEX "idx_last_active" ON "user_devices"("last_active_at"); + +-- CreateIndex +CREATE UNIQUE INDEX "uk_user_device" ON "user_devices"("user_id", "device_id"); + +-- CreateIndex +CREATE INDEX "idx_wallet_user" ON "wallet_addresses"("user_id"); + +-- CreateIndex +CREATE INDEX "idx_address" ON "wallet_addresses"("address"); + +-- CreateIndex +CREATE INDEX "idx_public_key" ON "wallet_addresses"("public_key"); + +-- CreateIndex +CREATE UNIQUE INDEX "uk_user_chain" ON "wallet_addresses"("user_id", "chain_type"); + +-- CreateIndex +CREATE UNIQUE INDEX "uk_chain_address" ON "wallet_addresses"("chain_type", "address"); + +-- CreateIndex +CREATE INDEX "idx_aggregate" ON "user_events"("aggregate_type", "aggregate_id"); + +-- CreateIndex +CREATE INDEX "idx_event_type" ON "user_events"("event_type"); + +-- CreateIndex +CREATE INDEX "idx_event_user" ON "user_events"("user_id"); + +-- CreateIndex +CREATE INDEX "idx_occurred" ON "user_events"("occurred_at"); + +-- CreateIndex +CREATE UNIQUE INDEX "device_tokens_refresh_token_hash_key" ON "device_tokens"("refresh_token_hash"); + +-- CreateIndex +CREATE INDEX "idx_user_device_token" ON "device_tokens"("user_id", "device_id"); + +-- CreateIndex +CREATE INDEX "idx_expires" ON "device_tokens"("expires_at"); + +-- CreateIndex +CREATE INDEX "idx_topic" ON "dead_letter_events"("topic"); + +-- CreateIndex +CREATE INDEX "idx_dead_letter_event_type" ON "dead_letter_events"("event_type"); + +-- CreateIndex +CREATE INDEX "idx_dead_letter_created" ON "dead_letter_events"("created_at"); + +-- CreateIndex +CREATE INDEX "idx_processed" ON "dead_letter_events"("processed_at"); + +-- CreateIndex +CREATE INDEX "idx_phone_purpose" ON "sms_codes"("phone_number", "purpose"); + +-- CreateIndex +CREATE INDEX "idx_sms_expires" ON "sms_codes"("expires_at"); + +-- CreateIndex +CREATE UNIQUE INDEX "mpc_key_shares_user_id_key" ON "mpc_key_shares"("user_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "mpc_key_shares_public_key_key" ON "mpc_key_shares"("public_key"); + +-- CreateIndex +CREATE INDEX "idx_mpc_public_key" ON "mpc_key_shares"("public_key"); + +-- CreateIndex +CREATE INDEX "idx_mpc_status" ON "mpc_key_shares"("status"); + +-- CreateIndex +CREATE INDEX "idx_session_type" ON "mpc_sessions"("session_type"); + +-- CreateIndex +CREATE INDEX "idx_session_user" ON "mpc_sessions"("user_id"); + +-- CreateIndex +CREATE INDEX "idx_session_status" ON "mpc_sessions"("status"); + +-- CreateIndex +CREATE INDEX "idx_session_created" ON "mpc_sessions"("created_at"); + +-- CreateIndex +CREATE UNIQUE INDEX "referral_links_short_code_key" ON "referral_links"("short_code"); + +-- CreateIndex +CREATE INDEX "idx_referral_link_user" ON "referral_links"("user_id"); + +-- CreateIndex +CREATE INDEX "idx_referral_link_code" ON "referral_links"("referral_code"); + +-- CreateIndex +CREATE INDEX "idx_referral_link_channel" ON "referral_links"("channel"); + +-- CreateIndex +CREATE INDEX "idx_referral_link_created" ON "referral_links"("created_at"); + +-- AddForeignKey +ALTER TABLE "user_devices" ADD CONSTRAINT "user_devices_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "user_accounts"("user_id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "wallet_addresses" ADD CONSTRAINT "wallet_addresses_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "user_accounts"("user_id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- Initialize sequence generator +INSERT INTO "account_sequence_generator" ("id", "current_sequence", "updated_at") +VALUES (1, 0, CURRENT_TIMESTAMP) +ON CONFLICT ("id") DO NOTHING;