diff --git a/apps/dokploy/drizzle/0066_rapid_morbius.sql b/apps/dokploy/drizzle/0066_rapid_morbius.sql new file mode 100644 index 00000000..9deea881 --- /dev/null +++ b/apps/dokploy/drizzle/0066_rapid_morbius.sql @@ -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; \ No newline at end of file diff --git a/apps/dokploy/drizzle/0066_soft_kronos.sql b/apps/dokploy/drizzle/0066_soft_kronos.sql deleted file mode 100644 index cc627fa8..00000000 --- a/apps/dokploy/drizzle/0066_soft_kronos.sql +++ /dev/null @@ -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; \ No newline at end of file diff --git a/apps/dokploy/drizzle/meta/0066_snapshot.json b/apps/dokploy/drizzle/meta/0066_snapshot.json index 3ffb0dbf..1bf9811a 100644 --- a/apps/dokploy/drizzle/meta/0066_snapshot.json +++ b/apps/dokploy/drizzle/meta/0066_snapshot.json @@ -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" diff --git a/apps/dokploy/drizzle/meta/_journal.json b/apps/dokploy/drizzle/meta/_journal.json index d3de7564..188a9700 100644 --- a/apps/dokploy/drizzle/meta/_journal.json +++ b/apps/dokploy/drizzle/meta/_journal.json @@ -467,8 +467,8 @@ { "idx": 66, "version": "7", - "when": 1739173929725, - "tag": "0066_soft_kronos", + "when": 1739425241338, + "tag": "0066_rapid_morbius", "breakpoints": true } ] diff --git a/apps/dokploy/migrate.ts b/apps/dokploy/migrate.ts new file mode 100644 index 00000000..72bbf2ab --- /dev/null +++ b/apps/dokploy/migrate.ts @@ -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); + }); diff --git a/apps/dokploy/package.json b/apps/dokploy/package.json index 9e531cf8..f68978c3 100644 --- a/apps/dokploy/package.json +++ b/apps/dokploy/package.json @@ -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", diff --git a/packages/server/auth-schema.ts b/packages/server/auth-schema.ts index 3e19bebe..bfb03d2e 100644 --- a/packages/server/auth-schema.ts +++ b/packages/server/auth-schema.ts @@ -26,7 +26,7 @@ export const session = pgTable("session", { userAgent: text("user_agent"), userId: text("user_id") .notNull() - .references(() => user.userId), + .references(() => user.id), activeOrganizationId: text("active_organization_id"), }); @@ -36,7 +36,7 @@ export const account = pgTable("account", { providerId: text("provider_id").notNull(), userId: text("user_id") .notNull() - .references(() => user.userId), + .references(() => user.id), accessToken: text("access_token"), refreshToken: text("refresh_token"), idToken: text("id_token"), diff --git a/packages/server/src/db/schema/account.ts b/packages/server/src/db/schema/account.ts index 24350c55..349428fd 100644 --- a/packages/server/src/db/schema/account.ts +++ b/packages/server/src/db/schema/account.ts @@ -1,13 +1,18 @@ import { boolean, pgTable, text, timestamp } from "drizzle-orm/pg-core"; -import { user } from "./user"; +import { users_temp } from "./user"; +import { nanoid } from "nanoid"; export const account = pgTable("account", { - id: text("id").primaryKey(), - accountId: text("account_id").notNull(), + id: text("id") + .primaryKey() + .$defaultFn(() => nanoid()), + accountId: text("account_id") + .notNull() + .$defaultFn(() => nanoid()), providerId: text("provider_id").notNull(), userId: text("user_id") .notNull() - .references(() => user.userId), + .references(() => users_temp.id), accessToken: text("access_token"), refreshToken: text("refresh_token"), idToken: text("id_token"), @@ -34,7 +39,9 @@ export const verification = pgTable("verification", { }); export const organization = pgTable("organization", { - id: text("id").primaryKey(), + id: text("id") + .primaryKey() + .$defaultFn(() => nanoid()), name: text("name").notNull(), slug: text("slug").unique(), logo: text("logo"), @@ -42,17 +49,19 @@ export const organization = pgTable("organization", { metadata: text("metadata"), ownerId: text("owner_id") .notNull() - .references(() => user.userId), + .references(() => users_temp.id), }); export const member = pgTable("member", { - id: text("id").primaryKey(), + id: text("id") + .primaryKey() + .$defaultFn(() => nanoid()), organizationId: text("organization_id") .notNull() .references(() => organization.id), userId: text("user_id") .notNull() - .references(() => user.userId), + .references(() => users_temp.id), role: text("role").notNull(), createdAt: timestamp("created_at").notNull(), }); @@ -68,5 +77,5 @@ export const invitation = pgTable("invitation", { expiresAt: timestamp("expires_at").notNull(), inviterId: text("inviter_id") .notNull() - .references(() => user.userId), + .references(() => users_temp.id), }); diff --git a/packages/server/src/db/schema/admin.ts b/packages/server/src/db/schema/admin.ts index c842bd7a..983f99fd 100644 --- a/packages/server/src/db/schema/admin.ts +++ b/packages/server/src/db/schema/admin.ts @@ -18,127 +18,128 @@ import { sshKeys } from "./ssh-key"; import { users } from "./user"; export const admins = pgTable("admin", { - // adminId: text("adminId") - // .notNull() - // .primaryKey() - // .$defaultFn(() => nanoid()), - // serverIp: text("serverIp"), - // certificateType: certificateType("certificateType").notNull().default("none"), - // host: text("host"), - // letsEncryptEmail: text("letsEncryptEmail"), - // sshPrivateKey: text("sshPrivateKey"), - // enableDockerCleanup: boolean("enableDockerCleanup").notNull().default(false), - // enableLogRotation: boolean("enableLogRotation").notNull().default(false), - // authId: text("authId") - // .notNull() - // .references(() => auth.id, { onDelete: "cascade" }), - // createdAt: text("createdAt") - // .notNull() - // .$defaultFn(() => new Date().toISOString()), - // stripeCustomerId: text("stripeCustomerId"), - // stripeSubscriptionId: text("stripeSubscriptionId"), - // serversQuantity: integer("serversQuantity").notNull().default(0), - // // Metrics - // enablePaidFeatures: boolean("enablePaidFeatures").notNull().default(false), - // metricsConfig: jsonb("metricsConfig") - // .$type<{ - // server: { - // type: "Dokploy" | "Remote"; - // refreshRate: number; - // port: number; - // token: string; - // urlCallback: string; - // retentionDays: number; - // cronJob: string; - // thresholds: { - // cpu: number; - // memory: number; - // }; - // }; - // containers: { - // refreshRate: number; - // services: { - // include: string[]; - // exclude: string[]; - // }; - // }; - // }>() - // .notNull() - // .default({ - // server: { - // type: "Dokploy", - // refreshRate: 60, - // port: 4500, - // token: "", - // retentionDays: 2, - // cronJob: "", - // urlCallback: "", - // thresholds: { - // cpu: 0, - // memory: 0, - // }, - // }, - // containers: { - // refreshRate: 60, - // services: { - // include: [], - // exclude: [], - // }, - // }, - // }), - // cleanupCacheApplications: boolean("cleanupCacheApplications") - // .notNull() - // .default(false), - // cleanupCacheOnPreviews: boolean("cleanupCacheOnPreviews") - // .notNull() - // .default(false), - // cleanupCacheOnCompose: boolean("cleanupCacheOnCompose") - // .notNull() - // .default(false), + adminId: text("adminId") + .notNull() + .primaryKey() + .$defaultFn(() => nanoid()), + serverIp: text("serverIp"), + certificateType: certificateType("certificateType").notNull().default("none"), + host: text("host"), + letsEncryptEmail: text("letsEncryptEmail"), + sshPrivateKey: text("sshPrivateKey"), + enableDockerCleanup: boolean("enableDockerCleanup").notNull().default(false), + enableLogRotation: boolean("enableLogRotation").notNull().default(false), + authId: text("authId") + .notNull() + .references(() => auth.id, { onDelete: "cascade" }), + createdAt: text("createdAt") + .notNull() + .$defaultFn(() => new Date().toISOString()), + stripeCustomerId: text("stripeCustomerId"), + stripeSubscriptionId: text("stripeSubscriptionId"), + serversQuantity: integer("serversQuantity").notNull().default(0), + + // Metrics + enablePaidFeatures: boolean("enablePaidFeatures").notNull().default(false), + metricsConfig: jsonb("metricsConfig") + .$type<{ + server: { + type: "Dokploy" | "Remote"; + refreshRate: number; + port: number; + token: string; + urlCallback: string; + retentionDays: number; + cronJob: string; + thresholds: { + cpu: number; + memory: number; + }; + }; + containers: { + refreshRate: number; + services: { + include: string[]; + exclude: string[]; + }; + }; + }>() + .notNull() + .default({ + server: { + type: "Dokploy", + refreshRate: 60, + port: 4500, + token: "", + retentionDays: 2, + cronJob: "", + urlCallback: "", + thresholds: { + cpu: 0, + memory: 0, + }, + }, + containers: { + refreshRate: 60, + services: { + include: [], + exclude: [], + }, + }, + }), + cleanupCacheApplications: boolean("cleanupCacheApplications") + .notNull() + .default(false), + cleanupCacheOnPreviews: boolean("cleanupCacheOnPreviews") + .notNull() + .default(false), + cleanupCacheOnCompose: boolean("cleanupCacheOnCompose") + .notNull() + .default(false), }); export const adminsRelations = relations(admins, ({ one, many }) => ({ - // auth: one(auth, { - // fields: [admins.authId], - // references: [auth.id], - // }), - // users: many(users), - // registry: many(registry), - // sshKeys: many(sshKeys), - // certificates: many(certificates), + auth: one(auth, { + fields: [admins.authId], + references: [auth.id], + }), + users: many(users), + registry: many(registry), + sshKeys: many(sshKeys), + certificates: many(certificates), })); const createSchema = createInsertSchema(admins, { - // adminId: z.string(), - // enableDockerCleanup: z.boolean().optional(), - // sshPrivateKey: z.string().optional(), - // certificateType: z.enum(["letsencrypt", "none"]).default("none"), - // serverIp: z.string().optional(), - // letsEncryptEmail: z.string().optional(), + adminId: z.string(), + enableDockerCleanup: z.boolean().optional(), + sshPrivateKey: z.string().optional(), + certificateType: z.enum(["letsencrypt", "none"]).default("none"), + serverIp: z.string().optional(), + letsEncryptEmail: z.string().optional(), }); export const apiUpdateAdmin = createSchema.partial(); export const apiSaveSSHKey = createSchema .pick({ - // sshPrivateKey: true, + sshPrivateKey: true, }) .required(); export const apiAssignDomain = createSchema .pick({ - // host: true, - // certificateType: true, - // letsEncryptEmail: true, + host: true, + certificateType: true, + letsEncryptEmail: true, }) .required() .partial({ - // letsEncryptEmail: true, + letsEncryptEmail: true, }); export const apiUpdateDockerCleanup = createSchema .pick({ - // enableDockerCleanup: true, + enableDockerCleanup: true, }) .required() .extend({ diff --git a/packages/server/src/db/schema/auth.ts b/packages/server/src/db/schema/auth.ts index 35f4dc85..7093a40c 100644 --- a/packages/server/src/db/schema/auth.ts +++ b/packages/server/src/db/schema/auth.ts @@ -5,7 +5,7 @@ import { createInsertSchema } from "drizzle-zod"; import { nanoid } from "nanoid"; import { z } from "zod"; // import { admins } from "./admin"; -import { user } from "./user"; +import { users } from "./user"; const randomImages = [ "/avatars/avatar-1.png", @@ -56,7 +56,7 @@ export const auth = pgTable("auth", { export const authRelations = relations(auth, ({ many }) => ({ // admins: many(admins), - users: many(user), + users: many(users), })); const createSchema = createInsertSchema(auth, { email: z.string().email(), diff --git a/packages/server/src/db/schema/certificate.ts b/packages/server/src/db/schema/certificate.ts index c1a57a5a..c72d189c 100644 --- a/packages/server/src/db/schema/certificate.ts +++ b/packages/server/src/db/schema/certificate.ts @@ -4,8 +4,10 @@ import { createInsertSchema } from "drizzle-zod"; import { nanoid } from "nanoid"; import { z } from "zod"; import { server } from "./server"; -import { user } from "./user"; +// import { user } from "./user"; import { generateAppName } from "./utils"; +import { admins } from "./admin"; +import { users_temp } from "./user"; export const certificates = pgTable("certificate", { certificateId: text("certificateId") @@ -20,9 +22,12 @@ export const certificates = pgTable("certificate", { .$defaultFn(() => generateAppName("certificate")) .unique(), autoRenew: boolean("autoRenew"), - userId: text("userId").references(() => user.userId, { - onDelete: "cascade", - }), + // userId: text("userId").references(() => user.userId, { + // onDelete: "cascade", + // }), + userId: text("userId") + .notNull() + .references(() => users_temp.id, { onDelete: "cascade" }), serverId: text("serverId").references(() => server.serverId, { onDelete: "cascade", }), @@ -35,10 +40,10 @@ export const certificatesRelations = relations( fields: [certificates.serverId], references: [server.serverId], }), - user: one(user, { - fields: [certificates.userId], - references: [user.id], - }), + // user: one(user, { + // fields: [certificates.userId], + // references: [user.id], + // }), }), ); diff --git a/packages/server/src/db/schema/destination.ts b/packages/server/src/db/schema/destination.ts index 1fe48a34..6b9ea5d9 100644 --- a/packages/server/src/db/schema/destination.ts +++ b/packages/server/src/db/schema/destination.ts @@ -5,7 +5,8 @@ import { nanoid } from "nanoid"; import { z } from "zod"; import { admins } from "./admin"; import { backups } from "./backups"; -import { user } from "./user"; +import { users_temp } from "./user"; +// import { user } from "./user"; export const destinations = pgTable("destination", { destinationId: text("destinationId") @@ -20,19 +21,22 @@ export const destinations = pgTable("destination", { region: text("region").notNull(), // maybe it can be null endpoint: text("endpoint").notNull(), + // userId: text("userId") + // .notNull() + // .references(() => user.userId, { onDelete: "cascade" }), userId: text("userId") .notNull() - .references(() => user.userId, { onDelete: "cascade" }), + .references(() => users_temp.id, { onDelete: "cascade" }), }); export const destinationsRelations = relations( destinations, ({ many, one }) => ({ backups: many(backups), - user: one(user, { - fields: [destinations.userId], - references: [user.id], - }), + // user: one(user, { + // fields: [destinations.userId], + // references: [user.id], + // }), }), ); diff --git a/packages/server/src/db/schema/git-provider.ts b/packages/server/src/db/schema/git-provider.ts index 3a3bade8..4d154ee3 100644 --- a/packages/server/src/db/schema/git-provider.ts +++ b/packages/server/src/db/schema/git-provider.ts @@ -7,7 +7,8 @@ import { admins } from "./admin"; import { bitbucket } from "./bitbucket"; import { github } from "./github"; import { gitlab } from "./gitlab"; -import { user } from "./user"; +import { users_temp } from "./user"; +// import { user } from "./user"; export const gitProviderType = pgEnum("gitProviderType", [ "github", @@ -25,9 +26,12 @@ export const gitProvider = pgTable("git_provider", { createdAt: text("createdAt") .notNull() .$defaultFn(() => new Date().toISOString()), - userId: text("userId").references(() => user.userId, { - onDelete: "cascade", - }), + // userId: text("userId").references(() => user.userId, { + // onDelete: "cascade", + // }), + userId: text("userId") + .notNull() + .references(() => users_temp.id, { onDelete: "cascade" }), }); export const gitProviderRelations = relations(gitProvider, ({ one, many }) => ({ @@ -43,10 +47,10 @@ export const gitProviderRelations = relations(gitProvider, ({ one, many }) => ({ fields: [gitProvider.gitProviderId], references: [bitbucket.gitProviderId], }), - user: one(user, { - fields: [gitProvider.userId], - references: [user.id], - }), + // user: one(user, { + // fields: [gitProvider.userId], + // references: [user.id], + // }), })); const createSchema = createInsertSchema(gitProvider); diff --git a/packages/server/src/db/schema/notification.ts b/packages/server/src/db/schema/notification.ts index 1771a92a..3ab25339 100644 --- a/packages/server/src/db/schema/notification.ts +++ b/packages/server/src/db/schema/notification.ts @@ -4,7 +4,8 @@ import { createInsertSchema } from "drizzle-zod"; import { nanoid } from "nanoid"; import { z } from "zod"; import { admins } from "./admin"; -import { user } from "./user"; +import { users_temp } from "./user"; +// import { user } from "./user"; export const notificationType = pgEnum("notificationType", [ "slack", @@ -45,9 +46,12 @@ export const notifications = pgTable("notification", { gotifyId: text("gotifyId").references(() => gotify.gotifyId, { onDelete: "cascade", }), - userId: text("userId").references(() => user.userId, { - onDelete: "cascade", - }), + // userId: text("userId").references(() => user.userId, { + // onDelete: "cascade", + // }), + userId: text("userId") + .notNull() + .references(() => users_temp.id, { onDelete: "cascade" }), }); export const slack = pgTable("slack", { @@ -122,10 +126,10 @@ export const notificationsRelations = relations(notifications, ({ one }) => ({ fields: [notifications.gotifyId], references: [gotify.gotifyId], }), - user: one(user, { - fields: [notifications.userId], - references: [user.id], - }), + // user: one(user, { + // fields: [notifications.userId], + // references: [user.id], + // }), })); export const notificationsSchema = createInsertSchema(notifications); diff --git a/packages/server/src/db/schema/project.ts b/packages/server/src/db/schema/project.ts index d83936a3..efde3c34 100644 --- a/packages/server/src/db/schema/project.ts +++ b/packages/server/src/db/schema/project.ts @@ -12,7 +12,8 @@ import { mongo } from "./mongo"; import { mysql } from "./mysql"; import { postgres } from "./postgres"; import { redis } from "./redis"; -import { user } from "./user"; +import { users, users_temp } from "./user"; +import { admins } from "./admin"; export const projects = pgTable("project", { projectId: text("projectId") @@ -24,9 +25,12 @@ export const projects = pgTable("project", { createdAt: text("createdAt") .notNull() .$defaultFn(() => new Date().toISOString()), + // userId: text("userId") + // .notNull() + // .references(() => user.userId, { onDelete: "cascade" }), userId: text("userId") .notNull() - .references(() => user.userId, { onDelete: "cascade" }), + .references(() => users_temp.id, { onDelete: "cascade" }), env: text("env").notNull().default(""), }); @@ -38,10 +42,10 @@ export const projectRelations = relations(projects, ({ many, one }) => ({ mongo: many(mongo), redis: many(redis), compose: many(compose), - user: one(user, { - fields: [projects.userId], - references: [user.id], - }), + // user: one(user, { + // fields: [projects.userId], + // references: [user.id], + // }), })); const createSchema = createInsertSchema(projects, { diff --git a/packages/server/src/db/schema/registry.ts b/packages/server/src/db/schema/registry.ts index 936f65fc..62c2b2d7 100644 --- a/packages/server/src/db/schema/registry.ts +++ b/packages/server/src/db/schema/registry.ts @@ -5,7 +5,8 @@ import { nanoid } from "nanoid"; import { z } from "zod"; import { admins } from "./admin"; import { applications } from "./application"; -import { user } from "./user"; +import { users_temp } from "./user"; +// import { user } from "./user"; /** * This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same * database instance for multiple projects. @@ -28,16 +29,19 @@ export const registry = pgTable("registry", { .notNull() .$defaultFn(() => new Date().toISOString()), registryType: registryType("selfHosted").notNull().default("cloud"), + // userId: text("userId") + // .notNull() + // .references(() => user.userId, { onDelete: "cascade" }), userId: text("userId") .notNull() - .references(() => user.userId, { onDelete: "cascade" }), + .references(() => users_temp.id, { onDelete: "cascade" }), }); export const registryRelations = relations(registry, ({ one, many }) => ({ - user: one(user, { - fields: [registry.userId], - references: [user.id], - }), + // user: one(user, { + // fields: [registry.userId], + // references: [user.id], + // }), applications: many(applications), })); diff --git a/packages/server/src/db/schema/server.ts b/packages/server/src/db/schema/server.ts index 4e238e23..b6b77dbc 100644 --- a/packages/server/src/db/schema/server.ts +++ b/packages/server/src/db/schema/server.ts @@ -22,8 +22,9 @@ import { mysql } from "./mysql"; import { postgres } from "./postgres"; import { redis } from "./redis"; import { sshKeys } from "./ssh-key"; -import { user } from "./user"; +// import { user } from "./user"; import { generateAppName } from "./utils"; +import { users_temp } from "./user"; export const serverStatus = pgEnum("serverStatus", ["active", "inactive"]); @@ -41,12 +42,14 @@ export const server = pgTable("server", { .notNull() .$defaultFn(() => generateAppName("server")), enableDockerCleanup: boolean("enableDockerCleanup").notNull().default(false), - createdAt: text("createdAt") - .notNull() - .$defaultFn(() => new Date().toISOString()), + createdAt: text("createdAt").notNull(), + // .$defaultFn(() => new Date().toISOString()), + // userId: text("userId") + // .notNull() + // .references(() => user.userId, { onDelete: "cascade" }), userId: text("userId") .notNull() - .references(() => user.userId, { onDelete: "cascade" }), + .references(() => users_temp.id, { onDelete: "cascade" }), serverStatus: serverStatus("serverStatus").notNull().default("active"), command: text("command").notNull().default(""), sshKeyId: text("sshKeyId").references(() => sshKeys.sshKeyId, { @@ -101,10 +104,10 @@ export const server = pgTable("server", { }); export const serverRelations = relations(server, ({ one, many }) => ({ - user: one(user, { - fields: [server.userId], - references: [user.id], - }), + // user: one(user, { + // fields: [server.userId], + // references: [user.id], + // }), deployments: many(deployments), sshKey: one(sshKeys, { fields: [server.sshKeyId], diff --git a/packages/server/src/db/schema/session.ts b/packages/server/src/db/schema/session.ts index d5932764..03a70c41 100644 --- a/packages/server/src/db/schema/session.ts +++ b/packages/server/src/db/schema/session.ts @@ -1,19 +1,31 @@ import { sql } from "drizzle-orm"; import { pgTable, text, timestamp } from "drizzle-orm/pg-core"; -import { user } from "./user"; +import { users_temp } from "./user"; +import { auth } from "./auth"; // OLD TABLE -export const session = pgTable("session", { +export const session = pgTable("session_temp", { id: text("id").primaryKey(), expiresAt: timestamp("expires_at").notNull(), - // token: text("token").notNull().unique().default(sql`gen_random_uuid()`), + token: text("token").notNull().unique(), createdAt: timestamp("created_at").notNull(), updatedAt: timestamp("updated_at").notNull(), ipAddress: text("ip_address"), userAgent: text("user_agent"), userId: text("user_id") .notNull() - .references(() => user.userId), + .references(() => users_temp.id), impersonatedBy: text("impersonated_by"), activeOrganizationId: text("active_organization_id"), }); + +export const sessionTable = pgTable("session", { + id: text("id").primaryKey(), + userId: text("user_id") + .notNull() + .references(() => auth.id, { onDelete: "cascade" }), + expiresAt: timestamp("expires_at", { + withTimezone: true, + mode: "date", + }).notNull(), +}); diff --git a/packages/server/src/db/schema/ssh-key.ts b/packages/server/src/db/schema/ssh-key.ts index 9bb69fee..cca9259b 100644 --- a/packages/server/src/db/schema/ssh-key.ts +++ b/packages/server/src/db/schema/ssh-key.ts @@ -7,7 +7,7 @@ import { admins } from "./admin"; import { applications } from "./application"; import { compose } from "./compose"; import { server } from "./server"; -import { user } from "./user"; +// import { user } from "./user"; export const sshKeys = pgTable("ssh-key", { sshKeyId: text("sshKeyId") @@ -22,19 +22,22 @@ export const sshKeys = pgTable("ssh-key", { .notNull() .$defaultFn(() => new Date().toISOString()), lastUsedAt: text("lastUsedAt"), - userId: text("userId").references(() => user.userId, { - onDelete: "cascade", - }), + // userId: text("userId").references(() => user.userId, { + // onDelete: "cascade", + // }), + adminId: text("adminId") + .notNull() + .references(() => admins.adminId, { onDelete: "cascade" }), }); export const sshKeysRelations = relations(sshKeys, ({ many, one }) => ({ applications: many(applications), compose: many(compose), servers: many(server), - user: one(user, { - fields: [sshKeys.userId], - references: [user.id], - }), + // user: one(user, { + // fields: [sshKeys.userId], + // references: [user.id], + // }), })); const createSchema = createInsertSchema( diff --git a/packages/server/src/db/schema/user.ts b/packages/server/src/db/schema/user.ts index 00e16679..5f2a14e9 100644 --- a/packages/server/src/db/schema/user.ts +++ b/packages/server/src/db/schema/user.ts @@ -21,11 +21,57 @@ import { certificateType } from "./shared"; */ // OLD TABLE -export const user = pgTable("user", { + +export const users = pgTable("user", { userId: text("userId") .notNull() .primaryKey() .$defaultFn(() => nanoid()), + + token: text("token").notNull(), + isRegistered: boolean("isRegistered").notNull().default(false), + expirationDate: timestamp("expirationDate", { + precision: 3, + mode: "string", + }).notNull(), + createdAt: text("createdAt") + .notNull() + .$defaultFn(() => new Date().toISOString()), + canCreateProjects: boolean("canCreateProjects").notNull().default(false), + canAccessToSSHKeys: boolean("canAccessToSSHKeys").notNull().default(false), + canCreateServices: boolean("canCreateServices").notNull().default(false), + canDeleteProjects: boolean("canDeleteProjects").notNull().default(false), + canDeleteServices: boolean("canDeleteServices").notNull().default(false), + canAccessToDocker: boolean("canAccessToDocker").notNull().default(false), + canAccessToAPI: boolean("canAccessToAPI").notNull().default(false), + canAccessToGitProviders: boolean("canAccessToGitProviders") + .notNull() + .default(false), + canAccessToTraefikFiles: boolean("canAccessToTraefikFiles") + .notNull() + .default(false), + accessedProjects: text("accesedProjects") + .array() + .notNull() + .default(sql`ARRAY[]::text[]`), + accessedServices: text("accesedServices") + .array() + .notNull() + .default(sql`ARRAY[]::text[]`), + adminId: text("adminId") + .notNull() + .references(() => admins.adminId, { onDelete: "cascade" }), + authId: text("authId") + .notNull() + .references(() => auth.id, { onDelete: "cascade" }), +}); + +// TEMP +export const users_temp = pgTable("user_temp", { + id: text("id") + .notNull() + .primaryKey() + .$defaultFn(() => nanoid()), name: text("name").notNull().default(""), token: text("token").notNull(), isRegistered: boolean("isRegistered").notNull().default(false), @@ -138,19 +184,19 @@ export const user = pgTable("user", { serversQuantity: integer("serversQuantity").notNull().default(0), }); -export const usersRelations = relations(user, ({ one }) => ({ - // auth: one(auth, { - // fields: [users.authId], - // references: [auth.id], - // }), - // admin: one(admins, { - // fields: [users.adminId], - // references: [admins.adminId], - // }), +export const usersRelations = relations(users, ({ one }) => ({ + auth: one(auth, { + fields: [users.authId], + references: [auth.id], + }), + admin: one(admins, { + fields: [users.adminId], + references: [admins.adminId], + }), })); -const createSchema = createInsertSchema(user, { - id: z.string().min(1), +const createSchema = createInsertSchema(users, { + userId: z.string().min(1), // authId: z.string().min(1), token: z.string().min(1), isRegistered: z.boolean().optional(), @@ -183,7 +229,7 @@ export const apiFindOneToken = createSchema export const apiAssignPermissions = createSchema .pick({ - id: true, + userId: true, canCreateProjects: true, canCreateServices: true, canDeleteProjects: true, @@ -200,7 +246,7 @@ export const apiAssignPermissions = createSchema export const apiFindOneUser = createSchema .pick({ - id: true, + userId: true, }) .required();