Refactor user schema and update database references: rename 'users_temp' to 'user' across the codebase, update related database queries, and enhance endpoint specifications for swarm settings in various database schemas.

This commit is contained in:
Mauricio Siu
2025-11-08 13:54:32 -06:00
parent 1ce153371a
commit 2619733915
29 changed files with 7033 additions and 169 deletions
@@ -122,6 +122,22 @@ const NetworkSwarmSchema = z.array(
const LabelsSwarmSchema = z.record(z.string());
const EndpointPortConfigSwarmSchema = z
.object({
Protocol: z.string().optional(),
TargetPort: z.number().optional(),
PublishedPort: z.number().optional(),
PublishMode: z.string().optional(),
})
.strict();
const EndpointSpecSwarmSchema = z
.object({
Mode: z.string().optional(),
Ports: z.array(EndpointPortConfigSwarmSchema).optional(),
})
.strict();
const createStringToJSONSchema = (schema: z.ZodTypeAny) => {
return z
.string()
@@ -178,6 +194,9 @@ const addSwarmSettings = z.object({
labelsSwarm: createStringToJSONSchema(LabelsSwarmSchema).nullable(),
networkSwarm: createStringToJSONSchema(NetworkSwarmSchema).nullable(),
stopGracePeriodSwarm: z.bigint().nullable(),
endpointSpecSwarm: createStringToJSONSchema(
EndpointSpecSwarmSchema,
).nullable(),
});
type AddSwarmSettings = z.infer<typeof addSwarmSettings>;
@@ -234,6 +253,7 @@ export const AddSwarmSettings = ({ id, type }: Props) => {
labelsSwarm: null,
networkSwarm: null,
stopGracePeriodSwarm: null,
endpointSpecSwarm: null,
},
resolver: zodResolver(addSwarmSettings),
});
@@ -275,6 +295,9 @@ export const AddSwarmSettings = ({ id, type }: Props) => {
? JSON.stringify(data.networkSwarm, null, 2)
: null,
stopGracePeriodSwarm: normalizedStopGracePeriod,
endpointSpecSwarm: data.endpointSpecSwarm
? JSON.stringify(data.endpointSpecSwarm, null, 2)
: null,
});
}
}, [form, form.reset, data]);
@@ -296,6 +319,7 @@ export const AddSwarmSettings = ({ id, type }: Props) => {
labelsSwarm: data.labelsSwarm,
networkSwarm: data.networkSwarm,
stopGracePeriodSwarm: data.stopGracePeriodSwarm ?? null,
endpointSpecSwarm: data.endpointSpecSwarm,
})
.then(async () => {
toast.success("Swarm settings updated");
@@ -846,6 +870,67 @@ export const AddSwarmSettings = ({ id, type }: Props) => {
</FormItem>
)}
/>
<FormField
control={form.control}
name="endpointSpecSwarm"
render={({ field }) => (
<FormItem className="relative ">
<FormLabel>Endpoint Spec</FormLabel>
<TooltipProvider delayDuration={0}>
<Tooltip>
<TooltipTrigger asChild>
<FormDescription className="break-all w-fit flex flex-row gap-1 items-center">
Check the interface
<HelpCircle className="size-4 text-muted-foreground" />
</FormDescription>
</TooltipTrigger>
<TooltipContent
className="w-full z-[999]"
align="start"
side="bottom"
>
<code>
<pre>
{`{
Mode?: string | undefined;
Ports?: Array<{
Protocol?: string | undefined;
TargetPort?: number | undefined;
PublishedPort?: number | undefined;
PublishMode?: string | undefined;
}> | undefined;
}`}
</pre>
</code>
</TooltipContent>
</Tooltip>
</TooltipProvider>
<FormControl>
<CodeEditor
language="json"
placeholder={`{
"Mode": "dnsrr",
"Ports": [
{
"Protocol": "tcp",
"TargetPort": 5432,
"PublishedPort": 5432,
"PublishMode": "host"
}
]
}`}
className="h-[17rem] font-mono"
{...field}
value={field?.value || ""}
/>
</FormControl>
<pre>
<FormMessage />
</pre>
</FormItem>
)}
/>
<DialogFooter className="flex w-full flex-row justify-end md:col-span-2 m-0 sticky bottom-0 right-0 bg-muted border">
<Button
isLoading={isLoading}
@@ -0,0 +1,38 @@
ALTER TABLE "user_temp" RENAME TO "users";--> statement-breakpoint
ALTER TABLE "users" DROP CONSTRAINT "user_temp_email_unique";--> 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 "backup" DROP CONSTRAINT "backup_userId_user_temp_id_fk";
--> statement-breakpoint
ALTER TABLE "git_provider" DROP CONSTRAINT "git_provider_userId_user_temp_id_fk";
--> statement-breakpoint
ALTER TABLE "schedule" DROP CONSTRAINT "schedule_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 "mariadb" ADD COLUMN "endpointSpecSwarm" json;--> statement-breakpoint
ALTER TABLE "mongo" ADD COLUMN "endpointSpecSwarm" json;--> statement-breakpoint
ALTER TABLE "mysql" ADD COLUMN "endpointSpecSwarm" json;--> statement-breakpoint
ALTER TABLE "postgres" ADD COLUMN "endpointSpecSwarm" json;--> statement-breakpoint
ALTER TABLE "redis" ADD COLUMN "endpointSpecSwarm" json;--> 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 "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 "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 "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 "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 "users" ADD CONSTRAINT "users_email_unique" UNIQUE("email");
File diff suppressed because it is too large Load Diff
+13 -6
View File
@@ -800,12 +800,12 @@
"tag": "0113_complete_rafael_vega",
"breakpoints": true
},
{
"idx": 114,
"version": "7",
"when": 1759643172958,
"tag": "0114_dry_black_tom",
"breakpoints": true
{
"idx": 114,
"version": "7",
"when": 1759643172958,
"tag": "0114_dry_black_tom",
"breakpoints": true
},
{
"idx": 115,
@@ -841,6 +841,13 @@
"when": 1762142756443,
"tag": "0119_bouncy_morbius",
"breakpoints": true
},
{
"idx": 120,
"version": "7",
"when": 1762631079937,
"tag": "0120_premium_radioactive_man",
"breakpoints": true
}
]
}
+19 -29
View File
@@ -4,7 +4,7 @@ import { asc, eq } from "drizzle-orm";
import type { NextApiRequest, NextApiResponse } from "next";
import Stripe from "stripe";
import { db } from "@/server/db";
import { organization, server, users_temp } from "@/server/db/schema";
import { organization, server, user } from "@/server/db/schema";
const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET!;
@@ -64,13 +64,13 @@ export default async function handler(
session.subscription as string,
);
await db
.update(users_temp)
.update(user)
.set({
stripeCustomerId: session.customer as string,
stripeSubscriptionId: session.subscription as string,
serversQuantity: subscription?.items?.data?.[0]?.quantity ?? 0,
})
.where(eq(users_temp.id, adminId))
.where(eq(user.id, adminId))
.returning();
const admin = await findUserById(adminId);
@@ -85,14 +85,12 @@ export default async function handler(
const newSubscription = event.data.object as Stripe.Subscription;
await db
.update(users_temp)
.update(user)
.set({
stripeSubscriptionId: newSubscription.id,
stripeCustomerId: newSubscription.customer as string,
})
.where(
eq(users_temp.stripeCustomerId, newSubscription.customer as string),
)
.where(eq(user.stripeCustomerId, newSubscription.customer as string))
.returning();
break;
@@ -102,14 +100,12 @@ export default async function handler(
const newSubscription = event.data.object as Stripe.Subscription;
await db
.update(users_temp)
.update(user)
.set({
stripeSubscriptionId: null,
serversQuantity: 0,
})
.where(
eq(users_temp.stripeCustomerId, newSubscription.customer as string),
);
.where(eq(user.stripeCustomerId, newSubscription.customer as string));
const admin = await findUserByStripeCustomerId(
newSubscription.customer as string,
@@ -135,24 +131,20 @@ export default async function handler(
if (newSubscription.status === "active") {
await db
.update(users_temp)
.update(user)
.set({
serversQuantity: newSubscription?.items?.data?.[0]?.quantity ?? 0,
})
.where(
eq(users_temp.stripeCustomerId, newSubscription.customer as string),
);
.where(eq(user.stripeCustomerId, newSubscription.customer as string));
const newServersQuantity = admin.serversQuantity;
await updateServersBasedOnQuantity(admin.id, newServersQuantity);
} else {
await disableServers(admin.id);
await db
.update(users_temp)
.update(user)
.set({ serversQuantity: 0 })
.where(
eq(users_temp.stripeCustomerId, newSubscription.customer as string),
);
.where(eq(user.stripeCustomerId, newSubscription.customer as string));
}
break;
@@ -172,11 +164,11 @@ export default async function handler(
}
await db
.update(users_temp)
.update(user)
.set({
serversQuantity: suscription?.items?.data?.[0]?.quantity ?? 0,
})
.where(eq(users_temp.stripeCustomerId, suscription.customer as string));
.where(eq(user.stripeCustomerId, suscription.customer as string));
const admin = await findUserByStripeCustomerId(
suscription.customer as string,
@@ -205,13 +197,11 @@ export default async function handler(
return res.status(400).send("Webhook Error: Admin not found");
}
await db
.update(users_temp)
.update(user)
.set({
serversQuantity: 0,
})
.where(
eq(users_temp.stripeCustomerId, newInvoice.customer as string),
);
.where(eq(user.stripeCustomerId, newInvoice.customer as string));
await disableServers(admin.id);
}
@@ -229,13 +219,13 @@ export default async function handler(
await disableServers(admin.id);
await db
.update(users_temp)
.update(user)
.set({
stripeCustomerId: null,
stripeSubscriptionId: null,
serversQuantity: 0,
})
.where(eq(users_temp.stripeCustomerId, customer.id));
.where(eq(user.stripeCustomerId, customer.id));
break;
}
@@ -262,8 +252,8 @@ const disableServers = async (userId: string) => {
};
const findUserByStripeCustomerId = async (stripeCustomerId: string) => {
const user = db.query.users_temp.findFirst({
where: eq(users_temp.stripeCustomerId, stripeCustomerId),
const user = db.query.user.findFirst({
where: eq(user.stripeCustomerId, stripeCustomerId),
});
return user;
};
+3 -3
View File
@@ -1,6 +1,6 @@
import { findAdmin } from "@dokploy/server";
import { db } from "@dokploy/server/db";
import { users_temp } from "@dokploy/server/db/schema";
import { user } from "@dokploy/server/db/schema";
import { eq } from "drizzle-orm";
(async () => {
@@ -8,11 +8,11 @@ import { eq } from "drizzle-orm";
const result = await findAdmin();
const update = await db
.update(users_temp)
.update(user)
.set({
twoFactorEnabled: false,
})
.where(eq(users_temp.id, result.userId));
.where(eq(user.id, result.userId));
if (update) {
console.log("2FA reset successful");
@@ -1,8 +1,8 @@
import {
createDiscordNotification,
createEmailNotification,
createLarkNotification,
createGotifyNotification,
createLarkNotification,
createNtfyNotification,
createSlackNotification,
createTelegramNotification,
@@ -11,16 +11,16 @@ import {
removeNotificationById,
sendDiscordNotification,
sendEmailNotification,
sendLarkNotification,
sendGotifyNotification,
sendLarkNotification,
sendNtfyNotification,
sendServerThresholdNotifications,
sendSlackNotification,
sendTelegramNotification,
updateDiscordNotification,
updateEmailNotification,
updateLarkNotification,
updateGotifyNotification,
updateLarkNotification,
updateNtfyNotification,
updateSlackNotification,
updateTelegramNotification,
@@ -38,29 +38,29 @@ import { db } from "@/server/db";
import {
apiCreateDiscord,
apiCreateEmail,
apiCreateLark,
apiCreateGotify,
apiCreateLark,
apiCreateNtfy,
apiCreateSlack,
apiCreateTelegram,
apiFindOneNotification,
apiTestDiscordConnection,
apiTestEmailConnection,
apiTestLarkConnection,
apiTestGotifyConnection,
apiTestLarkConnection,
apiTestNtfyConnection,
apiTestSlackConnection,
apiTestTelegramConnection,
apiUpdateDiscord,
apiUpdateEmail,
apiUpdateLark,
apiUpdateGotify,
apiUpdateLark,
apiUpdateNtfy,
apiUpdateSlack,
apiUpdateTelegram,
notifications,
server,
users_temp,
user,
} from "@/server/db/schema";
export const notificationRouter = createTRPCRouter({
@@ -359,9 +359,9 @@ export const notificationRouter = createTRPCRouter({
if (input.ServerType === "Dokploy") {
const result = await db
.select()
.from(users_temp)
.from(user)
.where(
sql`${users_temp.metricsConfig}::jsonb -> 'server' ->> 'token' = ${input.Token}`,
sql`${user.metricsConfig}::jsonb -> 'server' ->> 'token' = ${input.Token}`,
);
if (!result?.[0]?.id) {
+3 -3
View File
@@ -6,7 +6,7 @@
// boolean,
// } from "drizzle-orm/pg-core";
// export const users_temp = pgTable("users_temp", {
// export const user = pgTable("user", {
// id: text("id").primaryKey(),
// name: text("name").notNull(),
// email: text("email").notNull().unique(),
@@ -29,7 +29,7 @@
// userAgent: text("user_agent"),
// userId: text("user_id")
// .notNull()
// .references(() => users_temp.id, { onDelete: "cascade" }),
// .references(() => user.id, { onDelete: "cascade" }),
// activeOrganizationId: text("active_organization_id"),
// });
@@ -39,7 +39,7 @@
// providerId: text("provider_id").notNull(),
// userId: text("user_id")
// .notNull()
// .references(() => users_temp.id, { onDelete: "cascade" }),
// .references(() => user.id, { onDelete: "cascade" }),
// accessToken: text("access_token"),
// refreshToken: text("refresh_token"),
// idToken: text("id_token"),
+15 -15
View File
@@ -9,7 +9,7 @@ import {
import { nanoid } from "nanoid";
import { projects } from "./project";
import { server } from "./server";
import { users_temp } from "./user";
import { user } from "./user";
export const account = pgTable("account", {
id: text("id")
@@ -21,7 +21,7 @@ export const account = pgTable("account", {
providerId: text("provider_id").notNull(),
userId: text("user_id")
.notNull()
.references(() => users_temp.id, { onDelete: "cascade" }),
.references(() => user.id, { onDelete: "cascade" }),
accessToken: text("access_token"),
refreshToken: text("refresh_token"),
idToken: text("id_token"),
@@ -39,9 +39,9 @@ export const account = pgTable("account", {
});
export const accountRelations = relations(account, ({ one }) => ({
user: one(users_temp, {
user: one(user, {
fields: [account.userId],
references: [users_temp.id],
references: [user.id],
}),
}));
@@ -65,15 +65,15 @@ export const organization = pgTable("organization", {
metadata: text("metadata"),
ownerId: text("owner_id")
.notNull()
.references(() => users_temp.id, { onDelete: "cascade" }),
.references(() => user.id, { onDelete: "cascade" }),
});
export const organizationRelations = relations(
organization,
({ one, many }) => ({
owner: one(users_temp, {
owner: one(user, {
fields: [organization.ownerId],
references: [users_temp.id],
references: [user.id],
}),
servers: many(server),
projects: many(projects),
@@ -90,7 +90,7 @@ export const member = pgTable("member", {
.references(() => organization.id, { onDelete: "cascade" }),
userId: text("user_id")
.notNull()
.references(() => users_temp.id, { onDelete: "cascade" }),
.references(() => user.id, { onDelete: "cascade" }),
role: text("role").notNull().$type<"owner" | "member" | "admin">(),
createdAt: timestamp("created_at").notNull(),
teamId: text("team_id"),
@@ -134,9 +134,9 @@ export const memberRelations = relations(member, ({ one }) => ({
fields: [member.organizationId],
references: [organization.id],
}),
user: one(users_temp, {
user: one(user, {
fields: [member.userId],
references: [users_temp.id],
references: [user.id],
}),
}));
@@ -151,7 +151,7 @@ export const invitation = pgTable("invitation", {
expiresAt: timestamp("expires_at").notNull(),
inviterId: text("inviter_id")
.notNull()
.references(() => users_temp.id, { onDelete: "cascade" }),
.references(() => user.id, { onDelete: "cascade" }),
teamId: text("team_id"),
});
@@ -168,7 +168,7 @@ export const twoFactor = pgTable("two_factor", {
backupCodes: text("backup_codes").notNull(),
userId: text("user_id")
.notNull()
.references(() => users_temp.id, { onDelete: "cascade" }),
.references(() => user.id, { onDelete: "cascade" }),
});
export const apikey = pgTable("apikey", {
@@ -179,7 +179,7 @@ export const apikey = pgTable("apikey", {
key: text("key").notNull(),
userId: text("user_id")
.notNull()
.references(() => users_temp.id, { onDelete: "cascade" }),
.references(() => user.id, { onDelete: "cascade" }),
refillInterval: integer("refill_interval"),
refillAmount: integer("refill_amount"),
lastRefillAt: timestamp("last_refill_at"),
@@ -198,8 +198,8 @@ export const apikey = pgTable("apikey", {
});
export const apikeyRelations = relations(apikey, ({ one }) => ({
user: one(users_temp, {
user: one(user, {
fields: [apikey.userId],
references: [users_temp.id],
references: [user.id],
}),
}));
+4 -4
View File
@@ -19,7 +19,7 @@ import { mariadb } from "./mariadb";
import { mongo } from "./mongo";
import { mysql } from "./mysql";
import { postgres } from "./postgres";
import { users_temp } from "./user";
import { user } from "./user";
export const databaseType = pgEnum("databaseType", [
"postgres",
"mariadb",
@@ -74,7 +74,7 @@ export const backups = pgTable("backup", {
mongoId: text("mongoId").references((): AnyPgColumn => mongo.mongoId, {
onDelete: "cascade",
}),
userId: text("userId").references(() => users_temp.id),
userId: text("userId").references(() => user.id),
// Only for compose backups
metadata: jsonb("metadata").$type<
| {
@@ -118,9 +118,9 @@ export const backupsRelations = relations(backups, ({ one, many }) => ({
fields: [backups.mongoId],
references: [mongo.mongoId],
}),
user: one(users_temp, {
user: one(user, {
fields: [backups.userId],
references: [users_temp.id],
references: [user.id],
}),
compose: one(compose, {
fields: [backups.composeId],
@@ -8,7 +8,7 @@ import { bitbucket } from "./bitbucket";
import { gitea } from "./gitea";
import { github } from "./github";
import { gitlab } from "./gitlab";
import { users_temp } from "./user";
import { user } from "./user";
export const gitProviderType = pgEnum("gitProviderType", [
"github",
@@ -32,7 +32,7 @@ export const gitProvider = pgTable("git_provider", {
.references(() => organization.id, { onDelete: "cascade" }),
userId: text("userId")
.notNull()
.references(() => users_temp.id, { onDelete: "cascade" }),
.references(() => user.id, { onDelete: "cascade" }),
});
export const gitProviderRelations = relations(gitProvider, ({ one }) => ({
@@ -56,9 +56,9 @@ export const gitProviderRelations = relations(gitProvider, ({ one }) => ({
fields: [gitProvider.organizationId],
references: [organization.id],
}),
user: one(users_temp, {
user: one(user, {
fields: [gitProvider.userId],
references: [users_temp.id],
references: [user.id],
}),
}));
+4
View File
@@ -9,6 +9,8 @@ import { mounts } from "./mount";
import { server } from "./server";
import {
applicationStatus,
type EndpointSpecSwarm,
EndpointSpecSwarmSchema,
type HealthCheckSwarm,
HealthCheckSwarmSchema,
type LabelsSwarm,
@@ -63,6 +65,7 @@ export const mariadb = pgTable("mariadb", {
labelsSwarm: json("labelsSwarm").$type<LabelsSwarm>(),
networkSwarm: json("networkSwarm").$type<NetworkSwarm[]>(),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "bigint" }),
endpointSpecSwarm: json("endpointSpecSwarm").$type<EndpointSpecSwarm>(),
replicas: integer("replicas").default(1).notNull(),
createdAt: text("createdAt")
.notNull()
@@ -130,6 +133,7 @@ const createSchema = createInsertSchema(mariadb, {
labelsSwarm: LabelsSwarmSchema.nullable(),
networkSwarm: NetworkSwarmSchema.nullable(),
stopGracePeriodSwarm: z.bigint().nullable(),
endpointSpecSwarm: EndpointSpecSwarmSchema.nullable(),
});
export const apiCreateMariaDB = createSchema
+4
View File
@@ -16,6 +16,8 @@ import { mounts } from "./mount";
import { server } from "./server";
import {
applicationStatus,
type EndpointSpecSwarm,
EndpointSpecSwarmSchema,
type HealthCheckSwarm,
HealthCheckSwarmSchema,
type LabelsSwarm,
@@ -66,6 +68,7 @@ export const mongo = pgTable("mongo", {
labelsSwarm: json("labelsSwarm").$type<LabelsSwarm>(),
networkSwarm: json("networkSwarm").$type<NetworkSwarm[]>(),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "bigint" }),
endpointSpecSwarm: json("endpointSpecSwarm").$type<EndpointSpecSwarm>(),
replicas: integer("replicas").default(1).notNull(),
createdAt: text("createdAt")
.notNull()
@@ -127,6 +130,7 @@ const createSchema = createInsertSchema(mongo, {
labelsSwarm: LabelsSwarmSchema.nullable(),
networkSwarm: NetworkSwarmSchema.nullable(),
stopGracePeriodSwarm: z.bigint().nullable(),
endpointSpecSwarm: EndpointSpecSwarmSchema.nullable(),
});
export const apiCreateMongo = createSchema
+4
View File
@@ -9,6 +9,8 @@ import { mounts } from "./mount";
import { server } from "./server";
import {
applicationStatus,
type EndpointSpecSwarm,
EndpointSpecSwarmSchema,
type HealthCheckSwarm,
HealthCheckSwarmSchema,
type LabelsSwarm,
@@ -61,6 +63,7 @@ export const mysql = pgTable("mysql", {
labelsSwarm: json("labelsSwarm").$type<LabelsSwarm>(),
networkSwarm: json("networkSwarm").$type<NetworkSwarm[]>(),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "bigint" }),
endpointSpecSwarm: json("endpointSpecSwarm").$type<EndpointSpecSwarm>(),
replicas: integer("replicas").default(1).notNull(),
createdAt: text("createdAt")
.notNull()
@@ -127,6 +130,7 @@ const createSchema = createInsertSchema(mysql, {
labelsSwarm: LabelsSwarmSchema.nullable(),
networkSwarm: NetworkSwarmSchema.nullable(),
stopGracePeriodSwarm: z.bigint().nullable(),
endpointSpecSwarm: EndpointSpecSwarmSchema.nullable(),
});
export const apiCreateMySql = createSchema
@@ -9,6 +9,8 @@ import { mounts } from "./mount";
import { server } from "./server";
import {
applicationStatus,
type EndpointSpecSwarm,
EndpointSpecSwarmSchema,
type HealthCheckSwarm,
HealthCheckSwarmSchema,
type LabelsSwarm,
@@ -61,6 +63,7 @@ export const postgres = pgTable("postgres", {
labelsSwarm: json("labelsSwarm").$type<LabelsSwarm>(),
networkSwarm: json("networkSwarm").$type<NetworkSwarm[]>(),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "bigint" }),
endpointSpecSwarm: json("endpointSpecSwarm").$type<EndpointSpecSwarm>(),
replicas: integer("replicas").default(1).notNull(),
createdAt: text("createdAt")
.notNull()
@@ -120,6 +123,7 @@ const createSchema = createInsertSchema(postgres, {
labelsSwarm: LabelsSwarmSchema.nullable(),
networkSwarm: NetworkSwarmSchema.nullable(),
stopGracePeriodSwarm: z.bigint().nullable(),
endpointSpecSwarm: EndpointSpecSwarmSchema.nullable(),
});
export const apiCreatePostgres = createSchema
+4 -1
View File
@@ -5,10 +5,11 @@ import { nanoid } from "nanoid";
import { z } from "zod";
import { environments } from "./environment";
import { mounts } from "./mount";
import { projects } from "./project";
import { server } from "./server";
import {
applicationStatus,
type EndpointSpecSwarm,
EndpointSpecSwarmSchema,
type HealthCheckSwarm,
HealthCheckSwarmSchema,
type LabelsSwarm,
@@ -61,6 +62,7 @@ export const redis = pgTable("redis", {
labelsSwarm: json("labelsSwarm").$type<LabelsSwarm>(),
networkSwarm: json("networkSwarm").$type<NetworkSwarm[]>(),
stopGracePeriodSwarm: bigint("stopGracePeriodSwarm", { mode: "bigint" }),
endpointSpecSwarm: json("endpointSpecSwarm").$type<EndpointSpecSwarm>(),
replicas: integer("replicas").default(1).notNull(),
environmentId: text("environmentId")
@@ -110,6 +112,7 @@ const createSchema = createInsertSchema(redis, {
labelsSwarm: LabelsSwarmSchema.nullable(),
networkSwarm: NetworkSwarmSchema.nullable(),
stopGracePeriodSwarm: z.bigint().nullable(),
endpointSpecSwarm: EndpointSpecSwarmSchema.nullable(),
});
export const apiCreateRedis = createSchema
+4 -4
View File
@@ -7,7 +7,7 @@ import { applications } from "./application";
import { compose } from "./compose";
import { deployments } from "./deployment";
import { server } from "./server";
import { users_temp } from "./user";
import { user } from "./user";
import { generateAppName } from "./utils";
export const shellTypes = pgEnum("shellType", ["bash", "sh"]);
@@ -45,7 +45,7 @@ export const schedules = pgTable("schedule", {
serverId: text("serverId").references(() => server.serverId, {
onDelete: "cascade",
}),
userId: text("userId").references(() => users_temp.id, {
userId: text("userId").references(() => user.id, {
onDelete: "cascade",
}),
enabled: boolean("enabled").notNull().default(true),
@@ -69,9 +69,9 @@ export const schedulesRelations = relations(schedules, ({ one, many }) => ({
fields: [schedules.serverId],
references: [server.serverId],
}),
user: one(users_temp, {
user: one(user, {
fields: [schedules.userId],
references: [users_temp.id],
references: [user.id],
}),
deployments: many(deployments),
}));
+2 -2
View File
@@ -1,5 +1,5 @@
import { pgTable, text, timestamp } from "drizzle-orm/pg-core";
import { users_temp } from "./user";
import { user } from "./user";
// OLD TABLE
export const session = pgTable("session_temp", {
@@ -12,7 +12,7 @@ export const session = pgTable("session_temp", {
userAgent: text("user_agent"),
userId: text("user_id")
.notNull()
.references(() => users_temp.id, { onDelete: "cascade" }),
.references(() => user.id, { onDelete: "cascade" }),
impersonatedBy: text("impersonated_by"),
activeOrganizationId: text("active_organization_id"),
});
+28
View File
@@ -74,6 +74,18 @@ export interface LabelsSwarm {
[name: string]: string;
}
export interface EndpointPortConfigSwarm {
Protocol?: string | undefined;
TargetPort?: number | undefined;
PublishedPort?: number | undefined;
PublishMode?: string | undefined;
}
export interface EndpointSpecSwarm {
Mode?: string | undefined;
Ports?: EndpointPortConfigSwarm[] | undefined;
}
export const HealthCheckSwarmSchema = z
.object({
Test: z.array(z.string()).optional(),
@@ -161,3 +173,19 @@ export const NetworkSwarmSchema = z.array(
);
export const LabelsSwarmSchema = z.record(z.string());
export const EndpointPortConfigSwarmSchema = z
.object({
Protocol: z.string().optional(),
TargetPort: z.number().optional(),
PublishedPort: z.number().optional(),
PublishMode: z.string().optional(),
})
.strict();
export const EndpointSpecSwarmSchema = z
.object({
Mode: z.string().optional(),
Ports: z.array(EndpointPortConfigSwarmSchema).optional(),
})
.strict();
+4 -4
View File
@@ -26,7 +26,7 @@ import { certificateType } from "./shared";
// OLD TABLE
// TEMP
export const users_temp = pgTable("user_temp", {
export const user = pgTable("users", {
id: text("id")
.notNull()
.primaryKey()
@@ -122,9 +122,9 @@ export const users_temp = pgTable("user_temp", {
serversQuantity: integer("serversQuantity").notNull().default(0),
});
export const usersRelations = relations(users_temp, ({ one, many }) => ({
export const usersRelations = relations(user, ({ one, many }) => ({
account: one(account, {
fields: [users_temp.id],
fields: [user.id],
references: [account.userId],
}),
organizations: many(organization),
@@ -134,7 +134,7 @@ export const usersRelations = relations(users_temp, ({ one, many }) => ({
schedules: many(schedules),
}));
const createSchema = createInsertSchema(users_temp, {
const createSchema = createInsertSchema(user, {
id: z.string().min(1),
isRegistered: z.boolean().optional(),
}).omit({
+1 -1
View File
@@ -203,7 +203,7 @@ const { handler, api } = betterAuth({
updateAge: 60 * 60 * 24,
},
user: {
modelName: "users_temp",
modelName: "user",
additionalFields: {
role: {
type: "string",
+13 -13
View File
@@ -3,26 +3,26 @@ import {
invitation,
member,
organization,
users_temp,
user,
} from "@dokploy/server/db/schema";
import { TRPCError } from "@trpc/server";
import { eq } from "drizzle-orm";
import { IS_CLOUD } from "../constants";
export const findUserById = async (userId: string) => {
const user = await db.query.users_temp.findFirst({
where: eq(users_temp.id, userId),
const userResult = await db.query.user.findFirst({
where: eq(user.id, userId),
// with: {
// account: true,
// },
});
if (!user) {
if (!userResult) {
throw new TRPCError({
code: "NOT_FOUND",
message: "User not found",
});
}
return user;
return userResult;
};
export const findOrganizationById = async (organizationId: string) => {
@@ -64,7 +64,7 @@ export const findAdmin = async () => {
};
export const getUserByToken = async (token: string) => {
const user = await db.query.invitation.findFirst({
const userResult = await db.query.invitation.findFirst({
where: eq(invitation.id, token),
columns: {
id: true,
@@ -76,29 +76,29 @@ export const getUserByToken = async (token: string) => {
},
});
if (!user) {
if (!userResult) {
throw new TRPCError({
code: "NOT_FOUND",
message: "Invitation not found",
});
}
const userAlreadyExists = await db.query.users_temp.findFirst({
where: eq(users_temp.email, user?.email || ""),
const userAlreadyExists = await db.query.user.findFirst({
where: eq(user.email, userResult?.email || ""),
});
const { expiresAt, ...rest } = user;
const { expiresAt, ...rest } = userResult;
return {
...rest,
isExpired: user.expiresAt < new Date(),
isExpired: userResult.expiresAt < new Date(),
userAlreadyExists: !!userAlreadyExists,
};
};
export const removeUserById = async (userId: string) => {
await db
.delete(users_temp)
.where(eq(users_temp.id, userId))
.delete(user)
.where(eq(user.id, userId))
.returning()
.then((res) => res[0]);
};
+6 -6
View File
@@ -1,10 +1,10 @@
import { db } from "@dokploy/server/db";
import { apikey, member, users_temp } from "@dokploy/server/db/schema";
import { apikey, member, user } from "@dokploy/server/db/schema";
import { TRPCError } from "@trpc/server";
import { and, eq } from "drizzle-orm";
import { auth } from "../lib/auth";
export type User = typeof users_temp.$inferSelect;
export type User = typeof user.$inferSelect;
export const addNewProject = async (
userId: string,
@@ -403,16 +403,16 @@ export const updateUser = async (userId: string, userData: Partial<User>) => {
}
}
const user = await db
.update(users_temp)
const userResult = await db
.update(user)
.set({
...userData,
})
.where(eq(users_temp.id, userId))
.where(eq(user.id, userId))
.returning()
.then((res) => res[0]);
return user;
return userResult;
};
export const createApiKey = async (
+2 -13
View File
@@ -4,6 +4,7 @@ import {
calculateResources,
generateBindMounts,
generateConfigContainer,
generateEndpointSpec,
generateFileMounts,
generateVolumeMounts,
prepareEnvironmentVariables,
@@ -89,19 +90,7 @@ export const buildMariadb = async (mariadb: MariadbNested) => {
},
Mode,
RollbackConfig,
EndpointSpec: {
Mode: "dnsrr",
Ports: externalPort
? [
{
Protocol: "tcp",
TargetPort: 3306,
PublishedPort: externalPort,
PublishMode: "host",
},
]
: [],
},
EndpointSpec: generateEndpointSpec(mariadb, 3306),
UpdateConfig,
...(StopGracePeriod !== undefined &&
StopGracePeriod !== null && { StopGracePeriod }),
+2 -13
View File
@@ -4,6 +4,7 @@ import {
calculateResources,
generateBindMounts,
generateConfigContainer,
generateEndpointSpec,
generateFileMounts,
generateVolumeMounts,
prepareEnvironmentVariables,
@@ -142,19 +143,7 @@ ${command ?? "wait $MONGOD_PID"}`;
},
Mode,
RollbackConfig,
EndpointSpec: {
Mode: "dnsrr",
Ports: externalPort
? [
{
Protocol: "tcp",
TargetPort: 27017,
PublishedPort: externalPort,
PublishMode: "host",
},
]
: [],
},
EndpointSpec: generateEndpointSpec(mongo, 27017),
UpdateConfig,
...(StopGracePeriod !== undefined &&
StopGracePeriod !== null && { StopGracePeriod }),
+2 -13
View File
@@ -4,6 +4,7 @@ import {
calculateResources,
generateBindMounts,
generateConfigContainer,
generateEndpointSpec,
generateFileMounts,
generateVolumeMounts,
prepareEnvironmentVariables,
@@ -95,19 +96,7 @@ export const buildMysql = async (mysql: MysqlNested) => {
},
Mode,
RollbackConfig,
EndpointSpec: {
Mode: "dnsrr",
Ports: externalPort
? [
{
Protocol: "tcp",
TargetPort: 3306,
PublishedPort: externalPort,
PublishMode: "host",
},
]
: [],
},
EndpointSpec: generateEndpointSpec(mysql, 3306),
UpdateConfig,
...(StopGracePeriod !== undefined &&
StopGracePeriod !== null && { StopGracePeriod }),
@@ -4,6 +4,7 @@ import {
calculateResources,
generateBindMounts,
generateConfigContainer,
generateEndpointSpec,
generateFileMounts,
generateVolumeMounts,
prepareEnvironmentVariables,
@@ -88,19 +89,7 @@ export const buildPostgres = async (postgres: PostgresNested) => {
},
Mode,
RollbackConfig,
EndpointSpec: {
Mode: "dnsrr",
Ports: externalPort
? [
{
Protocol: "tcp",
TargetPort: 5432,
PublishedPort: externalPort,
PublishMode: "host",
},
]
: [],
},
EndpointSpec: generateEndpointSpec(postgres, 5432),
UpdateConfig,
...(StopGracePeriod !== undefined &&
StopGracePeriod !== null && { StopGracePeriod }),
+2 -13
View File
@@ -4,6 +4,7 @@ import {
calculateResources,
generateBindMounts,
generateConfigContainer,
generateEndpointSpec,
generateFileMounts,
generateVolumeMounts,
prepareEnvironmentVariables,
@@ -85,19 +86,7 @@ export const buildRedis = async (redis: RedisNested) => {
},
Mode,
RollbackConfig,
EndpointSpec: {
Mode: "dnsrr",
Ports: externalPort
? [
{
Protocol: "tcp",
TargetPort: 6379,
PublishedPort: externalPort,
PublishMode: "host",
},
]
: [],
},
EndpointSpec: generateEndpointSpec(redis, 6379),
UpdateConfig,
...(StopGracePeriod !== undefined &&
StopGracePeriod !== null && { StopGracePeriod }),
+36
View File
@@ -464,6 +464,42 @@ export const generateConfigContainer = (
};
};
export const generateEndpointSpec = (
database: Partial<
PostgresNested | MysqlNested | MariadbNested | MongoNested | RedisNested
>,
defaultTargetPort: number,
) => {
const { endpointSpecSwarm, externalPort } = database;
if (endpointSpecSwarm) {
return {
...(endpointSpecSwarm.Mode && { Mode: endpointSpecSwarm.Mode }),
Ports:
endpointSpecSwarm.Ports?.map((port) => ({
Protocol: (port.Protocol || "tcp") as "tcp" | "udp" | "sctp",
TargetPort: port.TargetPort,
PublishedPort: port.PublishedPort || 0,
PublishMode: (port.PublishMode || "host") as "ingress" | "host",
})) || [],
};
}
return {
Mode: "dnsrr" as const,
Ports: externalPort
? [
{
Protocol: "tcp" as const,
TargetPort: defaultTargetPort,
PublishedPort: externalPort,
PublishMode: "host" as const,
},
]
: [],
};
};
export const generateBindMounts = (mounts: ApplicationNested["mounts"]) => {
if (!mounts || mounts.length === 0) {
return [];