feat(database): introduce member_role table and update user roles

- Created a new "member_role" table to manage user roles with associated permissions.
- Migrated existing roles from the deprecated "organization_role" table and updated member records accordingly.
- Enhanced the "member" table by adding a foreign key reference to the new "member_role" table.
- Updated SQL migration scripts to reflect changes in user and role management, ensuring data integrity and consistency.
This commit is contained in:
Mauricio Siu
2025-07-13 00:02:52 -06:00
parent d78e634cb0
commit e8475730fa
14 changed files with 327 additions and 25381 deletions

View File

@@ -0,0 +1,188 @@
CREATE TABLE "member_role" (
"roleId" text PRIMARY KEY NOT NULL,
"name" text NOT NULL,
"description" text,
"canDelete" boolean DEFAULT true NOT NULL,
"is_system" boolean DEFAULT false,
"permissions" text[],
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL,
"organizationId" text NOT NULL,
CONSTRAINT "member_role_name_unique" UNIQUE("name")
);
-- Create default roles for each organization
DO $$
DECLARE
org RECORD;
BEGIN
FOR org IN SELECT id FROM "organization"
LOOP
-- Insert owner role
INSERT INTO "organization_role" ("roleId", "name", "description", "canDelete", "is_system", "permissions", "created_at", "updated_at", "organizationId")
VALUES (
org.id || '_owner',
'owner',
'Owner role with full access',
false,
true,
'{"project:create", "project:delete", "service:create", "service:delete", "traefik_files:access", "docker:view", "api:access", "ssh_keys:access", "git_providers:access", "schedules:access"}',
NOW(),
NOW(),
org.id
);
-- Insert admin role
INSERT INTO "organization_role" ("roleId", "name", "description", "canDelete", "is_system", "permissions", "created_at", "updated_at", "organizationId")
VALUES (
org.id || '_admin',
'admin',
'Administrator role with elevated access',
false,
true,
'{"project:create", "project:delete", "service:create", "service:delete", "traefik_files:access", "docker:view", "api:access", "ssh_keys:access", "schedules:access"}',
NOW(),
NOW(),
org.id
);
-- Insert member role
INSERT INTO "organization_role" ("roleId", "name", "description", "canDelete", "is_system", "permissions", "created_at", "updated_at", "organizationId")
VALUES (
org.id || '_member',
'member',
'Standard member role',
false,
true,
'{"project:create", "service:create", "docker:view"}',
NOW(),
NOW(),
org.id
);
END LOOP;
END $$;
--> statement-breakpoint
ALTER TABLE "user_temp" RENAME TO "users";--> statement-breakpoint
ALTER TABLE "users" DROP CONSTRAINT "user_temp_email_unique";--> statement-breakpoint
ALTER TABLE "backup" DROP CONSTRAINT "backup_userId_user_temp_id_fk";
--> statement-breakpoint
ALTER TABLE "session_temp" DROP CONSTRAINT "session_temp_user_id_user_temp_id_fk";
--> statement-breakpoint
ALTER TABLE "git_provider" DROP CONSTRAINT "git_provider_userId_user_temp_id_fk";
--> statement-breakpoint
ALTER TABLE "account" DROP CONSTRAINT "account_user_id_user_temp_id_fk";
--> statement-breakpoint
ALTER TABLE "apikey" DROP CONSTRAINT "apikey_user_id_user_temp_id_fk";
--> statement-breakpoint
ALTER TABLE "invitation" DROP CONSTRAINT "invitation_inviter_id_user_temp_id_fk";
--> statement-breakpoint
ALTER TABLE "member" DROP CONSTRAINT "member_user_id_user_temp_id_fk";
--> statement-breakpoint
ALTER TABLE "organization" DROP CONSTRAINT "organization_owner_id_user_temp_id_fk";
--> statement-breakpoint
ALTER TABLE "two_factor" DROP CONSTRAINT "two_factor_user_id_user_temp_id_fk";
--> statement-breakpoint
ALTER TABLE "schedule" DROP CONSTRAINT "schedule_userId_user_temp_id_fk";
--> statement-breakpoint
ALTER TABLE "member" ADD COLUMN "roleId" text;--> statement-breakpoint
ALTER TABLE "member_role" ADD CONSTRAINT "member_role_organizationId_organization_id_fk" FOREIGN KEY ("organizationId") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "backup" ADD CONSTRAINT "backup_userId_users_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "session_temp" ADD CONSTRAINT "session_temp_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "git_provider" ADD CONSTRAINT "git_provider_userId_users_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "account" ADD CONSTRAINT "account_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "apikey" ADD CONSTRAINT "apikey_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "invitation" ADD CONSTRAINT "invitation_inviter_id_users_id_fk" FOREIGN KEY ("inviter_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "member" ADD CONSTRAINT "member_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "member" ADD CONSTRAINT "member_roleId_member_role_roleId_fk" FOREIGN KEY ("roleId") REFERENCES "public"."member_role"("roleId") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
-- Update existing members with corresponding roles based on their current role type
DO $$
DECLARE
mem RECORD;
BEGIN
FOR mem IN SELECT m.id, m.organization_id, m.role as role_type FROM "member" m
LOOP
UPDATE "member"
SET "roleId" = mem.organization_id || '_' || mem.role_type
WHERE id = mem.id;
END LOOP;
END $$;
ALTER TABLE "member" ALTER COLUMN "roleId" SET NOT NULL;
ALTER TABLE "organization" ADD CONSTRAINT "organization_owner_id_users_id_fk" FOREIGN KEY ("owner_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "two_factor" ADD CONSTRAINT "two_factor_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "schedule" ADD CONSTRAINT "schedule_userId_users_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
--> statement-breakpoint
CREATE TABLE "web_server" (
"webServerId" text PRIMARY KEY NOT NULL,
"serverIp" text,
"certificateType" "certificateType" DEFAULT 'none' NOT NULL,
"https" boolean DEFAULT false NOT NULL,
"host" text,
"letsEncryptEmail" text,
"sshPrivateKey" text,
"enableDockerCleanup" boolean DEFAULT false NOT NULL,
"logCleanupCron" text DEFAULT '0 0 * * *',
"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
);
-- Migrar datos del usuario owner único hacia web_server
INSERT INTO "web_server" (
"webServerId",
"serverIp",
"certificateType",
"https",
"host",
"letsEncryptEmail",
"sshPrivateKey",
"enableDockerCleanup",
"logCleanupCron",
"metricsConfig"
)
SELECT
gen_random_uuid() as "webServerId",
u."serverIp",
COALESCE(u."certificateType", 'none') as "certificateType",
COALESCE(u."https", false) as "https",
u."host",
u."letsEncryptEmail",
u."sshPrivateKey",
COALESCE(u."enableDockerCleanup", false) as "enableDockerCleanup",
COALESCE(u."logCleanupCron", '0 0 * * *') as "logCleanupCron",
COALESCE(u."metricsConfig", '{"server":{"type":"Dokploy","refreshRate":60,"port":4500,"token":"","retentionDays":2,"cronJob":"","urlCallback":"","thresholds":{"cpu":0,"memory":0}},"containers":{"refreshRate":60,"services":{"include":[],"exclude":[]}}}') as "metricsConfig"
FROM "users" u
INNER JOIN "organization" o ON u.id = o.owner_id
LIMIT 1;
ALTER TABLE "users" DROP COLUMN "created_at";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "serverIp";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "certificateType";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "https";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "host";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "letsEncryptEmail";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "sshPrivateKey";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "enableDockerCleanup";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "logCleanupCron";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "metricsConfig";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "cleanupCacheApplications";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "cleanupCacheOnPreviews";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "cleanupCacheOnCompose";--> statement-breakpoint
ALTER TABLE "member" DROP COLUMN "role";--> statement-breakpoint
ALTER TABLE "member" DROP COLUMN "canCreateProjects";--> statement-breakpoint
ALTER TABLE "member" DROP COLUMN "canAccessToSSHKeys";--> statement-breakpoint
ALTER TABLE "member" DROP COLUMN "canCreateServices";--> statement-breakpoint
ALTER TABLE "member" DROP COLUMN "canDeleteProjects";--> statement-breakpoint
ALTER TABLE "member" DROP COLUMN "canDeleteServices";--> statement-breakpoint
ALTER TABLE "member" DROP COLUMN "canAccessToDocker";--> statement-breakpoint
ALTER TABLE "member" DROP COLUMN "canAccessToAPI";--> statement-breakpoint
ALTER TABLE "member" DROP COLUMN "canAccessToGitProviders";--> statement-breakpoint
ALTER TABLE "member" DROP COLUMN "canAccessToTraefikFiles";--> statement-breakpoint
ALTER TABLE "users" ADD CONSTRAINT "users_email_unique" UNIQUE("email");

View File

@@ -1,84 +0,0 @@
CREATE TABLE "organization_role" (
"roleId" text PRIMARY KEY NOT NULL,
"name" text NOT NULL,
"description" text,
"canDelete" boolean DEFAULT true NOT NULL,
"is_system" boolean DEFAULT false,
"permissions" text[],
"created_at" timestamp NOT NULL,
"updated_at" timestamp NOT NULL,
"organizationId" text NOT NULL
);
-- Create default roles for each organization
DO $$
DECLARE
org RECORD;
BEGIN
FOR org IN SELECT id FROM "organization"
LOOP
-- Insert owner role
INSERT INTO "organization_role" ("roleId", "name", "description", "canDelete", "is_system", "permissions", "created_at", "updated_at", "organizationId")
VALUES (
org.id || '_owner',
'owner',
'Owner role with full access',
false,
true,
'{"project:create", "project:delete", "service:create", "service:delete", "traefik_files:access", "docker:view", "api:access", "ssh_keys:access", "git_providers:access"}',
NOW(),
NOW(),
org.id
);
-- Insert admin role
INSERT INTO "organization_role" ("roleId", "name", "description", "canDelete", "is_system", "permissions", "created_at", "updated_at", "organizationId")
VALUES (
org.id || '_admin',
'admin',
'Administrator role with elevated access',
false,
true,
'{"project:create", "project:delete", "service:create", "service:delete", "traefik_files:access", "docker:view", "api:access", "ssh_keys:access"}',
NOW(),
NOW(),
org.id
);
-- Insert member role
INSERT INTO "organization_role" ("roleId", "name", "description", "canDelete", "is_system", "permissions", "created_at", "updated_at", "organizationId")
VALUES (
org.id || '_member',
'member',
'Standard member role',
false,
true,
'{"project:create", "service:create", "docker:view"}',
NOW(),
NOW(),
org.id
);
END LOOP;
END $$;
--> statement-breakpoint
ALTER TABLE "member" ADD COLUMN "roleId" text;
--> statement-breakpoint
ALTER TABLE "organization_role" ADD CONSTRAINT "organization_role_organizationId_organization_id_fk" FOREIGN KEY ("organizationId") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;
--> statement-breakpoint
ALTER TABLE "member" ADD CONSTRAINT "member_roleId_organization_role_roleId_fk" FOREIGN KEY ("roleId") REFERENCES "public"."organization_role"("roleId") ON DELETE cascade ON UPDATE no action;
-- Update existing members with corresponding roles based on their current role type
DO $$
DECLARE
mem RECORD;
BEGIN
FOR mem IN SELECT m.id, m.organization_id, m.role as role_type FROM "member" m
LOOP
UPDATE "member"
SET "roleId" = mem.organization_id || '_' || mem.role_type
WHERE id = mem.id;
END LOOP;
END $$;
ALTER TABLE "member" ALTER COLUMN "roleId" SET NOT NULL;

View File

@@ -1,3 +0,0 @@
ALTER TABLE "organization_role" ALTER COLUMN "created_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "organization_role" ALTER COLUMN "updated_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "organization_role" ADD CONSTRAINT "organization_role_name_unique" UNIQUE("name");

View File

@@ -1 +0,0 @@
ALTER TABLE "member" ALTER COLUMN "roleId" DROP NOT NULL;

View File

@@ -1,33 +0,0 @@
ALTER TABLE "user_temp" RENAME TO "users";--> statement-breakpoint
ALTER TABLE "users" DROP CONSTRAINT "user_temp_email_unique";--> statement-breakpoint
ALTER TABLE "backup" DROP CONSTRAINT "backup_userId_user_temp_id_fk";
--> statement-breakpoint
ALTER TABLE "session_temp" DROP CONSTRAINT "session_temp_user_id_user_temp_id_fk";
--> statement-breakpoint
ALTER TABLE "git_provider" DROP CONSTRAINT "git_provider_userId_user_temp_id_fk";
--> statement-breakpoint
ALTER TABLE "account" DROP CONSTRAINT "account_user_id_user_temp_id_fk";
--> statement-breakpoint
ALTER TABLE "apikey" DROP CONSTRAINT "apikey_user_id_user_temp_id_fk";
--> statement-breakpoint
ALTER TABLE "invitation" DROP CONSTRAINT "invitation_inviter_id_user_temp_id_fk";
--> statement-breakpoint
ALTER TABLE "member" DROP CONSTRAINT "member_user_id_user_temp_id_fk";
--> statement-breakpoint
ALTER TABLE "organization" DROP CONSTRAINT "organization_owner_id_user_temp_id_fk";
--> statement-breakpoint
ALTER TABLE "two_factor" DROP CONSTRAINT "two_factor_user_id_user_temp_id_fk";
--> statement-breakpoint
ALTER TABLE "schedule" DROP CONSTRAINT "schedule_userId_user_temp_id_fk";
--> statement-breakpoint
ALTER TABLE "backup" ADD CONSTRAINT "backup_userId_users_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "session_temp" ADD CONSTRAINT "session_temp_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "git_provider" ADD CONSTRAINT "git_provider_userId_users_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "account" ADD CONSTRAINT "account_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "apikey" ADD CONSTRAINT "apikey_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "invitation" ADD CONSTRAINT "invitation_inviter_id_users_id_fk" FOREIGN KEY ("inviter_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "member" ADD CONSTRAINT "member_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "organization" ADD CONSTRAINT "organization_owner_id_users_id_fk" FOREIGN KEY ("owner_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "two_factor" ADD CONSTRAINT "two_factor_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "schedule" ADD CONSTRAINT "schedule_userId_users_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "users" ADD CONSTRAINT "users_email_unique" UNIQUE("email");

View File

@@ -1,56 +0,0 @@
CREATE TABLE "web_server" (
"webServerId" text PRIMARY KEY NOT NULL,
"serverIp" text,
"certificateType" "certificateType" DEFAULT 'none' NOT NULL,
"https" boolean DEFAULT false NOT NULL,
"host" text,
"letsEncryptEmail" text,
"sshPrivateKey" text,
"enableDockerCleanup" boolean DEFAULT false NOT NULL,
"logCleanupCron" text DEFAULT '0 0 * * *',
"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
);
--> statement-breakpoint
-- Migrar datos del usuario owner único hacia web_server
INSERT INTO "web_server" (
"webServerId",
"serverIp",
"certificateType",
"https",
"host",
"letsEncryptEmail",
"sshPrivateKey",
"enableDockerCleanup",
"logCleanupCron",
"metricsConfig"
)
SELECT
gen_random_uuid() as "webServerId",
u."serverIp",
COALESCE(u."certificateType", 'none') as "certificateType",
COALESCE(u."https", false) as "https",
u."host",
u."letsEncryptEmail",
u."sshPrivateKey",
COALESCE(u."enableDockerCleanup", false) as "enableDockerCleanup",
COALESCE(u."logCleanupCron", '0 0 * * *') as "logCleanupCron",
COALESCE(u."metricsConfig", '{"server":{"type":"Dokploy","refreshRate":60,"port":4500,"token":"","retentionDays":2,"cronJob":"","urlCallback":"","thresholds":{"cpu":0,"memory":0}},"containers":{"refreshRate":60,"services":{"include":[],"exclude":[]}}}') as "metricsConfig"
FROM "users" u
INNER JOIN "organization" o ON u.id = o.owner_id
LIMIT 1;
--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "created_at";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "serverIp";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "certificateType";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "https";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "host";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "letsEncryptEmail";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "sshPrivateKey";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "enableDockerCleanup";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "logCleanupCron";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "metricsConfig";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "cleanupCacheApplications";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "cleanupCacheOnPreviews";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN "cleanupCacheOnCompose";

View File

@@ -1,5 +1,5 @@
{
"id": "fa456cf0-3862-4027-a092-068beceda3be",
"id": "6f7f4450-7a3f-4827-981d-1a609d1091e0",
"prevId": "218e3c9b-ef86-4665-98af-56d65282b73b",
"version": "7",
"dialect": "postgresql",
@@ -822,8 +822,8 @@
"checkConstraints": {},
"isRLSEnabled": false
},
"public.user_temp": {
"name": "user_temp",
"public.users": {
"name": "users",
"schema": "",
"columns": {
"id": {
@@ -858,13 +858,6 @@
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"two_factor_enabled": {
"name": "two_factor_enabled",
"type": "boolean",
@@ -913,59 +906,6 @@
"primaryKey": false,
"notNull": true
},
"serverIp": {
"name": "serverIp",
"type": "text",
"primaryKey": false,
"notNull": false
},
"certificateType": {
"name": "certificateType",
"type": "certificateType",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'none'"
},
"https": {
"name": "https",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"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
},
"logCleanupCron": {
"name": "logCleanupCron",
"type": "text",
"primaryKey": false,
"notNull": false,
"default": "'0 0 * * *'"
},
"role": {
"name": "role",
"type": "text",
@@ -987,34 +927,6 @@
"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
},
"stripeCustomerId": {
"name": "stripeCustomerId",
"type": "text",
@@ -1039,8 +951,8 @@
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"user_temp_email_unique": {
"name": "user_temp_email_unique",
"users_email_unique": {
"name": "users_email_unique",
"nullsNotDistinct": false,
"columns": [
"email"
@@ -1974,10 +1886,10 @@
"onDelete": "cascade",
"onUpdate": "no action"
},
"backup_userId_user_temp_id_fk": {
"name": "backup_userId_user_temp_id_fk",
"backup_userId_users_id_fk": {
"name": "backup_userId_users_id_fk",
"tableFrom": "backup",
"tableTo": "user_temp",
"tableTo": "users",
"columnsFrom": [
"userId"
],
@@ -2686,10 +2598,10 @@
},
"indexes": {},
"foreignKeys": {
"session_temp_user_id_user_temp_id_fk": {
"name": "session_temp_user_id_user_temp_id_fk",
"session_temp_user_id_users_id_fk": {
"name": "session_temp_user_id_users_id_fk",
"tableFrom": "session_temp",
"tableTo": "user_temp",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
@@ -4064,10 +3976,10 @@
"onDelete": "cascade",
"onUpdate": "no action"
},
"git_provider_userId_user_temp_id_fk": {
"name": "git_provider_userId_user_temp_id_fk",
"git_provider_userId_users_id_fk": {
"name": "git_provider_userId_users_id_fk",
"tableFrom": "git_provider",
"tableTo": "user_temp",
"tableTo": "users",
"columnsFrom": [
"userId"
],
@@ -4739,8 +4651,8 @@
"checkConstraints": {},
"isRLSEnabled": false
},
"public.organization_role": {
"name": "organization_role",
"public.member_role": {
"name": "member_role",
"schema": "",
"columns": {
"roleId": {
@@ -4785,13 +4697,15 @@
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
"notNull": true,
"default": "now()"
},
"organizationId": {
"name": "organizationId",
@@ -4802,9 +4716,9 @@
},
"indexes": {},
"foreignKeys": {
"organization_role_organizationId_organization_id_fk": {
"name": "organization_role_organizationId_organization_id_fk",
"tableFrom": "organization_role",
"member_role_organizationId_organization_id_fk": {
"name": "member_role_organizationId_organization_id_fk",
"tableFrom": "member_role",
"tableTo": "organization",
"columnsFrom": [
"organizationId"
@@ -4817,7 +4731,15 @@
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"uniqueConstraints": {
"member_role_name_unique": {
"name": "member_role_name_unique",
"nullsNotDistinct": false,
"columns": [
"name"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
@@ -4938,10 +4860,10 @@
},
"indexes": {},
"foreignKeys": {
"account_user_id_user_temp_id_fk": {
"name": "account_user_id_user_temp_id_fk",
"account_user_id_users_id_fk": {
"name": "account_user_id_users_id_fk",
"tableFrom": "account",
"tableTo": "user_temp",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
@@ -5091,10 +5013,10 @@
},
"indexes": {},
"foreignKeys": {
"apikey_user_id_user_temp_id_fk": {
"name": "apikey_user_id_user_temp_id_fk",
"apikey_user_id_users_id_fk": {
"name": "apikey_user_id_users_id_fk",
"tableFrom": "apikey",
"tableTo": "user_temp",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
@@ -5179,10 +5101,10 @@
"onDelete": "cascade",
"onUpdate": "no action"
},
"invitation_inviter_id_user_temp_id_fk": {
"name": "invitation_inviter_id_user_temp_id_fk",
"invitation_inviter_id_users_id_fk": {
"name": "invitation_inviter_id_users_id_fk",
"tableFrom": "invitation",
"tableTo": "user_temp",
"tableTo": "users",
"columnsFrom": [
"inviter_id"
],
@@ -5221,17 +5143,11 @@
"primaryKey": false,
"notNull": true
},
"role": {
"name": "role",
"type": "text",
"primaryKey": false,
"notNull": true
},
"roleId": {
"name": "roleId",
"type": "text",
"primaryKey": false,
"notNull": true
"notNull": false
},
"created_at": {
"name": "created_at",
@@ -5245,69 +5161,6 @@
"primaryKey": false,
"notNull": false
},
"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[]",
@@ -5338,10 +5191,10 @@
"onDelete": "cascade",
"onUpdate": "no action"
},
"member_user_id_user_temp_id_fk": {
"name": "member_user_id_user_temp_id_fk",
"member_user_id_users_id_fk": {
"name": "member_user_id_users_id_fk",
"tableFrom": "member",
"tableTo": "user_temp",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
@@ -5351,10 +5204,10 @@
"onDelete": "cascade",
"onUpdate": "no action"
},
"member_roleId_organization_role_roleId_fk": {
"name": "member_roleId_organization_role_roleId_fk",
"member_roleId_member_role_roleId_fk": {
"name": "member_roleId_member_role_roleId_fk",
"tableFrom": "member",
"tableTo": "organization_role",
"tableTo": "member_role",
"columnsFrom": [
"roleId"
],
@@ -5420,10 +5273,10 @@
},
"indexes": {},
"foreignKeys": {
"organization_owner_id_user_temp_id_fk": {
"name": "organization_owner_id_user_temp_id_fk",
"organization_owner_id_users_id_fk": {
"name": "organization_owner_id_users_id_fk",
"tableFrom": "organization",
"tableTo": "user_temp",
"tableTo": "users",
"columnsFrom": [
"owner_id"
],
@@ -5479,10 +5332,10 @@
},
"indexes": {},
"foreignKeys": {
"two_factor_user_id_user_temp_id_fk": {
"name": "two_factor_user_id_user_temp_id_fk",
"two_factor_user_id_users_id_fk": {
"name": "two_factor_user_id_users_id_fk",
"tableFrom": "two_factor",
"tableTo": "user_temp",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
@@ -5689,10 +5542,10 @@
"onDelete": "cascade",
"onUpdate": "no action"
},
"schedule_userId_user_temp_id_fk": {
"name": "schedule_userId_user_temp_id_fk",
"schedule_userId_users_id_fk": {
"name": "schedule_userId_users_id_fk",
"tableFrom": "schedule",
"tableTo": "user_temp",
"tableTo": "users",
"columnsFrom": [
"userId"
],
@@ -6012,6 +5865,85 @@
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.web_server": {
"name": "web_server",
"schema": "",
"columns": {
"webServerId": {
"name": "webServerId",
"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'"
},
"https": {
"name": "https",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"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
},
"logCleanupCron": {
"name": "logCleanupCron",
"type": "text",
"primaryKey": false,
"notNull": false,
"default": "'0 0 * * *'"
},
"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"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -726,36 +726,8 @@
{
"idx": 103,
"version": "7",
"when": 1752043274261,
"tag": "0103_misty_shockwave",
"breakpoints": true
},
{
"idx": 104,
"version": "7",
"when": 1752046360607,
"tag": "0104_dusty_miss_america",
"breakpoints": true
},
{
"idx": 105,
"version": "7",
"when": 1752080331479,
"tag": "0105_clammy_leopardon",
"breakpoints": true
},
{
"idx": 106,
"version": "7",
"when": 1752358951289,
"tag": "0106_low_fat_cobra",
"breakpoints": true
},
{
"idx": 107,
"version": "7",
"when": 1752359583291,
"tag": "0107_clever_cobalt_man",
"when": 1752386222325,
"tag": "0103_living_hemingway",
"breakpoints": true
}
]

View File

@@ -92,24 +92,10 @@ export const member = pgTable("member", {
userId: text("user_id")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
role: text("role").notNull().$type<"owner" | "member" | "admin">(),
roleId: text("roleId").references(() => role.roleId, { onDelete: "cascade" }),
createdAt: timestamp("created_at").notNull(),
teamId: text("team_id"),
// Permissions
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()

View File

@@ -110,7 +110,7 @@ export const defaultPermissions = [
},
] as const;
export const role = pgTable("organization_role", {
export const role = pgTable("member_role", {
roleId: text("roleId")
.primaryKey()
.$defaultFn(() => nanoid()),