From 6ede43b9fb412a649d7dfbb73d6b9dc161c9a0c9 Mon Sep 17 00:00:00 2001 From: oiov Date: Fri, 13 Jun 2025 17:16:28 +0800 Subject: [PATCH] feat: support custom config record types in domain config --- .../dashboard/records/record-list.tsx | 2 +- app/api/admin/domain/route.ts | 3 + components/forms/domain-form.tsx | 29 +++++++ components/forms/record-form.tsx | 81 +++++++++++-------- lib/dto/domains.ts | 10 +-- lib/validations/domain.ts | 1 + locales/en.json | 5 +- locales/zh.json | 5 +- .../migrations/20250613103314/migration.sql | 61 ++++++++++++++ prisma/schema.prisma | 1 + public/sw.js.map | 2 +- 11 files changed, 155 insertions(+), 45 deletions(-) create mode 100644 prisma/migrations/20250613103314/migration.sql diff --git a/app/(protected)/dashboard/records/record-list.tsx b/app/(protected)/dashboard/records/record-list.tsx index e2fd429..0653e9d 100644 --- a/app/(protected)/dashboard/records/record-list.tsx +++ b/app/(protected)/dashboard/records/record-list.tsx @@ -365,7 +365,7 @@ export default function UserRecordsList({ user, action }: RecordListProps) { className="h-7 text-nowrap px-1 text-xs sm:px-1.5" size="sm" variant={"outline"} - disabled + disabled={!isAdmin} onClick={() => { setCurrentEditRecord(record); setShowForm(false); diff --git a/app/api/admin/domain/route.ts b/app/api/admin/domain/route.ts index 196a087..8806479 100644 --- a/app/api/admin/domain/route.ts +++ b/app/api/admin/domain/route.ts @@ -58,6 +58,7 @@ export async function POST(req: NextRequest) { cf_zone_id: data.cf_zone_id, cf_api_key: data.cf_api_key, cf_email: data.cf_email, + cf_record_types: data.cf_record_types, cf_api_key_encrypted: false, resend_api_key: data.resend_api_key, max_short_links: data.max_short_links, @@ -90,6 +91,7 @@ export async function PUT(req: NextRequest) { cf_zone_id, cf_api_key, cf_email, + cf_record_types, resend_api_key, max_short_links, max_email_forwards, @@ -110,6 +112,7 @@ export async function PUT(req: NextRequest) { cf_zone_id, cf_api_key, cf_email, + cf_record_types, cf_api_key_encrypted: false, resend_api_key, max_short_links, diff --git a/components/forms/domain-form.tsx b/components/forms/domain-form.tsx index 4ae4706..88f89f1 100644 --- a/components/forms/domain-form.tsx +++ b/components/forms/domain-form.tsx @@ -84,6 +84,7 @@ export function DomainForm({ cf_zone_id: initData?.cf_zone_id || "", cf_api_key: initData?.cf_api_key || "", cf_email: initData?.cf_email || "", + cf_record_types: initData?.cf_record_types || "CNAME,A,TXT", cf_api_key_encrypted: initData?.cf_api_key_encrypted || false, resend_api_key: initData?.resend_api_key || "", max_short_links: initData?.max_short_links || 0, @@ -466,6 +467,34 @@ export function DomainForm({ + +
+ +
+ +
+ {errors?.cf_record_types ? ( +

+ {errors.cf_record_types.message} +

+ ) : ( +

+ {t("Required")}. {t("Allowed record types")},{" "} + {t("use `,` to separate")} +

+ )} +
+
+
+
diff --git a/components/forms/record-form.tsx b/components/forms/record-form.tsx index 88e1f16..173ebfe 100644 --- a/components/forms/record-form.tsx +++ b/components/forms/record-form.tsx @@ -3,6 +3,7 @@ import { Dispatch, SetStateAction, + useEffect, useMemo, useState, useTransition, @@ -68,6 +69,7 @@ export function RecordForm({ initData?.zone_name || "wr.do", ); const [email, setEmail] = useState(initData?.user.email || user.email); + const [allowedRecordTypes, setAllowedRecordTypes] = useState([]); const isAdmin = action.indexOf("admin") > -1; const t = useTranslations("List"); @@ -92,14 +94,12 @@ export function RecordForm({ }); // Fetch the record domains - const { data: recordDomains, isLoading } = useSWR<{ domain_name: string }[]>( - "/api/domain?feature=record", - fetcher, - { - revalidateOnFocus: false, - dedupingInterval: 10000, - }, - ); + const { data: recordDomains, isLoading } = useSWR< + { domain_name: string; cf_record_types: string }[] + >("/api/domain?feature=record", fetcher, { + revalidateOnFocus: false, + dedupingInterval: 10000, + }); const { data: configs } = useSWR>( "/api/configs?key=enable_subdomain_apply", @@ -119,6 +119,16 @@ export function RecordForm({ return recordDomains[0].domain_name; }, [recordDomains, initData?.zone_name]); + useEffect(() => { + if (recordDomains && recordDomains.length > 0) { + setAllowedRecordTypes( + recordDomains + .find((d) => d.domain_name === validDefaultDomain)! + .cf_record_types.split(","), + ); + } + }, [currentZoneName, recordDomains, validDefaultDomain]); + const onSubmit = handleSubmit((data) => { if (isAdmin && type === "edit" && initData?.active === 2) { handleApplyRecord(data); @@ -357,25 +367,29 @@ export function RecordForm({

- + {isLoading ? ( + + ) : ( + + )}

{t("Required")}.

@@ -394,8 +408,7 @@ export function RecordForm({ size={32} {...register("name")} /> - {(currentRecordType === "CNAME" || - currentRecordType === "A") && ( + {["CNAME", "A", "AAAA"].includes(currentRecordType) && ( .{currentZoneName} @@ -417,9 +430,9 @@ export function RecordForm({ ) : (

- {currentRecordType === "CNAME" + {["CNAME"].includes(currentRecordType) ? `${t("Required")}. ${t("Example")} www.example.com` - : currentRecordType === "A" + : ["A", "AAAA"].includes(currentRecordType) ? `${t("Required")}. ${t("Example")} 8.8.8.8` : t("Required")}

@@ -476,7 +489,7 @@ export function RecordForm({ {t("Optional")}. {t("Time To Live")}.

- {["A", "CNAME"].includes(currentRecordType) && ( + {["CNAME", "A", "AAAA"].includes(currentRecordType) && (