diff --git a/internal/domain/access.go b/internal/domain/access.go index 889d37fa..bd4f41c1 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -32,6 +32,11 @@ type QiniuAccess struct { SecretKey string `json:"secretKey"` } +type DogeCloudAccess struct { + AccessKey string `json:"accessKey"` + SecretKey string `json:"secretKey"` +} + type NameSiloAccess struct { ApiKey string `json:"apiKey"` } diff --git a/ui/public/imgs/providers/dogecloud.svg b/ui/public/imgs/providers/dogecloud.svg new file mode 100644 index 00000000..253f9ae7 --- /dev/null +++ b/ui/public/imgs/providers/dogecloud.svg @@ -0,0 +1 @@ + diff --git a/ui/public/imgs/providers/google.svg b/ui/public/imgs/providers/google.svg index d5f4dbeb..120a7921 100644 --- a/ui/public/imgs/providers/google.svg +++ b/ui/public/imgs/providers/google.svg @@ -1,28 +1 @@ - - - - - Google-color - Created with Sketch. - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + diff --git a/ui/src/components/certimate/AccessDogeCloudForm.tsx b/ui/src/components/certimate/AccessDogeCloudForm.tsx new file mode 100644 index 00000000..66c8db6f --- /dev/null +++ b/ui/src/components/certimate/AccessDogeCloudForm.tsx @@ -0,0 +1,188 @@ +import { useForm } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import z from "zod"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { ClientResponseError } from "pocketbase"; + +import { Button } from "@/components/ui/button"; +import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; +import { Input } from "@/components/ui/input"; +import { PbErrorData } from "@/domain/base"; +import { accessProvidersMap, accessTypeFormSchema, type Access, type DogeCloudConfig } from "@/domain/access"; +import { save } from "@/repository/access"; +import { useConfigContext } from "@/providers/config"; + +type AccessDogeCloudFormProps = { + op: "add" | "edit" | "copy"; + data?: Access; + onAfterReq: () => void; +}; + +const AccessDogeCloudForm = ({ data, op, onAfterReq }: AccessDogeCloudFormProps) => { + const { addAccess, updateAccess } = useConfigContext(); + const { t } = useTranslation(); + const formSchema = z.object({ + id: z.string().optional(), + name: z + .string() + .min(1, "access.authorization.form.name.placeholder") + .max(64, t("common.errmsg.string_max", { max: 64 })), + configType: accessTypeFormSchema, + accessKey: z.string().min(1, "access.authorization.form.access_key.placeholder").max(64), + secretKey: z.string().min(1, "access.authorization.form.secret_key.placeholder").max(64), + }); + + let config: DogeCloudConfig = { + accessKey: "", + secretKey: "", + }; + if (data) config = data.config as DogeCloudConfig; + + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + id: data?.id, + name: data?.name || "", + configType: "dogecloud", + accessKey: config.accessKey, + secretKey: config.secretKey, + }, + }); + + const onSubmit = async (data: z.infer) => { + const req: Access = { + id: data.id as string, + name: data.name, + configType: data.configType, + usage: accessProvidersMap.get(data.configType)!.usage, + config: { + accessKey: data.accessKey, + secretKey: data.secretKey, + }, + }; + + try { + req.id = op == "copy" ? "" : req.id; + const rs = await save(req); + + onAfterReq(); + + req.id = rs.id; + req.created = rs.created; + req.updated = rs.updated; + if (data.id && op == "edit") { + updateAccess(req); + return; + } + addAccess(req); + } catch (e) { + const err = e as ClientResponseError; + + Object.entries(err.response.data as PbErrorData).forEach(([key, value]) => { + form.setError(key as keyof z.infer, { + type: "manual", + message: value.message, + }); + }); + + return; + } + }; + + return ( + <> +
+ { + e.stopPropagation(); + form.handleSubmit(onSubmit)(e); + }} + className="space-y-8" + > + ( + + {t("access.authorization.form.name.label")} + + + + + + + )} + /> + + ( + + {t("access.authorization.form.config.label")} + + + + + + + )} + /> + + ( + + {t("access.authorization.form.config.label")} + + + + + + + )} + /> + + ( + + {t("access.authorization.form.access_key.label")} + + + + + + + )} + /> + + ( + + {t("access.authorization.form.secret_key.label")} + + + + + + + )} + /> + + + +
+ +
+ + + + ); +}; + +export default AccessDogeCloudForm; diff --git a/ui/src/components/certimate/AccessEditDialog.tsx b/ui/src/components/certimate/AccessEditDialog.tsx index afb23068..f5c3c65e 100644 --- a/ui/src/components/certimate/AccessEditDialog.tsx +++ b/ui/src/components/certimate/AccessEditDialog.tsx @@ -9,6 +9,7 @@ import AccessAliyunForm from "./AccessAliyunForm"; import AccessTencentForm from "./AccessTencentForm"; import AccessHuaweiCloudForm from "./AccessHuaweicloudForm"; import AccessQiniuForm from "./AccessQiniuForm"; +import AccessDogeCloudForm from "./AccessDogeCloudForm"; import AccessAwsForm from "./AccessAwsForm"; import AccessCloudflareForm from "./AccessCloudflareForm"; import AccessNamesiloForm from "./AccessNamesiloForm"; @@ -82,6 +83,17 @@ const AccessEditDialog = ({ trigger, op, data, className }: AccessEditProps) => /> ); break; + case "dogecloud": + childComponent = ( + { + setOpen(false); + }} + /> + ); + break; case "aws": childComponent = ( = n ["aliyun", "common.provider.aliyun", "/imgs/providers/aliyun.svg", "all", "阿里云:alibaba cloud"], ["tencent", "common.provider.tencent", "/imgs/providers/tencent.svg", "all", "腾讯云:tencent cloud"], ["huaweicloud", "common.provider.huaweicloud", "/imgs/providers/huaweicloud.svg", "all", "华为云:huawei cloud"], - ["qiniu", "common.provider.qiniu", "/imgs/providers/qiniu.svg", "deploy", "七牛:qiniu"], + ["qiniu", "common.provider.qiniu", "/imgs/providers/qiniu.svg", "deploy", "七牛云:qiniu"], + ["dogecloud", "common.provider.dogecloud", "/imgs/providers/dogecloud.svg", "deploy", "多吉云:dogecloud:doge cloud"], ["aws", "common.provider.aws", "/imgs/providers/aws.svg", "apply", "亚马逊:amazon:aws"], ["cloudflare", "common.provider.cloudflare", "/imgs/providers/cloudflare.svg", "apply", "cloudflare:cf:cloud flare"], ["namesilo", "common.provider.namesilo", "/imgs/providers/namesilo.svg", "apply", "namesilo"], @@ -35,6 +36,7 @@ export const accessTypeFormSchema = z.union( z.literal("tencent"), z.literal("huaweicloud"), z.literal("qiniu"), + z.literal("dogecloud"), z.literal("aws"), z.literal("cloudflare"), z.literal("namesilo"), @@ -60,6 +62,7 @@ export type Access = { | TencentConfig | HuaweiCloudConfig | QiniuConfig + | DogeCloudConfig | AwsConfig | CloudflareConfig | NamesiloConfig @@ -96,6 +99,11 @@ export type QiniuConfig = { secretKey: string; }; +export type DogeCloudConfig = { + accessKey: string; + secretKey: string; +}; + export type AwsConfig = { region: string; accessKeyId: string; diff --git a/ui/src/i18n/locales/en/nls.common.json b/ui/src/i18n/locales/en/nls.common.json index fc545b4c..66c63104 100644 --- a/ui/src/i18n/locales/en/nls.common.json +++ b/ui/src/i18n/locales/en/nls.common.json @@ -70,6 +70,7 @@ "common.provider.huaweicloud.elb": "Huawei Cloud - ELB", "common.provider.qiniu": "Qiniu Cloud", "common.provider.qiniu.cdn": "Qiniu Cloud - CDN", + "common.provider.dogecloud": "Doge Cloud", "common.provider.aws": "AWS", "common.provider.cloudflare": "Cloudflare", "common.provider.namesilo": "Namesilo", diff --git a/ui/src/i18n/locales/zh/nls.common.json b/ui/src/i18n/locales/zh/nls.common.json index 487f90c5..aec122d2 100644 --- a/ui/src/i18n/locales/zh/nls.common.json +++ b/ui/src/i18n/locales/zh/nls.common.json @@ -70,6 +70,7 @@ "common.provider.huaweicloud.elb": "华为云 - 弹性负载均衡 ELB", "common.provider.qiniu": "七牛云", "common.provider.qiniu.cdn": "七牛云 - 内容分发网络 CDN", + "common.provider.dogecloud": "多吉云", "common.provider.aws": "AWS", "common.provider.cloudflare": "Cloudflare", "common.provider.namesilo": "Namesilo",