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

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