refactor: test migrastion

This commit is contained in:
Mauricio Siu
2025-02-12 23:41:04 -06:00
parent 8f562eefc1
commit 60eee55f2d
20 changed files with 978 additions and 443 deletions

View File

@@ -0,0 +1,153 @@
CREATE TABLE "user_temp" (
"id" text PRIMARY KEY NOT NULL,
"name" text DEFAULT '' NOT NULL,
"token" text NOT NULL,
"isRegistered" boolean DEFAULT false NOT NULL,
"expirationDate" text NOT NULL,
"createdAt" text NOT NULL,
"canCreateProjects" boolean DEFAULT false NOT NULL,
"canAccessToSSHKeys" boolean DEFAULT false NOT NULL,
"canCreateServices" boolean DEFAULT false NOT NULL,
"canDeleteProjects" boolean DEFAULT false NOT NULL,
"canDeleteServices" boolean DEFAULT false NOT NULL,
"canAccessToDocker" boolean DEFAULT false NOT NULL,
"canAccessToAPI" boolean DEFAULT false NOT NULL,
"canAccessToGitProviders" boolean DEFAULT false NOT NULL,
"canAccessToTraefikFiles" boolean DEFAULT false NOT NULL,
"accesedProjects" text[] DEFAULT ARRAY[]::text[] NOT NULL,
"accesedServices" text[] DEFAULT ARRAY[]::text[] NOT NULL,
"email" text NOT NULL,
"email_verified" boolean NOT NULL,
"image" text,
"role" text,
"banned" boolean,
"ban_reason" text,
"ban_expires" timestamp,
"updated_at" timestamp NOT NULL,
"serverIp" text,
"certificateType" "certificateType" DEFAULT 'none' NOT NULL,
"host" text,
"letsEncryptEmail" text,
"sshPrivateKey" text,
"enableDockerCleanup" boolean DEFAULT false NOT NULL,
"enableLogRotation" boolean DEFAULT false NOT NULL,
"enablePaidFeatures" boolean DEFAULT false NOT NULL,
"metricsConfig" jsonb DEFAULT '{"server":{"type":"Dokploy","refreshRate":60,"port":4500,"token":"","retentionDays":2,"cronJob":"","urlCallback":"","thresholds":{"cpu":0,"memory":0}},"containers":{"refreshRate":60,"services":{"include":[],"exclude":[]}}}'::jsonb NOT NULL,
"cleanupCacheApplications" boolean DEFAULT false NOT NULL,
"cleanupCacheOnPreviews" boolean DEFAULT false NOT NULL,
"cleanupCacheOnCompose" boolean DEFAULT false NOT NULL,
"stripeCustomerId" text,
"stripeSubscriptionId" text,
"serversQuantity" integer DEFAULT 0 NOT NULL,
CONSTRAINT "user_temp_email_unique" UNIQUE("email")
);
--> statement-breakpoint
CREATE TABLE "session_temp" (
"id" text PRIMARY KEY NOT NULL,
"expires_at" timestamp NOT NULL,
"token" text NOT NULL,
"created_at" timestamp NOT NULL,
"updated_at" timestamp NOT NULL,
"ip_address" text,
"user_agent" text,
"user_id" text NOT NULL,
"impersonated_by" text,
"active_organization_id" text,
CONSTRAINT "session_temp_token_unique" UNIQUE("token")
);
--> statement-breakpoint
CREATE TABLE "account" (
"id" text PRIMARY KEY NOT NULL,
"account_id" text NOT NULL,
"provider_id" text NOT NULL,
"user_id" text NOT NULL,
"access_token" text,
"refresh_token" text,
"id_token" text,
"access_token_expires_at" timestamp,
"refresh_token_expires_at" timestamp,
"scope" text,
"password" text,
"is2FAEnabled" boolean DEFAULT false NOT NULL,
"created_at" timestamp NOT NULL,
"updated_at" timestamp NOT NULL,
"resetPasswordToken" text,
"resetPasswordExpiresAt" text,
"confirmationToken" text,
"confirmationExpiresAt" text
);
--> statement-breakpoint
CREATE TABLE "invitation" (
"id" text PRIMARY KEY NOT NULL,
"organization_id" text NOT NULL,
"email" text NOT NULL,
"role" text,
"status" text NOT NULL,
"expires_at" timestamp NOT NULL,
"inviter_id" text NOT NULL
);
--> statement-breakpoint
CREATE TABLE "member" (
"id" text PRIMARY KEY NOT NULL,
"organization_id" text NOT NULL,
"user_id" text NOT NULL,
"role" text NOT NULL,
"created_at" timestamp NOT NULL
);
--> statement-breakpoint
CREATE TABLE "organization" (
"id" text PRIMARY KEY NOT NULL,
"name" text NOT NULL,
"slug" text,
"logo" text,
"created_at" timestamp NOT NULL,
"metadata" text,
"owner_id" text NOT NULL,
CONSTRAINT "organization_slug_unique" UNIQUE("slug")
);
--> statement-breakpoint
CREATE TABLE "verification" (
"id" text PRIMARY KEY NOT NULL,
"identifier" text NOT NULL,
"value" text NOT NULL,
"expires_at" timestamp NOT NULL,
"created_at" timestamp,
"updated_at" timestamp
);
--> statement-breakpoint
ALTER TABLE "project" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
ALTER TABLE "destination" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
ALTER TABLE "certificate" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
ALTER TABLE "registry" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
ALTER TABLE "notification" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
ALTER TABLE "git_provider" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
ALTER TABLE "server" RENAME COLUMN "adminId" TO "userId";--> statement-breakpoint
ALTER TABLE "project" DROP CONSTRAINT "project_adminId_admin_adminId_fk";
--> statement-breakpoint
ALTER TABLE "destination" DROP CONSTRAINT "destination_adminId_admin_adminId_fk";
--> statement-breakpoint
ALTER TABLE "certificate" DROP CONSTRAINT "certificate_adminId_admin_adminId_fk";
--> statement-breakpoint
ALTER TABLE "registry" DROP CONSTRAINT "registry_adminId_admin_adminId_fk";
--> statement-breakpoint
ALTER TABLE "notification" DROP CONSTRAINT "notification_adminId_admin_adminId_fk";
--> statement-breakpoint
ALTER TABLE "git_provider" DROP CONSTRAINT "git_provider_adminId_admin_adminId_fk";
--> statement-breakpoint
ALTER TABLE "server" DROP CONSTRAINT "server_adminId_admin_adminId_fk";
--> statement-breakpoint
ALTER TABLE "ssh-key" ALTER COLUMN "adminId" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "session_temp" ADD CONSTRAINT "session_temp_user_id_user_temp_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user_temp"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "account" ADD CONSTRAINT "account_user_id_user_temp_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user_temp"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "invitation" ADD CONSTRAINT "invitation_organization_id_organization_id_fk" FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "invitation" ADD CONSTRAINT "invitation_inviter_id_user_temp_id_fk" FOREIGN KEY ("inviter_id") REFERENCES "public"."user_temp"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "member" ADD CONSTRAINT "member_organization_id_organization_id_fk" FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "member" ADD CONSTRAINT "member_user_id_user_temp_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user_temp"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "organization" ADD CONSTRAINT "organization_owner_id_user_temp_id_fk" FOREIGN KEY ("owner_id") REFERENCES "public"."user_temp"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "project" ADD CONSTRAINT "project_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "destination" ADD CONSTRAINT "destination_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "certificate" ADD CONSTRAINT "certificate_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "registry" ADD CONSTRAINT "registry_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "notification" ADD CONSTRAINT "notification_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "git_provider" ADD CONSTRAINT "git_provider_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "server" ADD CONSTRAINT "server_userId_user_temp_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user_temp"("id") ON DELETE cascade ON UPDATE no action;

