Skip to content

Commit 48ec0a7

Browse files
authored
Merge pull request #1637 from Dokploy/1601-duplicate-domain-bug
feat(settings): add HTTPS support and update user schema
2 parents b3bd9ba + bca6af7 commit 48ec0a7

File tree

8 files changed

+5502
-49
lines changed

8 files changed

+5502
-49
lines changed

apps/dokploy/__test__/traefik/server/update-server-config.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
import { beforeEach, expect, test, vi } from "vitest";
1515

1616
const baseAdmin: User = {
17+
https: false,
1718
enablePaidFeatures: false,
1819
metricsConfig: {
1920
containers: {
@@ -73,7 +74,6 @@ beforeEach(() => {
7374

7475
test("Should read the configuration file", () => {
7576
const config: FileConfig = loadOrCreateConfig("dokploy");
76-
7777
expect(config.http?.routers?.["dokploy-router-app"]?.service).toBe(
7878
"dokploy-service-app",
7979
);
@@ -83,6 +83,7 @@ test("Should apply redirect-to-https", () => {
8383
updateServerTraefik(
8484
{
8585
...baseAdmin,
86+
https: true,
8687
certificateType: "letsencrypt",
8788
},
8889
"example.com",

apps/dokploy/components/dashboard/settings/web-domain.tsx

Lines changed: 74 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
import {
1010
Form,
1111
FormControl,
12+
FormDescription,
1213
FormField,
1314
FormItem,
1415
FormLabel,
@@ -22,6 +23,7 @@ import {
2223
SelectTrigger,
2324
SelectValue,
2425
} from "@/components/ui/select";
26+
import { Switch } from "@/components/ui/switch";
2527
import { api } from "@/utils/api";
2628
import { zodResolver } from "@hookform/resolvers/zod";
2729
import { GlobeIcon } from "lucide-react";
@@ -33,11 +35,19 @@ import { z } from "zod";
3335

3436
const addServerDomain = z
3537
.object({
36-
domain: z.string().min(1, { message: "URL is required" }),
38+
domain: z.string(),
3739
letsEncryptEmail: z.string(),
40+
https: z.boolean().optional(),
3841
certificateType: z.enum(["letsencrypt", "none", "custom"]),
3942
})
4043
.superRefine((data, ctx) => {
44+
if (data.https && !data.certificateType) {
45+
ctx.addIssue({
46+
code: z.ZodIssueCode.custom,
47+
path: ["certificateType"],
48+
message: "Required",
49+
});
50+
}
4151
if (data.certificateType === "letsencrypt" && !data.letsEncryptEmail) {
4252
ctx.addIssue({
4353
code: z.ZodIssueCode.custom,
@@ -61,15 +71,18 @@ export const WebDomain = () => {
6171
domain: "",
6272
certificateType: "none",
6373
letsEncryptEmail: "",
74+
https: false,
6475
},
6576
resolver: zodResolver(addServerDomain),
6677
});
78+
const https = form.watch("https");
6779
useEffect(() => {
6880
if (data) {
6981
form.reset({
7082
domain: data?.user?.host || "",
7183
certificateType: data?.user?.certificateType,
7284
letsEncryptEmail: data?.user?.letsEncryptEmail || "",
85+
https: data?.user?.https || false,
7386
});
7487
}
7588
}, [form, form.reset, data]);
@@ -79,6 +92,7 @@ export const WebDomain = () => {
7992
host: data.domain,
8093
letsEncryptEmail: data.letsEncryptEmail,
8194
certificateType: data.certificateType,
95+
https: data.https,
8296
})
8397
.then(async () => {
8498
await refetch();
@@ -155,44 +169,67 @@ export const WebDomain = () => {
155169
/>
156170
<FormField
157171
control={form.control}
158-
name="certificateType"
159-
render={({ field }) => {
160-
return (
161-
<FormItem className="md:col-span-2">
162-
<FormLabel>
163-
{t("settings.server.domain.form.certificate.label")}
164-
</FormLabel>
165-
<Select
166-
onValueChange={field.onChange}
167-
value={field.value}
168-
>
169-
<FormControl>
170-
<SelectTrigger>
171-
<SelectValue
172-
placeholder={t(
173-
"settings.server.domain.form.certificate.placeholder",
174-
)}
175-
/>
176-
</SelectTrigger>
177-
</FormControl>
178-
<SelectContent>
179-
<SelectItem value={"none"}>
180-
{t(
181-
"settings.server.domain.form.certificateOptions.none",
182-
)}
183-
</SelectItem>
184-
<SelectItem value={"letsencrypt"}>
185-
{t(
186-
"settings.server.domain.form.certificateOptions.letsencrypt",
187-
)}
188-
</SelectItem>
189-
</SelectContent>
190-
</Select>
172+
name="https"
173+
render={({ field }) => (
174+
<FormItem className="flex flex-row items-center justify-between p-3 mt-4 border rounded-lg shadow-sm w-full col-span-2">
175+
<div className="space-y-0.5">
176+
<FormLabel>HTTPS</FormLabel>
177+
<FormDescription>
178+
Automatically provision SSL Certificate.
179+
</FormDescription>
191180
<FormMessage />
192-
</FormItem>
193-
);
194-
}}
181+
</div>
182+
<FormControl>
183+
<Switch
184+
checked={field.value}
185+
onCheckedChange={field.onChange}
186+
/>
187+
</FormControl>
188+
</FormItem>
189+
)}
195190
/>
191+
{https && (
192+
<FormField
193+
control={form.control}
194+
name="certificateType"
195+
render={({ field }) => {
196+
return (
197+
<FormItem className="md:col-span-2">
198+
<FormLabel>
199+
{t("settings.server.domain.form.certificate.label")}
200+
</FormLabel>
201+
<Select
202+
onValueChange={field.onChange}
203+
value={field.value}
204+
>
205+
<FormControl>
206+
<SelectTrigger>
207+
<SelectValue
208+
placeholder={t(
209+
"settings.server.domain.form.certificate.placeholder",
210+
)}
211+
/>
212+
</SelectTrigger>
213+
</FormControl>
214+
<SelectContent>
215+
<SelectItem value={"none"}>
216+
{t(
217+
"settings.server.domain.form.certificateOptions.none",
218+
)}
219+
</SelectItem>
220+
<SelectItem value={"letsencrypt"}>
221+
{t(
222+
"settings.server.domain.form.certificateOptions.letsencrypt",
223+
)}
224+
</SelectItem>
225+
</SelectContent>
226+
</Select>
227+
<FormMessage />
228+
</FormItem>
229+
);
230+
}}
231+
/>
232+
)}
196233

197234
<div className="flex w-full justify-end col-span-2">
198235
<Button isLoading={isLoading} type="submit">
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE "user_temp" ADD COLUMN "https" boolean DEFAULT false NOT NULL;

0 commit comments

Comments
 (0)