import { useContext, useEffect, useState, createContext } from "react"; import { useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { z } from "zod"; import { zodResolver } from "@hookform/resolvers/zod"; import { Button } from "@/components/ui/button"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import { useToast } from "@/components/ui/use-toast"; import { getErrMessage } from "@/lib/error"; import { cn } from "@/lib/utils"; import { SSLProvider as SSLProviderType, SSLProviderSetting, Setting } from "@/domain/settings"; import { getSetting, update } from "@/repository/settings"; import { produce } from "immer"; type SSLProviderContext = { setting: Setting; onSubmit: (data: Setting) => void; setConfig: (config: Setting) => void; }; const Context = createContext({} as SSLProviderContext); export const useSSLProviderContext = () => { return useContext(Context); }; const SSLProvider = () => { const { t } = useTranslation(); const [config, setConfig] = useState>({ id: "", content: { provider: "letsencrypt", config: {}, }, }); const { toast } = useToast(); useEffect(() => { const fetchData = async () => { const setting = await getSetting("ssl-provider"); if (setting) { setConfig(setting); } }; fetchData(); }, []); const setProvider = (val: SSLProviderType) => { const newData = produce(config, (draft) => { if (draft.content) { draft.content.provider = val; } else { draft.content = { provider: val, config: {}, }; } }); setConfig(newData); }; const getOptionCls = (val: string) => { if (config.content?.provider === val) { return "border-primary dark:border-primary"; } return ""; }; const onSubmit = async (data: Setting) => { try { console.log(data); const resp = await update({ ...data }); setConfig(resp); toast({ title: t("common.update.succeeded.message"), description: t("common.update.succeeded.message"), }); } catch (e) { const message = getErrMessage(e); toast({ title: t("common.update.failed.message"), description: message, variant: "destructive", }); } }; return ( <>
{ setProvider(val as SSLProviderType); }} value={config.content?.provider} >
); }; const SSLProviderForm = ({ kind }: { kind: string }) => { const getForm = () => { switch (kind) { case "zerossl": return ; case "gts": return ; default: return ; } }; return ( <>
{getForm()}
); }; const getConfigStr = (content: SSLProviderSetting, kind: string, key: string) => { if (!content.config) { return ""; } if (!content.config[kind]) { return ""; } return content.config[kind][key] ?? ""; }; const SSLProviderLetsEncryptForm = () => { const { t } = useTranslation(); const { setting, onSubmit } = useSSLProviderContext(); const formSchema = z.object({ kind: z.literal("letsencrypt"), }); const form = useForm>({ resolver: zodResolver(formSchema), defaultValues: { kind: "letsencrypt", }, }); const onLocalSubmit = async (data: z.infer) => { const newData = produce(setting, (draft) => { if (!draft.content) { draft.content = { provider: data.kind, config: { letsencrypt: {}, }, }; } }); onSubmit(newData); }; return (
( )} />
); }; const SSLProviderZeroSSLForm = () => { const { t } = useTranslation(); const { setting, onSubmit } = useSSLProviderContext(); const formSchema = z.object({ kind: z.literal("zerossl"), eabKid: z.string().min(1, { message: t("settings.ca.eab_kid_hmac_key.errmsg.empty") }), eabHmacKey: z.string().min(1, { message: t("settings.ca.eab_kid_hmac_key.errmsg.empty") }), }); const form = useForm>({ resolver: zodResolver(formSchema), defaultValues: { kind: "zerossl", eabKid: "", eabHmacKey: "", }, }); useEffect(() => { if (setting.content) { const content = setting.content; form.reset({ eabKid: getConfigStr(content, "zerossl", "eabKid"), eabHmacKey: getConfigStr(content, "zerossl", "eabHmacKey"), }); } }, [setting]); const onLocalSubmit = async (data: z.infer) => { const newData = produce(setting, (draft) => { if (!draft.content) { draft.content = { provider: "zerossl", config: { zerossl: {}, }, }; } draft.content.config.zerossl = { eabKid: data.eabKid, eabHmacKey: data.eabHmacKey, }; }); onSubmit(newData); }; return (
( )} /> ( EAB_KID )} /> ( EAB_HMAC_KEY )} />
); }; const SSLProviderGtsForm = () => { const { t } = useTranslation(); const { setting, onSubmit } = useSSLProviderContext(); const formSchema = z.object({ kind: z.literal("gts"), eabKid: z.string().min(1, { message: t("settings.ca.eab_kid_hmac_key.errmsg.empty") }), eabHmacKey: z.string().min(1, { message: t("settings.ca.eab_kid_hmac_key.errmsg.empty") }), }); const form = useForm>({ resolver: zodResolver(formSchema), defaultValues: { kind: "gts", eabKid: "", eabHmacKey: "", }, }); useEffect(() => { if (setting.content) { const content = setting.content; form.reset({ eabKid: getConfigStr(content, "gts", "eabKid"), eabHmacKey: getConfigStr(content, "gts", "eabHmacKey"), }); } }, [setting]); const onLocalSubmit = async (data: z.infer) => { const newData = produce(setting, (draft) => { if (!draft.content) { draft.content = { provider: "gts", config: { zerossl: {}, }, }; } draft.content.config.gts = { eabKid: data.eabKid, eabHmacKey: data.eabHmacKey, }; }); onSubmit(newData); }; return (
( )} /> ( EAB_KID )} /> ( EAB_HMAC_KEY )} />
); }; export default SSLProvider;