View File

@@ -1,187 +0,0 @@
-- Create new tables
CREATE TABLE IF NOT EXISTS "account" (
"id" text PRIMARY KEY NOT NULL,
"accountId" text NOT NULL,
"providerId" text NOT NULL,
"userId" text NOT NULL REFERENCES "user"("userId"),
"accessToken" text,
"refreshToken" text,
"idToken" text,
"accessTokenExpiresAt" timestamp,
"refreshTokenExpiresAt" timestamp,
"scope" text,
"password" text,
"is2FAEnabled" boolean DEFAULT false NOT NULL,
"createdAt" timestamp NOT NULL,
"updatedAt" timestamp NOT NULL,
"resetPasswordToken" text,
"resetPasswordExpiresAt" text,
"confirmationToken" text,
"confirmationExpiresAt" text
);
CREATE TABLE IF NOT EXISTS "organization" (
"id" text PRIMARY KEY NOT NULL,mn cj.
"name" text NOT NULL,
"slug" text,
"logo" text,
"createdAt" timestamp NOT NULL,
"metadata" text,
"ownerId" text NOT NULL REFERENCES "user"("userId"),
CONSTRAINT "organization_slug_unique" UNIQUE("slug")
);
CREATE TABLE IF NOT EXISTS "member" (
"id" text PRIMARY KEY NOT NULL,
"organizationId" text NOT NULL REFERENCES "organization"("id"),
"userId" text NOT NULL REFERENCES "user"("userId"),
"role" text NOT NULL,
"createdAt" timestamp NOT NULL
);
CREATE TABLE IF NOT EXISTS "invitation" (
"id" text PRIMARY KEY NOT NULL,
"organizationId" text NOT NULL,
"email" text NOT NULL,
"role" text,
"status" text NOT NULL,
"expiresAt" timestamp NOT NULL,
"inviterId" text NOT NULL
);
CREATE TABLE IF NOT EXISTS "verification" (
"id" text PRIMARY KEY NOT NULL,
"identifier" text NOT NULL,
"value" text NOT NULL,
"expiresAt" timestamp NOT NULL,
"createdAt" timestamp,
"updatedAt" timestamp
);
-- Alter existing user table to add new columns
ALTER TABLE "user"
ADD COLUMN IF NOT EXISTS "email" text,
ADD COLUMN IF NOT EXISTS "emailVerified" boolean DEFAULT false,
ADD COLUMN IF NOT EXISTS "role" text,
ADD COLUMN IF NOT EXISTS "certificateType" text DEFAULT 'none',
ADD COLUMN IF NOT EXISTS "serverIp" text,
ADD COLUMN IF NOT EXISTS "host" text,
ADD COLUMN IF NOT EXISTS "letsEncryptEmail" text,
ADD COLUMN IF NOT EXISTS "sshPrivateKey" text,
ADD COLUMN IF NOT EXISTS "enableDockerCleanup" boolean DEFAULT false,
ADD COLUMN IF NOT EXISTS "enableLogRotation" boolean DEFAULT false,
ADD COLUMN IF NOT EXISTS "enablePaidFeatures" boolean DEFAULT false,
ADD COLUMN IF NOT EXISTS "metricsConfig" jsonb DEFAULT '{}',
ADD COLUMN IF NOT EXISTS "cleanupCacheApplications" boolean DEFAULT false,
ADD COLUMN IF NOT EXISTS "cleanupCacheOnPreviews" boolean DEFAULT false,
ADD COLUMN IF NOT EXISTS "cleanupCacheOnCompose" boolean DEFAULT false,
ADD COLUMN IF NOT EXISTS "stripeCustomerId" text,
ADD COLUMN IF NOT EXISTS "stripeSubscriptionId" text,
ADD COLUMN IF NOT EXISTS "serversQuantity" integer DEFAULT 0;
-- Migrate email from auth table to user table
UPDATE "user" u
SET "email" = a."email"
FROM "auth" a
WHERE a."id" = u."userId";
-- Migrate admin users
WITH admin_users AS (
UPDATE "user" u
SET
"emailVerified" = true,
"role" = 'admin',
"token" = a."token",
"certificateType" = adm."certificateType",
"serverIp" = adm."serverIp",
"host" = adm."host",
"letsEncryptEmail" = adm."letsEncryptEmail",
"sshPrivateKey" = adm."sshPrivateKey",
"enableDockerCleanup" = adm."enableDockerCleanup",
"enableLogRotation" = adm."enableLogRotation",
"enablePaidFeatures" = adm."enablePaidFeatures",
"metricsConfig" = adm."metricsConfig",
"cleanupCacheApplications" = adm."cleanupCacheApplications",
"cleanupCacheOnPreviews" = adm."cleanupCacheOnPreviews",
"cleanupCacheOnCompose" = adm."cleanupCacheOnCompose",
"stripeCustomerId" = adm."stripeCustomerId",
"stripeSubscriptionId" = adm."stripeSubscriptionId",
"serversQuantity" = adm."serversQuantity"
FROM "auth" a
INNER JOIN "admin" adm ON a."id" = adm."adminId"
WHERE a."id" = u."userId"
RETURNING u."userId", u."email"
)
INSERT INTO "account" ("id", "accountId", "providerId", "password", "userId", "createdAt", "updatedAt")
SELECT
gen_random_uuid(),
a."id",
'credentials',
a."password",
au."userId",
NOW(),
NOW()
FROM "auth" a
INNER JOIN admin_users au ON a."email" = au."email";
-- Create organizations for admin users
WITH admin_orgs AS (
INSERT INTO "organization" ("id", "name", "slug", "createdAt", "ownerId")
SELECT
gen_random_uuid(),
'My Organization',
concat('org/', u."userId"),
NOW(),
u."userId"
FROM "user" u
WHERE u."role" = 'admin'
RETURNING *
)
-- Migrate regular users
UPDATE "user" u
SET
"emailVerified" = true,
"role" = 'user',
"token" = a."token",
"canCreateProjects" = usr."canCreateProjects",
"canAccessToSSHKeys" = usr."canAccessToSSHKeys"
FROM "auth" a
INNER JOIN "user" usr ON a."id" = usr."userId"
WHERE a."id" = u."userId"
AND NOT EXISTS (
SELECT 1 FROM "admin" adm WHERE a."id" = adm."adminId"
);
-- Create accounts for regular users
INSERT INTO "account" ("id", "accountId", "providerId", "password", "userId", "createdAt", "updatedAt")
SELECT
gen_random_uuid(),
a."id",
'credentials',
a."password",
u."userId",
NOW(),
NOW()
FROM "auth" a
INNER JOIN "user" u ON a."email" = u."email"
WHERE u."role" = 'user';
-- Create member relationships
INSERT INTO "member" ("id", "organizationId", "role", "userId", "createdAt")
SELECT
gen_random_uuid(),
o."id",
'user',
u."userId",
NOW()
FROM "user" usr
INNER JOIN "user" u ON usr."userId" = u."userId"
INNER JOIN "admin" adm ON usr."adminId" = adm."adminId"
INNER JOIN "user" admin_u ON adm."adminId" = admin_u."userId"
INNER JOIN "organization" o ON o."ownerId" = admin_u."userId"
WHERE u."role" = 'user';
-- Drop old tables (after all data is migrated)
DROP TABLE IF EXISTS "sessionTable" CASCADE;
DROP TABLE IF EXISTS "admin" CASCADE;
DROP TABLE IF EXISTS "auth" CASCADE;

