mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-06-24 08:35:26 +02:00
Merge branch 'canary' of github.com:ChristoferMendes/dokploy into feature/add-custom-webhook-notification-provider
This commit is contained in:
@@ -42,6 +42,7 @@ const baseApp: ApplicationNested = {
|
||||
triggerType: "push",
|
||||
appName: "",
|
||||
autoDeploy: true,
|
||||
endpointSpecSwarm: null,
|
||||
serverId: "",
|
||||
registryUrl: "",
|
||||
branch: null,
|
||||
|
||||
@@ -15,6 +15,7 @@ const baseApp: ApplicationNested = {
|
||||
giteaId: "",
|
||||
cleanCache: false,
|
||||
applicationStatus: "done",
|
||||
endpointSpecSwarm: null,
|
||||
appName: "",
|
||||
autoDeploy: true,
|
||||
enableSubmodules: false,
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -67,9 +67,10 @@ export const Dropzone = React.forwardRef<HTMLDivElement, DropzoneProps>(
|
||||
ref={inputRef}
|
||||
type="file"
|
||||
className={cn("hidden", className)}
|
||||
onChange={(e: ChangeEvent<HTMLInputElement>) =>
|
||||
onChange(e.target.files)
|
||||
}
|
||||
onChange={(e: ChangeEvent<HTMLInputElement>) => {
|
||||
onChange(e.target.files);
|
||||
e.target.value = "";
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
|
||||
39
apps/dokploy/drizzle/0120_lame_captain_midlands.sql
Normal file
39
apps/dokploy/drizzle/0120_lame_captain_midlands.sql
Normal file
@@ -0,0 +1,39 @@
|
||||
ALTER TABLE "user_temp" RENAME TO "user";--> statement-breakpoint
|
||||
ALTER TABLE "user" 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 "application" ADD COLUMN "endpointSpecSwarm" json;--> 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_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "apikey" ADD CONSTRAINT "apikey_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "invitation" ADD CONSTRAINT "invitation_inviter_id_user_id_fk" FOREIGN KEY ("inviter_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "member" ADD CONSTRAINT "member_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "organization" ADD CONSTRAINT "organization_owner_id_user_id_fk" FOREIGN KEY ("owner_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "two_factor" ADD CONSTRAINT "two_factor_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "backup" ADD CONSTRAINT "backup_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "git_provider" ADD CONSTRAINT "git_provider_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "schedule" ADD CONSTRAINT "schedule_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "session_temp" ADD CONSTRAINT "session_temp_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "user" ADD CONSTRAINT "user_email_unique" UNIQUE("email");
|
||||
6722
apps/dokploy/drizzle/meta/0120_snapshot.json
Normal file
6722
apps/dokploy/drizzle/meta/0120_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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": 1762632540024,
|
||||
"tag": "0120_lame_captain_midlands",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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,10 +252,10 @@ const disableServers = async (userId: string) => {
|
||||
};
|
||||
|
||||
const findUserByStripeCustomerId = async (stripeCustomerId: string) => {
|
||||
const user = db.query.users_temp.findFirst({
|
||||
where: eq(users_temp.stripeCustomerId, stripeCustomerId),
|
||||
const userResult = await db.query.user.findFirst({
|
||||
where: eq(user.stripeCustomerId, stripeCustomerId),
|
||||
});
|
||||
return user;
|
||||
return userResult;
|
||||
};
|
||||
|
||||
const activateServer = async (serverId: string) => {
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -66,7 +66,7 @@ import {
|
||||
apiUpdateTelegram,
|
||||
notifications,
|
||||
server,
|
||||
users_temp,
|
||||
user,
|
||||
} from "@/server/db/schema";
|
||||
|
||||
export const notificationRouter = createTRPCRouter({
|
||||
@@ -366,9 +366,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) {
|
||||
|
||||
Reference in New Issue
Block a user