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",

View File

@ -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"),

View File

@ -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),
});

View File

@ -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({

View File

@ -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(),

View File

@ -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],
// }),
}),
);

View File

@ -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],
// }),
}),
);

View File

@ -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);

View File

@ -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);

View File

@ -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, {

View File

@ -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),
}));

View File

@ -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],

View File

@ -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(),
});

View File

@ -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(

View File

@ -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();