From cd068d58630eee0ebf8e2dceb4b25671ff3a9dd9 Mon Sep 17 00:00:00 2001 From: npmrun <1549469775@qq.com> Date: Sun, 12 Apr 2026 21:25:39 +0800 Subject: [PATCH] feat(db): auth schema and migrations Made-with: Cursor --- packages/drizzle-pkg/lib/schema/schema.ts | 74 ++++- packages/drizzle-pkg/migrations/0001_auth_user.sql | 32 +++ .../drizzle-pkg/migrations/meta/0001_snapshot.json | 306 +++++++++++++++++++++ packages/drizzle-pkg/migrations/meta/_journal.json | 7 + 4 files changed, 415 insertions(+), 4 deletions(-) create mode 100644 packages/drizzle-pkg/migrations/0001_auth_user.sql create mode 100644 packages/drizzle-pkg/migrations/meta/0001_snapshot.json diff --git a/packages/drizzle-pkg/lib/schema/schema.ts b/packages/drizzle-pkg/lib/schema/schema.ts index 0f15b51..548e500 100644 --- a/packages/drizzle-pkg/lib/schema/schema.ts +++ b/packages/drizzle-pkg/lib/schema/schema.ts @@ -1,8 +1,74 @@ -import { integer, pgTable, varchar } from "drizzle-orm/pg-core"; +import { + integer, + pgTable, + varchar, + timestamp, + text, + pgEnum, + uniqueIndex, + index, +} from "drizzle-orm/pg-core"; + +export const authChallengeTypeEnum = pgEnum("auth_challenge_type", [ + "email_verify", + "password_reset", +]); export const usersTable = pgTable("users_table", { id: integer().primaryKey().generatedAlwaysAsIdentity(), - name: varchar().notNull(), + name: varchar({ length: 255 }).notNull(), age: integer().notNull(), - email: varchar().notNull().unique(), -}); \ No newline at end of file + email: varchar({ length: 320 }).notNull().unique(), + passwordHash: text("password_hash").notNull(), + emailVerifiedAt: timestamp("email_verified_at", { + withTimezone: true, + }), + sessionVersion: integer("session_version").notNull().default(0), + createdAt: timestamp("created_at", { withTimezone: true }) + .notNull() + .defaultNow(), + updatedAt: timestamp("updated_at", { withTimezone: true }) + .notNull() + .defaultNow(), +}); + +export const authChallengesTable = pgTable( + "auth_challenges", + { + id: integer().primaryKey().generatedAlwaysAsIdentity(), + userId: integer("user_id") + .notNull() + .references(() => usersTable.id, { onDelete: "cascade" }), + type: authChallengeTypeEnum("type").notNull(), + tokenHash: varchar("token_hash", { length: 64 }).notNull(), + expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(), + consumedAt: timestamp("consumed_at", { withTimezone: true }), + createdAt: timestamp("created_at", { withTimezone: true }) + .notNull() + .defaultNow(), + }, + (t) => ({ + tokenHashIdx: index("auth_challenges_token_hash_idx").on(t.tokenHash), + }), +); + +export const linkedAccountsTable = pgTable( + "linked_accounts", + { + id: integer().primaryKey().generatedAlwaysAsIdentity(), + userId: integer("user_id") + .notNull() + .references(() => usersTable.id, { onDelete: "cascade" }), + provider: varchar({ length: 64 }).notNull(), + providerUserId: varchar("provider_user_id", { length: 255 }).notNull(), + createdAt: timestamp("created_at", { withTimezone: true }) + .notNull() + .defaultNow(), + }, + (t) => ({ + providerUserUnique: uniqueIndex("linked_accounts_provider_uid").on( + t.provider, + t.providerUserId, + ), + }), +); diff --git a/packages/drizzle-pkg/migrations/0001_auth_user.sql b/packages/drizzle-pkg/migrations/0001_auth_user.sql new file mode 100644 index 0000000..8213b33 --- /dev/null +++ b/packages/drizzle-pkg/migrations/0001_auth_user.sql @@ -0,0 +1,32 @@ +CREATE TYPE "public"."auth_challenge_type" AS ENUM('email_verify', 'password_reset');--> statement-breakpoint +CREATE TABLE "auth_challenges" ( + "id" integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "auth_challenges_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1), + "user_id" integer NOT NULL, + "type" "auth_challenge_type" NOT NULL, + "token_hash" varchar(64) NOT NULL, + "expires_at" timestamp with time zone NOT NULL, + "consumed_at" timestamp with time zone, + "created_at" timestamp with time zone DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "linked_accounts" ( + "id" integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "linked_accounts_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1), + "user_id" integer NOT NULL, + "provider" varchar(64) NOT NULL, + "provider_user_id" varchar(255) NOT NULL, + "created_at" timestamp with time zone DEFAULT now() NOT NULL +); +--> statement-breakpoint +ALTER TABLE "users_table" ALTER COLUMN "name" SET DATA TYPE varchar(255);--> statement-breakpoint +ALTER TABLE "users_table" ALTER COLUMN "email" SET DATA TYPE varchar(320);--> statement-breakpoint +ALTER TABLE "users_table" ADD COLUMN "password_hash" text;--> statement-breakpoint +UPDATE "users_table" SET "password_hash" = '$2b$10$eUiiFSTi9m98IWSuXJ80jun3VctJ0pKL44rRwvHT.9WOfxvc7r6Ey' WHERE "password_hash" IS NULL;--> statement-breakpoint +ALTER TABLE "users_table" ALTER COLUMN "password_hash" SET NOT NULL;--> statement-breakpoint +ALTER TABLE "users_table" ADD COLUMN "email_verified_at" timestamp with time zone;--> statement-breakpoint +ALTER TABLE "users_table" ADD COLUMN "session_version" integer DEFAULT 0 NOT NULL;--> statement-breakpoint +ALTER TABLE "users_table" ADD COLUMN "created_at" timestamp with time zone DEFAULT now() NOT NULL;--> statement-breakpoint +ALTER TABLE "users_table" ADD COLUMN "updated_at" timestamp with time zone DEFAULT now() NOT NULL;--> statement-breakpoint +ALTER TABLE "auth_challenges" ADD CONSTRAINT "auth_challenges_user_id_users_table_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users_table"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "linked_accounts" ADD CONSTRAINT "linked_accounts_user_id_users_table_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users_table"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +CREATE INDEX "auth_challenges_token_hash_idx" ON "auth_challenges" USING btree ("token_hash");--> statement-breakpoint +CREATE UNIQUE INDEX "linked_accounts_provider_uid" ON "linked_accounts" USING btree ("provider","provider_user_id"); \ No newline at end of file diff --git a/packages/drizzle-pkg/migrations/meta/0001_snapshot.json b/packages/drizzle-pkg/migrations/meta/0001_snapshot.json new file mode 100644 index 0000000..0becce7 --- /dev/null +++ b/packages/drizzle-pkg/migrations/meta/0001_snapshot.json @@ -0,0 +1,306 @@ +{ + "id": "d83420ac-013e-46cd-b8b4-82360fa63544", + "prevId": "ccacc841-1a4a-434b-bfaa-8d18a9a641b2", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.auth_challenges": { + "name": "auth_challenges", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "auth_challenges_id_seq", + "schema": "public", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "user_id": { + "name": "user_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "auth_challenge_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "token_hash": { + "name": "token_hash", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "consumed_at": { + "name": "consumed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "auth_challenges_token_hash_idx": { + "name": "auth_challenges_token_hash_idx", + "columns": [ + { + "expression": "token_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "auth_challenges_user_id_users_table_id_fk": { + "name": "auth_challenges_user_id_users_table_id_fk", + "tableFrom": "auth_challenges", + "tableTo": "users_table", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.linked_accounts": { + "name": "linked_accounts", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "linked_accounts_id_seq", + "schema": "public", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "user_id": { + "name": "user_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "provider_user_id": { + "name": "provider_user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "linked_accounts_provider_uid": { + "name": "linked_accounts_provider_uid", + "columns": [ + { + "expression": "provider", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "linked_accounts_user_id_users_table_id_fk": { + "name": "linked_accounts_user_id_users_table_id_fk", + "tableFrom": "linked_accounts", + "tableTo": "users_table", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.users_table": { + "name": "users_table", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "users_table_id_seq", + "schema": "public", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "age": { + "name": "age", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "varchar(320)", + "primaryKey": false, + "notNull": true + }, + "password_hash": { + "name": "password_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email_verified_at": { + "name": "email_verified_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "session_version": { + "name": "session_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "users_table_email_unique": { + "name": "users_table_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.auth_challenge_type": { + "name": "auth_challenge_type", + "schema": "public", + "values": [ + "email_verify", + "password_reset" + ] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/packages/drizzle-pkg/migrations/meta/_journal.json b/packages/drizzle-pkg/migrations/meta/_journal.json index 1822e99..08f4116 100644 --- a/packages/drizzle-pkg/migrations/meta/_journal.json +++ b/packages/drizzle-pkg/migrations/meta/_journal.json @@ -8,6 +8,13 @@ "when": 1775935934813, "tag": "0000_init", "breakpoints": true + }, + { + "idx": 1, + "version": "7", + "when": 1776000315737, + "tag": "0001_auth_user", + "breakpoints": true } ] } \ No newline at end of file