diff --git a/go.mod b/go.mod index 23063186..0140ddc8 100644 --- a/go.mod +++ b/go.mod @@ -35,6 +35,7 @@ require ( github.com/blinkbean/dingtalk v1.1.3 github.com/byteplus-sdk/byteplus-sdk-golang v1.0.56 github.com/go-acme/lego/v4 v4.25.2 + github.com/go-cmd/cmd v1.4.3 github.com/go-lark/lark v1.16.0 github.com/go-resty/resty/v2 v2.16.5 github.com/go-viper/mapstructure/v2 v2.4.0 @@ -65,6 +66,7 @@ require ( github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.21 github.com/volcengine/volc-sdk-golang v1.0.219 github.com/volcengine/volcengine-go-sdk v1.1.30 + github.com/xhit/go-str2duration/v2 v2.1.0 gitlab.ecloud.com/ecloud/ecloudsdkclouddns v1.0.1 gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0 golang.org/x/crypto v0.41.0 @@ -97,7 +99,6 @@ require ( github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/go-acme/alidns-20150109/v4 v4.5.10 // indirect github.com/go-acme/tencentclouddnspod v1.0.1208 // indirect - github.com/go-cmd/cmd v1.4.3 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect @@ -127,6 +128,7 @@ require ( github.com/namedotcom/go/v4 v4.0.2 // indirect github.com/nrdcg/bunny-go v0.0.0-20250327222614-988a091fc7ea // indirect github.com/nrdcg/desec v0.11.0 // indirect + github.com/nrdcg/goacmedns v0.2.0 // indirect github.com/nrdcg/mailinabox v0.2.0 // indirect github.com/nrdcg/porkbun v0.4.0 // indirect github.com/peterhellberg/link v1.2.0 // indirect @@ -206,7 +208,7 @@ require ( github.com/nrdcg/namesilo v0.2.1 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/spf13/cast v1.9.2 // indirect - github.com/spf13/cobra v1.9.1 // indirect + github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.9 github.com/tjfoc/gmsm v1.4.1 // indirect golang.org/x/image v0.29.0 // indirect @@ -217,7 +219,7 @@ require ( golang.org/x/sys v0.35.0 // indirect golang.org/x/term v0.34.0 // indirect golang.org/x/text v0.28.0 // indirect - golang.org/x/time v0.12.0 + golang.org/x/time v0.12.0 // indirect golang.org/x/tools v0.36.0 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum index e925f0e7..74227562 100644 --- a/go.sum +++ b/go.sum @@ -404,9 +404,8 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8Wd github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= -github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= +github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= @@ -691,6 +690,8 @@ github.com/nrdcg/bunny-go v0.0.0-20250327222614-988a091fc7ea h1:OSgRS4kqOs/WuxuF github.com/nrdcg/bunny-go v0.0.0-20250327222614-988a091fc7ea/go.mod h1:IDRRngAngb2eTEaWgpO0hukQFI/vJId46fT1KErMytA= github.com/nrdcg/desec v0.11.0 h1:XZVHy07sg12y8FozMp+l7XvzPsdzog0AYXuQMaHBsfs= github.com/nrdcg/desec v0.11.0/go.mod h1:5+4vyhMRTs49V9CNoODF/HwT8Mwxv9DJ6j+7NekUnBs= +github.com/nrdcg/goacmedns v0.2.0 h1:ADMbThobzEMnr6kg2ohs4KGa3LFqmgiBA22/6jUWJR0= +github.com/nrdcg/goacmedns v0.2.0/go.mod h1:T5o6+xvSLrQpugmwHvrSNkzWht0UGAwj2ACBMhh73Cg= github.com/nrdcg/mailinabox v0.2.0 h1:IKq8mfKiVwNW2hQii/ng1dJ4yYMMv3HAP3fMFIq2CFk= github.com/nrdcg/mailinabox v0.2.0/go.mod h1:0yxqeYOiGyxAu7Sb94eMxHPIOsPYXAjTeA9ZhePhGnc= github.com/nrdcg/namesilo v0.2.1 h1:kLjCjsufdW/IlC+iSfAqj0iQGgKjlbUUeDJio5Y6eMg= @@ -893,6 +894,8 @@ github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+ github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= +github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= +github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/internal/certapply/applicators/sp_acmedns.go b/internal/certapply/applicators/sp_acmedns.go new file mode 100644 index 00000000..2a9ca423 --- /dev/null +++ b/internal/certapply/applicators/sp_acmedns.go @@ -0,0 +1,28 @@ +package applicators + +import ( + "fmt" + + "github.com/go-acme/lego/v4/challenge" + + "github.com/certimate-go/certimate/internal/domain" + "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/acmedns" + xmaps "github.com/certimate-go/certimate/pkg/utils/maps" +) + +func init() { + if err := ACMEDns01Registries.Register(domain.ACMEDns01ProviderTypeACMEDNS, func(options *ProviderFactoryOptions) (challenge.Provider, error) { + credentials := domain.AccessConfigForACMEDNS{} + if err := xmaps.Populate(options.ProviderAccessConfig, &credentials); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + provider, err := acmedns.NewChallengeProvider(&acmedns.ChallengeProviderConfig{ + ServerUrl: credentials.ServerUrl, + Credentials: credentials.Credentials, + }) + return provider, err + }); err != nil { + panic(err) + } +} diff --git a/internal/certapply/client_certifier.go b/internal/certapply/client_certifier.go index e547aa5f..30c1574e 100644 --- a/internal/certapply/client_certifier.go +++ b/internal/certapply/client_certifier.go @@ -22,8 +22,9 @@ import ( ) type ObtainCertificateRequest struct { - Domains []string - KeyType certcrypto.KeyType + Domains []string + KeyType certcrypto.KeyType + ValidityTo time.Time // 提供商相关 ChallengeType string @@ -153,6 +154,7 @@ func (c *ACMEClient) ObtainCertificate(request *ObtainCertificateRequest) (*Obta Domains: request.Domains, Bundle: true, Profile: request.ACMEProfile, + NotAfter: request.ValidityTo, ReplacesCertID: lo.If(request.ARIReplacesAcctUrl == c.account.ACMEAcctUrl, request.ARIReplacesCertId).Else(""), } resp, err := c.client.Certificate.Obtain(req) diff --git a/internal/domain/access.go b/internal/domain/access.go index de11b2af..d43462ed 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -32,6 +32,11 @@ type AccessConfigForACMECA struct { Endpoint string `json:"endpoint"` } +type AccessConfigForACMEDNS struct { + ServerUrl string `json:"serverUrl"` + Credentials string `json:"credentials"` +} + type AccessConfigForACMEHttpReq struct { Endpoint string `json:"endpoint"` Mode string `json:"mode,omitempty"` diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 4da89030..c7f32c2c 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -11,6 +11,7 @@ NOTICE: If you add new constant, please keep ASCII order. const ( AccessProviderType1Panel = AccessProviderType("1panel") AccessProviderTypeACMECA = AccessProviderType("acmeca") + AccessProviderTypeACMEDNS = AccessProviderType("acmedns") AccessProviderTypeACMEHttpReq = AccessProviderType("acmehttpreq") AccessProviderTypeAkamai = AccessProviderType("akamai") // Akamai(预留) AccessProviderTypeAliyun = AccessProviderType("aliyun") @@ -121,6 +122,7 @@ ACME DNS-01 提供商常量值。 NOTICE: If you add new constant, please keep ASCII order. */ const ( + ACMEDns01ProviderTypeACMEDNS = ACMEDns01ProviderType(AccessProviderTypeACMEDNS) ACMEDns01ProviderTypeACMEHttpReq = ACMEDns01ProviderType(AccessProviderTypeACMEHttpReq) ACMEDns01ProviderTypeAliyun = ACMEDns01ProviderType(AccessProviderTypeAliyun) // 兼容旧值,等同于 [ACMEDns01ProviderTypeAliyunDNS] ACMEDns01ProviderTypeAliyunDNS = ACMEDns01ProviderType(AccessProviderTypeAliyun + "-dns") diff --git a/internal/domain/workflow.go b/internal/domain/workflow.go index d3b48432..f5b1f13b 100644 --- a/internal/domain/workflow.go +++ b/internal/domain/workflow.go @@ -150,6 +150,7 @@ func (c WorkflowNodeConfig) AsBizApply() WorkflowNodeConfigForBizApply { CAProvider: xmaps.GetString(c, "caProvider"), CAProviderAccessId: xmaps.GetString(c, "caProviderAccessId"), CAProviderConfig: xmaps.GetKVMapAny(c, "caProviderConfig"), + ValidityLifetime: xmaps.GetString(c, "validityLifetime"), ACMEProfile: xmaps.GetString(c, "acmeProfile"), Nameservers: nameservers, DnsPropagationWait: xmaps.GetInt32(c, "dnsPropagationWait"), @@ -216,10 +217,11 @@ type WorkflowNodeConfigForBizApply struct { Provider string `json:"provider"` // 质询提供商 ProviderAccessId string `json:"providerAccessId"` // 质询提供商授权记录 ID ProviderConfig map[string]any `json:"providerConfig,omitempty"` // 质询提供商额外配置 - KeyAlgorithm string `json:"keyAlgorithm,omitempty"` // 证书算法 CAProvider string `json:"caProvider,omitempty"` // CA 提供商(零值时使用全局配置) CAProviderAccessId string `json:"caProviderAccessId,omitempty"` // CA 提供商授权记录 ID CAProviderConfig map[string]any `json:"caProviderConfig,omitempty"` // CA 提供商额外配置 + KeyAlgorithm string `json:"keyAlgorithm,omitempty"` // 证书算法 + ValidityLifetime string `json:"validityLifetime,omitempty"` // 证书有效期,形如 "30d"、"6h" ACMEProfile string `json:"acmeProfile,omitempty"` // ACME Profiles Extension Nameservers []string `json:"nameservers,omitempty"` // DNS 服务器列表,以半角分号分隔 DnsPropagationWait int32 `json:"dnsPropagationWait,omitempty"` // DNS 传播等待时间,等同于 lego 的 `--dns-propagation-wait` 参数 diff --git a/internal/tools/mproc/sender.go b/internal/tools/mproc/sender.go index 822be69c..2a2f3add 100644 --- a/internal/tools/mproc/sender.go +++ b/internal/tools/mproc/sender.go @@ -41,7 +41,7 @@ func (s *sender[TIn, TOut]) SendWithContext(ctx context.Context, params *TIn) (* aesCryptor := xcrypto.NewAESCryptor(aesKey) // 准备临时输入文件 - tempIn, err := os.CreateTemp("", "certimate_mprocin_*.tmp") + tempIn, err := os.CreateTemp("", "certimate.mprocin_*.tmp") if err != nil { return nil, fmt.Errorf("failed to create temp input file: %w", err) } else { @@ -64,7 +64,7 @@ func (s *sender[TIn, TOut]) SendWithContext(ctx context.Context, params *TIn) (* defer os.Remove(tempIn.Name()) // 准备临时输出文件 - tempOut, err := os.CreateTemp("", "certimate_mprocout_*.tmp") + tempOut, err := os.CreateTemp("", "certimate.mprocout_*.tmp") if err != nil { return nil, fmt.Errorf("failed to create temp output file: %w", err) } else { @@ -73,7 +73,7 @@ func (s *sender[TIn, TOut]) SendWithContext(ctx context.Context, params *TIn) (* defer os.Remove(tempOut.Name()) // 准备临时错误文件 - tempErr, err := os.CreateTemp("", "certimate_mprocerr_*.tmp") + tempErr, err := os.CreateTemp("", "certimate.mprocerr_*.tmp") if err != nil { return nil, fmt.Errorf("failed to create temp error file: %w", err) } else { diff --git a/internal/workflow/engine/executor_bizapply.go b/internal/workflow/engine/executor_bizapply.go index 68f107e2..a69d09ed 100644 --- a/internal/workflow/engine/executor_bizapply.go +++ b/internal/workflow/engine/executor_bizapply.go @@ -15,6 +15,7 @@ import ( "github.com/go-acme/lego/v4/lego" legolog "github.com/go-acme/lego/v4/log" "github.com/samber/lo" + "github.com/xhit/go-str2duration/v2" "github.com/certimate-go/certimate/internal/app" "github.com/certimate-go/certimate/internal/certapply" @@ -261,7 +262,15 @@ func (ne *bizApplyNodeExecutor) executeObtain(execCtx *NodeExecutionContext, nod DnsPropagationTimeout: nodeCfg.DnsPropagationTimeout, DnsTTL: nodeCfg.DnsTTL, HttpDelayWait: nodeCfg.HttpDelayWait, - ACMEProfile: nodeCfg.ACMEProfile, + ValidityTo: lo.If(nodeCfg.ValidityLifetime == "", time.Time{}). + ElseF(func() time.Time { + duration, err := str2duration.ParseDuration(nodeCfg.ValidityLifetime) + if err != nil { + return time.Time{} + } + return time.Now().Add(duration) + }), + ACMEProfile: nodeCfg.ACMEProfile, ARIReplacesAcctUrl: lo.If(lastCertificate == nil, ""). ElseF(func() string { if lastCertificate.ACMERenewed { diff --git a/pkg/core/ssl-applicator/acme-dns01/providers/acmedns/acmedns.go b/pkg/core/ssl-applicator/acme-dns01/providers/acmedns/acmedns.go new file mode 100644 index 00000000..33f95652 --- /dev/null +++ b/pkg/core/ssl-applicator/acme-dns01/providers/acmedns/acmedns.go @@ -0,0 +1,44 @@ +package acmedns + +import ( + "errors" + "fmt" + "os" + + "github.com/go-acme/lego/v4/providers/dns/acmedns" + + "github.com/certimate-go/certimate/pkg/core" +) + +type ChallengeProviderConfig struct { + ServerUrl string `json:"serverUrl"` + Credentials string `json:"credentials"` +} + +func NewChallengeProvider(config *ChallengeProviderConfig) (core.ACMEChallenger, error) { + if config == nil { + return nil, errors.New("the configuration of the acme challenge provider is nil") + } + + tempfile, err := os.CreateTemp("", "certimate.acmedns_*.tmp") + if err != nil { + return nil, fmt.Errorf("failed to create temp credentials file: %w", err) + } else { + if _, err := tempfile.Write([]byte(config.Credentials)); err != nil { + return nil, fmt.Errorf("failed to write temp credentials file: %w", err) + } + + tempfile.Close() + } + + providerConfig := acmedns.NewDefaultConfig() + providerConfig.APIBase = config.ServerUrl + providerConfig.StoragePath = tempfile.Name() + + provider, err := acmedns.NewDNSProviderConfig(providerConfig) + if err != nil { + return nil, err + } + + return provider, nil +} diff --git a/ui/public/imgs/providers/acmedns.png b/ui/public/imgs/providers/acmedns.png new file mode 100644 index 00000000..9d0f5a9f Binary files /dev/null and b/ui/public/imgs/providers/acmedns.png differ diff --git a/ui/src/components/access/AccessForm.tsx b/ui/src/components/access/AccessForm.tsx index a339ed3f..742782a8 100644 --- a/ui/src/components/access/AccessForm.tsx +++ b/ui/src/components/access/AccessForm.tsx @@ -13,6 +13,7 @@ import { FormNestedFieldsContextProvider } from "./forms/_context"; import { useProviderFilterByUsage } from "./forms/_hooks"; import AccessConfigFieldsProvider1Panel from "./forms/AccessConfigFieldsProvider1Panel"; import AccessConfigFieldsProviderACMECA from "./forms/AccessConfigFieldsProviderACMECA"; +import AccessConfigFieldsProviderACMEDNS from "./forms/AccessConfigFieldsProviderACMEDNS"; import AccessConfigFieldsProviderACMEHttpReq from "./forms/AccessConfigFieldsProviderACMEHttpReq"; import AccessConfigFieldsProviderAliyun from "./forms/AccessConfigFieldsProviderAliyun"; import AccessConfigFieldsProviderAPISIX from "./forms/AccessConfigFieldsProviderAPISIX"; @@ -133,6 +134,9 @@ const AccessForm = ({ className, style, disabled, initialValues, mode, usage, .. case ACCESS_PROVIDERS.ACMECA: { return ; } + case ACCESS_PROVIDERS.ACMEDNS: { + return ; + } case ACCESS_PROVIDERS.ACMEHTTPREQ: { return ; } diff --git a/ui/src/components/access/forms/AccessConfigFieldsProvider1Panel.tsx b/ui/src/components/access/forms/AccessConfigFieldsProvider1Panel.tsx index c2e79e45..6441e14e 100644 --- a/ui/src/components/access/forms/AccessConfigFieldsProvider1Panel.tsx +++ b/ui/src/components/access/forms/AccessConfigFieldsProvider1Panel.tsx @@ -21,6 +21,7 @@ const AccessConfigFormFieldsProvider1Panel = () => { name={[parentNamePath, "serverUrl"]} initialValue={initialValues.serverUrl} label={t("access.form.1panel_server_url.label")} + extra={t("access.form.1panel_server_url.help")} rules={[formRule]} > diff --git a/ui/src/components/access/forms/AccessConfigFieldsProviderACMEDNS.tsx b/ui/src/components/access/forms/AccessConfigFieldsProviderACMEDNS.tsx new file mode 100644 index 00000000..c26cd012 --- /dev/null +++ b/ui/src/components/access/forms/AccessConfigFieldsProviderACMEDNS.tsx @@ -0,0 +1,77 @@ +import { getI18n, useTranslation } from "react-i18next"; +import { Form, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod/v4"; + +import TextFileInput from "@/components/TextFileInput"; + +import { useFormNestedFieldsContext } from "./_context"; + +const AccessConfigFieldsProviderACMEDNS = () => { + const { i18n, t } = useTranslation(); + + const { parentNamePath } = useFormNestedFieldsContext(); + const formSchema = z.object({ + [parentNamePath]: getSchema({ i18n }), + }); + const formRule = createSchemaFieldRule(formSchema); + const initialValues = getInitialValues(); + + return ( + <> + + + + + } + > + + + + ); +}; + +const getInitialValues = (): Nullish>> => { + return { + serverUrl: "https://auth.acme-dns.io/", + credentials: "", + }; +}; + +const getSchema = ({ i18n = getI18n() }: { i18n: ReturnType }) => { + const { t } = i18n; + + return z.object({ + serverUrl: z.url(t("common.errmsg.url_invalid")), + credentials: z + .string() + .max(20480, t("common.errmsg.string_max", { max: 20480 })) + .refine((v) => { + if (!v) return false; + + try { + const obj = JSON.parse(v); + return typeof obj === "object" && !Array.isArray(obj); + } catch { + return false; + } + }, t("access.form.acmedns_credentials.errmsg.json_invalid")), + }); +}; + +const _default = Object.assign(AccessConfigFieldsProviderACMEDNS, { + getInitialValues, + getSchema, +}); + +export default _default; diff --git a/ui/src/components/access/forms/AccessConfigFieldsProviderBaotaPanel.tsx b/ui/src/components/access/forms/AccessConfigFieldsProviderBaotaPanel.tsx index c5eca4b5..67802dd6 100644 --- a/ui/src/components/access/forms/AccessConfigFieldsProviderBaotaPanel.tsx +++ b/ui/src/components/access/forms/AccessConfigFieldsProviderBaotaPanel.tsx @@ -21,6 +21,7 @@ const AccessConfigFormFieldsProviderBaotaPanel = () => { name={[parentNamePath, "serverUrl"]} initialValue={initialValues.serverUrl} label={t("access.form.baotapanel_server_url.label")} + extra={t("access.form.baotapanel_server_url.help")} rules={[formRule]} > diff --git a/ui/src/components/access/forms/AccessConfigFieldsProviderBaotaWAF.tsx b/ui/src/components/access/forms/AccessConfigFieldsProviderBaotaWAF.tsx index dc4cd422..980534fd 100644 --- a/ui/src/components/access/forms/AccessConfigFieldsProviderBaotaWAF.tsx +++ b/ui/src/components/access/forms/AccessConfigFieldsProviderBaotaWAF.tsx @@ -21,6 +21,7 @@ const AccessConfigFormFieldsProviderBaotaWAF = () => { name={[parentNamePath, "serverUrl"]} initialValue={initialValues.serverUrl} label={t("access.form.baotawaf_server_url.label")} + extra={t("access.form.baotawaf_server_url.help")} rules={[formRule]} > diff --git a/ui/src/components/access/forms/AccessConfigFieldsProviderRatPanel.tsx b/ui/src/components/access/forms/AccessConfigFieldsProviderRatPanel.tsx index 09c4d156..675617b4 100644 --- a/ui/src/components/access/forms/AccessConfigFieldsProviderRatPanel.tsx +++ b/ui/src/components/access/forms/AccessConfigFieldsProviderRatPanel.tsx @@ -21,6 +21,7 @@ const AccessConfigFormFieldsProviderRatPanel = () => { name={[parentNamePath, "serverUrl"]} initialValue={initialValues.serverUrl} label={t("access.form.ratpanel_server_url.label")} + extra={t("access.form.ratpanel_server_url.help")} rules={[formRule]} > diff --git a/ui/src/components/access/forms/AccessConfigFormProvider1Panel.tsx b/ui/src/components/access/forms/AccessConfigFormProvider1Panel.tsx deleted file mode 100644 index c2e79e45..00000000 --- a/ui/src/components/access/forms/AccessConfigFormProvider1Panel.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { getI18n, useTranslation } from "react-i18next"; -import { Form, Input, Select, Switch } from "antd"; -import { createSchemaFieldRule } from "antd-zod"; -import { z } from "zod"; - -import { useFormNestedFieldsContext } from "./_context"; - -const AccessConfigFormFieldsProvider1Panel = () => { - const { i18n, t } = useTranslation(); - - const { parentNamePath } = useFormNestedFieldsContext(); - const formSchema = z.object({ - [parentNamePath]: getSchema({ i18n }), - }); - const formRule = createSchemaFieldRule(formSchema); - const initialValues = getInitialValues(); - - return ( - <> - - - - - - +
+