View File

@@ -1,5 +1,5 @@
{
"id": "d76ab830-b647-4e53-b6cc-0cf515968758",
"id": "de382c48-6f10-4578-a307-884fecb4baa3",
"prevId": "1240ec96-1751-4de3-b64f-cef9cb716786",
"version": "7",
"dialect": "postgresql",
@@ -741,6 +741,166 @@
"primaryKey": true,
"notNull": true
},
"token": {
"name": "token",
"type": "text",
"primaryKey": false,
"notNull": true
},
"isRegistered": {
"name": "isRegistered",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"expirationDate": {
"name": "expirationDate",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "text",
"primaryKey": false,
"notNull": true
},
"canCreateProjects": {
"name": "canCreateProjects",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"canAccessToSSHKeys": {
"name": "canAccessToSSHKeys",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"canCreateServices": {
"name": "canCreateServices",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"canDeleteProjects": {
"name": "canDeleteProjects",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"canDeleteServices": {
"name": "canDeleteServices",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"canAccessToDocker": {
"name": "canAccessToDocker",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"canAccessToAPI": {
"name": "canAccessToAPI",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"canAccessToGitProviders": {
"name": "canAccessToGitProviders",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"canAccessToTraefikFiles": {
"name": "canAccessToTraefikFiles",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"accesedProjects": {
"name": "accesedProjects",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "ARRAY[]::text[]"
},
"accesedServices": {
"name": "accesedServices",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "ARRAY[]::text[]"
},
"adminId": {
"name": "adminId",
"type": "text",
"primaryKey": false,
"notNull": true
},
"authId": {
"name": "authId",
"type": "text",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"user_adminId_admin_adminId_fk": {
"name": "user_adminId_admin_adminId_fk",
"tableFrom": "user",
"tableTo": "admin",
"columnsFrom": [
"adminId"
],
"columnsTo": [
"adminId"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"user_authId_auth_id_fk": {
"name": "user_authId_auth_id_fk",
"tableFrom": "user",
"tableTo": "auth",
"columnsFrom": [
"authId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.user_temp": {
"name": "user_temp",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
@@ -1003,8 +1163,8 @@
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"user_email_unique": {
"name": "user_email_unique",
"user_temp_email_unique": {
"name": "user_temp_email_unique",
"nullsNotDistinct": false,
"columns": [
"email"
@@ -1018,9 +1178,142 @@
"public.admin": {
"name": "admin",
"schema": "",
"columns": {},
"columns": {
"adminId": {
"name": "adminId",
"type": "text",
"primaryKey": true,
"notNull": true
},
"serverIp": {
"name": "serverIp",
"type": "text",
"primaryKey": false,
"notNull": false
},
"certificateType": {
"name": "certificateType",
"type": "certificateType",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'none'"
},
"host": {
"name": "host",
"type": "text",
"primaryKey": false,
"notNull": false
},
"letsEncryptEmail": {
"name": "letsEncryptEmail",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sshPrivateKey": {
"name": "sshPrivateKey",
"type": "text",
"primaryKey": false,
"notNull": false
},
"enableDockerCleanup": {
"name": "enableDockerCleanup",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"enableLogRotation": {
"name": "enableLogRotation",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"authId": {
"name": "authId",
"type": "text",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "text",
"primaryKey": false,
"notNull": true
},
"stripeCustomerId": {
"name": "stripeCustomerId",
"type": "text",
"primaryKey": false,
"notNull": false
},
"stripeSubscriptionId": {
"name": "stripeSubscriptionId",
"type": "text",
"primaryKey": false,
"notNull": false
},
"serversQuantity": {
"name": "serversQuantity",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"enablePaidFeatures": {
"name": "enablePaidFeatures",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"metricsConfig": {
"name": "metricsConfig",
"type": "jsonb",
"primaryKey": false,
"notNull": true,
"default": "'{\"server\":{\"type\":\"Dokploy\",\"refreshRate\":60,\"port\":4500,\"token\":\"\",\"retentionDays\":2,\"cronJob\":\"\",\"urlCallback\":\"\",\"thresholds\":{\"cpu\":0,\"memory\":0}},\"containers\":{\"refreshRate\":60,\"services\":{\"include\":[],\"exclude\":[]}}}'::jsonb"
},
"cleanupCacheApplications": {
"name": "cleanupCacheApplications",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"cleanupCacheOnPreviews": {
"name": "cleanupCacheOnPreviews",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"cleanupCacheOnCompose": {
"name": "cleanupCacheOnCompose",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
}
},
"indexes": {},
"foreignKeys": {},
"foreignKeys": {
"admin_authId_auth_id_fk": {
"name": "admin_authId_auth_id_fk",
"tableFrom": "admin",
"tableTo": "auth",
"columnsFrom": [
"authId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
@@ -1172,15 +1465,15 @@
},
"indexes": {},
"foreignKeys": {
"project_userId_user_userId_fk": {
"name": "project_userId_user_userId_fk",
"project_userId_user_temp_id_fk": {
"name": "project_userId_user_temp_id_fk",
"tableFrom": "project",
"tableTo": "user",
"tableTo": "user_temp",
"columnsFrom": [
"userId"
],
"columnsTo": [
"userId"
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
@@ -2042,15 +2335,15 @@
},
"indexes": {},
"foreignKeys": {
"destination_userId_user_userId_fk": {
"name": "destination_userId_user_userId_fk",
"destination_userId_user_temp_id_fk": {
"name": "destination_userId_user_temp_id_fk",
"tableFrom": "destination",
"tableTo": "user",
"tableTo": "user_temp",
"columnsFrom": [
"userId"
],
"columnsTo": [
"userId"
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
@@ -2445,7 +2738,7 @@
"name": "userId",
"type": "text",
"primaryKey": false,
"notNull": false
"notNull": true
},
"serverId": {
"name": "serverId",
@@ -2456,15 +2749,15 @@
},
"indexes": {},
"foreignKeys": {
"certificate_userId_user_userId_fk": {
"name": "certificate_userId_user_userId_fk",
"certificate_userId_user_temp_id_fk": {
"name": "certificate_userId_user_temp_id_fk",
"tableFrom": "certificate",
"tableTo": "user",
"tableTo": "user_temp",
"columnsFrom": [
"userId"
],
"columnsTo": [
"userId"
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
@@ -2497,8 +2790,8 @@
"checkConstraints": {},
"isRLSEnabled": false
},
"public.session": {
"name": "session",
"public.session_temp": {
"name": "session_temp",
"schema": "",
"columns": {
"id": {
@@ -2513,6 +2806,12 @@
"primaryKey": false,
"notNull": true
},
"token": {
"name": "token",
"type": "text",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
@@ -2558,21 +2857,74 @@
},
"indexes": {},
"foreignKeys": {
"session_user_id_user_userId_fk": {
"name": "session_user_id_user_userId_fk",
"tableFrom": "session",
"tableTo": "user",
"session_temp_user_id_user_temp_id_fk": {
"name": "session_temp_user_id_user_temp_id_fk",
"tableFrom": "session_temp",
"tableTo": "user_temp",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"userId"
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"session_temp_token_unique": {
"name": "session_temp_token_unique",
"nullsNotDistinct": false,
"columns": [
"token"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.session": {
"name": "session",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"expires_at": {
"name": "expires_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"session_user_id_auth_id_fk": {
"name": "session_user_id_auth_id_fk",
"tableFrom": "session",
"tableTo": "auth",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
@@ -3308,15 +3660,15 @@
},
"indexes": {},
"foreignKeys": {
"registry_userId_user_userId_fk": {
"name": "registry_userId_user_userId_fk",
"registry_userId_user_temp_id_fk": {
"name": "registry_userId_user_temp_id_fk",
"tableFrom": "registry",
"tableTo": "user",
"tableTo": "user_temp",
"columnsFrom": [
"userId"
],
"columnsTo": [
"userId"
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
@@ -3563,7 +3915,7 @@
"name": "userId",
"type": "text",
"primaryKey": false,
"notNull": false
"notNull": true
}
},
"indexes": {},
@@ -3633,15 +3985,15 @@
"onDelete": "cascade",
"onUpdate": "no action"
},
"notification_userId_user_userId_fk": {
"name": "notification_userId_user_userId_fk",
"notification_userId_user_temp_id_fk": {
"name": "notification_userId_user_temp_id_fk",
"tableFrom": "notification",
"tableTo": "user",
"tableTo": "user_temp",
"columnsFrom": [
"userId"
],
"columnsTo": [
"userId"
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
@@ -3762,24 +4114,24 @@
"primaryKey": false,
"notNull": false
},
"userId": {
"name": "userId",
"adminId": {
"name": "adminId",
"type": "text",
"primaryKey": false,
"notNull": false
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"ssh-key_userId_user_userId_fk": {
"name": "ssh-key_userId_user_userId_fk",
"ssh-key_adminId_admin_adminId_fk": {
"name": "ssh-key_adminId_admin_adminId_fk",
"tableFrom": "ssh-key",
"tableTo": "user",
"tableTo": "admin",
"columnsFrom": [
"userId"
"adminId"
],
"columnsTo": [
"userId"
"adminId"
],
"onDelete": "cascade",
"onUpdate": "no action"
@@ -3825,20 +4177,20 @@
"name": "userId",
"type": "text",
"primaryKey": false,
"notNull": false
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"git_provider_userId_user_userId_fk": {
"name": "git_provider_userId_user_userId_fk",
"git_provider_userId_user_temp_id_fk": {
"name": "git_provider_userId_user_temp_id_fk",
"tableFrom": "git_provider",
"tableTo": "user",
"tableTo": "user_temp",
"columnsFrom": [
"userId"
],
"columnsTo": [
"userId"
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
@@ -4173,15 +4525,15 @@
},
"indexes": {},
"foreignKeys": {
"server_userId_user_userId_fk": {
"name": "server_userId_user_userId_fk",
"server_userId_user_temp_id_fk": {
"name": "server_userId_user_temp_id_fk",
"tableFrom": "server",
"tableTo": "user",
"tableTo": "user_temp",
"columnsFrom": [
"userId"
],
"columnsTo": [
"userId"
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
@@ -4450,15 +4802,15 @@
},
"indexes": {},
"foreignKeys": {
"account_user_id_user_userId_fk": {
"name": "account_user_id_user_userId_fk",
"account_user_id_user_temp_id_fk": {
"name": "account_user_id_user_temp_id_fk",
"tableFrom": "account",
"tableTo": "user",
"tableTo": "user_temp",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"userId"
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
@@ -4532,15 +4884,15 @@
"onDelete": "no action",
"onUpdate": "no action"
},
"invitation_inviter_id_user_userId_fk": {
"name": "invitation_inviter_id_user_userId_fk",
"invitation_inviter_id_user_temp_id_fk": {
"name": "invitation_inviter_id_user_temp_id_fk",
"tableFrom": "invitation",
"tableTo": "user",
"tableTo": "user_temp",
"columnsFrom": [
"inviter_id"
],
"columnsTo": [
"userId"
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
@@ -4602,15 +4954,15 @@
"onDelete": "no action",
"onUpdate": "no action"
},
"member_user_id_user_userId_fk": {
"name": "member_user_id_user_userId_fk",
"member_user_id_user_temp_id_fk": {
"name": "member_user_id_user_temp_id_fk",
"tableFrom": "member",
"tableTo": "user",
"tableTo": "user_temp",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"userId"
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
@@ -4671,15 +5023,15 @@
},
"indexes": {},
"foreignKeys": {
"organization_owner_id_user_userId_fk": {
"name": "organization_owner_id_user_userId_fk",
"organization_owner_id_user_temp_id_fk": {
"name": "organization_owner_id_user_temp_id_fk",
"tableFrom": "organization",
"tableTo": "user",
"tableTo": "user_temp",
"columnsFrom": [
"owner_id"
],
"columnsTo": [
"userId"
"id"
],
"onDelete": "no action",
"onUpdate": "no action"

View File

@@ -467,8 +467,8 @@
{
"idx": 66,
"version": "7",
"when": 1739173929725,
"tag": "0066_soft_kronos",
"when": 1739425241338,
"tag": "0066_rapid_morbius",
"breakpoints": true
}
]

117
apps/dokploy/migrate.ts Normal file
View File

@@ -0,0 +1,117 @@
import { drizzle } from "drizzle-orm/postgres-js";
import { migrate } from "drizzle-orm/postgres-js/migrator";
import postgres from "postgres";
import * as schema from "./server/db/schema";
import { nanoid } from "nanoid";
const connectionString = process.env.DATABASE_URL!;
const sql = postgres(connectionString, { max: 1 });
const db = drizzle(sql, {
schema,
});
await db
.transaction(async (db) => {
const admins = await db.query.admins.findMany({
with: {
auth: true,
users: {
with: {
auth: true,
},
},
},
});
for (const admin of admins) {
const user = await db
.insert(schema.users_temp)
.values({
id: admin.adminId,
email: admin.auth.email,
token: admin.auth.token || "",
emailVerified: true,
updatedAt: new Date(),
role: "admin",
serverIp: admin.serverIp,
image: admin.auth.image,
certificateType: admin.certificateType,
host: admin.host,
letsEncryptEmail: admin.letsEncryptEmail,
sshPrivateKey: admin.sshPrivateKey,
enableDockerCleanup: admin.enableDockerCleanup,
enableLogRotation: admin.enableLogRotation,
enablePaidFeatures: admin.enablePaidFeatures,
metricsConfig: admin.metricsConfig,
cleanupCacheApplications: admin.cleanupCacheApplications,
cleanupCacheOnPreviews: admin.cleanupCacheOnPreviews,
cleanupCacheOnCompose: admin.cleanupCacheOnCompose,
stripeCustomerId: admin.stripeCustomerId,
stripeSubscriptionId: admin.stripeSubscriptionId,
serversQuantity: admin.serversQuantity,
})
.returning()
.then((user) => user[0]);
await db.insert(schema.account).values({
providerId: "credentials",
userId: user?.id || "",
password: admin.auth.password,
is2FAEnabled: admin.auth.is2FAEnabled || false,
createdAt: new Date(admin.auth.createdAt) || new Date(),
updatedAt: new Date(admin.auth.createdAt) || new Date(),
});
const organization = await db
.insert(schema.organization)
.values({
name: "My Organization",
slug: nanoid(),
ownerId: user?.id || "",
createdAt: new Date(admin.createdAt) || new Date(),
})
.returning()
.then((organization) => organization[0]);
for (const member of admin.users) {
const userTemp = await db
.insert(schema.users_temp)
.values({
id: member.userId,
email: member.auth.email,
token: member.token || "",
emailVerified: true,
updatedAt: new Date(admin.createdAt) || new Date(),
role: "user",
image: member.auth.image,
createdAt: admin.createdAt,
canAccessToAPI: member.canAccessToAPI || false,
canAccessToDocker: member.canAccessToDocker || false,
canAccessToGitProviders: member.canAccessToGitProviders || false,
canAccessToSSHKeys: member.canAccessToSSHKeys || false,
canAccessToTraefikFiles: member.canAccessToTraefikFiles || false,
canCreateProjects: member.canCreateProjects || false,
canCreateServices: member.canCreateServices || false,
canDeleteProjects: member.canDeleteProjects || false,
canDeleteServices: member.canDeleteServices || false,
accessedProjects: member.accessedProjects || [],
accessedServices: member.accessedServices || [],
})
.returning()
.then((userTemp) => userTemp[0]);
await db.insert(schema.member).values({
organizationId: organization?.id || "",
userId: userTemp?.id || "",
role: "admin",
createdAt: new Date(member.createdAt) || new Date(),
});
}
}
})
.then(() => {
console.log("Migration finished");
})
.catch((error) => {
console.error(error);
});

View File

@@ -16,6 +16,7 @@
"studio": "drizzle-kit studio --config ./server/db/drizzle.config.ts",
"migration:generate": "drizzle-kit generate --config ./server/db/drizzle.config.ts",
"migration:run": "tsx -r dotenv/config migration.ts",
"manual-migration:run": "tsx -r dotenv/config migrate.ts",
"migration:up": "drizzle-kit up --config ./server/db/drizzle.config.ts",
"migration:drop": "drizzle-kit drop --config ./server/db/drizzle.config.ts",
"db:push": "drizzle-kit push --config ./server/db/drizzle.config.ts",