From 71c093c042dc008928711a13f43e92bb13a3d309 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Sun, 25 May 2025 21:54:39 +0800 Subject: [PATCH 01/11] refactor: clean code --- internal/applicant/providers.go | 2 +- internal/deployer/providers.go | 28 ++-- internal/domain/access.go | 22 +-- .../aliyun-esa/internal/lego.go | 10 +- .../lego-providers/powerdns/powerdns.go | 6 +- .../1panel-console/1panel_console.go | 6 +- .../1panel-console/1panel_console_test.go | 10 +- .../providers/1panel-site/1panel_site.go | 8 +- .../providers/1panel-site/1panel_site_test.go | 10 +- .../baotapanel-console/baotapanel_console.go | 6 +- .../baotapanel_console_test.go | 10 +- .../baotapanel-site/baotapanel_site.go | 6 +- .../baotapanel-site/baotapanel_site_test.go | 10 +- .../baotawaf-console/baotawaf_console.go | 6 +- .../baotawaf-console/baotawaf_console_test.go | 10 +- .../providers/baotawaf-site/baotawaf_site.go | 6 +- .../baotawaf-site/baotawaf_site_test.go | 10 +- .../core/deployer/providers/cdnfly/cdnfly.go | 6 +- .../deployer/providers/cdnfly/cdnfly_test.go | 10 +- .../deployer/providers/flexcdn/flexcdn.go | 6 +- .../providers/flexcdn/flexcdn_test.go | 10 +- .../core/deployer/providers/goedge/goedge.go | 6 +- .../deployer/providers/goedge/goedge_test.go | 10 +- .../core/deployer/providers/lecdn/lecdn.go | 6 +- .../deployer/providers/lecdn/lecdn_test.go | 10 +- .../deployer/providers/proxmoxve/proxmoxve.go | 6 +- .../providers/proxmoxve/proxmoxve_test.go | 10 +- .../ratpanel-console/ratpanel_console.go | 6 +- .../ratpanel-console/ratpanel_console_test.go | 10 +- .../providers/ratpanel-site/ratpanel_site.go | 6 +- .../ratpanel-site/ratpanel_site_test.go | 10 +- .../deployer/providers/safeline/safeline.go | 6 +- .../providers/safeline/safeline_test.go | 10 +- .../providers/mattermost/mattermost.go | 8 +- .../providers/1panel-ssl/1panel_ssl.go | 6 +- .../providers/1panel-ssl/1panel_ssl_test.go | 10 +- migrations/1748178000_upgrade.go | 60 ++++++++ .../access/AccessForm1PanelConfig.tsx | 14 +- .../access/AccessFormBaotaPanelConfig.tsx | 14 +- .../access/AccessFormBaotaWAFConfig.tsx | 14 +- .../access/AccessFormCdnflyConfig.tsx | 14 +- .../access/AccessFormFlexCDNConfig.tsx | 14 +- .../access/AccessFormGoEdgeConfig.tsx | 14 +- .../access/AccessFormLeCDNConfig.tsx | 14 +- .../access/AccessFormPowerDNSConfig.tsx | 14 +- .../access/AccessFormProxmoxVEConfig.tsx | 14 +- .../access/AccessFormRatPanelConfig.tsx | 14 +- .../access/AccessFormSafeLineConfig.tsx | 14 +- .../access/AccessFormWebhookConfig.tsx | 6 +- .../components/workflow/node/_SharedNode.tsx | 132 +++++++++++------- ui/src/domain/access.ts | 22 +-- ui/src/i18n/locales/en/nls.access.json | 83 ++++------- ui/src/i18n/locales/zh/nls.access.json | 83 ++++------- ui/src/i18n/locales/zh/nls.settings.json | 4 +- 54 files changed, 445 insertions(+), 417 deletions(-) create mode 100644 migrations/1748178000_upgrade.go diff --git a/internal/applicant/providers.go b/internal/applicant/providers.go index de47ae18..3e4de205 100644 --- a/internal/applicant/providers.go +++ b/internal/applicant/providers.go @@ -476,7 +476,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi } applicant, err := pPowerDNS.NewChallengeProvider(&pPowerDNS.ChallengeProviderConfig{ - ApiUrl: access.ApiUrl, + ServerUrl: access.ServerUrl, ApiKey: access.ApiKey, AllowInsecureConnections: access.AllowInsecureConnections, DnsPropagationTimeout: options.DnsPropagationTimeout, diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index d1d72408..e8dbaf1a 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -119,7 +119,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer switch options.Provider { case domain.DeploymentProviderType1PanelConsole: deployer, err := p1PanelConsole.NewDeployer(&p1PanelConsole.DeployerConfig{ - ApiUrl: access.ApiUrl, + ServerUrl: access.ServerUrl, ApiVersion: access.ApiVersion, ApiKey: access.ApiKey, AllowInsecureConnections: access.AllowInsecureConnections, @@ -129,7 +129,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer case domain.DeploymentProviderType1PanelSite: deployer, err := p1PanelSite.NewDeployer(&p1PanelSite.DeployerConfig{ - ApiUrl: access.ApiUrl, + ServerUrl: access.ServerUrl, ApiVersion: access.ApiVersion, ApiKey: access.ApiKey, AllowInsecureConnections: access.AllowInsecureConnections, @@ -454,7 +454,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer switch options.Provider { case domain.DeploymentProviderTypeBaotaPanelConsole: deployer, err := pBaotaPanelConsole.NewDeployer(&pBaotaPanelConsole.DeployerConfig{ - ApiUrl: access.ApiUrl, + ServerUrl: access.ServerUrl, ApiKey: access.ApiKey, AllowInsecureConnections: access.AllowInsecureConnections, AutoRestart: maputil.GetBool(options.ProviderServiceConfig, "autoRestart"), @@ -463,7 +463,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer case domain.DeploymentProviderTypeBaotaPanelSite: deployer, err := pBaotaPanelSite.NewDeployer(&pBaotaPanelSite.DeployerConfig{ - ApiUrl: access.ApiUrl, + ServerUrl: access.ServerUrl, ApiKey: access.ApiKey, AllowInsecureConnections: access.AllowInsecureConnections, SiteType: maputil.GetOrDefaultString(options.ProviderServiceConfig, "siteType", "other"), @@ -487,7 +487,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer switch options.Provider { case domain.DeploymentProviderTypeBaotaWAFConsole: deployer, err := pBaotaWAFConsole.NewDeployer(&pBaotaWAFConsole.DeployerConfig{ - ApiUrl: access.ApiUrl, + ServerUrl: access.ServerUrl, ApiKey: access.ApiKey, AllowInsecureConnections: access.AllowInsecureConnections, }) @@ -495,7 +495,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer case domain.DeploymentProviderTypeBaotaWAFSite: deployer, err := pBaotaWAFSite.NewDeployer(&pBaotaWAFSite.DeployerConfig{ - ApiUrl: access.ApiUrl, + ServerUrl: access.ServerUrl, ApiKey: access.ApiKey, AllowInsecureConnections: access.AllowInsecureConnections, SiteName: maputil.GetString(options.ProviderServiceConfig, "siteName"), @@ -565,7 +565,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer } deployer, err := pCdnfly.NewDeployer(&pCdnfly.DeployerConfig{ - ApiUrl: access.ApiUrl, + ServerUrl: access.ServerUrl, ApiKey: access.ApiKey, ApiSecret: access.ApiSecret, AllowInsecureConnections: access.AllowInsecureConnections, @@ -614,7 +614,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer } deployer, err := pFlexCDN.NewDeployer(&pFlexCDN.DeployerConfig{ - ApiUrl: access.ApiUrl, + ServerUrl: access.ServerUrl, ApiRole: access.ApiRole, AccessKeyId: access.AccessKeyId, AccessKey: access.AccessKey, @@ -654,7 +654,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer } deployer, err := pGoEdge.NewDeployer(&pGoEdge.DeployerConfig{ - ApiUrl: access.ApiUrl, + ServerUrl: access.ServerUrl, ApiRole: access.ApiRole, AccessKeyId: access.AccessKeyId, AccessKey: access.AccessKey, @@ -773,7 +773,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer } deployer, err := pLeCDN.NewDeployer(&pLeCDN.DeployerConfig{ - ApiUrl: access.ApiUrl, + ServerUrl: access.ServerUrl, ApiVersion: access.ApiVersion, ApiRole: access.ApiRole, Username: access.Username, @@ -845,7 +845,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer } deployer, err := pProxmoxVE.NewDeployer(&pProxmoxVE.DeployerConfig{ - ApiUrl: access.ApiUrl, + ServerUrl: access.ServerUrl, ApiToken: access.ApiToken, ApiTokenSecret: access.ApiTokenSecret, AllowInsecureConnections: access.AllowInsecureConnections, @@ -916,7 +916,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer switch options.Provider { case domain.DeploymentProviderTypeRatPanelConsole: deployer, err := pRatPanelConsole.NewDeployer(&pRatPanelConsole.DeployerConfig{ - ApiUrl: access.ApiUrl, + ServerUrl: access.ServerUrl, AccessTokenId: access.AccessTokenId, AccessToken: access.AccessToken, AllowInsecureConnections: access.AllowInsecureConnections, @@ -925,7 +925,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer case domain.DeploymentProviderTypeRatPanelSite: deployer, err := pRatPanelSite.NewDeployer(&pRatPanelSite.DeployerConfig{ - ApiUrl: access.ApiUrl, + ServerUrl: access.ServerUrl, AccessTokenId: access.AccessTokenId, AccessToken: access.AccessToken, AllowInsecureConnections: access.AllowInsecureConnections, @@ -946,7 +946,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer } deployer, err := pSafeLine.NewDeployer(&pSafeLine.DeployerConfig{ - ApiUrl: access.ApiUrl, + ServerUrl: access.ServerUrl, ApiToken: access.ApiToken, AllowInsecureConnections: access.AllowInsecureConnections, ResourceType: pSafeLine.ResourceType(maputil.GetString(options.ProviderServiceConfig, "resourceType")), diff --git a/internal/domain/access.go b/internal/domain/access.go index 13975392..7e1549f1 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -16,7 +16,7 @@ type Access struct { } type AccessConfigFor1Panel struct { - ApiUrl string `json:"apiUrl"` + ServerUrl string `json:"serverUrl"` ApiVersion string `json:"apiVersion"` ApiKey string `json:"apiKey"` AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` @@ -62,13 +62,13 @@ type AccessConfigForBaishan struct { } type AccessConfigForBaotaPanel struct { - ApiUrl string `json:"apiUrl"` + ServerUrl string `json:"serverUrl"` ApiKey string `json:"apiKey"` AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` } type AccessConfigForBaotaWAF struct { - ApiUrl string `json:"apiUrl"` + ServerUrl string `json:"serverUrl"` ApiKey string `json:"apiKey"` AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` } @@ -87,7 +87,7 @@ type AccessConfigForCacheFly struct { } type AccessConfigForCdnfly struct { - ApiUrl string `json:"apiUrl"` + ServerUrl string `json:"serverUrl"` ApiKey string `json:"apiKey"` ApiSecret string `json:"apiSecret"` AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` @@ -147,7 +147,7 @@ type AccessConfigForEmail struct { } type AccessConfigForFlexCDN struct { - ApiUrl string `json:"apiUrl"` + ServerUrl string `json:"serverUrl"` ApiRole string `json:"apiRole"` AccessKeyId string `json:"accessKeyId"` AccessKey string `json:"accessKey"` @@ -169,7 +169,7 @@ type AccessConfigForGoDaddy struct { } type AccessConfigForGoEdge struct { - ApiUrl string `json:"apiUrl"` + ServerUrl string `json:"serverUrl"` ApiRole string `json:"apiRole"` AccessKeyId string `json:"accessKeyId"` AccessKey string `json:"accessKey"` @@ -200,7 +200,7 @@ type AccessConfigForLarkBot struct { } type AccessConfigForLeCDN struct { - ApiUrl string `json:"apiUrl"` + ServerUrl string `json:"serverUrl"` ApiVersion string `json:"apiVersion"` ApiRole string `json:"apiRole"` Username string `json:"username"` @@ -249,13 +249,13 @@ type AccessConfigForPorkbun struct { } type AccessConfigForPowerDNS struct { - ApiUrl string `json:"apiUrl"` + ServerUrl string `json:"serverUrl"` ApiKey string `json:"apiKey"` AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` } type AccessConfigForProxmoxVE struct { - ApiUrl string `json:"apiUrl"` + ServerUrl string `json:"serverUrl"` ApiToken string `json:"apiToken"` ApiTokenSecret string `json:"apiTokenSecret,omitempty"` AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` @@ -271,14 +271,14 @@ type AccessConfigForRainYun struct { } type AccessConfigForRatPanel struct { - ApiUrl string `json:"apiUrl"` + ServerUrl string `json:"serverUrl"` AccessTokenId int32 `json:"accessTokenId"` AccessToken string `json:"accessToken"` AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` } type AccessConfigForSafeLine struct { - ApiUrl string `json:"apiUrl"` + ServerUrl string `json:"serverUrl"` ApiToken string `json:"apiToken"` AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun-esa/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun-esa/internal/lego.go index 51d4e7c4..5a576af1 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun-esa/internal/lego.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun-esa/internal/lego.go @@ -102,9 +102,10 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { return fmt.Errorf("alicloud-esa: could not find zone for domain %q: %w", domain, err) } - siteId, err := d.getSiteId(strings.TrimRight(authZone, ".")) + siteName := strings.TrimRight(authZone, ".") + siteId, err := d.getSiteId(siteName) if err != nil { - return fmt.Errorf("alicloud-esa: could not find site for zone %q: %w", authZone, err) + return fmt.Errorf("alicloud-esa: could not find site for zone %q: %w", siteName, err) } if err := d.addOrUpdateDNSRecord(siteId, strings.TrimRight(info.EffectiveFQDN, "."), info.Value); err != nil { @@ -122,9 +123,10 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { return fmt.Errorf("alicloud-esa: could not find zone for domain %q: %w", domain, err) } - siteId, err := d.getSiteId(strings.TrimRight(authZone, ".")) + siteName := strings.TrimRight(authZone, ".") + siteId, err := d.getSiteId(siteName) if err != nil { - return fmt.Errorf("alicloud-esa: could not find site for zone %q: %w", authZone, err) + return fmt.Errorf("alicloud-esa: could not find site for zone %q: %w", siteName, err) } if err := d.removeDNSRecord(siteId, strings.TrimRight(info.EffectiveFQDN, ".")); err != nil { diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns/powerdns.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns/powerdns.go index 7630633c..b34516d4 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns/powerdns.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns/powerdns.go @@ -11,7 +11,7 @@ import ( ) type ChallengeProviderConfig struct { - ApiUrl string `json:"apiUrl"` + ServerUrl string `json:"serverUrl"` ApiKey string `json:"apiKey"` AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` @@ -23,9 +23,9 @@ func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, panic("config is nil") } - host, _ := url.Parse(config.ApiUrl) + serverUrl, _ := url.Parse(config.ServerUrl) providerConfig := pdns.NewDefaultConfig() - providerConfig.Host = host + providerConfig.Host = serverUrl providerConfig.APIKey = config.ApiKey if config.AllowInsecureConnections { providerConfig.HTTPClient.Transport = &http.Transport{ diff --git a/internal/pkg/core/deployer/providers/1panel-console/1panel_console.go b/internal/pkg/core/deployer/providers/1panel-console/1panel_console.go index e81b264f..0f7efed1 100644 --- a/internal/pkg/core/deployer/providers/1panel-console/1panel_console.go +++ b/internal/pkg/core/deployer/providers/1panel-console/1panel_console.go @@ -13,8 +13,8 @@ import ( ) type DeployerConfig struct { - // 1Panel 地址。 - ApiUrl string `json:"apiUrl"` + // 1Panel 服务地址。 + ServerUrl string `json:"serverUrl"` // 1Panel 版本。 // 可取值 "v1"、"v2"。 ApiVersion string `json:"apiVersion"` @@ -39,7 +39,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { panic("config is nil") } - client, err := createSdkClient(config.ApiUrl, config.ApiVersion, config.ApiKey, config.AllowInsecureConnections) + client, err := createSdkClient(config.ServerUrl, config.ApiVersion, config.ApiKey, config.AllowInsecureConnections) if err != nil { return nil, fmt.Errorf("failed to create sdk client: %w", err) } diff --git a/internal/pkg/core/deployer/providers/1panel-console/1panel_console_test.go b/internal/pkg/core/deployer/providers/1panel-console/1panel_console_test.go index 88bf961a..0feae021 100644 --- a/internal/pkg/core/deployer/providers/1panel-console/1panel_console_test.go +++ b/internal/pkg/core/deployer/providers/1panel-console/1panel_console_test.go @@ -14,7 +14,7 @@ import ( var ( fInputCertPath string fInputKeyPath string - fApiUrl string + fServerUrl string fApiVersion string fApiKey string ) @@ -24,7 +24,7 @@ func init() { flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") - flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") + flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "") flag.StringVar(&fApiVersion, argsPrefix+"APIVERSION", "v1", "") flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "") } @@ -35,7 +35,7 @@ Shell command to run this test: go test -v ./1panel_console_test.go -args \ --CERTIMATE_DEPLOYER_1PANELCONSOLE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_1PANELCONSOLE_INPUTKEYPATH="/path/to/your-input-key.pem" \ - --CERTIMATE_DEPLOYER_1PANELCONSOLE_APIURL="http://127.0.0.1:20410" \ + --CERTIMATE_DEPLOYER_1PANELCONSOLE_SERVERURL="http://127.0.0.1:20410" \ --CERTIMATE_DEPLOYER_1PANELCONSOLE_APIVERSION="v1" \ --CERTIMATE_DEPLOYER_1PANELCONSOLE_APIKEY="your-api-key" */ @@ -47,13 +47,13 @@ func TestDeploy(t *testing.T) { "args:", fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), - fmt.Sprintf("APIURL: %v", fApiUrl), + fmt.Sprintf("SERVERURL: %v", fServerUrl), fmt.Sprintf("APIVERSION: %v", fApiVersion), fmt.Sprintf("APIKEY: %v", fApiKey), }, "\n")) deployer, err := provider.NewDeployer(&provider.DeployerConfig{ - ApiUrl: fApiUrl, + ServerUrl: fServerUrl, ApiVersion: fApiVersion, ApiKey: fApiKey, AllowInsecureConnections: true, diff --git a/internal/pkg/core/deployer/providers/1panel-site/1panel_site.go b/internal/pkg/core/deployer/providers/1panel-site/1panel_site.go index 690e5242..a546c1bb 100644 --- a/internal/pkg/core/deployer/providers/1panel-site/1panel_site.go +++ b/internal/pkg/core/deployer/providers/1panel-site/1panel_site.go @@ -16,8 +16,8 @@ import ( ) type DeployerConfig struct { - // 1Panel 地址。 - ApiUrl string `json:"apiUrl"` + // 1Panel 服务地址。 + ServerUrl string `json:"serverUrl"` // 1Panel 版本。 // 可取值 "v1"、"v2"。 ApiVersion string `json:"apiVersion"` @@ -49,13 +49,13 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { panic("config is nil") } - client, err := createSdkClient(config.ApiUrl, config.ApiVersion, config.ApiKey, config.AllowInsecureConnections) + client, err := createSdkClient(config.ServerUrl, config.ApiVersion, config.ApiKey, config.AllowInsecureConnections) if err != nil { return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ - ApiUrl: config.ApiUrl, + ServerUrl: config.ServerUrl, ApiVersion: config.ApiVersion, ApiKey: config.ApiKey, }) diff --git a/internal/pkg/core/deployer/providers/1panel-site/1panel_site_test.go b/internal/pkg/core/deployer/providers/1panel-site/1panel_site_test.go index 1d5bafef..91b1ebb0 100644 --- a/internal/pkg/core/deployer/providers/1panel-site/1panel_site_test.go +++ b/internal/pkg/core/deployer/providers/1panel-site/1panel_site_test.go @@ -14,7 +14,7 @@ import ( var ( fInputCertPath string fInputKeyPath string - fApiUrl string + fServerUrl string fApiVersion string fApiKey string fWebsiteId int64 @@ -25,7 +25,7 @@ func init() { flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") - flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") + flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "") flag.StringVar(&fApiVersion, argsPrefix+"APIVERSION", "v1", "") flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "") flag.Int64Var(&fWebsiteId, argsPrefix+"WEBSITEID", 0, "") @@ -37,7 +37,7 @@ Shell command to run this test: go test -v ./1panel_site_test.go -args \ --CERTIMATE_DEPLOYER_1PANELSITE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_1PANELSITE_INPUTKEYPATH="/path/to/your-input-key.pem" \ - --CERTIMATE_DEPLOYER_1PANELSITE_APIURL="http://127.0.0.1:20410" \ + --CERTIMATE_DEPLOYER_1PANELSITE_SERVERURL="http://127.0.0.1:20410" \ --CERTIMATE_DEPLOYER_1PANELSITE_APIVERSION="v1" \ --CERTIMATE_DEPLOYER_1PANELSITE_APIKEY="your-api-key" \ --CERTIMATE_DEPLOYER_1PANELSITE_WEBSITEID="your-website-id" @@ -50,14 +50,14 @@ func TestDeploy(t *testing.T) { "args:", fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), - fmt.Sprintf("APIURL: %v", fApiUrl), + fmt.Sprintf("SERVERURL: %v", fServerUrl), fmt.Sprintf("APIVERSION: %v", fApiVersion), fmt.Sprintf("APIKEY: %v", fApiKey), fmt.Sprintf("WEBSITEID: %v", fWebsiteId), }, "\n")) deployer, err := provider.NewDeployer(&provider.DeployerConfig{ - ApiUrl: fApiUrl, + ServerUrl: fServerUrl, ApiVersion: fApiVersion, ApiKey: fApiKey, AllowInsecureConnections: true, diff --git a/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go index b1a57a81..b5deb005 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go +++ b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go @@ -13,8 +13,8 @@ import ( ) type DeployerConfig struct { - // 宝塔面板地址。 - ApiUrl string `json:"apiUrl"` + // 宝塔面板服务地址。 + ServerUrl string `json:"serverUrl"` // 宝塔面板接口密钥。 ApiKey string `json:"apiKey"` // 是否允许不安全的连接。 @@ -36,7 +36,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { panic("config is nil") } - client, err := createSdkClient(config.ApiUrl, config.ApiKey, config.AllowInsecureConnections) + client, err := createSdkClient(config.ServerUrl, config.ApiKey, config.AllowInsecureConnections) if err != nil { return nil, fmt.Errorf("failed to create sdk client: %w", err) } diff --git a/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console_test.go b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console_test.go index 5f3845e4..2fd4cc5b 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console_test.go +++ b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console_test.go @@ -14,7 +14,7 @@ import ( var ( fInputCertPath string fInputKeyPath string - fApiUrl string + fServerUrl string fApiKey string ) @@ -23,7 +23,7 @@ func init() { flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") - flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") + flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "") flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "") } @@ -33,7 +33,7 @@ Shell command to run this test: go test -v ./baotapanel_console_test.go -args \ --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_INPUTKEYPATH="/path/to/your-input-key.pem" \ - --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_APIURL="http://127.0.0.1:8888" \ + --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_SERVERURL="http://127.0.0.1:8888" \ --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_APIKEY="your-api-key" */ func TestDeploy(t *testing.T) { @@ -44,12 +44,12 @@ func TestDeploy(t *testing.T) { "args:", fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), - fmt.Sprintf("APIURL: %v", fApiUrl), + fmt.Sprintf("SERVERURL: %v", fServerUrl), fmt.Sprintf("APIKEY: %v", fApiKey), }, "\n")) deployer, err := provider.NewDeployer(&provider.DeployerConfig{ - ApiUrl: fApiUrl, + ServerUrl: fServerUrl, ApiKey: fApiKey, AllowInsecureConnections: true, AutoRestart: true, diff --git a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go index 4d481f7f..f9936e2d 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go +++ b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go @@ -14,8 +14,8 @@ import ( ) type DeployerConfig struct { - // 宝塔面板地址。 - ApiUrl string `json:"apiUrl"` + // 宝塔面板服务地址。 + ServerUrl string `json:"serverUrl"` // 宝塔面板接口密钥。 ApiKey string `json:"apiKey"` // 是否允许不安全的连接。 @@ -41,7 +41,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { panic("config is nil") } - client, err := createSdkClient(config.ApiUrl, config.ApiKey, config.AllowInsecureConnections) + client, err := createSdkClient(config.ServerUrl, config.ApiKey, config.AllowInsecureConnections) if err != nil { return nil, fmt.Errorf("failed to create sdk client: %w", err) } diff --git a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go index 5fece978..9e4659ea 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go +++ b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go @@ -14,7 +14,7 @@ import ( var ( fInputCertPath string fInputKeyPath string - fApiUrl string + fServerUrl string fApiKey string fSiteType string fSiteName string @@ -25,7 +25,7 @@ func init() { flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") - flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") + flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "") flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "") flag.StringVar(&fSiteType, argsPrefix+"SITETYPE", "", "") flag.StringVar(&fSiteName, argsPrefix+"SITENAME", "", "") @@ -37,7 +37,7 @@ Shell command to run this test: go test -v ./baotapanel_site_test.go -args \ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_INPUTKEYPATH="/path/to/your-input-key.pem" \ - --CERTIMATE_DEPLOYER_BAOTAPANELSITE_APIURL="http://127.0.0.1:8888" \ + --CERTIMATE_DEPLOYER_BAOTAPANELSITE_SERVERURL="http://127.0.0.1:8888" \ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_APIKEY="your-api-key" \ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_SITETYPE="php" \ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_SITENAME="your-site-name" @@ -50,14 +50,14 @@ func TestDeploy(t *testing.T) { "args:", fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), - fmt.Sprintf("APIURL: %v", fApiUrl), + fmt.Sprintf("SERVERURL: %v", fServerUrl), fmt.Sprintf("APIKEY: %v", fApiKey), fmt.Sprintf("SITETYPE: %v", fSiteType), fmt.Sprintf("SITENAME: %v", fSiteName), }, "\n")) deployer, err := provider.NewDeployer(&provider.DeployerConfig{ - ApiUrl: fApiUrl, + ServerUrl: fServerUrl, ApiKey: fApiKey, AllowInsecureConnections: true, SiteType: fSiteType, diff --git a/internal/pkg/core/deployer/providers/baotawaf-console/baotawaf_console.go b/internal/pkg/core/deployer/providers/baotawaf-console/baotawaf_console.go index 811b350b..bf8a3892 100644 --- a/internal/pkg/core/deployer/providers/baotawaf-console/baotawaf_console.go +++ b/internal/pkg/core/deployer/providers/baotawaf-console/baotawaf_console.go @@ -13,8 +13,8 @@ import ( ) type DeployerConfig struct { - // 堡塔云 WAF 地址。 - ApiUrl string `json:"apiUrl"` + // 堡塔云 WAF 服务地址。 + ServerUrl string `json:"serverUrl"` // 堡塔云 WAF 接口密钥。 ApiKey string `json:"apiKey"` // 是否允许不安全的连接。 @@ -34,7 +34,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { panic("config is nil") } - client, err := createSdkClient(config.ApiUrl, config.ApiKey, config.AllowInsecureConnections) + client, err := createSdkClient(config.ServerUrl, config.ApiKey, config.AllowInsecureConnections) if err != nil { return nil, fmt.Errorf("failed to create sdk client: %w", err) } diff --git a/internal/pkg/core/deployer/providers/baotawaf-console/baotawaf_console_test.go b/internal/pkg/core/deployer/providers/baotawaf-console/baotawaf_console_test.go index ba6ddd26..b3804fb5 100644 --- a/internal/pkg/core/deployer/providers/baotawaf-console/baotawaf_console_test.go +++ b/internal/pkg/core/deployer/providers/baotawaf-console/baotawaf_console_test.go @@ -14,7 +14,7 @@ import ( var ( fInputCertPath string fInputKeyPath string - fApiUrl string + fServerUrl string fApiKey string fSiteName string fSitePort int64 @@ -25,7 +25,7 @@ func init() { flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") - flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") + flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "") flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "") } @@ -35,7 +35,7 @@ Shell command to run this test: go test -v ./baotawaf_console_test.go -args \ --CERTIMATE_DEPLOYER_BAOTAWAFCONSOLE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_BAOTAWAFCONSOLE_INPUTKEYPATH="/path/to/your-input-key.pem" \ - --CERTIMATE_DEPLOYER_BAOTAWAFCONSOLE_APIURL="http://127.0.0.1:8888" \ + --CERTIMATE_DEPLOYER_BAOTAWAFCONSOLE_SERVERURL="http://127.0.0.1:8888" \ --CERTIMATE_DEPLOYER_BAOTAWAFCONSOLE_APIKEY="your-api-key" */ func TestDeploy(t *testing.T) { @@ -46,12 +46,12 @@ func TestDeploy(t *testing.T) { "args:", fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), - fmt.Sprintf("APIURL: %v", fApiUrl), + fmt.Sprintf("SERVERURL: %v", fServerUrl), fmt.Sprintf("APIKEY: %v", fApiKey), }, "\n")) deployer, err := provider.NewDeployer(&provider.DeployerConfig{ - ApiUrl: fApiUrl, + ServerUrl: fServerUrl, ApiKey: fApiKey, AllowInsecureConnections: true, }) diff --git a/internal/pkg/core/deployer/providers/baotawaf-site/baotawaf_site.go b/internal/pkg/core/deployer/providers/baotawaf-site/baotawaf_site.go index ed05937a..faaf5681 100644 --- a/internal/pkg/core/deployer/providers/baotawaf-site/baotawaf_site.go +++ b/internal/pkg/core/deployer/providers/baotawaf-site/baotawaf_site.go @@ -14,8 +14,8 @@ import ( ) type DeployerConfig struct { - // 堡塔云 WAF 地址。 - ApiUrl string `json:"apiUrl"` + // 堡塔云 WAF 服务地址。 + ServerUrl string `json:"serverUrl"` // 堡塔云 WAF 接口密钥。 ApiKey string `json:"apiKey"` // 是否允许不安全的连接。 @@ -40,7 +40,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { panic("config is nil") } - client, err := createSdkClient(config.ApiUrl, config.ApiKey, config.AllowInsecureConnections) + client, err := createSdkClient(config.ServerUrl, config.ApiKey, config.AllowInsecureConnections) if err != nil { return nil, fmt.Errorf("failed to create sdk client: %w", err) } diff --git a/internal/pkg/core/deployer/providers/baotawaf-site/baotawaf_site_test.go b/internal/pkg/core/deployer/providers/baotawaf-site/baotawaf_site_test.go index 4e1ffe34..6bead4b5 100644 --- a/internal/pkg/core/deployer/providers/baotawaf-site/baotawaf_site_test.go +++ b/internal/pkg/core/deployer/providers/baotawaf-site/baotawaf_site_test.go @@ -14,7 +14,7 @@ import ( var ( fInputCertPath string fInputKeyPath string - fApiUrl string + fServerUrl string fApiKey string fSiteName string fSitePort int64 @@ -25,7 +25,7 @@ func init() { flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") - flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") + flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "") flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "") flag.StringVar(&fSiteName, argsPrefix+"SITENAME", "", "") flag.Int64Var(&fSitePort, argsPrefix+"SITEPORT", 0, "") @@ -37,7 +37,7 @@ Shell command to run this test: go test -v ./baotawaf_site_test.go -args \ --CERTIMATE_DEPLOYER_BAOTAWAFSITE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_BAOTAWAFSITE_INPUTKEYPATH="/path/to/your-input-key.pem" \ - --CERTIMATE_DEPLOYER_BAOTAWAFSITE_APIURL="http://127.0.0.1:8888" \ + --CERTIMATE_DEPLOYER_BAOTAWAFSITE_SERVERURL="http://127.0.0.1:8888" \ --CERTIMATE_DEPLOYER_BAOTAWAFSITE_APIKEY="your-api-key" \ --CERTIMATE_DEPLOYER_BAOTAWAFSITE_SITENAME="your-site-name"\ --CERTIMATE_DEPLOYER_BAOTAWAFSITE_SITEPORT=443 @@ -50,14 +50,14 @@ func TestDeploy(t *testing.T) { "args:", fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), - fmt.Sprintf("APIURL: %v", fApiUrl), + fmt.Sprintf("SERVERURL: %v", fServerUrl), fmt.Sprintf("APIKEY: %v", fApiKey), fmt.Sprintf("SITENAME: %v", fSiteName), fmt.Sprintf("SITEPORT: %v", fSitePort), }, "\n")) deployer, err := provider.NewDeployer(&provider.DeployerConfig{ - ApiUrl: fApiUrl, + ServerUrl: fServerUrl, ApiKey: fApiKey, AllowInsecureConnections: true, SiteName: fSiteName, diff --git a/internal/pkg/core/deployer/providers/cdnfly/cdnfly.go b/internal/pkg/core/deployer/providers/cdnfly/cdnfly.go index 909caf3e..6b7c3ec7 100644 --- a/internal/pkg/core/deployer/providers/cdnfly/cdnfly.go +++ b/internal/pkg/core/deployer/providers/cdnfly/cdnfly.go @@ -15,8 +15,8 @@ import ( ) type DeployerConfig struct { - // Cdnfly 地址。 - ApiUrl string `json:"apiUrl"` + // Cdnfly 服务地址。 + ServerUrl string `json:"serverUrl"` // Cdnfly 用户端 API Key。 ApiKey string `json:"apiKey"` // Cdnfly 用户端 API Secret。 @@ -46,7 +46,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { panic("config is nil") } - client, err := createSdkClient(config.ApiUrl, config.ApiKey, config.ApiSecret, config.AllowInsecureConnections) + client, err := createSdkClient(config.ServerUrl, config.ApiKey, config.ApiSecret, config.AllowInsecureConnections) if err != nil { return nil, fmt.Errorf("failed to create sdk client: %w", err) } diff --git a/internal/pkg/core/deployer/providers/cdnfly/cdnfly_test.go b/internal/pkg/core/deployer/providers/cdnfly/cdnfly_test.go index 26486721..73128183 100644 --- a/internal/pkg/core/deployer/providers/cdnfly/cdnfly_test.go +++ b/internal/pkg/core/deployer/providers/cdnfly/cdnfly_test.go @@ -14,7 +14,7 @@ import ( var ( fInputCertPath string fInputKeyPath string - fApiUrl string + fServerUrl string fApiKey string fApiSecret string fCertificateId string @@ -25,7 +25,7 @@ func init() { flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") - flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") + flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "") flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "") flag.StringVar(&fApiSecret, argsPrefix+"APISECRET", "", "") flag.StringVar(&fCertificateId, argsPrefix+"CERTIFICATEID", "", "") @@ -37,7 +37,7 @@ Shell command to run this test: go test -v ./cdnfly_test.go -args \ --CERTIMATE_DEPLOYER_CDNFLY_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_CDNFLY_INPUTKEYPATH="/path/to/your-input-key.pem" \ - --CERTIMATE_DEPLOYER_CDNFLY_APIURL="http://127.0.0.1:88" \ + --CERTIMATE_DEPLOYER_CDNFLY_SERVERURL="http://127.0.0.1:88" \ --CERTIMATE_DEPLOYER_CDNFLY_APIKEY="your-api-key" \ --CERTIMATE_DEPLOYER_CDNFLY_APISECRET="your-api-secret" \ --CERTIMATE_DEPLOYER_CDNFLY_CERTIFICATEID="your-cert-id" @@ -50,14 +50,14 @@ func TestDeploy(t *testing.T) { "args:", fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), - fmt.Sprintf("APIURL: %v", fApiUrl), + fmt.Sprintf("SERVERURL: %v", fServerUrl), fmt.Sprintf("APIKEY: %v", fApiKey), fmt.Sprintf("APISECRET: %v", fApiSecret), fmt.Sprintf("CERTIFICATEID: %v", fCertificateId), }, "\n")) deployer, err := provider.NewDeployer(&provider.DeployerConfig{ - ApiUrl: fApiUrl, + ServerUrl: fServerUrl, ApiKey: fApiKey, ApiSecret: fApiSecret, AllowInsecureConnections: true, diff --git a/internal/pkg/core/deployer/providers/flexcdn/flexcdn.go b/internal/pkg/core/deployer/providers/flexcdn/flexcdn.go index a12ed164..7925a72a 100644 --- a/internal/pkg/core/deployer/providers/flexcdn/flexcdn.go +++ b/internal/pkg/core/deployer/providers/flexcdn/flexcdn.go @@ -16,8 +16,8 @@ import ( ) type DeployerConfig struct { - // FlexCDN URL。 - ApiUrl string `json:"apiUrl"` + // FlexCDN 服务地址。 + ServerUrl string `json:"serverUrl"` // FlexCDN 用户角色。 // 可取值 "user"、"admin"。 ApiRole string `json:"apiRole"` @@ -47,7 +47,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { panic("config is nil") } - client, err := createSdkClient(config.ApiUrl, config.ApiRole, config.AccessKeyId, config.AccessKey, config.AllowInsecureConnections) + client, err := createSdkClient(config.ServerUrl, config.ApiRole, config.AccessKeyId, config.AccessKey, config.AllowInsecureConnections) if err != nil { return nil, fmt.Errorf("failed to create sdk client: %w", err) } diff --git a/internal/pkg/core/deployer/providers/flexcdn/flexcdn_test.go b/internal/pkg/core/deployer/providers/flexcdn/flexcdn_test.go index b9b8de07..6725140a 100644 --- a/internal/pkg/core/deployer/providers/flexcdn/flexcdn_test.go +++ b/internal/pkg/core/deployer/providers/flexcdn/flexcdn_test.go @@ -14,7 +14,7 @@ import ( var ( fInputCertPath string fInputKeyPath string - fApiUrl string + fServerUrl string fAccessKeyId string fAccessKey string fCertificateId int64 @@ -25,7 +25,7 @@ func init() { flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") - flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") + flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "") flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "") flag.StringVar(&fAccessKey, argsPrefix+"ACCESSKEY", "", "") flag.Int64Var(&fCertificateId, argsPrefix+"CERTIFICATEID", 0, "") @@ -37,7 +37,7 @@ Shell command to run this test: go test -v ./flexcdn_test.go -args \ --CERTIMATE_DEPLOYER_FLEXCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_FLEXCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \ - --CERTIMATE_DEPLOYER_FLEXCDN_APIURL="http://127.0.0.1:7788" \ + --CERTIMATE_DEPLOYER_FLEXCDN_SERVERURL="http://127.0.0.1:7788" \ --CERTIMATE_DEPLOYER_FLEXCDN_ACCESSKEYID="your-access-key-id" \ --CERTIMATE_DEPLOYER_FLEXCDN_ACCESSKEY="your-access-key" \ --CERTIMATE_DEPLOYER_FLEXCDN_CERTIFICATEID="your-cerficiate-id" @@ -50,14 +50,14 @@ func TestDeploy(t *testing.T) { "args:", fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), - fmt.Sprintf("APIURL: %v", fApiUrl), + fmt.Sprintf("SERVERURL: %v", fServerUrl), fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId), fmt.Sprintf("ACCESSKEY: %v", fAccessKey), fmt.Sprintf("CERTIFICATEID: %v", fCertificateId), }, "\n")) deployer, err := provider.NewDeployer(&provider.DeployerConfig{ - ApiUrl: fApiUrl, + ServerUrl: fServerUrl, ApiRole: "user", AccessKeyId: fAccessKeyId, AccessKey: fAccessKey, diff --git a/internal/pkg/core/deployer/providers/goedge/goedge.go b/internal/pkg/core/deployer/providers/goedge/goedge.go index ecae774e..5b3e2dc9 100644 --- a/internal/pkg/core/deployer/providers/goedge/goedge.go +++ b/internal/pkg/core/deployer/providers/goedge/goedge.go @@ -16,8 +16,8 @@ import ( ) type DeployerConfig struct { - // GoEdge URL。 - ApiUrl string `json:"apiUrl"` + // GoEdge 服务地址。 + ServerUrl string `json:"serverUrl"` // GoEdge 用户角色。 // 可取值 "user"、"admin"。 ApiRole string `json:"apiRole"` @@ -47,7 +47,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { panic("config is nil") } - client, err := createSdkClient(config.ApiUrl, config.ApiRole, config.AccessKeyId, config.AccessKey, config.AllowInsecureConnections) + client, err := createSdkClient(config.ServerUrl, config.ApiRole, config.AccessKeyId, config.AccessKey, config.AllowInsecureConnections) if err != nil { return nil, fmt.Errorf("failed to create sdk client: %w", err) } diff --git a/internal/pkg/core/deployer/providers/goedge/goedge_test.go b/internal/pkg/core/deployer/providers/goedge/goedge_test.go index d10f931c..ae03db1d 100644 --- a/internal/pkg/core/deployer/providers/goedge/goedge_test.go +++ b/internal/pkg/core/deployer/providers/goedge/goedge_test.go @@ -14,7 +14,7 @@ import ( var ( fInputCertPath string fInputKeyPath string - fApiUrl string + fServerUrl string fAccessKeyId string fAccessKey string fCertificateId int64 @@ -25,7 +25,7 @@ func init() { flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") - flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") + flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "") flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "") flag.StringVar(&fAccessKey, argsPrefix+"ACCESSKEY", "", "") flag.Int64Var(&fCertificateId, argsPrefix+"CERTIFICATEID", 0, "") @@ -37,7 +37,7 @@ Shell command to run this test: go test -v ./goedge_test.go -args \ --CERTIMATE_DEPLOYER_GOEDGE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_GOEDGE_INPUTKEYPATH="/path/to/your-input-key.pem" \ - --CERTIMATE_DEPLOYER_GOEDGE_APIURL="http://127.0.0.1:7788" \ + --CERTIMATE_DEPLOYER_GOEDGE_SERVERURL="http://127.0.0.1:7788" \ --CERTIMATE_DEPLOYER_GOEDGE_ACCESSKEYID="your-access-key-id" \ --CERTIMATE_DEPLOYER_GOEDGE_ACCESSKEY="your-access-key" \ --CERTIMATE_DEPLOYER_GOEDGE_CERTIFICATEID="your-cerficiate-id" @@ -50,14 +50,14 @@ func TestDeploy(t *testing.T) { "args:", fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), - fmt.Sprintf("APIURL: %v", fApiUrl), + fmt.Sprintf("SERVERURL: %v", fServerUrl), fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId), fmt.Sprintf("ACCESSKEY: %v", fAccessKey), fmt.Sprintf("CERTIFICATEID: %v", fCertificateId), }, "\n")) deployer, err := provider.NewDeployer(&provider.DeployerConfig{ - ApiUrl: fApiUrl, + ServerUrl: fServerUrl, ApiRole: "user", AccessKeyId: fAccessKeyId, AccessKey: fAccessKey, diff --git a/internal/pkg/core/deployer/providers/lecdn/lecdn.go b/internal/pkg/core/deployer/providers/lecdn/lecdn.go index 1ad88dcf..15c5dba9 100644 --- a/internal/pkg/core/deployer/providers/lecdn/lecdn.go +++ b/internal/pkg/core/deployer/providers/lecdn/lecdn.go @@ -15,8 +15,8 @@ import ( ) type DeployerConfig struct { - // LeCDN URL。 - ApiUrl string `json:"apiUrl"` + // LeCDN 服务地址。 + ServerUrl string `json:"serverUrl"` // LeCDN 版本。 // 可取值 "v3"。 ApiVersion string `json:"apiVersion"` @@ -59,7 +59,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { panic("config is nil") } - client, err := createSdkClient(config.ApiUrl, config.ApiVersion, config.ApiRole, config.Username, config.Password, config.AllowInsecureConnections) + client, err := createSdkClient(config.ServerUrl, config.ApiVersion, config.ApiRole, config.Username, config.Password, config.AllowInsecureConnections) if err != nil { return nil, fmt.Errorf("failed to create sdk client: %w", err) } diff --git a/internal/pkg/core/deployer/providers/lecdn/lecdn_test.go b/internal/pkg/core/deployer/providers/lecdn/lecdn_test.go index cbaa4523..fda880c4 100644 --- a/internal/pkg/core/deployer/providers/lecdn/lecdn_test.go +++ b/internal/pkg/core/deployer/providers/lecdn/lecdn_test.go @@ -14,7 +14,7 @@ import ( var ( fInputCertPath string fInputKeyPath string - fApiUrl string + fServerUrl string fApiVersion string fUsername string fPassword string @@ -26,7 +26,7 @@ func init() { flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") - flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") + flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "") flag.StringVar(&fApiVersion, argsPrefix+"APIVERSION", "v3", "") flag.StringVar(&fUsername, argsPrefix+"USERNAME", "", "") flag.StringVar(&fPassword, argsPrefix+"PASSWORD", "", "") @@ -39,7 +39,7 @@ Shell command to run this test: go test -v ./lecdn_test.go -args \ --CERTIMATE_DEPLOYER_LECDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_LECDN_INPUTKEYPATH="/path/to/your-input-key.pem" \ - --CERTIMATE_DEPLOYER_LECDN_APIURL="http://127.0.0.1:5090" \ + --CERTIMATE_DEPLOYER_LECDN_SERVERURL="http://127.0.0.1:5090" \ --CERTIMATE_DEPLOYER_LECDN_USERNAME="your-username" \ --CERTIMATE_DEPLOYER_LECDN_PASSWORD="your-password" \ --CERTIMATE_DEPLOYER_LECDN_CERTIFICATEID="your-cerficiate-id" @@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) { "args:", fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), - fmt.Sprintf("APIURL: %v", fApiUrl), + fmt.Sprintf("SERVERURL: %v", fServerUrl), fmt.Sprintf("APIVERSION: %v", fApiVersion), fmt.Sprintf("USERNAME: %v", fUsername), fmt.Sprintf("PASSWORD: %v", fPassword), @@ -60,7 +60,7 @@ func TestDeploy(t *testing.T) { }, "\n")) deployer, err := provider.NewDeployer(&provider.DeployerConfig{ - ApiUrl: fApiUrl, + ServerUrl: fServerUrl, ApiVersion: fApiVersion, ApiRole: "user", Username: fUsername, diff --git a/internal/pkg/core/deployer/providers/proxmoxve/proxmoxve.go b/internal/pkg/core/deployer/providers/proxmoxve/proxmoxve.go index d2e92460..455ccf6d 100644 --- a/internal/pkg/core/deployer/providers/proxmoxve/proxmoxve.go +++ b/internal/pkg/core/deployer/providers/proxmoxve/proxmoxve.go @@ -16,8 +16,8 @@ import ( ) type DeployerConfig struct { - // Proxmox VE 地址。 - ApiUrl string `json:"apiUrl"` + // Proxmox VE 服务地址。 + ServerUrl string `json:"serverUrl"` // Proxmox VE API Token。 ApiToken string `json:"apiToken"` // Proxmox VE API Token Secret。 @@ -43,7 +43,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { panic("config is nil") } - client, err := createSdkClient(config.ApiUrl, config.ApiToken, config.ApiTokenSecret, config.AllowInsecureConnections) + client, err := createSdkClient(config.ServerUrl, config.ApiToken, config.ApiTokenSecret, config.AllowInsecureConnections) if err != nil { return nil, fmt.Errorf("failed to create sdk client: %w", err) } diff --git a/internal/pkg/core/deployer/providers/proxmoxve/proxmoxve_test.go b/internal/pkg/core/deployer/providers/proxmoxve/proxmoxve_test.go index 6251bd75..8ae02f3b 100644 --- a/internal/pkg/core/deployer/providers/proxmoxve/proxmoxve_test.go +++ b/internal/pkg/core/deployer/providers/proxmoxve/proxmoxve_test.go @@ -14,7 +14,7 @@ import ( var ( fInputCertPath string fInputKeyPath string - fApiUrl string + fServerUrl string fApiToken string fApiTokenSecret string fNodeName string @@ -25,7 +25,7 @@ func init() { flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") - flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") + flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "") flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "") flag.StringVar(&fApiTokenSecret, argsPrefix+"APITOKENSECRET", "", "") flag.StringVar(&fNodeName, argsPrefix+"NODENAME", "", "") @@ -37,7 +37,7 @@ Shell command to run this test: go test -v ./proxmoxve_test.go -args \ --CERTIMATE_DEPLOYER_PROXMOXVE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_PROXMOXVE_INPUTKEYPATH="/path/to/your-input-key.pem" \ - --CERTIMATE_DEPLOYER_PROXMOXVE_APIURL="http://127.0.0.1:8006" \ + --CERTIMATE_DEPLOYER_PROXMOXVE_SERVERURL="http://127.0.0.1:8006" \ --CERTIMATE_DEPLOYER_PROXMOXVE_APITOKEN="your-api-token" \ --CERTIMATE_DEPLOYER_PROXMOXVE_APITOKENSECRET="your-api-token-secret" \ --CERTIMATE_DEPLOYER_PROXMOXVE_NODENAME="your-cluster-node-name" @@ -50,14 +50,14 @@ func TestDeploy(t *testing.T) { "args:", fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), - fmt.Sprintf("APIURL: %v", fApiUrl), + fmt.Sprintf("SERVERURL: %v", fServerUrl), fmt.Sprintf("APITOKEN: %v", fApiToken), fmt.Sprintf("APITOKENSECRET: %v", fApiTokenSecret), fmt.Sprintf("NODENAME: %v", fNodeName), }, "\n")) deployer, err := provider.NewDeployer(&provider.DeployerConfig{ - ApiUrl: fApiUrl, + ServerUrl: fServerUrl, ApiToken: fApiToken, ApiTokenSecret: fApiTokenSecret, AllowInsecureConnections: true, diff --git a/internal/pkg/core/deployer/providers/ratpanel-console/ratpanel_console.go b/internal/pkg/core/deployer/providers/ratpanel-console/ratpanel_console.go index 51faf4f2..a6c560ae 100644 --- a/internal/pkg/core/deployer/providers/ratpanel-console/ratpanel_console.go +++ b/internal/pkg/core/deployer/providers/ratpanel-console/ratpanel_console.go @@ -13,8 +13,8 @@ import ( ) type DeployerConfig struct { - // 耗子面板地址。 - ApiUrl string `json:"apiUrl"` + // 耗子面板服务地址。 + ServerUrl string `json:"serverUrl"` // 耗子面板访问令牌 ID。 AccessTokenId int32 `json:"accessTokenId"` // 耗子面板访问令牌。 @@ -36,7 +36,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { panic("config is nil") } - client, err := createSdkClient(config.ApiUrl, config.AccessTokenId, config.AccessToken, config.AllowInsecureConnections) + client, err := createSdkClient(config.ServerUrl, config.AccessTokenId, config.AccessToken, config.AllowInsecureConnections) if err != nil { return nil, fmt.Errorf("failed to create sdk client: %w", err) } diff --git a/internal/pkg/core/deployer/providers/ratpanel-console/ratpanel_console_test.go b/internal/pkg/core/deployer/providers/ratpanel-console/ratpanel_console_test.go index 3f3193b3..3366b06c 100644 --- a/internal/pkg/core/deployer/providers/ratpanel-console/ratpanel_console_test.go +++ b/internal/pkg/core/deployer/providers/ratpanel-console/ratpanel_console_test.go @@ -14,7 +14,7 @@ import ( var ( fInputCertPath string fInputKeyPath string - fApiUrl string + fServerUrl string fAccessTokenId int64 fAccessToken string ) @@ -24,7 +24,7 @@ func init() { flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") - flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") + flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "") flag.Int64Var(&fAccessTokenId, argsPrefix+"ACCESSTOKENID", 0, "") flag.StringVar(&fAccessToken, argsPrefix+"ACCESSTOKEN", "", "") } @@ -35,7 +35,7 @@ Shell command to run this test: go test -v ./ratpanel_console_test.go -args \ --CERTIMATE_DEPLOYER_RATPANELCONSOLE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_RATPANELCONSOLE_INPUTKEYPATH="/path/to/your-input-key.pem" \ - --CERTIMATE_DEPLOYER_RATPANELCONSOLE_APIURL="http://127.0.0.1:8888" \ + --CERTIMATE_DEPLOYER_RATPANELCONSOLE_SERVERURL="http://127.0.0.1:8888" \ --CERTIMATE_DEPLOYER_RATPANELCONSOLE_ACCESSTOKENID="your-access-token-id" \ --CERTIMATE_DEPLOYER_RATPANELCONSOLE_ACCESSTOKEN="your-access-token" */ @@ -47,13 +47,13 @@ func TestDeploy(t *testing.T) { "args:", fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), - fmt.Sprintf("APIURL: %v", fApiUrl), + fmt.Sprintf("SERVERURL: %v", fServerUrl), fmt.Sprintf("ACCESSTOKENID: %v", fAccessTokenId), fmt.Sprintf("ACCESSTOKEN: %v", fAccessToken), }, "\n")) deployer, err := provider.NewDeployer(&provider.DeployerConfig{ - ApiUrl: fApiUrl, + ServerUrl: fServerUrl, AccessTokenId: int32(fAccessTokenId), AccessToken: fAccessToken, AllowInsecureConnections: true, diff --git a/internal/pkg/core/deployer/providers/ratpanel-site/ratpanel_site.go b/internal/pkg/core/deployer/providers/ratpanel-site/ratpanel_site.go index b4e283be..a296c95e 100644 --- a/internal/pkg/core/deployer/providers/ratpanel-site/ratpanel_site.go +++ b/internal/pkg/core/deployer/providers/ratpanel-site/ratpanel_site.go @@ -13,8 +13,8 @@ import ( ) type DeployerConfig struct { - // 耗子面板地址。 - ApiUrl string `json:"apiUrl"` + // 耗子面板服务地址。 + ServerUrl string `json:"serverUrl"` // 耗子面板访问令牌 ID。 AccessTokenId int32 `json:"accessTokenId"` // 耗子面板访问令牌。 @@ -38,7 +38,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { panic("config is nil") } - client, err := createSdkClient(config.ApiUrl, config.AccessTokenId, config.AccessToken, config.AllowInsecureConnections) + client, err := createSdkClient(config.ServerUrl, config.AccessTokenId, config.AccessToken, config.AllowInsecureConnections) if err != nil { return nil, fmt.Errorf("failed to create sdk client: %w", err) } diff --git a/internal/pkg/core/deployer/providers/ratpanel-site/ratpanel_site_test.go b/internal/pkg/core/deployer/providers/ratpanel-site/ratpanel_site_test.go index 658175fb..cd84b3ea 100644 --- a/internal/pkg/core/deployer/providers/ratpanel-site/ratpanel_site_test.go +++ b/internal/pkg/core/deployer/providers/ratpanel-site/ratpanel_site_test.go @@ -14,7 +14,7 @@ import ( var ( fInputCertPath string fInputKeyPath string - fApiUrl string + fServerUrl string fAccessTokenId int64 fAccessToken string fSiteName string @@ -25,7 +25,7 @@ func init() { flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") - flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") + flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "") flag.Int64Var(&fAccessTokenId, argsPrefix+"ACCESSTOKENID", 0, "") flag.StringVar(&fAccessToken, argsPrefix+"ACCESSTOKEN", "", "") flag.StringVar(&fSiteName, argsPrefix+"SITENAME", "", "") @@ -37,7 +37,7 @@ Shell command to run this test: go test -v ./ratpanel_site_test.go -args \ --CERTIMATE_DEPLOYER_RATPANELSITE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_RATPANELSITE_INPUTKEYPATH="/path/to/your-input-key.pem" \ - --CERTIMATE_DEPLOYER_RATPANELSITE_APIURL="http://127.0.0.1:8888" \ + --CERTIMATE_DEPLOYER_RATPANELSITE_SERVERURL="http://127.0.0.1:8888" \ --CERTIMATE_DEPLOYER_RATPANELSITE_ACCESSTOKENID="your-access-token-id" \ --CERTIMATE_DEPLOYER_RATPANELSITE_ACCESSTOKEN="your-access-token" \ --CERTIMATE_DEPLOYER_RATPANELSITE_SITENAME="your-site-name" @@ -50,14 +50,14 @@ func TestDeploy(t *testing.T) { "args:", fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), - fmt.Sprintf("APIURL: %v", fApiUrl), + fmt.Sprintf("SERVERURL: %v", fServerUrl), fmt.Sprintf("ACCESSTOKENID: %v", fAccessTokenId), fmt.Sprintf("ACCESSTOKEN: %v", fAccessToken), fmt.Sprintf("SITENAME: %v", fSiteName), }, "\n")) deployer, err := provider.NewDeployer(&provider.DeployerConfig{ - ApiUrl: fApiUrl, + ServerUrl: fServerUrl, AccessTokenId: int32(fAccessTokenId), AccessToken: fAccessToken, AllowInsecureConnections: true, diff --git a/internal/pkg/core/deployer/providers/safeline/safeline.go b/internal/pkg/core/deployer/providers/safeline/safeline.go index f737fda9..0abee743 100644 --- a/internal/pkg/core/deployer/providers/safeline/safeline.go +++ b/internal/pkg/core/deployer/providers/safeline/safeline.go @@ -13,8 +13,8 @@ import ( ) type DeployerConfig struct { - // 雷池 URL。 - ApiUrl string `json:"apiUrl"` + // 雷池服务地址。 + ServerUrl string `json:"serverUrl"` // 雷池 API Token。 ApiToken string `json:"apiToken"` // 是否允许不安全的连接。 @@ -39,7 +39,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { panic("config is nil") } - client, err := createSdkClient(config.ApiUrl, config.ApiToken, config.AllowInsecureConnections) + client, err := createSdkClient(config.ServerUrl, config.ApiToken, config.AllowInsecureConnections) if err != nil { return nil, fmt.Errorf("failed to create sdk client: %w", err) } diff --git a/internal/pkg/core/deployer/providers/safeline/safeline_test.go b/internal/pkg/core/deployer/providers/safeline/safeline_test.go index 67fe6755..9730473c 100644 --- a/internal/pkg/core/deployer/providers/safeline/safeline_test.go +++ b/internal/pkg/core/deployer/providers/safeline/safeline_test.go @@ -14,7 +14,7 @@ import ( var ( fInputCertPath string fInputKeyPath string - fApiUrl string + fServerUrl string fApiToken string fCertificateId int64 ) @@ -24,7 +24,7 @@ func init() { flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") - flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") + flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "") flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "") flag.Int64Var(&fCertificateId, argsPrefix+"CERTIFICATEID", 0, "") } @@ -35,7 +35,7 @@ Shell command to run this test: go test -v ./safeline_test.go -args \ --CERTIMATE_DEPLOYER_SAFELINE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_SAFELINE_INPUTKEYPATH="/path/to/your-input-key.pem" \ - --CERTIMATE_DEPLOYER_SAFELINE_APIURL="http://127.0.0.1:9443" \ + --CERTIMATE_DEPLOYER_SAFELINE_SERVERURL="http://127.0.0.1:9443" \ --CERTIMATE_DEPLOYER_SAFELINE_APITOKEN="your-api-token" \ --CERTIMATE_DEPLOYER_SAFELINE_CERTIFICATEID="your-cerficiate-id" */ @@ -47,13 +47,13 @@ func TestDeploy(t *testing.T) { "args:", fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), - fmt.Sprintf("APIURL: %v", fApiUrl), + fmt.Sprintf("SERVERURL: %v", fServerUrl), fmt.Sprintf("APITOKEN: %v", fApiToken), fmt.Sprintf("CERTIFICATEID: %v", fCertificateId), }, "\n")) deployer, err := provider.NewDeployer(&provider.DeployerConfig{ - ApiUrl: fApiUrl, + ServerUrl: fServerUrl, ApiToken: fApiToken, AllowInsecureConnections: true, ResourceType: provider.RESOURCE_TYPE_CERTIFICATE, diff --git a/internal/pkg/core/notifier/providers/mattermost/mattermost.go b/internal/pkg/core/notifier/providers/mattermost/mattermost.go index a9b2f4d6..8e4fb24d 100644 --- a/internal/pkg/core/notifier/providers/mattermost/mattermost.go +++ b/internal/pkg/core/notifier/providers/mattermost/mattermost.go @@ -12,13 +12,13 @@ import ( ) type NotifierConfig struct { - // 服务地址。 + // Mattermost 服务地址。 ServerUrl string `json:"serverUrl"` - // 用户名。 + // Mattermost 用户名。 Username string `json:"username"` - // 密码。 + // Mattermost 密码。 Password string `json:"password"` - // 频道 ID。 + // Mattermost 频道 ID。 ChannelId string `json:"channelId"` } diff --git a/internal/pkg/core/uploader/providers/1panel-ssl/1panel_ssl.go b/internal/pkg/core/uploader/providers/1panel-ssl/1panel_ssl.go index 63900125..387944e3 100644 --- a/internal/pkg/core/uploader/providers/1panel-ssl/1panel_ssl.go +++ b/internal/pkg/core/uploader/providers/1panel-ssl/1panel_ssl.go @@ -14,8 +14,8 @@ import ( ) type UploaderConfig struct { - // 1Panel 地址。 - ApiUrl string `json:"apiUrl"` + // 1Panel 服务地址。 + ServerUrl string `json:"serverUrl"` // 1Panel 版本。 ApiVersion string `json:"apiVersion"` // 1Panel 接口密钥。 @@ -35,7 +35,7 @@ func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { panic("config is nil") } - client, err := createSdkClient(config.ApiUrl, config.ApiVersion, config.ApiKey) + client, err := createSdkClient(config.ServerUrl, config.ApiVersion, config.ApiKey) if err != nil { return nil, fmt.Errorf("failed to create sdk client: %w", err) } diff --git a/internal/pkg/core/uploader/providers/1panel-ssl/1panel_ssl_test.go b/internal/pkg/core/uploader/providers/1panel-ssl/1panel_ssl_test.go index cfb250be..d0af7c12 100644 --- a/internal/pkg/core/uploader/providers/1panel-ssl/1panel_ssl_test.go +++ b/internal/pkg/core/uploader/providers/1panel-ssl/1panel_ssl_test.go @@ -15,7 +15,7 @@ import ( var ( fInputCertPath string fInputKeyPath string - fApiUrl string + fServerUrl string fApiVersion string fApiKey string ) @@ -25,7 +25,7 @@ func init() { flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") - flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") + flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "") flag.StringVar(&fApiVersion, argsPrefix+"APIVERSION", "v1", "") flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "") } @@ -36,7 +36,7 @@ Shell command to run this test: go test -v ./1panel_ssl_test.go -args \ --CERTIMATE_UPLOADER_1PANELSSL_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_UPLOADER_1PANELSSL_INPUTKEYPATH="/path/to/your-input-key.pem" \ - --CERTIMATE_UPLOADER_1PANELSSL_APIURL="http://127.0.0.1:20410" \ + --CERTIMATE_UPLOADER_1PANELSSL_SERVERURL="http://127.0.0.1:20410" \ --CERTIMATE_UPLOADER_1PANELSSL_APIVERSION="v1" \ --CERTIMATE_UPLOADER_1PANELSSL_APIKEY="your-api-key" */ @@ -48,13 +48,13 @@ func TestDeploy(t *testing.T) { "args:", fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), - fmt.Sprintf("APIURL: %v", fApiUrl), + fmt.Sprintf("SERVERURL: %v", fServerUrl), fmt.Sprintf("APIVERSION: %v", fApiVersion), fmt.Sprintf("APIKEY: %v", fApiKey), }, "\n")) uploader, err := provider.NewUploader(&provider.UploaderConfig{ - ApiUrl: fApiUrl, + ServerUrl: fServerUrl, ApiVersion: fApiVersion, ApiKey: fApiKey, }) diff --git a/migrations/1748178000_upgrade.go b/migrations/1748178000_upgrade.go new file mode 100644 index 00000000..719ed64f --- /dev/null +++ b/migrations/1748178000_upgrade.go @@ -0,0 +1,60 @@ +package migrations + +import ( + "slices" + + "github.com/pocketbase/pocketbase/core" + m "github.com/pocketbase/pocketbase/migrations" +) + +func init() { + m.Register(func(app core.App) error { + // migrate data + { + accesses, err := app.FindAllRecords("access") + if err != nil { + return err + } + + providersToUpdate := []string{ + "1panel", + "baotapanel", + "baotawaf", + "cdnfly", + "flexcdn", + "goedge", + "lecdn", + "powerdns", + "proxmoxve", + "ratpanel", + "safeline", + } + for _, access := range accesses { + changed := false + + if slices.Contains(providersToUpdate, access.GetString("provider")) { + config := make(map[string]any) + if err := access.UnmarshalJSONField("config", &config); err != nil { + return err + } + + config["serverUrl"] = config["apiUrl"] + delete(config, "apiUrl") + access.Set("config", config) + changed = true + } + + if changed { + err = app.Save(access) + if err != nil { + return err + } + } + } + } + + return nil + }, func(app core.App) error { + return nil + }) +} diff --git a/ui/src/components/access/AccessForm1PanelConfig.tsx b/ui/src/components/access/AccessForm1PanelConfig.tsx index 29481f15..56792a02 100644 --- a/ui/src/components/access/AccessForm1PanelConfig.tsx +++ b/ui/src/components/access/AccessForm1PanelConfig.tsx @@ -17,7 +17,7 @@ export type AccessForm1PanelConfigProps = { const initFormModel = (): AccessForm1PanelConfigFieldValues => { return { - apiUrl: "http://:20410/", + serverUrl: "http://:20410/", apiVersion: "v1", apiKey: "", }; @@ -27,7 +27,7 @@ const AccessForm1PanelConfig = ({ form: formInst, formName, disabled, initialVal const { t } = useTranslation(); const formSchema = z.object({ - apiUrl: z.string().url(t("common.errmsg.url_invalid")), + serverUrl: z.string().url(t("common.errmsg.url_invalid")), apiVersion: z.string().nonempty(t("access.form.1panel_api_version.placeholder")), apiKey: z .string() @@ -51,8 +51,8 @@ const AccessForm1PanelConfig = ({ form: formInst, formName, disabled, initialVal name={formName} onValuesChange={handleFormChange} > - - + + @@ -68,10 +68,10 @@ const AccessForm1PanelConfig = ({ form: formInst, formName, disabled, initialVal - + diff --git a/ui/src/components/access/AccessFormBaotaPanelConfig.tsx b/ui/src/components/access/AccessFormBaotaPanelConfig.tsx index dd355b5e..d9cc2752 100644 --- a/ui/src/components/access/AccessFormBaotaPanelConfig.tsx +++ b/ui/src/components/access/AccessFormBaotaPanelConfig.tsx @@ -17,7 +17,7 @@ export type AccessFormBaotaPanelConfigProps = { const initFormModel = (): AccessFormBaotaPanelConfigFieldValues => { return { - apiUrl: "http://:8888/", + serverUrl: "http://:8888/", apiKey: "", }; }; @@ -26,7 +26,7 @@ const AccessFormBaotaPanelConfig = ({ form: formInst, formName, disabled, initia const { t } = useTranslation(); const formSchema = z.object({ - apiUrl: z.string().url(t("common.errmsg.url_invalid")), + serverUrl: z.string().url(t("common.errmsg.url_invalid")), apiKey: z.string().nonempty(t("access.form.baotapanel_api_key.placeholder")).trim(), allowInsecureConnections: z.boolean().nullish(), }); @@ -45,8 +45,8 @@ const AccessFormBaotaPanelConfig = ({ form: formInst, formName, disabled, initia name={formName} onValuesChange={handleFormChange} > - - + + - + diff --git a/ui/src/components/access/AccessFormBaotaWAFConfig.tsx b/ui/src/components/access/AccessFormBaotaWAFConfig.tsx index e87ed596..edf18642 100644 --- a/ui/src/components/access/AccessFormBaotaWAFConfig.tsx +++ b/ui/src/components/access/AccessFormBaotaWAFConfig.tsx @@ -17,7 +17,7 @@ export type AccessFormBaotaWAFConfigProps = { const initFormModel = (): AccessFormBaotaWAFConfigFieldValues => { return { - apiUrl: "http://:8379/", + serverUrl: "http://:8379/", apiKey: "", }; }; @@ -26,7 +26,7 @@ const AccessFormBaotaWAFConfig = ({ form: formInst, formName, disabled, initialV const { t } = useTranslation(); const formSchema = z.object({ - apiUrl: z.string().url(t("common.errmsg.url_invalid")), + serverUrl: z.string().url(t("common.errmsg.url_invalid")), apiKey: z.string().nonempty(t("access.form.baotawaf_api_key.placeholder")).trim(), allowInsecureConnections: z.boolean().nullish(), }); @@ -45,8 +45,8 @@ const AccessFormBaotaWAFConfig = ({ form: formInst, formName, disabled, initialV name={formName} onValuesChange={handleFormChange} > - - + + - + diff --git a/ui/src/components/access/AccessFormCdnflyConfig.tsx b/ui/src/components/access/AccessFormCdnflyConfig.tsx index e95e230b..10422c3b 100644 --- a/ui/src/components/access/AccessFormCdnflyConfig.tsx +++ b/ui/src/components/access/AccessFormCdnflyConfig.tsx @@ -17,7 +17,7 @@ export type AccessFormCdnflyConfigProps = { const initFormModel = (): AccessFormCdnflyConfigFieldValues => { return { - apiUrl: "http://:88/", + serverUrl: "http://:88/", apiKey: "", apiSecret: "", }; @@ -27,7 +27,7 @@ const AccessFormCdnflyConfig = ({ form: formInst, formName, disabled, initialVal const { t } = useTranslation(); const formSchema = z.object({ - apiUrl: z.string().url(t("common.errmsg.url_invalid")), + serverUrl: z.string().url(t("common.errmsg.url_invalid")), apiKey: z .string() .min(1, t("access.form.cdnfly_api_key.placeholder")) @@ -55,8 +55,8 @@ const AccessFormCdnflyConfig = ({ form: formInst, formName, disabled, initialVal name={formName} onValuesChange={handleFormChange} > - - + + - + diff --git a/ui/src/components/access/AccessFormFlexCDNConfig.tsx b/ui/src/components/access/AccessFormFlexCDNConfig.tsx index 6ca020bf..71aa9607 100644 --- a/ui/src/components/access/AccessFormFlexCDNConfig.tsx +++ b/ui/src/components/access/AccessFormFlexCDNConfig.tsx @@ -17,7 +17,7 @@ export type AccessFormFlexCDNConfigProps = { const initFormModel = (): AccessFormFlexCDNConfigFieldValues => { return { - apiUrl: "http://:8000/", + serverUrl: "http://:8000/", apiRole: "user", accessKeyId: "", accessKey: "", @@ -28,7 +28,7 @@ const AccessFormFlexCDNConfig = ({ form: formInst, formName, disabled, initialVa const { t } = useTranslation(); const formSchema = z.object({ - apiUrl: z.string().url(t("common.errmsg.url_invalid")), + serverUrl: z.string().url(t("common.errmsg.url_invalid")), role: z.union([z.literal("user"), z.literal("admin")], { message: t("access.form.flexcdn_api_role.placeholder"), }), @@ -51,8 +51,8 @@ const AccessFormFlexCDNConfig = ({ form: formInst, formName, disabled, initialVa name={formName} onValuesChange={handleFormChange} > - - + + @@ -77,10 +77,10 @@ const AccessFormFlexCDNConfig = ({ form: formInst, formName, disabled, initialVa - + diff --git a/ui/src/components/access/AccessFormGoEdgeConfig.tsx b/ui/src/components/access/AccessFormGoEdgeConfig.tsx index 9c03f2be..641e2276 100644 --- a/ui/src/components/access/AccessFormGoEdgeConfig.tsx +++ b/ui/src/components/access/AccessFormGoEdgeConfig.tsx @@ -17,7 +17,7 @@ export type AccessFormGoEdgeConfigProps = { const initFormModel = (): AccessFormGoEdgeConfigFieldValues => { return { - apiUrl: "http://:7788/", + serverUrl: "http://:7788/", apiRole: "user", accessKeyId: "", accessKey: "", @@ -28,7 +28,7 @@ const AccessFormGoEdgeConfig = ({ form: formInst, formName, disabled, initialVal const { t } = useTranslation(); const formSchema = z.object({ - apiUrl: z.string().url(t("common.errmsg.url_invalid")), + serverUrl: z.string().url(t("common.errmsg.url_invalid")), role: z.union([z.literal("user"), z.literal("admin")], { message: t("access.form.goedge_api_role.placeholder"), }), @@ -51,8 +51,8 @@ const AccessFormGoEdgeConfig = ({ form: formInst, formName, disabled, initialVal name={formName} onValuesChange={handleFormChange} > - - + + @@ -77,10 +77,10 @@ const AccessFormGoEdgeConfig = ({ form: formInst, formName, disabled, initialVal - + diff --git a/ui/src/components/access/AccessFormLeCDNConfig.tsx b/ui/src/components/access/AccessFormLeCDNConfig.tsx index 4af5a639..282afa8d 100644 --- a/ui/src/components/access/AccessFormLeCDNConfig.tsx +++ b/ui/src/components/access/AccessFormLeCDNConfig.tsx @@ -17,7 +17,7 @@ export type AccessFormLeCDNConfigProps = { const initFormModel = (): AccessFormLeCDNConfigFieldValues => { return { - apiUrl: "http://:5090/", + serverUrl: "http://:5090/", apiVersion: "v3", apiRole: "user", username: "", @@ -29,7 +29,7 @@ const AccessFormLeCDNConfig = ({ form: formInst, formName, disabled, initialValu const { t } = useTranslation(); const formSchema = z.object({ - apiUrl: z.string().url(t("common.errmsg.url_invalid")), + serverUrl: z.string().url(t("common.errmsg.url_invalid")), role: z.union([z.literal("client"), z.literal("master")], { message: t("access.form.lecdn_api_role.placeholder"), }), @@ -52,8 +52,8 @@ const AccessFormLeCDNConfig = ({ form: formInst, formName, disabled, initialValu name={formName} onValuesChange={handleFormChange} > - - + + @@ -72,10 +72,10 @@ const AccessFormLeCDNConfig = ({ form: formInst, formName, disabled, initialValu - + diff --git a/ui/src/components/access/AccessFormPowerDNSConfig.tsx b/ui/src/components/access/AccessFormPowerDNSConfig.tsx index b2bfb081..33447cc8 100644 --- a/ui/src/components/access/AccessFormPowerDNSConfig.tsx +++ b/ui/src/components/access/AccessFormPowerDNSConfig.tsx @@ -17,7 +17,7 @@ export type AccessFormPowerDNSConfigProps = { const initFormModel = (): AccessFormPowerDNSConfigFieldValues => { return { - apiUrl: "http://:8082/", + serverUrl: "http://:8082/", apiKey: "", }; }; @@ -26,7 +26,7 @@ const AccessFormPowerDNSConfig = ({ form: formInst, formName, disabled, initialV const { t } = useTranslation(); const formSchema = z.object({ - apiUrl: z.string().url(t("common.errmsg.url_invalid")), + serverUrl: z.string().url(t("common.errmsg.url_invalid")), apiKey: z .string() .min(1, t("access.form.powerdns_api_key.placeholder")) @@ -49,8 +49,8 @@ const AccessFormPowerDNSConfig = ({ form: formInst, formName, disabled, initialV name={formName} onValuesChange={handleFormChange} > - - + + - + diff --git a/ui/src/components/access/AccessFormProxmoxVEConfig.tsx b/ui/src/components/access/AccessFormProxmoxVEConfig.tsx index d0a66745..29280b1c 100644 --- a/ui/src/components/access/AccessFormProxmoxVEConfig.tsx +++ b/ui/src/components/access/AccessFormProxmoxVEConfig.tsx @@ -17,7 +17,7 @@ export type AccessFormProxmoxVEConfigProps = { const initFormModel = (): AccessFormProxmoxVEConfigFieldValues => { return { - apiUrl: "http://:8006/", + serverUrl: "http://:8006/", apiToken: "", }; }; @@ -26,7 +26,7 @@ const AccessFormProxmoxVEConfig = ({ form: formInst, formName, disabled, initial const { t } = useTranslation(); const formSchema = z.object({ - apiUrl: z.string().url(t("common.errmsg.url_invalid")), + serverUrl: z.string().url(t("common.errmsg.url_invalid")), apiToken: z.string().nonempty(t("access.form.proxmoxve_api_token.placeholder")).trim(), apiTokenSecret: z.string().nullish(), allowInsecureConnections: z.boolean().nullish(), @@ -46,8 +46,8 @@ const AccessFormProxmoxVEConfig = ({ form: formInst, formName, disabled, initial name={formName} onValuesChange={handleFormChange} > - - + + - + diff --git a/ui/src/components/access/AccessFormRatPanelConfig.tsx b/ui/src/components/access/AccessFormRatPanelConfig.tsx index ca3d2182..04a71cd1 100644 --- a/ui/src/components/access/AccessFormRatPanelConfig.tsx +++ b/ui/src/components/access/AccessFormRatPanelConfig.tsx @@ -17,7 +17,7 @@ export type AccessFormRatPanelConfigProps = { const initFormModel = (): AccessFormRatPanelConfigFieldValues => { return { - apiUrl: "http://:8888/", + serverUrl: "http://:8888/", accessTokenId: 1, accessToken: "", }; @@ -27,7 +27,7 @@ const AccessFormRatPanelConfig = ({ form: formInst, formName, disabled, initialV const { t } = useTranslation(); const formSchema = z.object({ - apiUrl: z.string().url(t("common.errmsg.url_invalid")), + serverUrl: z.string().url(t("common.errmsg.url_invalid")), accessTokenId: z.preprocess((v) => Number(v), z.number().positive(t("access.form.ratpanel_access_token_id.placeholder"))), accessToken: z.string().nonempty(t("access.form.ratpanel_access_token.placeholder")).trim(), allowInsecureConnections: z.boolean().nullish(), @@ -47,8 +47,8 @@ const AccessFormRatPanelConfig = ({ form: formInst, formName, disabled, initialV name={formName} onValuesChange={handleFormChange} > - - + + - + diff --git a/ui/src/components/access/AccessFormSafeLineConfig.tsx b/ui/src/components/access/AccessFormSafeLineConfig.tsx index 2fde089d..c698d066 100644 --- a/ui/src/components/access/AccessFormSafeLineConfig.tsx +++ b/ui/src/components/access/AccessFormSafeLineConfig.tsx @@ -17,7 +17,7 @@ export type AccessFormSafeLineConfigProps = { const initFormModel = (): AccessFormSafeLineConfigFieldValues => { return { - apiUrl: "http://:9443/", + serverUrl: "http://:9443/", apiToken: "", }; }; @@ -26,7 +26,7 @@ const AccessFormSafeLineConfig = ({ form: formInst, formName, disabled, initialV const { t } = useTranslation(); const formSchema = z.object({ - apiUrl: z.string().url(t("common.errmsg.url_invalid")), + serverUrl: z.string().url(t("common.errmsg.url_invalid")), apiToken: z .string() .min(1, t("access.form.safeline_api_token.placeholder")) @@ -49,8 +49,8 @@ const AccessFormSafeLineConfig = ({ form: formInst, formName, disabled, initialV name={formName} onValuesChange={handleFormChange} > - - + + - + diff --git a/ui/src/components/access/AccessFormWebhookConfig.tsx b/ui/src/components/access/AccessFormWebhookConfig.tsx index 6e6ec87a..d79f848d 100644 --- a/ui/src/components/access/AccessFormWebhookConfig.tsx +++ b/ui/src/components/access/AccessFormWebhookConfig.tsx @@ -362,10 +362,10 @@ const AccessFormWebhookConfig = ({ form: formInst, formName, disabled, initialVa - + diff --git a/ui/src/components/workflow/node/_SharedNode.tsx b/ui/src/components/workflow/node/_SharedNode.tsx index 510a0154..7bec1e90 100644 --- a/ui/src/components/workflow/node/_SharedNode.tsx +++ b/ui/src/components/workflow/node/_SharedNode.tsx @@ -1,13 +1,14 @@ -import { memo, useRef } from "react"; +import { memo, useMemo, useRef } from "react"; import { useTranslation } from "react-i18next"; import { CloseCircleOutlined as CloseCircleOutlinedIcon, EllipsisOutlined as EllipsisOutlinedIcon, FormOutlined as FormOutlinedIcon, + MergeOutlined as MergeOutlinedIcon, MoreOutlined as MoreOutlinedIcon, } from "@ant-design/icons"; import { useControllableValue } from "ahooks"; -import { Button, Card, Drawer, Dropdown, Input, type InputRef, Modal, Popover, Space } from "antd"; +import { Button, Card, Drawer, Dropdown, Input, type InputRef, type MenuProps, Modal, Popover, Space } from "antd"; import { produce } from "immer"; import { isEqual } from "radash"; @@ -59,12 +60,13 @@ const SharedNodeTitle = ({ className, style, node, disabled }: SharedNodeTitlePr type SharedNodeMenuProps = SharedNodeProps & { branchId?: string; branchIndex?: number; + menus?: Array<"rename" | "duplicate" | "remove">; trigger: React.ReactNode; afterUpdate?: () => void; afterDelete?: () => void; }; -const isBranchingNode = (node: WorkflowNode) => { +const isNodeBranchLike = (node: WorkflowNode) => { return ( node.type === WorkflowNodeType.Branch || node.type === WorkflowNodeType.Condition || @@ -74,7 +76,11 @@ const isBranchingNode = (node: WorkflowNode) => { ); }; -const SharedNodeMenu = ({ trigger, node, disabled, branchId, branchIndex, afterUpdate, afterDelete }: SharedNodeMenuProps) => { +const isNodeReadOnly = (node: WorkflowNode) => { + return node.type === WorkflowNodeType.Start || node.type === WorkflowNodeType.End; +}; + +const SharedNodeMenu = ({ menus, trigger, node, disabled, branchId, branchIndex, afterUpdate, afterDelete }: SharedNodeMenuProps) => { const { t } = useTranslation(); const { updateNode, removeNode, removeBranch } = useWorkflowStore(useZustandShallowSelector(["updateNode", "removeNode", "removeBranch"])); @@ -101,7 +107,7 @@ const SharedNodeMenu = ({ trigger, node, disabled, branchId, branchIndex, afterU }; const handleDeleteClick = async () => { - if (isBranchingNode(node)) { + if (isNodeBranchLike(node)) { await removeBranch(branchId!, branchIndex!); } else { await removeNode(node.id); @@ -110,56 +116,82 @@ const SharedNodeMenu = ({ trigger, node, disabled, branchId, branchIndex, afterU afterDelete?.(); }; + const menuItems = useMemo(() => { + let temp = [ + { + key: "rename", + disabled: disabled, + label: isNodeBranchLike(node) ? t("workflow_node.action.rename_branch") : t("workflow_node.action.rename_node"), + icon: , + onClick: () => { + nameRef.current = node.name; + + const dialog = modalApi.confirm({ + title: isNodeBranchLike(node) ? t("workflow_node.action.rename_branch") : t("workflow_node.action.rename_node"), + content: ( +
+ (nameRef.current = e.target.value)} + onPressEnter={async () => { + await handleRenameConfirm(); + dialog.destroy(); + }} + /> +
+ ), + icon: null, + okText: t("common.button.save"), + onOk: handleRenameConfirm, + }); + setTimeout(() => nameInputRef.current?.focus(), 1); + }, + }, + // { + // key: "duplicate", + // disabled: disabled || isNodeReadOnly(node), + // label: isNodeBranchLike(node) ? t("workflow_node.action.duplicate_branch") : t("workflow_node.action.duplicate_node"), + // icon: , + // }, + { + type: "divider", + }, + { + key: "remove", + disabled: disabled || isNodeReadOnly(node), + label: isNodeBranchLike(node) ? t("workflow_node.action.remove_branch") : t("workflow_node.action.remove_node"), + icon: , + danger: true, + onClick: handleDeleteClick, + }, + ] satisfies MenuProps["items"]; + + if (menus) { + temp = temp.filter((item) => item.type === "divider" || menus.includes(item.key as "rename" | "remove")); + temp = temp.filter((item, index, array) => { + if (item.type !== "divider") return true; + return index === 0 || array[index - 1].type !== "divider"; + }); + if (temp[0]?.type === "divider") { + temp.shift(); + } + if (temp[temp.length - 1]?.type === "divider") { + temp.pop(); + } + } + + return temp; + }, [disabled, node]); + return ( <> {ModelContextHolder} , - onClick: () => { - nameRef.current = node.name; - - const dialog = modalApi.confirm({ - title: isBranchingNode(node) ? t("workflow_node.action.rename_branch") : t("workflow_node.action.rename_node"), - content: ( -
- (nameRef.current = e.target.value)} - onPressEnter={async () => { - await handleRenameConfirm(); - dialog.destroy(); - }} - /> -
- ), - icon: null, - okText: t("common.button.save"), - onOk: handleRenameConfirm, - }); - setTimeout(() => nameInputRef.current?.focus(), 1); - }, - }, - { - type: "divider", - }, - { - key: "remove", - disabled: disabled || node.type === WorkflowNodeType.Start, - label: isBranchingNode(node) ? t("workflow_node.action.remove_branch") : t("workflow_node.action.remove_node"), - icon: , - danger: true, - onClick: handleDeleteClick, - }, - ], + items: menuItems, }} trigger={["click"]} > @@ -264,7 +296,6 @@ const SharedNodeConfigDrawer = ({ const { promise, resolve, reject } = Promise.withResolvers(); if (changed) { - console.log(oldValues, newValues); modalApi.confirm({ title: t("common.text.operation_confirm"), content: t("workflow_node.unsaved_changes.confirm"), @@ -288,6 +319,7 @@ const SharedNodeConfigDrawer = ({ destroyOnHidden extra={ } type="text" />} diff --git a/ui/src/domain/access.ts b/ui/src/domain/access.ts index f60f39c8..3765310a 100644 --- a/ui/src/domain/access.ts +++ b/ui/src/domain/access.ts @@ -73,7 +73,7 @@ export interface AccessModel extends BaseModel { // #region AccessConfig export type AccessConfigFor1Panel = { - apiUrl: string; + serverUrl: string; apiVersion: string; apiKey: string; allowInsecureConnections?: boolean; @@ -119,13 +119,13 @@ export type AccessConfigForBaishan = { }; export type AccessConfigForBaotaPanel = { - apiUrl: string; + serverUrl: string; apiKey: string; allowInsecureConnections?: boolean; }; export type AccessConfigForBaotaWAF = { - apiUrl: string; + serverUrl: string; apiKey: string; allowInsecureConnections?: boolean; }; @@ -144,7 +144,7 @@ export type AccessConfigForCacheFly = { }; export type AccessConfigForCdnfly = { - apiUrl: string; + serverUrl: string; apiKey: string; apiSecret: string; allowInsecureConnections?: boolean; @@ -204,7 +204,7 @@ export type AccessConfigForEmail = { }; export type AccessConfigForFlexCDN = { - apiUrl: string; + serverUrl: string; apiRole: string; accessKeyId: string; accessKey: string; @@ -226,7 +226,7 @@ export type AccessConfigForGoDaddy = { }; export type AccessConfigForGoEdge = { - apiUrl: string; + serverUrl: string; apiRole: string; accessKeyId: string; accessKey: string; @@ -257,7 +257,7 @@ export type AccessConfigForLarkBot = { }; export type AccessConfigForLeCDN = { - apiUrl: string; + serverUrl: string; apiVersion: string; apiRole: string; username: string; @@ -306,13 +306,13 @@ export type AccessConfigForPorkbun = { }; export type AccessConfigForPowerDNS = { - apiUrl: string; + serverUrl: string; apiKey: string; allowInsecureConnections?: boolean; }; export type AccessConfigForProxmoxVE = { - apiUrl: string; + serverUrl: string; apiToken: string; apiTokenSecret?: string; allowInsecureConnections?: boolean; @@ -328,14 +328,14 @@ export type AccessConfigForRainYun = { }; export type AccessConfigForRatPanel = { - apiUrl: string; + serverUrl: string; accessTokenId: number; accessToken: string; allowInsecureConnections?: boolean; }; export type AccessConfigForSafeLine = { - apiUrl: string; + serverUrl: string; apiToken: string; allowInsecureConnections?: boolean; }; diff --git a/ui/src/i18n/locales/en/nls.access.json b/ui/src/i18n/locales/en/nls.access.json index 41b81636..c2e52c6a 100644 --- a/ui/src/i18n/locales/en/nls.access.json +++ b/ui/src/i18n/locales/en/nls.access.json @@ -34,16 +34,16 @@ "access.form.certificate_authority.placeholder": "Please select a certificate authority", "access.form.notification_channel.label": "Notification channel", "access.form.notification_channel.placeholder": "Please select a notification channel", - "access.form.1panel_api_url.label": "1Panel URL", - "access.form.1panel_api_url.placeholder": "Please enter 1Panel URL", + "access.form.1panel_server_url.label": "1Panel server URL", + "access.form.1panel_server_url.placeholder": "Please enter 1Panel server URL", "access.form.1panel_api_version.label": "1Panel version", "access.form.1panel_api_version.placeholder": "Please select 1Panel version", "access.form.1panel_api_key.label": "1Panel API key", "access.form.1panel_api_key.placeholder": "Please enter 1Panel API key", "access.form.1panel_api_key.tooltip": "For more information, see https://docs.1panel.pro/dev_manual/api_manual/", - "access.form.1panel_allow_insecure_conns.label": "Insecure SSL/TLS connections", - "access.form.1panel_allow_insecure_conns.switch.on": "Allow", - "access.form.1panel_allow_insecure_conns.switch.off": "Disallow", + "access.form.common_allow_insecure_conns.label": "Insecure SSL/TLS connections", + "access.form.common_allow_insecure_conns.switch.on": "Allow", + "access.form.common_allow_insecure_conns.switch.off": "Disallow", "access.form.acmeca_endpoint.label": "Endpoint", "access.form.acmeca_endpoint.placeholder": "Please enter endpoint", "access.form.acmeca_endpoint.tooltip": "For more information, see https://datatracker.ietf.org/doc/html/rfc8555#section-7.1.1", @@ -104,22 +104,16 @@ "access.form.upyun_password.tooltip": "For more information, see https://console.upyun.com/account/subaccount/", "access.form.baishan_api_token.label": "Baishan Cloud API token", "access.form.baishan_api_token.placeholder": "Please enter Baishan Cloud API token", - "access.form.baotapanel_api_url.label": "aaPanel URL", - "access.form.baotapanel_api_url.placeholder": "Please enter aaPanel URL", + "access.form.baotapanel_server_url.label": "aaPanel server URL", + "access.form.baotapanel_server_url.placeholder": "Please enter aaPanel server URL", "access.form.baotapanel_api_key.label": "aaPanel API key", "access.form.baotapanel_api_key.placeholder": "Please enter aaPanel API key", "access.form.baotapanel_api_key.tooltip": "For more information, see https://www.bt.cn/bbs/thread-20376-1-1.html", - "access.form.baotapanel_allow_insecure_conns.label": "Insecure SSL/TLS connections", - "access.form.baotapanel_allow_insecure_conns.switch.on": "Allow", - "access.form.baotapanel_allow_insecure_conns.switch.off": "Disallow", - "access.form.baotawaf_api_url.label": "aaWAF URL", - "access.form.baotawaf_api_url.placeholder": "Please enter aaWAF URL", + "access.form.baotawaf_server_url.label": "aaWAF server URL", + "access.form.baotawaf_server_url.placeholder": "Please enter aaWAF server URL", "access.form.baotawaf_api_key.label": "aaWAF API key", "access.form.baotawaf_api_key.placeholder": "Please enter aaWAF API key", "access.form.baotawaf_api_key.tooltip": "For more information, see https://github.com/aaPanel/aaWAF/blob/main/API.md", - "access.form.baotawaf_allow_insecure_conns.label": "Insecure SSL/TLS connections", - "access.form.baotawaf_allow_insecure_conns.switch.on": "Allow", - "access.form.baotawaf_allow_insecure_conns.switch.off": "Disallow", "access.form.byteplus_access_key.label": "BytePlus AccessKey", "access.form.byteplus_access_key.placeholder": "Please enter BytePlus AccessKey", "access.form.byteplus_access_key.tooltip": "For more information, see https://docs.byteplus.com/en/docs/byteplus-platform/docs-managing-keys", @@ -129,17 +123,14 @@ "access.form.cachefly_api_token.label": "CacheFly API token", "access.form.cachefly_api_token.placeholder": "Please enter CacheFly API token", "access.form.cachefly_api_token.tooltip": "For more information, see https://kb.cachefly.com/kb/guide/en/generating-tokens-and-keys-Oll9Irt5TI/Steps/2460228", - "access.form.cdnfly_api_url.label": "Cdnfly URL", - "access.form.cdnfly_api_url.placeholder": "Please enter Cdnfly URL", + "access.form.cdnfly_server_url.label": "Cdnfly server URL", + "access.form.cdnfly_server_url.placeholder": "Please enter Cdnfly server URL", "access.form.cdnfly_api_key.label": "Cdnfly user API key", "access.form.cdnfly_api_key.placeholder": "Please enter Cdnfly user API key", "access.form.cdnfly_api_key.tooltip": "For more information, see https://doc.cdnfly.cn/shiyongjieshao.html", "access.form.cdnfly_api_secret.label": "Cdnfly user API secret", "access.form.cdnfly_api_secret.placeholder": "Please enter Cdnfly user API secret", "access.form.cdnfly_api_secret.tooltip": "For more information, see https://doc.cdnfly.cn/shiyongjieshao.html", - "access.form.cdnfly_allow_insecure_conns.label": "Insecure SSL/TLS connections", - "access.form.cdnfly_allow_insecure_conns.switch.on": "Allow", - "access.form.cdnfly_allow_insecure_conns.switch.off": "Disallow", "access.form.cloudflare_dns_api_token.label": "Cloudflare DNS API token", "access.form.cloudflare_dns_api_token.placeholder": "Please enter Cloudflare DNS API token", "access.form.cloudflare_dns_api_token.tooltip": "For more information, see https://developers.cloudflare.com/fundamentals/api/get-started/create-token/", @@ -201,8 +192,8 @@ "access.form.email_default_sender_address.placeholder": "Please enter default sender email address", "access.form.email_default_receiver_address.label": "Default receiver email address (Optional)", "access.form.email_default_receiver_address.placeholder": "Please enter default receiver email address", - "access.form.flexcdn_api_url.label": "FlexCDN URL", - "access.form.flexcdn_api_url.placeholder": "Please enter FlexCDN URL", + "access.form.flexcdn_server_url.label": "FlexCDN server URL", + "access.form.flexcdn_server_url.placeholder": "Please enter FlexCDN server URL", "access.form.flexcdn_api_role.label": "FlexCDN user role", "access.form.flexcdn_api_role.placeholder": "Please select FlexCDN user role", "access.form.flexcdn_api_role.option.user.label": "Platform user", @@ -213,9 +204,6 @@ "access.form.flexcdn_access_key.label": "FlexCDN AccessKey", "access.form.flexcdn_access_key.placeholder": "Please enter FlexCDN AccessKey", "access.form.flexcdn_access_key.tooltip": "For more information, see https://flexcdn.cn/docs/api/auth", - "access.form.flexcdn_allow_insecure_conns.label": "Insecure SSL/TLS connections", - "access.form.flexcdn_allow_insecure_conns.switch.on": "Allow", - "access.form.flexcdn_allow_insecure_conns.switch.off": "Disallow", "access.form.gcore_api_token.label": "Gcore API token", "access.form.gcore_api_token.placeholder": "Please enter Gcore API token", "access.form.gcore_api_token.tooltip": "For more information, see https://api.gcore.com/docs/iam#section/Authentication", @@ -231,8 +219,8 @@ "access.form.godaddy_api_secret.label": "GoDaddy API secret", "access.form.godaddy_api_secret.placeholder": "Please enter GoDaddy API secret", "access.form.godaddy_api_secret.tooltip": "For more information, see https://developer.godaddy.com/", - "access.form.goedge_api_url.label": "GoEdge URL", - "access.form.goedge_api_url.placeholder": "Please enter GoEdge URL", + "access.form.goedge_server_url.label": "GoEdge server URL", + "access.form.goedge_server_url.placeholder": "Please enter GoEdge server URL", "access.form.goedge_api_role.label": "GoEdge user role", "access.form.goedge_api_role.placeholder": "Please select GoEdge user role", "access.form.goedge_api_role.option.user.label": "Platform user", @@ -243,9 +231,6 @@ "access.form.goedge_access_key.label": "GoEdge AccessKey", "access.form.goedge_access_key.placeholder": "Please enter GoEdge AccessKey", "access.form.goedge_access_key.tooltip": "For more information, see https://goedge.cloud/docs/API/Auth.md", - "access.form.goedge_allow_insecure_conns.label": "Insecure SSL/TLS connections", - "access.form.goedge_allow_insecure_conns.switch.on": "Allow", - "access.form.goedge_allow_insecure_conns.switch.off": "Disallow", "access.form.googletrustservices_eab_kid.label": "ACME EAB KID", "access.form.googletrustservices_eab_kid.placeholder": "Please enter ACME EAB KID", "access.form.googletrustservices_eab_kid.tooltip": "For more information, see https://cloud.google.com/certificate-manager/docs/public-ca-tutorial", @@ -270,8 +255,8 @@ "access.form.larkbot_webhook_url.label": "Lark bot Webhook URL", "access.form.larkbot_webhook_url.placeholder": "Please enter Lark bot Webhook URL", "access.form.larkbot_webhook_url.tooltip": "For more information, see https://www.feishu.cn/hc/en-US/articles/807992406756", - "access.form.lecdn_api_url.label": "LeCDN URL", - "access.form.lecdn_api_url.placeholder": "Please enter LeCDN URL", + "access.form.lecdn_server_url.label": "LeCDN server URL", + "access.form.lecdn_server_url.placeholder": "Please enter LeCDN server URL", "access.form.lecdn_api_version.label": "LeCDN version", "access.form.lecdn_api_version.placeholder": "Please select LeCDN version", "access.form.lecdn_api_role.label": "LeCDN user role", @@ -282,9 +267,6 @@ "access.form.lecdn_username.placeholder": "Please enter LeCDN username", "access.form.lecdn_password.label": "LeCDN password", "access.form.lecdn_password.placeholder": "Please enter GoEdge password", - "access.form.lecdn_allow_insecure_conns.label": "Insecure SSL/TLS connections", - "access.form.lecdn_allow_insecure_conns.switch.on": "Allow", - "access.form.lecdn_allow_insecure_conns.switch.off": "Disallow", "access.form.mattermost_server_url.label": "Mattermost server URL", "access.form.mattermost_server_url.placeholder": "Please enter Mattermost server URL", "access.form.mattermost_username.label": "Mattermost username", @@ -330,25 +312,19 @@ "access.form.porkbun_secret_api_key.label": "Porkbun secret API key", "access.form.porkbun_secret_api_key.placeholder": "Please enter Porkbun secret API key", "access.form.porkbun_secret_api_key.tooltip": "For more information, see https://porkbun.com/api/json/v3/documentation", - "access.form.powerdns_api_url.label": "PowerDNS URL", - "access.form.powerdns_api_url.placeholder": "Please enter PowerDNS URL", + "access.form.powerdns_server_url.label": "PowerDNS server URL", + "access.form.powerdns_server_url.placeholder": "Please enter PowerDNS server URL", "access.form.powerdns_api_key.label": "PowerDNS API key", "access.form.powerdns_api_key.placeholder": "Please enter PowerDNS API key", "access.form.powerdns_api_key.tooltip": "For more information, see https://doc.powerdns.com/authoritative/http-api/index.html#enabling-the-api", - "access.form.powerdns_allow_insecure_conns.label": "Insecure SSL/TLS connections", - "access.form.powerdns_allow_insecure_conns.switch.on": "Allow", - "access.form.powerdns_allow_insecure_conns.switch.off": "Disallow", - "access.form.proxmoxve_api_url.label": "Proxmox VE URL", - "access.form.proxmoxve_api_url.placeholder": "Please enter Proxmox VE URL", + "access.form.proxmoxve_server_url.label": "Proxmox VE server URL", + "access.form.proxmoxve_server_url.placeholder": "Please enter Proxmox VE server URL", "access.form.proxmoxve_api_token.label": "Proxmox VE API token", "access.form.proxmoxve_api_token.placeholder": "Please enter Proxmox VE API token", "access.form.proxmoxve_api_token.tooltip": "For more information, see https://pve.proxmox.com/pve-docs/pve-admin-guide.html#pveum_tokens", "access.form.proxmoxve_api_token_secret.label": "Proxmox VE API token secret (Optional)", "access.form.proxmoxve_api_token_secret.placeholder": "Please enter Proxmox VE API token secret", "access.form.proxmoxve_api_token_secret.tooltip": "For more information, see https://pve.proxmox.com/pve-docs/pve-admin-guide.html#pveum_tokens", - "access.form.proxmoxve_allow_insecure_conns.label": "Insecure SSL/TLS connections", - "access.form.proxmoxve_allow_insecure_conns.switch.on": "Allow", - "access.form.proxmoxve_allow_insecure_conns.switch.off": "Disallow", "access.form.qiniu_access_key.label": "Qiniu AccessKey", "access.form.qiniu_access_key.placeholder": "Please enter Qiniu AccessKey", "access.form.qiniu_access_key.tooltip": "For more information, see https://portal.qiniu.com/", @@ -358,25 +334,19 @@ "access.form.rainyun_api_key.label": "Rain Yun API key", "access.form.rainyun_api_key.placeholder": "Please enter Rain Yun API key", "access.form.rainyun_api_key.tooltip": "For more information, see https://app.rainyun.com/account/settings/api-key", - "access.form.ratpanel_api_url.label": "RatPanel URL", - "access.form.ratpanel_api_url.placeholder": "Please enter RatPanel URL", + "access.form.ratpanel_server_url.label": "RatPanel server URL", + "access.form.ratpanel_server_url.placeholder": "Please enter RatPanel server URL", "access.form.ratpanel_access_token_id.label": "RatPanel access token ID", "access.form.ratpanel_access_token_id.placeholder": "Please enter RatPanel access token ID", "access.form.ratpanel_access_token_id.tooltip": "For more information, see https://ratpanel.github.io/advanced/api.html", "access.form.ratpanel_access_token.label": "RatPanel access token", "access.form.ratpanel_access_token.placeholder": "Please enter RatPanel access token", "access.form.ratpanel_access_token.tooltip": "For more information, see https://ratpanel.github.io/advanced/api.html", - "access.form.ratpanel_allow_insecure_conns.label": "Insecure SSL/TLS connections", - "access.form.ratpanel_allow_insecure_conns.switch.on": "Allow", - "access.form.ratpanel_allow_insecure_conns.switch.off": "Disallow", - "access.form.safeline_api_url.label": "SafeLine URL", - "access.form.safeline_api_url.placeholder": "Please enter SafeLine URL", + "access.form.safeline_server_url.label": "SafeLine server URL", + "access.form.safeline_server_url.placeholder": "Please enter SafeLine server URL", "access.form.safeline_api_token.label": "SafeLine API token", "access.form.safeline_api_token.placeholder": "Please enter SafeLine API token", "access.form.safeline_api_token.tooltip": "For more information, see https://docs.waf.chaitin.com/en/reference/articles/openapi", - "access.form.safeline_allow_insecure_conns.label": "Insecure SSL/TLS connections", - "access.form.safeline_allow_insecure_conns.switch.on": "Allow", - "access.form.safeline_allow_insecure_conns.switch.off": "Disallow", "access.form.ssh_host.label": "Server host", "access.form.ssh_host.placeholder": "Please enter server host", "access.form.ssh_port.label": "Server port", @@ -466,9 +436,6 @@ "access.form.webhook_preset_data.option.pushplus.label": "PushPlus", "access.form.webhook_preset_data.option.serverchan.label": "ServerChan", "access.form.webhook_preset_data.option.common.label": "General template", - "access.form.webhook_allow_insecure_conns.label": "Insecure SSL/TLS connections", - "access.form.webhook_allow_insecure_conns.switch.on": "Allow", - "access.form.webhook_allow_insecure_conns.switch.off": "Disallow", "access.form.wecombot_webhook_url.label": "WeCom bot Webhook URL", "access.form.wecombot_webhook_url.placeholder": "Please enter WeCom bot Webhook URL", "access.form.wecombot_webhook_url.tooltip": "For more information, see https://open.work.weixin.qq.com/help2/pc/18401", diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index a5e89438..fdae1705 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -34,16 +34,16 @@ "access.form.certificate_authority.placeholder": "请选择证书颁发机构", "access.form.notification_channel.label": "通知渠道", "access.form.notification_channel.placeholder": "请选择通知渠道", - "access.form.1panel_api_url.label": "1Panel URL", - "access.form.1panel_api_url.placeholder": "请输入 1Panel URL", + "access.form.common_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误", + "access.form.common_allow_insecure_conns.switch.on": "允许", + "access.form.common_allow_insecure_conns.switch.off": "不允许", + "access.form.1panel_server_url.label": "1Panel 服务地址", + "access.form.1panel_server_url.placeholder": "请输入 1Panel 服务地址", "access.form.1panel_api_version.label": "1Panel 版本", "access.form.1panel_api_version.placeholder": "请选择 1Panel 版本", "access.form.1panel_api_key.label": "1Panel 接口密钥", "access.form.1panel_api_key.placeholder": "请输入 1Panel 接口密钥", "access.form.1panel_api_key.tooltip": "这是什么?请参阅 https://1panel.cn/docs/dev_manual/api_manual/", - "access.form.1panel_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误", - "access.form.1panel_allow_insecure_conns.switch.on": "允许", - "access.form.1panel_allow_insecure_conns.switch.off": "不允许", "access.form.acmeca_endpoint.label": "服务端点", "access.form.acmeca_endpoint.placeholder": "请输入服务端点", "access.form.acmeca_endpoint.tooltip": "这是什么?请参阅 https://datatracker.ietf.org/doc/html/rfc8555#section-7.1.1", @@ -95,22 +95,16 @@ "access.form.baiducloud_secret_access_key.tooltip": "这是什么?请参阅 https://cloud.baidu.com/doc/Reference/s/jjwvz2e3p", "access.form.baishan_api_token.label": "白山云 API Token", "access.form.baishan_api_token.placeholder": "请输入白山云 API Token", - "access.form.baotapanel_api_url.label": "宝塔面板 URL", - "access.form.baotapanel_api_url.placeholder": "请输入宝塔面板 URL", + "access.form.baotapanel_server_url.label": "宝塔面板服务地址", + "access.form.baotapanel_server_url.placeholder": "请输入宝塔面板服务地址", "access.form.baotapanel_api_key.label": "宝塔面板接口密钥", "access.form.baotapanel_api_key.placeholder": "请输入宝塔面板接口密钥", "access.form.baotapanel_api_key.tooltip": "这是什么?请参阅 https://www.bt.cn/bbs/thread-113890-1-1.html", - "access.form.baotapanel_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误", - "access.form.baotapanel_allow_insecure_conns.switch.on": "允许", - "access.form.baotapanel_allow_insecure_conns.switch.off": "不允许", - "access.form.baotawaf_api_url.label": "堡塔云 WAF URL", - "access.form.baotawaf_api_url.placeholder": "请输入堡塔云 WAF URL", + "access.form.baotawaf_server_url.label": "堡塔云 WAF 服务地址", + "access.form.baotawaf_server_url.placeholder": "请输入堡塔云 WAF 服务地址", "access.form.baotawaf_api_key.label": "堡塔云 WAF 接口密钥", "access.form.baotawaf_api_key.placeholder": "请输入 堡塔云 WAF 接口密钥", "access.form.baotawaf_api_key.tooltip": "这是什么?请参阅 https://github.com/aaPanel/aaWAF/blob/main/API.md", - "access.form.baotawaf_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误", - "access.form.baotawaf_allow_insecure_conns.switch.on": "允许", - "access.form.baotawaf_allow_insecure_conns.switch.off": "不允许", "access.form.bunny_api_key.label": "Bunny API Key", "access.form.bunny_api_key.placeholder": "请输入 Bunny API Key", "access.form.bunny_api_key.tooltip": "这是什么?请参阅 https://docs.bunny.net/reference/bunnynet-api-overview", @@ -123,17 +117,14 @@ "access.form.cachefly_api_token.label": "CacheFly API Token", "access.form.cachefly_api_token.placeholder": "请输入 CacheFly API Token", "access.form.cachefly_api_token.tooltip": "这是什么?请参阅 https://kb.cachefly.com/kb/guide/en/generating-tokens-and-keys-Oll9Irt5TI/Steps/2460228", - "access.form.cdnfly_api_url.label": "Cdnfly URL", - "access.form.cdnfly_api_url.placeholder": "请输入 Cdnfly URL", + "access.form.cdnfly_server_url.label": "Cdnfly 服务地址", + "access.form.cdnfly_server_url.placeholder": "请输入 Cdnfly 服务地址", "access.form.cdnfly_api_key.label": "Cdnfly 用户端 API Key", "access.form.cdnfly_api_key.placeholder": "请输入 Cdnfly 用户端 API Key", "access.form.cdnfly_api_key.tooltip": "这是什么?请参阅 https://doc.cdnfly.cn/shiyongjieshao.html", "access.form.cdnfly_api_secret.label": "Cdnfly 用户端 API Secret", "access.form.cdnfly_api_secret.placeholder": "请输入 Cdnfly 用户端 API Secret", "access.form.cdnfly_api_secret.tooltip": "这是什么?请参阅 https://doc.cdnfly.cn/shiyongjieshao.html", - "access.form.cdnfly_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误", - "access.form.cdnfly_allow_insecure_conns.switch.on": "允许", - "access.form.cdnfly_allow_insecure_conns.switch.off": "不允许", "access.form.cloudflare_dns_api_token.label": "Cloudflare DNS API 令牌", "access.form.cloudflare_dns_api_token.placeholder": "请输入 Cloudflare DNS API 令牌", "access.form.cloudflare_dns_api_token.tooltip": "这是什么?请参阅 https://developers.cloudflare.com/fundamentals/api/get-started/create-token/", @@ -195,8 +186,8 @@ "access.form.email_default_sender_address.placeholder": "请输入默认的发送邮箱地址", "access.form.email_default_receiver_address.label": "默认的接收邮箱地址(可选)", "access.form.email_default_receiver_address.placeholder": "请输入默认的接收邮箱地址", - "access.form.flexcdn_api_url.label": "FlexCDN URL", - "access.form.flexcdn_api_url.placeholder": "请输入 FlexCDN URL", + "access.form.flexcdn_server_url.label": "FlexCDN 服务地址", + "access.form.flexcdn_server_url.placeholder": "请输入 FlexCDN 服务地址", "access.form.flexcdn_api_role.label": "FlexCDN 用户角色", "access.form.flexcdn_api_role.placeholder": "请选择 FlexCDN 用户角色", "access.form.flexcdn_api_role.option.user.label": "平台用户", @@ -207,9 +198,6 @@ "access.form.flexcdn_access_key.label": "FlexCDN AccessKey", "access.form.flexcdn_access_key.placeholder": "请输入 FlexCDN AccessKey", "access.form.flexcdn_access_key.tooltip": "这是什么?请参阅 https://flexcdn.cn/docs/api/auth", - "access.form.flexcdn_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误", - "access.form.flexcdn_allow_insecure_conns.switch.on": "允许", - "access.form.flexcdn_allow_insecure_conns.switch.off": "不允许", "access.form.gcore_api_token.label": "Gcore API Token", "access.form.gcore_api_token.placeholder": "请输入 Gcore API Token", "access.form.gcore_api_token.tooltip": "这是什么?请参阅 https://api.gcore.com/docs/iam#section/Authentication", @@ -225,8 +213,8 @@ "access.form.godaddy_api_secret.label": "GoDaddy API Secret", "access.form.godaddy_api_secret.placeholder": "请输入 GoDaddy API Secret", "access.form.godaddy_api_secret.tooltip": "这是什么?请参阅 https://developer.godaddy.com/", - "access.form.goedge_api_url.label": "GoEdge URL", - "access.form.goedge_api_url.placeholder": "请输入 GoEdge URL", + "access.form.goedge_server_url.label": "GoEdge 服务地址", + "access.form.goedge_server_url.placeholder": "请输入 GoEdge 服务地址", "access.form.goedge_api_role.label": "GoEdge 用户角色", "access.form.goedge_api_role.placeholder": "请选择 GoEdge 用户角色", "access.form.goedge_api_role.option.user.label": "平台用户", @@ -237,9 +225,6 @@ "access.form.goedge_access_key.label": "GoEdge AccessKey", "access.form.goedge_access_key.placeholder": "请输入 GoEdge AccessKey", "access.form.goedge_access_key.tooltip": "这是什么?请参阅 https://goedge.cloud/docs/API/Auth.md", - "access.form.goedge_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误", - "access.form.goedge_allow_insecure_conns.switch.on": "允许", - "access.form.goedge_allow_insecure_conns.switch.off": "不允许", "access.form.googletrustservices_eab_kid.label": "ACME EAB KID", "access.form.googletrustservices_eab_kid.placeholder": "请输入 ACME EAB KID", "access.form.googletrustservices_eab_kid.tooltip": "这是什么?请参阅 https://cloud.google.com/certificate-manager/docs/public-ca-tutorial", @@ -264,8 +249,8 @@ "access.form.larkbot_webhook_url.label": "飞书群机器人 Webhook 地址", "access.form.larkbot_webhook_url.placeholder": "请输入飞书群机器人 Webhook 地址", "access.form.larkbot_webhook_url.tooltip": "这是什么?请参阅 https://www.feishu.cn/hc/zh-CN/articles/807992406756", - "access.form.lecdn_api_url.label": "LeCDN URL", - "access.form.lecdn_api_url.placeholder": "请输入 LeCDN URL", + "access.form.lecdn_server_url.label": "LeCDN 服务地址", + "access.form.lecdn_server_url.placeholder": "请输入 LeCDN 服务地址", "access.form.lecdn_api_version.label": "LeCDN 版本", "access.form.lecdn_api_version.placeholder": "请选择 LeCDN 版本", "access.form.lecdn_api_role.label": "LeCDN 用户角色", @@ -276,9 +261,6 @@ "access.form.lecdn_username.placeholder": "请输入 LeCDN 用户名", "access.form.lecdn_password.label": "LeCDN 用户密码", "access.form.lecdn_password.placeholder": "请输入 LeCDN 用户密码", - "access.form.lecdn_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误", - "access.form.lecdn_allow_insecure_conns.switch.on": "允许", - "access.form.lecdn_allow_insecure_conns.switch.off": "不允许", "access.form.mattermost_server_url.label": "Mattermost 服务地址", "access.form.mattermost_server_url.placeholder": "请输入 Mattermost 服务地址", "access.form.mattermost_username.label": "Mattermost 用户名", @@ -324,25 +306,19 @@ "access.form.porkbun_secret_api_key.label": "Porkbun Secret API Key", "access.form.porkbun_secret_api_key.placeholder": "请输入 Porkbun Secret API Key", "access.form.porkbun_secret_api_key.tooltip": "这是什么?请参阅 https://porkbun.com/api/json/v3/documentation", - "access.form.powerdns_api_url.label": "PowerDNS URL", - "access.form.powerdns_api_url.placeholder": "请输入 PowerDNS URL", + "access.form.powerdns_server_url.label": "PowerDNS 服务地址", + "access.form.powerdns_server_url.placeholder": "请输入 PowerDNS 服务地址", "access.form.powerdns_api_key.label": "PowerDNS API Key", "access.form.powerdns_api_key.placeholder": "请输入 PowerDNS API Key", "access.form.powerdns_api_key.tooltip": "这是什么?请参阅 https://doc.powerdns.com/authoritative/http-api/index.html#enabling-the-api", - "access.form.powerdns_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误", - "access.form.powerdns_allow_insecure_conns.switch.on": "允许", - "access.form.powerdns_allow_insecure_conns.switch.off": "不允许", - "access.form.proxmoxve_api_url.label": "Proxmox VE URL", - "access.form.proxmoxve_api_url.placeholder": "请输入 Proxmox VE URL", + "access.form.proxmoxve_server_url.label": "Proxmox VE 服务地址", + "access.form.proxmoxve_server_url.placeholder": "请输入 Proxmox VE 服务地址", "access.form.proxmoxve_api_token.label": "Proxmox VE API Token", "access.form.proxmoxve_api_token.placeholder": "请输入 Proxmox VE API Token", "access.form.proxmoxve_api_token.tooltip": "这是什么?请参阅 https://pve.proxmox.com/pve-docs/pve-admin-guide.html#pveum_tokens", "access.form.proxmoxve_api_token_secret.label": "Proxmox VE API Token Secret(可选)", "access.form.proxmoxve_api_token_secret.placeholder": "请输入 Proxmox VE API Token Secret", "access.form.proxmoxve_api_token_secret.tooltip": "这是什么?请参阅 https://pve.proxmox.com/pve-docs/pve-admin-guide.html#pveum_tokens", - "access.form.proxmoxve_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误", - "access.form.proxmoxve_allow_insecure_conns.switch.on": "允许", - "access.form.proxmoxve_allow_insecure_conns.switch.off": "不允许", "access.form.qiniu_access_key.label": "七牛云 AccessKey", "access.form.qiniu_access_key.placeholder": "请输入七牛云 AccessKey", "access.form.qiniu_access_key.tooltip": "这是什么?请参阅 https://portal.qiniu.com/", @@ -352,25 +328,19 @@ "access.form.rainyun_api_key.label": "雨云 API 密钥", "access.form.rainyun_api_key.placeholder": "请输入雨云 API 密钥", "access.form.rainyun_api_key.tooltip": "这是什么?请参阅 https://app.rainyun.com/account/settings/api-key", - "access.form.ratpanel_api_url.label": "耗子面板 URL", - "access.form.ratpanel_api_url.placeholder": "请输入耗子面板 URL", + "access.form.ratpanel_server_url.label": "耗子面板服务地址", + "access.form.ratpanel_server_url.placeholder": "请输入耗子面板服务地址", "access.form.ratpanel_access_token_id.label": "耗子面板 AccessToken ID", "access.form.ratpanel_access_token_id.placeholder": "请输入耗子面板 AccessToken ID", "access.form.ratpanel_access_token_id.tooltip": "这是什么?请参阅 https://ratpanel.github.io/advanced/api.html", "access.form.ratpanel_access_token.label": "耗子面板 AccessToken", "access.form.ratpanel_access_token.placeholder": "请输入耗子面板 AccessToken", "access.form.ratpanel_access_token.tooltip": "这是什么?请参阅 https://ratpanel.github.io/advanced/api.html", - "access.form.ratpanel_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误", - "access.form.ratpanel_allow_insecure_conns.switch.on": "允许", - "access.form.ratpanel_allow_insecure_conns.switch.off": "不允许", - "access.form.safeline_api_url.label": "雷池 URL", - "access.form.safeline_api_url.placeholder": "请输入雷池 URL", + "access.form.safeline_server_url.label": "雷池服务地址", + "access.form.safeline_server_url.placeholder": "请输入雷池服务地址", "access.form.safeline_api_token.label": "雷池 API Token", "access.form.safeline_api_token.placeholder": "请输入雷池 API Token", "access.form.safeline_api_token.tooltip": "这是什么?请参阅 https://docs.waf-ce.chaitin.cn/zh/更多技术文档/OPENAPI", - "access.form.safeline_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误", - "access.form.safeline_allow_insecure_conns.switch.on": "允许", - "access.form.safeline_allow_insecure_conns.switch.off": "不允许", "access.form.ssh_host.label": "服务器地址", "access.form.ssh_host.placeholder": "请输入服务器地址", "access.form.ssh_port.label": "服务器端口", @@ -466,9 +436,6 @@ "access.form.webhook_preset_data.option.pushplus.label": "PushPlus 推送加", "access.form.webhook_preset_data.option.serverchan.label": "Server 酱", "access.form.webhook_preset_data.option.common.label": "通用模板", - "access.form.webhook_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误", - "access.form.webhook_allow_insecure_conns.switch.on": "允许", - "access.form.webhook_allow_insecure_conns.switch.off": "不允许", "access.form.wecombot_webhook_url.label": "企业微信群机器人 Webhook 地址", "access.form.wecombot_webhook_url.placeholder": "请输入企业微信群机器人 Webhook 地址", "access.form.wecombot_webhook_url.tooltip": "这是什么?请参阅 https://open.work.weixin.qq.com/help2/pc/18401", diff --git a/ui/src/i18n/locales/zh/nls.settings.json b/ui/src/i18n/locales/zh/nls.settings.json index cde8ec0f..b3da01aa 100644 --- a/ui/src/i18n/locales/zh/nls.settings.json +++ b/ui/src/i18n/locales/zh/nls.settings.json @@ -28,8 +28,8 @@ "settings.notification.channel.switch.off": "停用", "settings.notification.push_test.button": "推送测试消息", "settings.notification.push_test.pushed": "已推送", - "settings.notification.channel.form.bark_server_url.label": "服务器地址", - "settings.notification.channel.form.bark_server_url.placeholder": "请输入服务器地址", + "settings.notification.channel.form.bark_server_url.label": "服务地址", + "settings.notification.channel.form.bark_server_url.placeholder": "请输入服务地址", "settings.notification.channel.form.bark_server_url.tooltip": "这是什么?请参阅 https://bark.day.app/

为空时,将使用 Bark 默认服务器。", "settings.notification.channel.form.bark_device_key.label": "设备密钥", "settings.notification.channel.form.bark_device_key.placeholder": "请输入设备密钥", From b798b824dbdea7d4dac581c7b976927429fcf8eb Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Sun, 25 May 2025 23:05:08 +0800 Subject: [PATCH 02/11] refactor(ui): MultipleSplitValueInput --- ui/src/components/MultipleSplitValueInput.tsx | 108 ++++++++++++ .../workflow/node/ApplyNodeConfigForm.tsx | 152 ++--------------- ...loyNodeConfigFormAliyunCASDeployConfig.tsx | 161 ++---------------- ...ployNodeConfigFormBaotaPanelSiteConfig.tsx | 84 ++------- ...eConfigFormTencentCloudSSLDeployConfig.tsx | 85 ++------- .../DeployNodeConfigFormWangsuCDNConfig.tsx | 85 ++------- .../i18n/locales/en/nls.workflow.nodes.json | 2 + .../i18n/locales/zh/nls.workflow.nodes.json | 2 + 8 files changed, 178 insertions(+), 501 deletions(-) create mode 100644 ui/src/components/MultipleSplitValueInput.tsx diff --git a/ui/src/components/MultipleSplitValueInput.tsx b/ui/src/components/MultipleSplitValueInput.tsx new file mode 100644 index 00000000..5f94ec7d --- /dev/null +++ b/ui/src/components/MultipleSplitValueInput.tsx @@ -0,0 +1,108 @@ +import { type ChangeEvent, useEffect } from "react"; +import { FormOutlined as FormOutlinedIcon } from "@ant-design/icons"; +import { nanoid } from "@ant-design/pro-components"; +import { useControllableValue } from "ahooks"; +import { Button, Form, Input, type InputProps, Space } from "antd"; + +import { useAntdForm } from "@/hooks"; +import ModalForm from "./ModalForm"; +import MultipleInput from "./MultipleInput"; + +type SplitOptions = { + removeEmpty?: boolean; + trim?: boolean; +}; + +export type MultipleSplitValueInputProps = Omit & { + defaultValue?: string; + delimiter?: string; + maxCount?: number; + minCount?: number; + modalTitle?: string; + modalWidth?: number; + placeholderInModal?: string; + showSortButton?: boolean; + splitOptions?: SplitOptions; + value?: string[]; + onChange?: (value: string) => void; +}; + +const DEFAULT_DELIMITER = ";"; + +const MultipleSplitValueInput = ({ + className, + style, + delimiter = DEFAULT_DELIMITER, + disabled, + maxCount, + minCount, + modalTitle, + modalWidth = 480, + placeholder, + placeholderInModal, + showSortButton = true, + splitOptions = {}, + onClear, + ...props +}: MultipleSplitValueInputProps) => { + const [value, setValue] = useControllableValue(props, { + valuePropName: "value", + defaultValuePropName: "defaultValue", + trigger: "onChange", + }); + + const { form: formInst, formProps } = useAntdForm({ + name: "componentMultipleSplitValueInput_" + nanoid(), + initialValues: { value: value?.split(delimiter) }, + onSubmit: (values) => { + const temp = values.value ?? []; + if (splitOptions.trim) { + temp.map((e) => e.trim()); + } + if (splitOptions.removeEmpty) { + temp.filter((e) => !!e); + } + + setValue(temp.join(delimiter)); + }, + }); + + useEffect(() => { + formInst.setFieldValue("value", value?.split(delimiter)); + }, [delimiter, value]); + + const handleChange = (e: ChangeEvent) => { + setValue(e.target.value); + }; + + const handleClear = () => { + setValue(""); + onClear?.(); + }; + + return ( + + + + + + } + validateTrigger="onSubmit" + width={modalWidth} + > + + + + + + ); +}; + +export default MultipleSplitValueInput; diff --git a/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx b/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx index 22cb57d5..7faa148e 100644 --- a/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx @@ -1,12 +1,7 @@ import { forwardRef, memo, useEffect, useImperativeHandle, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { Link } from "react-router"; -import { - FormOutlined as FormOutlinedIcon, - PlusOutlined as PlusOutlinedIcon, - QuestionCircleOutlined as QuestionCircleOutlinedIcon, - RightOutlined as RightOutlinedIcon, -} from "@ant-design/icons"; +import { PlusOutlined as PlusOutlinedIcon, QuestionCircleOutlined as QuestionCircleOutlinedIcon, RightOutlined as RightOutlinedIcon } from "@ant-design/icons"; import { useControllableValue } from "ahooks"; import { AutoComplete, @@ -19,7 +14,6 @@ import { Input, InputNumber, Select, - Space, Switch, Tooltip, Typography, @@ -29,8 +23,7 @@ import { z } from "zod"; import AccessEditModal from "@/components/access/AccessEditModal"; import AccessSelect from "@/components/access/AccessSelect"; -import ModalForm from "@/components/ModalForm"; -import MultipleInput from "@/components/MultipleInput"; +import MultipleSplitValueInput from "@/components/MultipleSplitValueInput"; import ACMEDns01ProviderSelect from "@/components/provider/ACMEDns01ProviderSelect"; import CAProviderSelect from "@/components/provider/CAProviderSelect"; import Show from "@/components/Show"; @@ -152,11 +145,9 @@ const ApplyNodeConfigForm = forwardRef("domains", formInst); const fieldProvider = Form.useWatch("provider", { form: formInst, preserve: true }); const fieldProviderAccessId = Form.useWatch("providerAccessId", formInst); const fieldCAProvider = Form.useWatch("caProvider", formInst); - const fieldNameservers = Form.useWatch("nameservers", formInst); const [showProvider, setShowProvider] = useState(false); useEffect(() => { @@ -294,25 +285,17 @@ const ApplyNodeConfigForm = forwardRef
} > - - - - - - - - } - onChange={(v) => { - formInst.setFieldValue("domains", v); - }} - /> - + } > - - - { - formInst.setFieldValue("nameservers", e.target.value); - }} - onClear={() => { - formInst.setFieldValue("nameservers", undefined); - }} - /> - - - - - } - onChange={(value) => { - formInst.setFieldValue("nameservers", value); - }} - /> - + void }) => { - const { t } = useTranslation(); - - const formSchema = z.object({ - domains: z.array(z.string()).refine((v) => { - return v.every((e) => !e?.trim() || validDomainName(e.trim(), { allowWildcard: true })); - }, t("common.errmsg.domain_invalid")), - }); - const formRule = createSchemaFieldRule(formSchema); - const { form: formInst, formProps } = useAntdForm({ - name: "workflowNodeApplyConfigFormDomainsModalInput", - initialValues: { domains: value?.split(MULTIPLE_INPUT_DELIMITER) }, - onSubmit: (values) => { - onChange?.( - values.domains - .map((e) => e.trim()) - .filter((e) => !!e) - .join(MULTIPLE_INPUT_DELIMITER) - ); - }, - }); - - return ( - - - - - - ); -}); - -const NameserversModalInput = memo(({ trigger, value, onChange }: { trigger?: React.ReactNode; value?: string; onChange?: (value: string) => void }) => { - const { t } = useTranslation(); - - const formSchema = z.object({ - nameservers: z.array(z.string()).refine((v) => { - return v.every((e) => !e?.trim() || validIPv4Address(e) || validIPv6Address(e) || validDomainName(e)); - }, t("common.errmsg.domain_invalid")), - }); - const formRule = createSchemaFieldRule(formSchema); - const { form: formInst, formProps } = useAntdForm({ - name: "workflowNodeApplyConfigFormNameserversModalInput", - initialValues: { nameservers: value?.split(MULTIPLE_INPUT_DELIMITER) }, - onSubmit: (values) => { - onChange?.( - values.nameservers - .map((e) => e.trim()) - .filter((e) => !!e) - .join(MULTIPLE_INPUT_DELIMITER) - ); - }, - }); - - return ( - - - - - - ); -}); - export default memo(ApplyNodeConfigForm); diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormAliyunCASDeployConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormAliyunCASDeployConfig.tsx index 4e3db0db..980e89fe 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigFormAliyunCASDeployConfig.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigFormAliyunCASDeployConfig.tsx @@ -1,13 +1,9 @@ -import { memo } from "react"; import { useTranslation } from "react-i18next"; -import { FormOutlined as FormOutlinedIcon } from "@ant-design/icons"; -import { Alert, Button, Form, type FormInstance, Input, Space } from "antd"; +import { Alert, Form, type FormInstance, Input } from "antd"; import { createSchemaFieldRule } from "antd-zod"; import { z } from "zod"; -import ModalForm from "@/components/ModalForm"; -import MultipleInput from "@/components/MultipleInput"; -import { useAntdForm } from "@/hooks"; +import MultipleSplitValueInput from "@/components/MultipleSplitValueInput"; type DeployNodeConfigFormAliyunCASDeployConfigFieldValues = Nullish<{ region: string; @@ -61,9 +57,6 @@ const DeployNodeConfigFormAliyunCASDeployConfig = ({ }); const formRule = createSchemaFieldRule(formSchema); - const fieldResourceIds = Form.useWatch("resourceIds", formInst); - const fieldContactIds = Form.useWatch("contactIds", formInst); - const handleFormChange = (_: unknown, values: z.infer) => { onValuesChange?.(values); }; @@ -87,69 +80,31 @@ const DeployNodeConfigFormAliyunCASDeployConfig = ({ } > - - - { - formInst.setFieldValue("resourceIds", e.target.value); - }} - onClear={() => { - formInst.setFieldValue("resourceIds", ""); - }} - /> - - - - - } - onChange={(value) => { - formInst.setFieldValue("resourceIds", value); - }} - /> - + } > - - - { - formInst.setFieldValue("contactIds", e.target.value); - }} - onClear={() => { - formInst.setFieldValue("contactIds", ""); - }} - /> - - - - - } - onChange={(value) => { - formInst.setFieldValue("contactIds", value); - }} - /> - + @@ -159,84 +114,4 @@ const DeployNodeConfigFormAliyunCASDeployConfig = ({ ); }; -const ResourceIdsModalInput = memo(({ value, trigger, onChange }: { value?: string; trigger?: React.ReactNode; onChange?: (value: string) => void }) => { - const { t } = useTranslation(); - - const formSchema = z.object({ - resourceIds: z.array(z.string()).refine((v) => { - return v.every((e) => !e?.trim() || /^[1-9]\d*$/.test(e)); - }, t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.errmsg.invalid")), - }); - const formRule = createSchemaFieldRule(formSchema); - const { form: formInst, formProps } = useAntdForm({ - name: "workflowNodeDeployConfigFormAliyunCASResourceIdsModalInput", - initialValues: { resourceIds: value?.split(MULTIPLE_INPUT_DELIMITER) }, - onSubmit: (values) => { - onChange?.( - values.resourceIds - .map((e) => e.trim()) - .filter((e) => !!e) - .join(MULTIPLE_INPUT_DELIMITER) - ); - }, - }); - - return ( - - - - - - ); -}); - -const ContactIdsModalInput = memo(({ value, trigger, onChange }: { value?: string; trigger?: React.ReactNode; onChange?: (value: string) => void }) => { - const { t } = useTranslation(); - - const formSchema = z.object({ - contactIds: z.array(z.string()).refine((v) => { - return v.every((e) => !e?.trim() || /^[1-9]\d*$/.test(e)); - }, t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.errmsg.invalid")), - }); - const formRule = createSchemaFieldRule(formSchema); - const { form: formInst, formProps } = useAntdForm({ - name: "workflowNodeDeployConfigFormAliyunCASDeploymentJobContactIdsModalInput", - initialValues: { contactIds: value?.split(MULTIPLE_INPUT_DELIMITER) }, - onSubmit: (values) => { - onChange?.( - values.contactIds - .map((e) => e.trim()) - .filter((e) => !!e) - .join(MULTIPLE_INPUT_DELIMITER) - ); - }, - }); - - return ( - - - - - - ); -}); - export default DeployNodeConfigFormAliyunCASDeployConfig; diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormBaotaPanelSiteConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormBaotaPanelSiteConfig.tsx index acc9d187..54507cdb 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigFormBaotaPanelSiteConfig.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigFormBaotaPanelSiteConfig.tsx @@ -1,14 +1,10 @@ -import { memo } from "react"; import { useTranslation } from "react-i18next"; -import { FormOutlined as FormOutlinedIcon } from "@ant-design/icons"; -import { Button, Form, type FormInstance, Input, Select, Space } from "antd"; +import { Form, type FormInstance, Input, Select } from "antd"; import { createSchemaFieldRule } from "antd-zod"; import { z } from "zod"; -import ModalForm from "@/components/ModalForm"; -import MultipleInput from "@/components/MultipleInput"; +import MultipleSplitValueInput from "@/components/MultipleSplitValueInput"; import Show from "@/components/Show"; -import { useAntdForm } from "@/hooks"; type DeployNodeConfigFormBaotaPanelSiteConfigFieldValues = Nullish<{ siteType: string; @@ -71,7 +67,6 @@ const DeployNodeConfigFormBaotaPanelSiteConfig = ({ const formRule = createSchemaFieldRule(formSchema); const fieldSiteType = Form.useWatch("siteType", formInst); - const fieldSiteNames = Form.useWatch("siteNames", formInst); const handleFormChange = (_: unknown, values: z.infer) => { onValuesChange?.(values); @@ -110,80 +105,21 @@ const DeployNodeConfigFormBaotaPanelSiteConfig = ({ } > - - - { - formInst.setFieldValue("siteNames", e.target.value); - }} - onClear={() => { - formInst.setFieldValue("siteNames", ""); - }} - /> - - - - - } - onChange={(value) => { - formInst.setFieldValue("siteNames", value); - }} - /> - + ); }; -const SiteNamesModalInput = memo(({ value, trigger, onChange }: { value?: string; trigger?: React.ReactNode; onChange?: (value: string) => void }) => { - const { t } = useTranslation(); - - const formSchema = z.object({ - siteNames: z.array(z.string()).refine((v) => { - return v.every((e) => !!e?.trim()); - }, t("workflow_node.deploy.form.baotapanel_site_names.errmsg.invalid")), - }); - const formRule = createSchemaFieldRule(formSchema); - const { form: formInst, formProps } = useAntdForm({ - name: "workflowNodeDeployConfigFormBaotaPanelSiteNamesModalInput", - initialValues: { siteNames: value?.split(MULTIPLE_INPUT_DELIMITER) }, - onSubmit: (values) => { - onChange?.( - values.siteNames - .map((e) => e.trim()) - .filter((e) => !!e) - .join(MULTIPLE_INPUT_DELIMITER) - ); - }, - }); - - return ( - - - - - - ); -}); - export default DeployNodeConfigFormBaotaPanelSiteConfig; diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormTencentCloudSSLDeployConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormTencentCloudSSLDeployConfig.tsx index 2a4e7d12..4fcb4e76 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigFormTencentCloudSSLDeployConfig.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigFormTencentCloudSSLDeployConfig.tsx @@ -1,13 +1,9 @@ -import { memo } from "react"; import { useTranslation } from "react-i18next"; -import { FormOutlined as FormOutlinedIcon } from "@ant-design/icons"; -import { Alert, AutoComplete, Button, Form, type FormInstance, Input, Space } from "antd"; +import { Alert, AutoComplete, Form, type FormInstance, Input } from "antd"; import { createSchemaFieldRule } from "antd-zod"; import { z } from "zod"; -import ModalForm from "@/components/ModalForm"; -import MultipleInput from "@/components/MultipleInput"; -import { useAntdForm } from "@/hooks"; +import MultipleSplitValueInput from "@/components/MultipleSplitValueInput"; type DeployNodeConfigFormTencentCloudSSLDeployConfigFieldValues = Nullish<{ region: string; @@ -56,8 +52,6 @@ const DeployNodeConfigFormTencentCloudSSLDeployConfig = ({ }); const formRule = createSchemaFieldRule(formSchema); - const fieldResourceIds = Form.useWatch("resourceIds", formInst); - const handleFormChange = (_: unknown, values: z.infer) => { onValuesChange?.(values); }; @@ -94,36 +88,17 @@ const DeployNodeConfigFormTencentCloudSSLDeployConfig = ({ } > - - - { - formInst.setFieldValue("resourceIds", e.target.value); - }} - onClear={() => { - formInst.setFieldValue("resourceIds", ""); - }} - /> - - - - - } - onChange={(value) => { - formInst.setFieldValue("resourceIds", value); - }} - /> - + @@ -133,44 +108,4 @@ const DeployNodeConfigFormTencentCloudSSLDeployConfig = ({ ); }; -const ResourceIdsModalInput = memo(({ value, trigger, onChange }: { value?: string; trigger?: React.ReactNode; onChange?: (value: string) => void }) => { - const { t } = useTranslation(); - - const formSchema = z.object({ - resourceIds: z.array(z.string()).refine((v) => { - return v.every((e) => !e?.trim() || /^[A-Za-z0-9*._-|]+$/.test(e)); - }, t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.errmsg.invalid")), - }); - const formRule = createSchemaFieldRule(formSchema); - const { form: formInst, formProps } = useAntdForm({ - name: "workflowNodeDeployConfigFormTencentCloudSSLDeployResourceIdsModalInput", - initialValues: { resourceIds: value?.split(MULTIPLE_INPUT_DELIMITER) }, - onSubmit: (values) => { - onChange?.( - values.resourceIds - .map((e) => e.trim()) - .filter((e) => !!e) - .join(MULTIPLE_INPUT_DELIMITER) - ); - }, - }); - - return ( - - - - - - ); -}); - export default DeployNodeConfigFormTencentCloudSSLDeployConfig; diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormWangsuCDNConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormWangsuCDNConfig.tsx index 57d0d381..d64e6eba 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigFormWangsuCDNConfig.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigFormWangsuCDNConfig.tsx @@ -1,13 +1,9 @@ -import { memo } from "react"; import { useTranslation } from "react-i18next"; -import { FormOutlined as FormOutlinedIcon } from "@ant-design/icons"; -import { Button, Form, type FormInstance, Input, Space } from "antd"; +import { Form, type FormInstance } from "antd"; import { createSchemaFieldRule } from "antd-zod"; import { z } from "zod"; -import ModalForm from "@/components/ModalForm"; -import MultipleInput from "@/components/MultipleInput"; -import { useAntdForm } from "@/hooks"; +import MultipleSplitValueInput from "@/components/MultipleSplitValueInput"; import { validDomainName } from "@/utils/validators"; type DeployNodeConfigFormWangsuCDNConfigFieldValues = Nullish<{ @@ -52,8 +48,6 @@ const DeployNodeConfigFormWangsuCDNConfig = ({ }); const formRule = createSchemaFieldRule(formSchema); - const fieldDomains = Form.useWatch("domains", formInst); - const handleFormChange = (_: unknown, values: z.infer) => { onValuesChange?.(values); }; @@ -68,79 +62,20 @@ const DeployNodeConfigFormWangsuCDNConfig = ({ onValuesChange={handleFormChange} > } > - - - { - formInst.setFieldValue("domains", e.target.value); - }} - onClear={() => { - formInst.setFieldValue("domains", ""); - }} - /> - - - - - } - onChange={(value) => { - formInst.setFieldValue("domains", value); - }} - /> - + ); }; -const SiteNamesModalInput = memo(({ value, trigger, onChange }: { value?: string; trigger?: React.ReactNode; onChange?: (value: string) => void }) => { - const { t } = useTranslation(); - - const formSchema = z.object({ - domains: z.array(z.string()).refine((v) => { - return v.every((e) => validDomainName(e)); - }, t("workflow_node.deploy.form.wangsu_cdn_domains.errmsg.invalid")), - }); - const formRule = createSchemaFieldRule(formSchema); - const { form: formInst, formProps } = useAntdForm({ - name: "workflowNodeDeployConfigFormWangsuCDNNamesModalInput", - initialValues: { domains: value?.split(MULTIPLE_INPUT_DELIMITER) }, - onSubmit: (values) => { - onChange?.( - values.domains - .map((e) => e.trim()) - .filter((e) => !!e) - .join(MULTIPLE_INPUT_DELIMITER) - ); - }, - }); - - return ( - - - - - - ); -}); - export default DeployNodeConfigFormWangsuCDNConfig; diff --git a/ui/src/i18n/locales/en/nls.workflow.nodes.json b/ui/src/i18n/locales/en/nls.workflow.nodes.json index 80237287..ca60aedb 100644 --- a/ui/src/i18n/locales/en/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/en/nls.workflow.nodes.json @@ -1,9 +1,11 @@ { "workflow_node.action.configure_node": "Configure node", "workflow_node.action.add_node": "Add node", + "workflow_node.action.duplicate_node": "Duplicate node", "workflow_node.action.rename_node": "Rename node", "workflow_node.action.remove_node": "Delete node", "workflow_node.action.add_branch": "Add branch", + "workflow_node.action.duplicate_branch": "Duplicate branch", "workflow_node.action.rename_branch": "Rename branch", "workflow_node.action.remove_branch": "Delete branch", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index faf40816..3da2c838 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -1,9 +1,11 @@ { "workflow_node.action.configure_node": "配置节点", "workflow_node.branch.add_node": "添加节点", + "workflow_node.action.duplicate_node": "复制节点", "workflow_node.action.rename_node": "重命名", "workflow_node.action.remove_node": "删除节点", "workflow_node.action.add_branch": "添加并行分支", + "workflow_node.action.duplicate_branch": "复制分支", "workflow_node.action.rename_branch": "重命名", "workflow_node.action.remove_branch": "删除分支", From 0909671be65fdf23025280fdef507b49ca3e0d6c Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Sun, 25 May 2025 23:32:41 +0800 Subject: [PATCH 03/11] refactor: clean code --- .../providers/1panel-console/1panel_console.go | 8 ++++---- .../core/deployer/providers/1panel-site/1panel_site.go | 8 ++++---- .../providers/baotapanel-console/baotapanel_console.go | 8 ++++---- .../providers/baotapanel-site/baotapanel_site.go | 8 ++++---- .../providers/baotawaf-console/baotawaf_console.go | 8 ++++---- .../deployer/providers/baotawaf-site/baotawaf_site.go | 8 ++++---- internal/pkg/core/deployer/providers/cdnfly/cdnfly.go | 8 ++++---- .../pkg/core/deployer/providers/flexcdn/flexcdn.go | 8 ++++---- internal/pkg/core/deployer/providers/goedge/goedge.go | 8 ++++---- internal/pkg/core/deployer/providers/lecdn/lecdn.go | 10 +++++----- .../pkg/core/deployer/providers/proxmoxve/proxmoxve.go | 8 ++++---- .../providers/ratpanel-console/ratpanel_console.go | 8 ++++---- .../deployer/providers/ratpanel-site/ratpanel_site.go | 8 ++++---- .../pkg/core/deployer/providers/safeline/safeline.go | 8 ++++---- .../core/uploader/providers/1panel-ssl/1panel_ssl.go | 8 ++++---- internal/pkg/sdk3rd/1panel/client.go | 4 ++-- internal/pkg/sdk3rd/btpanel/client.go | 4 ++-- internal/pkg/sdk3rd/btwaf/client.go | 4 ++-- internal/pkg/sdk3rd/cdnfly/client.go | 4 ++-- internal/pkg/sdk3rd/flexcdn/client.go | 4 ++-- internal/pkg/sdk3rd/goedge/client.go | 4 ++-- internal/pkg/sdk3rd/lecdn/v3/client/client.go | 4 ++-- internal/pkg/sdk3rd/lecdn/v3/master/client.go | 4 ++-- internal/pkg/sdk3rd/ratpanel/client.go | 4 ++-- internal/pkg/sdk3rd/safeline/client.go | 4 ++-- ui/src/components/workflow/node/_SharedNode.tsx | 7 ------- ui/src/i18n/locales/en/nls.workflow.nodes.json | 2 -- ui/src/i18n/locales/zh/nls.workflow.nodes.json | 2 -- 28 files changed, 81 insertions(+), 92 deletions(-) diff --git a/internal/pkg/core/deployer/providers/1panel-console/1panel_console.go b/internal/pkg/core/deployer/providers/1panel-console/1panel_console.go index 0f7efed1..cdeb8af5 100644 --- a/internal/pkg/core/deployer/providers/1panel-console/1panel_console.go +++ b/internal/pkg/core/deployer/providers/1panel-console/1panel_console.go @@ -82,9 +82,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE return &deployer.DeployResult{}, nil } -func createSdkClient(apiUrl, apiVersion, apiKey string, skipTlsVerify bool) (*onepanelsdk.Client, error) { - if _, err := url.Parse(apiUrl); err != nil { - return nil, errors.New("invalid 1panel api url") +func createSdkClient(serverUrl, apiVersion, apiKey string, skipTlsVerify bool) (*onepanelsdk.Client, error) { + if _, err := url.Parse(serverUrl); err != nil { + return nil, errors.New("invalid 1panel server url") } if apiVersion == "" { @@ -95,7 +95,7 @@ func createSdkClient(apiUrl, apiVersion, apiKey string, skipTlsVerify bool) (*on return nil, errors.New("invalid 1panel api key") } - client := onepanelsdk.NewClient(apiUrl, apiVersion, apiKey) + client := onepanelsdk.NewClient(serverUrl, apiVersion, apiKey) if skipTlsVerify { client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) } diff --git a/internal/pkg/core/deployer/providers/1panel-site/1panel_site.go b/internal/pkg/core/deployer/providers/1panel-site/1panel_site.go index a546c1bb..30414689 100644 --- a/internal/pkg/core/deployer/providers/1panel-site/1panel_site.go +++ b/internal/pkg/core/deployer/providers/1panel-site/1panel_site.go @@ -177,9 +177,9 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri return nil } -func createSdkClient(apiUrl, apiVersion, apiKey string, skipTlsVerify bool) (*onepanelsdk.Client, error) { - if _, err := url.Parse(apiUrl); err != nil { - return nil, errors.New("invalid 1panel api url") +func createSdkClient(serverUrl, apiVersion, apiKey string, skipTlsVerify bool) (*onepanelsdk.Client, error) { + if _, err := url.Parse(serverUrl); err != nil { + return nil, errors.New("invalid 1panel server url") } if apiVersion == "" { @@ -190,7 +190,7 @@ func createSdkClient(apiUrl, apiVersion, apiKey string, skipTlsVerify bool) (*on return nil, errors.New("invalid 1panel api key") } - client := onepanelsdk.NewClient(apiUrl, apiVersion, apiKey) + client := onepanelsdk.NewClient(serverUrl, apiVersion, apiKey) if skipTlsVerify { client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) } diff --git a/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go index b5deb005..5709f82d 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go +++ b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go @@ -82,16 +82,16 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE return &deployer.DeployResult{}, nil } -func createSdkClient(apiUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) { - if _, err := url.Parse(apiUrl); err != nil { - return nil, errors.New("invalid baota api url") +func createSdkClient(serverUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) { + if _, err := url.Parse(serverUrl); err != nil { + return nil, errors.New("invalid baota server url") } if apiKey == "" { return nil, errors.New("invalid baota api key") } - client := btsdk.NewClient(apiUrl, apiKey) + client := btsdk.NewClient(serverUrl, apiKey) if skipTlsVerify { client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) } diff --git a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go index f9936e2d..d6ee1533 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go +++ b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go @@ -124,16 +124,16 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE return &deployer.DeployResult{}, nil } -func createSdkClient(apiUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) { - if _, err := url.Parse(apiUrl); err != nil { - return nil, errors.New("invalid baota api url") +func createSdkClient(serverUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) { + if _, err := url.Parse(serverUrl); err != nil { + return nil, errors.New("invalid baota server url") } if apiKey == "" { return nil, errors.New("invalid baota api key") } - client := btsdk.NewClient(apiUrl, apiKey) + client := btsdk.NewClient(serverUrl, apiKey) if skipTlsVerify { client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) } diff --git a/internal/pkg/core/deployer/providers/baotawaf-console/baotawaf_console.go b/internal/pkg/core/deployer/providers/baotawaf-console/baotawaf_console.go index bf8a3892..482ca8e4 100644 --- a/internal/pkg/core/deployer/providers/baotawaf-console/baotawaf_console.go +++ b/internal/pkg/core/deployer/providers/baotawaf-console/baotawaf_console.go @@ -70,16 +70,16 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE return &deployer.DeployResult{}, nil } -func createSdkClient(apiUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) { - if _, err := url.Parse(apiUrl); err != nil { - return nil, errors.New("invalid baota api url") +func createSdkClient(serverUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) { + if _, err := url.Parse(serverUrl); err != nil { + return nil, errors.New("invalid baota server url") } if apiKey == "" { return nil, errors.New("invalid baota api key") } - client := btsdk.NewClient(apiUrl, apiKey) + client := btsdk.NewClient(serverUrl, apiKey) if skipTlsVerify { client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) } diff --git a/internal/pkg/core/deployer/providers/baotawaf-site/baotawaf_site.go b/internal/pkg/core/deployer/providers/baotawaf-site/baotawaf_site.go index faaf5681..435f7a69 100644 --- a/internal/pkg/core/deployer/providers/baotawaf-site/baotawaf_site.go +++ b/internal/pkg/core/deployer/providers/baotawaf-site/baotawaf_site.go @@ -133,16 +133,16 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE return &deployer.DeployResult{}, nil } -func createSdkClient(apiUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) { - if _, err := url.Parse(apiUrl); err != nil { - return nil, errors.New("invalid baota api url") +func createSdkClient(serverUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) { + if _, err := url.Parse(serverUrl); err != nil { + return nil, errors.New("invalid baota server url") } if apiKey == "" { return nil, errors.New("invalid baota api key") } - client := btsdk.NewClient(apiUrl, apiKey) + client := btsdk.NewClient(serverUrl, apiKey) if skipTlsVerify { client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) } diff --git a/internal/pkg/core/deployer/providers/cdnfly/cdnfly.go b/internal/pkg/core/deployer/providers/cdnfly/cdnfly.go index 6b7c3ec7..1ced8caf 100644 --- a/internal/pkg/core/deployer/providers/cdnfly/cdnfly.go +++ b/internal/pkg/core/deployer/providers/cdnfly/cdnfly.go @@ -160,9 +160,9 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri return nil } -func createSdkClient(apiUrl, apiKey, apiSecret string, skipTlsVerify bool) (*cfsdk.Client, error) { - if _, err := url.Parse(apiUrl); err != nil { - return nil, errors.New("invalid cachefly api url") +func createSdkClient(serverUrl, apiKey, apiSecret string, skipTlsVerify bool) (*cfsdk.Client, error) { + if _, err := url.Parse(serverUrl); err != nil { + return nil, errors.New("invalid cachefly server url") } if apiKey == "" { @@ -173,7 +173,7 @@ func createSdkClient(apiUrl, apiKey, apiSecret string, skipTlsVerify bool) (*cfs return nil, errors.New("invalid cachefly api secret") } - client := cfsdk.NewClient(apiUrl, apiKey, apiSecret) + client := cfsdk.NewClient(serverUrl, apiKey, apiSecret) if skipTlsVerify { client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) } diff --git a/internal/pkg/core/deployer/providers/flexcdn/flexcdn.go b/internal/pkg/core/deployer/providers/flexcdn/flexcdn.go index 7925a72a..8b692e90 100644 --- a/internal/pkg/core/deployer/providers/flexcdn/flexcdn.go +++ b/internal/pkg/core/deployer/providers/flexcdn/flexcdn.go @@ -119,9 +119,9 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri return nil } -func createSdkClient(apiUrl, apiRole, accessKeyId, accessKey string, skipTlsVerify bool) (*flexcdnsdk.Client, error) { - if _, err := url.Parse(apiUrl); err != nil { - return nil, errors.New("invalid flexcdn api url") +func createSdkClient(serverUrl, apiRole, accessKeyId, accessKey string, skipTlsVerify bool) (*flexcdnsdk.Client, error) { + if _, err := url.Parse(serverUrl); err != nil { + return nil, errors.New("invalid flexcdn server url") } if apiRole != "user" && apiRole != "admin" { @@ -136,7 +136,7 @@ func createSdkClient(apiUrl, apiRole, accessKeyId, accessKey string, skipTlsVeri return nil, errors.New("invalid flexcdn access key") } - client := flexcdnsdk.NewClient(apiUrl, apiRole, accessKeyId, accessKey) + client := flexcdnsdk.NewClient(serverUrl, apiRole, accessKeyId, accessKey) if skipTlsVerify { client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) } diff --git a/internal/pkg/core/deployer/providers/goedge/goedge.go b/internal/pkg/core/deployer/providers/goedge/goedge.go index 5b3e2dc9..25caeb01 100644 --- a/internal/pkg/core/deployer/providers/goedge/goedge.go +++ b/internal/pkg/core/deployer/providers/goedge/goedge.go @@ -119,9 +119,9 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri return nil } -func createSdkClient(apiUrl, apiRole, accessKeyId, accessKey string, skipTlsVerify bool) (*goedgesdk.Client, error) { - if _, err := url.Parse(apiUrl); err != nil { - return nil, errors.New("invalid goedge api url") +func createSdkClient(serverUrl, apiRole, accessKeyId, accessKey string, skipTlsVerify bool) (*goedgesdk.Client, error) { + if _, err := url.Parse(serverUrl); err != nil { + return nil, errors.New("invalid goedge server url") } if apiRole != "user" && apiRole != "admin" { @@ -136,7 +136,7 @@ func createSdkClient(apiUrl, apiRole, accessKeyId, accessKey string, skipTlsVeri return nil, errors.New("invalid goedge access key") } - client := goedgesdk.NewClient(apiUrl, apiRole, accessKeyId, accessKey) + client := goedgesdk.NewClient(serverUrl, apiRole, accessKeyId, accessKey) if skipTlsVerify { client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) } diff --git a/internal/pkg/core/deployer/providers/lecdn/lecdn.go b/internal/pkg/core/deployer/providers/lecdn/lecdn.go index 15c5dba9..c85f6558 100644 --- a/internal/pkg/core/deployer/providers/lecdn/lecdn.go +++ b/internal/pkg/core/deployer/providers/lecdn/lecdn.go @@ -141,9 +141,9 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri return nil } -func createSdkClient(apiUrl, apiVersion, apiRole, username, password string, skipTlsVerify bool) (interface{}, error) { - if _, err := url.Parse(apiUrl); err != nil { - return nil, errors.New("invalid lecdn api url") +func createSdkClient(serverUrl, apiVersion, apiRole, username, password string, skipTlsVerify bool) (interface{}, error) { + if _, err := url.Parse(serverUrl); err != nil { + return nil, errors.New("invalid lecdn server url") } if username == "" { @@ -156,7 +156,7 @@ func createSdkClient(apiUrl, apiVersion, apiRole, username, password string, ski if apiVersion == apiVersionV3 && apiRole == apiRoleClient { // v3 版客户端 - client := leclientsdkv3.NewClient(apiUrl, username, password) + client := leclientsdkv3.NewClient(serverUrl, username, password) if skipTlsVerify { client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) } @@ -164,7 +164,7 @@ func createSdkClient(apiUrl, apiVersion, apiRole, username, password string, ski return client, nil } else if apiVersion == apiVersionV3 && apiRole == apiRoleMaster { // v3 版主控端 - client := lemastersdkv3.NewClient(apiUrl, username, password) + client := lemastersdkv3.NewClient(serverUrl, username, password) if skipTlsVerify { client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) } diff --git a/internal/pkg/core/deployer/providers/proxmoxve/proxmoxve.go b/internal/pkg/core/deployer/providers/proxmoxve/proxmoxve.go index 455ccf6d..349c3a16 100644 --- a/internal/pkg/core/deployer/providers/proxmoxve/proxmoxve.go +++ b/internal/pkg/core/deployer/providers/proxmoxve/proxmoxve.go @@ -91,9 +91,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE return &deployer.DeployResult{}, nil } -func createSdkClient(apiUrl, apiToken, apiTokenSecret string, skipTlsVerify bool) (*proxmox.Client, error) { - if _, err := url.Parse(apiUrl); err != nil { - return nil, errors.New("invalid pve api url") +func createSdkClient(serverUrl, apiToken, apiTokenSecret string, skipTlsVerify bool) (*proxmox.Client, error) { + if _, err := url.Parse(serverUrl); err != nil { + return nil, errors.New("invalid pve server url") } if apiToken == "" { @@ -112,7 +112,7 @@ func createSdkClient(apiUrl, apiToken, apiTokenSecret string, skipTlsVerify bool } } client := proxmox.NewClient( - strings.TrimRight(apiUrl, "/")+"/api2/json", + strings.TrimRight(serverUrl, "/")+"/api2/json", proxmox.WithHTTPClient(httpClient), proxmox.WithAPIToken(apiToken, apiTokenSecret), ) diff --git a/internal/pkg/core/deployer/providers/ratpanel-console/ratpanel_console.go b/internal/pkg/core/deployer/providers/ratpanel-console/ratpanel_console.go index a6c560ae..651ae0ac 100644 --- a/internal/pkg/core/deployer/providers/ratpanel-console/ratpanel_console.go +++ b/internal/pkg/core/deployer/providers/ratpanel-console/ratpanel_console.go @@ -72,9 +72,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE return &deployer.DeployResult{}, nil } -func createSdkClient(apiUrl string, accessTokenId int32, accessToken string, skipTlsVerify bool) (*rpsdk.Client, error) { - if _, err := url.Parse(apiUrl); err != nil { - return nil, errors.New("invalid ratpanel api url") +func createSdkClient(serverUrl string, accessTokenId int32, accessToken string, skipTlsVerify bool) (*rpsdk.Client, error) { + if _, err := url.Parse(serverUrl); err != nil { + return nil, errors.New("invalid ratpanel server url") } if accessTokenId == 0 { @@ -85,7 +85,7 @@ func createSdkClient(apiUrl string, accessTokenId int32, accessToken string, ski return nil, errors.New("invalid ratpanel access token") } - client := rpsdk.NewClient(apiUrl, accessTokenId, accessToken) + client := rpsdk.NewClient(serverUrl, accessTokenId, accessToken) if skipTlsVerify { client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) } diff --git a/internal/pkg/core/deployer/providers/ratpanel-site/ratpanel_site.go b/internal/pkg/core/deployer/providers/ratpanel-site/ratpanel_site.go index a296c95e..8d605b3d 100644 --- a/internal/pkg/core/deployer/providers/ratpanel-site/ratpanel_site.go +++ b/internal/pkg/core/deployer/providers/ratpanel-site/ratpanel_site.go @@ -79,9 +79,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE return &deployer.DeployResult{}, nil } -func createSdkClient(apiUrl string, accessTokenId int32, accessToken string, skipTlsVerify bool) (*rpsdk.Client, error) { - if _, err := url.Parse(apiUrl); err != nil { - return nil, errors.New("invalid ratpanel api url") +func createSdkClient(serverUrl string, accessTokenId int32, accessToken string, skipTlsVerify bool) (*rpsdk.Client, error) { + if _, err := url.Parse(serverUrl); err != nil { + return nil, errors.New("invalid ratpanel server url") } if accessTokenId == 0 { @@ -92,7 +92,7 @@ func createSdkClient(apiUrl string, accessTokenId int32, accessToken string, ski return nil, errors.New("invalid ratpanel access token") } - client := rpsdk.NewClient(apiUrl, accessTokenId, accessToken) + client := rpsdk.NewClient(serverUrl, accessTokenId, accessToken) if skipTlsVerify { client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) } diff --git a/internal/pkg/core/deployer/providers/safeline/safeline.go b/internal/pkg/core/deployer/providers/safeline/safeline.go index 0abee743..f1b6b039 100644 --- a/internal/pkg/core/deployer/providers/safeline/safeline.go +++ b/internal/pkg/core/deployer/providers/safeline/safeline.go @@ -98,16 +98,16 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri return nil } -func createSdkClient(apiUrl, apiToken string, skipTlsVerify bool) (*safelinesdk.Client, error) { - if _, err := url.Parse(apiUrl); err != nil { - return nil, errors.New("invalid safeline api url") +func createSdkClient(serverUrl, apiToken string, skipTlsVerify bool) (*safelinesdk.Client, error) { + if _, err := url.Parse(serverUrl); err != nil { + return nil, errors.New("invalid safeline server url") } if apiToken == "" { return nil, errors.New("invalid safeline api token") } - client := safelinesdk.NewClient(apiUrl, apiToken) + client := safelinesdk.NewClient(serverUrl, apiToken) if skipTlsVerify { client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) } diff --git a/internal/pkg/core/uploader/providers/1panel-ssl/1panel_ssl.go b/internal/pkg/core/uploader/providers/1panel-ssl/1panel_ssl.go index 387944e3..c0283ccd 100644 --- a/internal/pkg/core/uploader/providers/1panel-ssl/1panel_ssl.go +++ b/internal/pkg/core/uploader/providers/1panel-ssl/1panel_ssl.go @@ -132,9 +132,9 @@ func (u *UploaderProvider) getCertIfExists(ctx context.Context, certPEM string, return nil, nil } -func createSdkClient(apiUrl, apiVersion, apiKey string) (*onepanelsdk.Client, error) { - if _, err := url.Parse(apiUrl); err != nil { - return nil, errors.New("invalid 1panel api url") +func createSdkClient(serverUrl, apiVersion, apiKey string) (*onepanelsdk.Client, error) { + if _, err := url.Parse(serverUrl); err != nil { + return nil, errors.New("invalid 1panel server url") } if apiVersion == "" { @@ -145,6 +145,6 @@ func createSdkClient(apiUrl, apiVersion, apiKey string) (*onepanelsdk.Client, er return nil, errors.New("invalid 1panel api key") } - client := onepanelsdk.NewClient(apiUrl, apiVersion, apiKey) + client := onepanelsdk.NewClient(serverUrl, apiVersion, apiKey) return client, nil } diff --git a/internal/pkg/sdk3rd/1panel/client.go b/internal/pkg/sdk3rd/1panel/client.go index 003203d3..3fe549a0 100644 --- a/internal/pkg/sdk3rd/1panel/client.go +++ b/internal/pkg/sdk3rd/1panel/client.go @@ -19,13 +19,13 @@ type Client struct { client *resty.Client } -func NewClient(apiHost, apiVersion, apiKey string) *Client { +func NewClient(serverUrl, apiVersion, apiKey string) *Client { if apiVersion == "" { apiVersion = "v1" } client := resty.New(). - SetBaseURL(strings.TrimRight(apiHost, "/") + "/api/" + apiVersion). + SetBaseURL(strings.TrimRight(serverUrl, "/") + "/api/" + apiVersion). SetPreRequestHook(func(c *resty.Client, req *http.Request) error { timestamp := fmt.Sprintf("%d", time.Now().Unix()) tokenMd5 := md5.Sum([]byte("1panel" + apiKey + timestamp)) diff --git a/internal/pkg/sdk3rd/btpanel/client.go b/internal/pkg/sdk3rd/btpanel/client.go index 1da625da..aafee04f 100644 --- a/internal/pkg/sdk3rd/btpanel/client.go +++ b/internal/pkg/sdk3rd/btpanel/client.go @@ -19,9 +19,9 @@ type Client struct { client *resty.Client } -func NewClient(apiHost, apiKey string) *Client { +func NewClient(serverUrl, apiKey string) *Client { client := resty.New(). - SetBaseURL(strings.TrimRight(apiHost, "/")) + SetBaseURL(strings.TrimRight(serverUrl, "/")) return &Client{ apiKey: apiKey, diff --git a/internal/pkg/sdk3rd/btwaf/client.go b/internal/pkg/sdk3rd/btwaf/client.go index 5ae545cc..083db0c1 100644 --- a/internal/pkg/sdk3rd/btwaf/client.go +++ b/internal/pkg/sdk3rd/btwaf/client.go @@ -17,9 +17,9 @@ type Client struct { client *resty.Client } -func NewClient(apiHost, apiKey string) *Client { +func NewClient(serverUrl, apiKey string) *Client { client := resty.New(). - SetBaseURL(strings.TrimRight(apiHost, "/") + "/api"). + SetBaseURL(strings.TrimRight(serverUrl, "/") + "/api"). SetPreRequestHook(func(c *resty.Client, req *http.Request) error { timestamp := fmt.Sprintf("%d", time.Now().Unix()) keyMd5 := md5.Sum([]byte(apiKey)) diff --git a/internal/pkg/sdk3rd/cdnfly/client.go b/internal/pkg/sdk3rd/cdnfly/client.go index c8753ed5..2dabf6fd 100644 --- a/internal/pkg/sdk3rd/cdnfly/client.go +++ b/internal/pkg/sdk3rd/cdnfly/client.go @@ -15,9 +15,9 @@ type Client struct { client *resty.Client } -func NewClient(apiHost, apiKey, apiSecret string) *Client { +func NewClient(serverUrl, apiKey, apiSecret string) *Client { client := resty.New(). - SetBaseURL(strings.TrimRight(apiHost, "/")). + SetBaseURL(strings.TrimRight(serverUrl, "/")). SetHeader("api-key", apiKey). SetHeader("api-secret", apiSecret) diff --git a/internal/pkg/sdk3rd/flexcdn/client.go b/internal/pkg/sdk3rd/flexcdn/client.go index beae469a..b478ffac 100644 --- a/internal/pkg/sdk3rd/flexcdn/client.go +++ b/internal/pkg/sdk3rd/flexcdn/client.go @@ -24,14 +24,14 @@ type Client struct { client *resty.Client } -func NewClient(apiHost, apiRole, accessKeyId, accessKey string) *Client { +func NewClient(serverUrl, apiRole, accessKeyId, accessKey string) *Client { client := &Client{ apiRole: apiRole, accessKeyId: accessKeyId, accessKey: accessKey, } client.client = resty.New(). - SetBaseURL(strings.TrimRight(apiHost, "/")). + SetBaseURL(strings.TrimRight(serverUrl, "/")). SetPreRequestHook(func(c *resty.Client, req *http.Request) error { if client.accessToken != "" { req.Header.Set("X-Cloud-Access-Token", client.accessToken) diff --git a/internal/pkg/sdk3rd/goedge/client.go b/internal/pkg/sdk3rd/goedge/client.go index 3dc961e3..3cd4900a 100644 --- a/internal/pkg/sdk3rd/goedge/client.go +++ b/internal/pkg/sdk3rd/goedge/client.go @@ -24,14 +24,14 @@ type Client struct { client *resty.Client } -func NewClient(apiHost, apiRole, accessKeyId, accessKey string) *Client { +func NewClient(serverUrl, apiRole, accessKeyId, accessKey string) *Client { client := &Client{ apiRole: apiRole, accessKeyId: accessKeyId, accessKey: accessKey, } client.client = resty.New(). - SetBaseURL(strings.TrimRight(apiHost, "/")). + SetBaseURL(strings.TrimRight(serverUrl, "/")). SetPreRequestHook(func(c *resty.Client, req *http.Request) error { if client.accessToken != "" { req.Header.Set("X-Edge-Access-Token", client.accessToken) diff --git a/internal/pkg/sdk3rd/lecdn/v3/client/client.go b/internal/pkg/sdk3rd/lecdn/v3/client/client.go index ad3a752e..3fa822eb 100644 --- a/internal/pkg/sdk3rd/lecdn/v3/client/client.go +++ b/internal/pkg/sdk3rd/lecdn/v3/client/client.go @@ -22,13 +22,13 @@ type Client struct { client *resty.Client } -func NewClient(apiHost, username, password string) *Client { +func NewClient(serverUrl, username, password string) *Client { client := &Client{ username: username, password: password, } client.client = resty.New(). - SetBaseURL(strings.TrimRight(apiHost, "/") + "/prod-api"). + SetBaseURL(strings.TrimRight(serverUrl, "/") + "/prod-api"). SetPreRequestHook(func(c *resty.Client, req *http.Request) error { if client.accessToken != "" { req.Header.Set("Authorization", "Bearer "+client.accessToken) diff --git a/internal/pkg/sdk3rd/lecdn/v3/master/client.go b/internal/pkg/sdk3rd/lecdn/v3/master/client.go index 2da0c0c4..ee1abaca 100644 --- a/internal/pkg/sdk3rd/lecdn/v3/master/client.go +++ b/internal/pkg/sdk3rd/lecdn/v3/master/client.go @@ -22,13 +22,13 @@ type Client struct { client *resty.Client } -func NewClient(apiHost, username, password string) *Client { +func NewClient(serverUrl, username, password string) *Client { client := &Client{ username: username, password: password, } client.client = resty.New(). - SetBaseURL(strings.TrimRight(apiHost, "/") + "/prod-api"). + SetBaseURL(strings.TrimRight(serverUrl, "/") + "/prod-api"). SetPreRequestHook(func(c *resty.Client, req *http.Request) error { if client.accessToken != "" { req.Header.Set("Authorization", "Bearer "+client.accessToken) diff --git a/internal/pkg/sdk3rd/ratpanel/client.go b/internal/pkg/sdk3rd/ratpanel/client.go index 47202a04..f1d20359 100644 --- a/internal/pkg/sdk3rd/ratpanel/client.go +++ b/internal/pkg/sdk3rd/ratpanel/client.go @@ -20,9 +20,9 @@ type Client struct { client *resty.Client } -func NewClient(apiHost string, accessTokenId int32, accessToken string) *Client { +func NewClient(serverUrl string, accessTokenId int32, accessToken string) *Client { client := resty.New(). - SetBaseURL(strings.TrimRight(apiHost, "/")+"/api"). + SetBaseURL(strings.TrimRight(serverUrl, "/")+"/api"). SetHeader("Accept", "application/json"). SetHeader("Content-Type", "application/json"). SetPreRequestHook(func(c *resty.Client, req *http.Request) error { diff --git a/internal/pkg/sdk3rd/safeline/client.go b/internal/pkg/sdk3rd/safeline/client.go index efcd3bd6..93d884a3 100644 --- a/internal/pkg/sdk3rd/safeline/client.go +++ b/internal/pkg/sdk3rd/safeline/client.go @@ -14,9 +14,9 @@ type Client struct { client *resty.Client } -func NewClient(apiHost, apiToken string) *Client { +func NewClient(serverUrl, apiToken string) *Client { client := resty.New(). - SetBaseURL(strings.TrimRight(apiHost, "/")). + SetBaseURL(strings.TrimRight(serverUrl, "/")). SetHeader("X-SLCE-API-TOKEN", apiToken) return &Client{ diff --git a/ui/src/components/workflow/node/_SharedNode.tsx b/ui/src/components/workflow/node/_SharedNode.tsx index 7bec1e90..44c894ef 100644 --- a/ui/src/components/workflow/node/_SharedNode.tsx +++ b/ui/src/components/workflow/node/_SharedNode.tsx @@ -4,7 +4,6 @@ import { CloseCircleOutlined as CloseCircleOutlinedIcon, EllipsisOutlined as EllipsisOutlinedIcon, FormOutlined as FormOutlinedIcon, - MergeOutlined as MergeOutlinedIcon, MoreOutlined as MoreOutlinedIcon, } from "@ant-design/icons"; import { useControllableValue } from "ahooks"; @@ -149,12 +148,6 @@ const SharedNodeMenu = ({ menus, trigger, node, disabled, branchId, branchIndex, setTimeout(() => nameInputRef.current?.focus(), 1); }, }, - // { - // key: "duplicate", - // disabled: disabled || isNodeReadOnly(node), - // label: isNodeBranchLike(node) ? t("workflow_node.action.duplicate_branch") : t("workflow_node.action.duplicate_node"), - // icon: , - // }, { type: "divider", }, diff --git a/ui/src/i18n/locales/en/nls.workflow.nodes.json b/ui/src/i18n/locales/en/nls.workflow.nodes.json index ca60aedb..80237287 100644 --- a/ui/src/i18n/locales/en/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/en/nls.workflow.nodes.json @@ -1,11 +1,9 @@ { "workflow_node.action.configure_node": "Configure node", "workflow_node.action.add_node": "Add node", - "workflow_node.action.duplicate_node": "Duplicate node", "workflow_node.action.rename_node": "Rename node", "workflow_node.action.remove_node": "Delete node", "workflow_node.action.add_branch": "Add branch", - "workflow_node.action.duplicate_branch": "Duplicate branch", "workflow_node.action.rename_branch": "Rename branch", "workflow_node.action.remove_branch": "Delete branch", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index 3da2c838..faf40816 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -1,11 +1,9 @@ { "workflow_node.action.configure_node": "配置节点", "workflow_node.branch.add_node": "添加节点", - "workflow_node.action.duplicate_node": "复制节点", "workflow_node.action.rename_node": "重命名", "workflow_node.action.remove_node": "删除节点", "workflow_node.action.add_branch": "添加并行分支", - "workflow_node.action.duplicate_branch": "复制分支", "workflow_node.action.rename_branch": "重命名", "workflow_node.action.remove_branch": "删除分支", From 4c13a3e86ad54d29d8ae7bd272bad36edb387005 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Mon, 26 May 2025 13:19:15 +0800 Subject: [PATCH 04/11] feat: new acme dns-01 provider: hetzner --- internal/applicant/providers.go | 16 ++++++ internal/domain/access.go | 4 ++ internal/domain/provider.go | 2 + .../lego-providers/hetzner/hetzner.go | 36 ++++++++++++ ui/public/imgs/providers/hetzner.svg | 1 + ui/src/components/access/AccessForm.tsx | 3 + .../access/AccessFormHetznerConfig.tsx | 57 +++++++++++++++++++ ui/src/domain/access.ts | 5 ++ ui/src/domain/provider.ts | 4 ++ ui/src/i18n/locales/en/nls.access.json | 3 + ui/src/i18n/locales/en/nls.provider.json | 1 + ui/src/i18n/locales/zh/nls.access.json | 3 + ui/src/i18n/locales/zh/nls.provider.json | 1 + 13 files changed, 136 insertions(+) create mode 100644 internal/pkg/core/applicant/acme-dns-01/lego-providers/hetzner/hetzner.go create mode 100644 ui/public/imgs/providers/hetzner.svg create mode 100644 ui/src/components/access/AccessFormHetznerConfig.tsx diff --git a/internal/applicant/providers.go b/internal/applicant/providers.go index 81cf8156..f967aef9 100644 --- a/internal/applicant/providers.go +++ b/internal/applicant/providers.go @@ -22,6 +22,7 @@ import ( pGcore "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore" pGname "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname" pGoDaddy "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy" + pHetzner "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/hetzner" pHuaweiCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud" pJDCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud" pNamecheap "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namecheap" @@ -324,6 +325,21 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi return applicant, err } + case domain.ACMEDns01ProviderTypeHetzner: + { + access := domain.AccessConfigForHetzner{} + if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + applicant, err := pHetzner.NewChallengeProvider(&pHetzner.ChallengeProviderConfig{ + ApiToken: access.ApiToken, + DnsPropagationTimeout: options.DnsPropagationTimeout, + DnsTTL: options.DnsTTL, + }) + return applicant, err + } + case domain.ACMEDns01ProviderTypeHuaweiCloud, domain.ACMEDns01ProviderTypeHuaweiCloudDNS: { access := domain.AccessConfigForHuaweiCloud{} diff --git a/internal/domain/access.go b/internal/domain/access.go index 7e1549f1..30088bdf 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -181,6 +181,10 @@ type AccessConfigForGoogleTrustServices struct { EabHmacKey string `json:"eabHmacKey"` } +type AccessConfigForHetzner struct { + ApiToken string `json:"apiToken"` +} + type AccessConfigForHuaweiCloud struct { AccessKeyId string `json:"accessKeyId"` SecretAccessKey string `json:"secretAccessKey"` diff --git a/internal/domain/provider.go b/internal/domain/provider.go index db0de59d..4552553d 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -44,6 +44,7 @@ const ( AccessProviderTypeGoDaddy = AccessProviderType("godaddy") AccessProviderTypeGoEdge = AccessProviderType("goedge") AccessProviderTypeGoogleTrustServices = AccessProviderType("googletrustservices") + AccessProviderTypeHetzner = AccessProviderType("hetzner") AccessProviderTypeHuaweiCloud = AccessProviderType("huaweicloud") AccessProviderTypeJDCloud = AccessProviderType("jdcloud") AccessProviderTypeKubernetes = AccessProviderType("k8s") @@ -131,6 +132,7 @@ const ( ACMEDns01ProviderTypeGcore = ACMEDns01ProviderType(AccessProviderTypeGcore) ACMEDns01ProviderTypeGname = ACMEDns01ProviderType(AccessProviderTypeGname) ACMEDns01ProviderTypeGoDaddy = ACMEDns01ProviderType(AccessProviderTypeGoDaddy) + ACMEDns01ProviderTypeHetzner = ACMEDns01ProviderType(AccessProviderTypeHetzner) ACMEDns01ProviderTypeHuaweiCloud = ACMEDns01ProviderType(AccessProviderTypeHuaweiCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeHuaweiCloudDNS] ACMEDns01ProviderTypeHuaweiCloudDNS = ACMEDns01ProviderType(AccessProviderTypeHuaweiCloud + "-dns") ACMEDns01ProviderTypeJDCloud = ACMEDns01ProviderType(AccessProviderTypeJDCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeJDCloudDNS] diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/hetzner/hetzner.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/hetzner/hetzner.go new file mode 100644 index 00000000..c202cc78 --- /dev/null +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/hetzner/hetzner.go @@ -0,0 +1,36 @@ +package namedotcom + +import ( + "time" + + "github.com/go-acme/lego/v4/challenge" + "github.com/go-acme/lego/v4/providers/dns/hetzner" +) + +type ChallengeProviderConfig struct { + ApiToken string `json:"apiToken"` + DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` + DnsTTL int32 `json:"dnsTTL,omitempty"` +} + +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { + if config == nil { + panic("config is nil") + } + + providerConfig := hetzner.NewDefaultConfig() + providerConfig.APIKey = config.ApiToken + if config.DnsPropagationTimeout != 0 { + providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second + } + if config.DnsTTL != 0 { + providerConfig.TTL = int(config.DnsTTL) + } + + provider, err := hetzner.NewDNSProviderConfig(providerConfig) + if err != nil { + return nil, err + } + + return provider, nil +} diff --git a/ui/public/imgs/providers/hetzner.svg b/ui/public/imgs/providers/hetzner.svg new file mode 100644 index 00000000..670cdda8 --- /dev/null +++ b/ui/public/imgs/providers/hetzner.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ui/src/components/access/AccessForm.tsx b/ui/src/components/access/AccessForm.tsx index fdf4f93f..6f4d5086 100644 --- a/ui/src/components/access/AccessForm.tsx +++ b/ui/src/components/access/AccessForm.tsx @@ -41,6 +41,7 @@ import AccessFormGnameConfig from "./AccessFormGnameConfig"; import AccessFormGoDaddyConfig from "./AccessFormGoDaddyConfig"; import AccessFormGoEdgeConfig from "./AccessFormGoEdgeConfig"; import AccessFormGoogleTrustServicesConfig from "./AccessFormGoogleTrustServicesConfig"; +import AccessFormHetznerConfig from "./AccessFormHetznerConfig"; import AccessFormHuaweiCloudConfig from "./AccessFormHuaweiCloudConfig"; import AccessFormJDCloudConfig from "./AccessFormJDCloudConfig"; import AccessFormKubernetesConfig from "./AccessFormKubernetesConfig"; @@ -239,6 +240,8 @@ const AccessForm = forwardRef(({ className, return ; case ACCESS_PROVIDERS.GOOGLETRUSTSERVICES: return ; + case ACCESS_PROVIDERS.HETZNER: + return ; case ACCESS_PROVIDERS.HUAWEICLOUD: return ; case ACCESS_PROVIDERS.JDCLOUD: diff --git a/ui/src/components/access/AccessFormHetznerConfig.tsx b/ui/src/components/access/AccessFormHetznerConfig.tsx new file mode 100644 index 00000000..12bf21b2 --- /dev/null +++ b/ui/src/components/access/AccessFormHetznerConfig.tsx @@ -0,0 +1,57 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForHetzner } from "@/domain/access"; + +type AccessFormHetznerConfigFieldValues = Nullish; + +export type AccessFormHetznerConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormHetznerConfigFieldValues; + onValuesChange?: (values: AccessFormHetznerConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormHetznerConfigFieldValues => { + return { + apiToken: "", + }; +}; + +const AccessFormHetznerConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormHetznerConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + apiToken: z.string().nonempty(t("access.form.hetzner_api_token.placeholder")).trim(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + +
+ ); +}; + +export default AccessFormHetznerConfig; diff --git a/ui/src/domain/access.ts b/ui/src/domain/access.ts index 3765310a..1576fd67 100644 --- a/ui/src/domain/access.ts +++ b/ui/src/domain/access.ts @@ -36,6 +36,7 @@ export interface AccessModel extends BaseModel { | AccessConfigForGoDaddy | AccessConfigForGoEdge | AccessConfigForGoogleTrustServices + | AccessConfigForHetzner | AccessConfigForHuaweiCloud | AccessConfigForJDCloud | AccessConfigForKubernetes @@ -238,6 +239,10 @@ export type AccessConfigForGoogleTrustServices = { eabHmacKey: string; }; +export type AccessConfigForHetzner = { + apiToken: string; +}; + export type AccessConfigForHuaweiCloud = { accessKeyId: string; secretAccessKey: string; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index 15542455..712530d7 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -35,6 +35,7 @@ export const ACCESS_PROVIDERS = Object.freeze({ GODADDY: "godaddy", GOEDGE: "goedge", GOOGLETRUSTSERVICES: "googletrustservices", + HETZNER: "hetzner", HUAWEICLOUD: "huaweicloud", JDCLOUD: "jdcloud", KUBERNETES: "k8s", @@ -142,6 +143,7 @@ export const accessProvidersMap: Maphttps://cloud.google.com/certificate-manager/docs/public-ca-tutorial", + "access.form.hetzner_api_token.label": "Hetzner API token", + "access.form.hetzner_api_token.placeholder": "Please enter Hetzner API token", + "access.form.hetzner_api_token.tooltip": "For more information, see https://docs.hetzner.com/cloud/api/getting-started/generating-api-token", "access.form.huaweicloud_access_key_id.label": "Huawei Cloud AccessKeyId", "access.form.huaweicloud_access_key_id.placeholder": "Please enter Huawei Cloud AccessKeyId", "access.form.huaweicloud_access_key_id.tooltip": "For more information, see https://support.huaweicloud.com/intl/en-us/usermanual-ca/ca_01_0003.html", diff --git a/ui/src/i18n/locales/en/nls.provider.json b/ui/src/i18n/locales/en/nls.provider.json index a3bbfecc..e9122149 100644 --- a/ui/src/i18n/locales/en/nls.provider.json +++ b/ui/src/i18n/locales/en/nls.provider.json @@ -74,6 +74,7 @@ "provider.godaddy": "GoDaddy", "provider.goedge": "GoEdge", "provider.googletrustservices": "Google Trust Services", + "provider.hetzner": "Hetzner", "provider.huaweicloud": "Huawei Cloud", "provider.huaweicloud.cdn": "Huawei Cloud - CDN (Content Delivery Network)", "provider.huaweicloud.dns": "Huawei Cloud - DNS (Domain Name Service)", diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index fdae1705..e2cacc1f 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -231,6 +231,9 @@ "access.form.googletrustservices_eab_hmac_key.label": "ACME EAB HMAC Key", "access.form.googletrustservices_eab_hmac_key.placeholder": "请输入 ACME EAB HMAC Key", "access.form.googletrustservices_eab_hmac_key.tooltip": "这是什么?请参阅 https://cloud.google.com/certificate-manager/docs/public-ca-tutorial", + "access.form.hetzner_api_token.label": "Hetzner API Token", + "access.form.hetzner_api_token.placeholder": "请输入 Hetzner API Token", + "access.form.hetzner_api_token.tooltip": "这是什么?请参阅 https://docs.hetzner.com/cloud/api/getting-started/generating-api-token", "access.form.huaweicloud_access_key_id.label": "华为云 AccessKeyId", "access.form.huaweicloud_access_key_id.placeholder": "请输入华为云 AccessKeyId", "access.form.huaweicloud_access_key_id.tooltip": "这是什么?请参阅 https://support.huaweicloud.com/usermanual-ca/ca_01_0003.html", diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json index b9fb8777..a6b94779 100644 --- a/ui/src/i18n/locales/zh/nls.provider.json +++ b/ui/src/i18n/locales/zh/nls.provider.json @@ -74,6 +74,7 @@ "provider.godaddy": "GoDaddy", "provider.goedge": "GoEdge", "provider.googletrustservices": "Google Trust Services", + "provider.hetzner": "Hetzner", "provider.huaweicloud": "华为云", "provider.huaweicloud.cdn": "华为云 - 内容分发网络 CDN", "provider.huaweicloud.dns": "华为云 - 云解析 DNS", From 40f4488009db60b768f35026a9dffcbb615c1b0a Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Mon, 26 May 2025 13:29:48 +0800 Subject: [PATCH 05/11] feat: new acme dns-01 provider: digitalocean --- internal/applicant/providers.go | 16 ++++++ internal/domain/access.go | 4 ++ internal/domain/provider.go | 2 + .../digitalocean/digitalocean.go | 36 ++++++++++++ ui/public/imgs/providers/digitalocean.svg | 1 + ui/src/components/access/AccessForm.tsx | 3 + .../access/AccessFormDigitalOceanConfig.tsx | 57 +++++++++++++++++++ ui/src/domain/access.ts | 4 ++ ui/src/domain/provider.ts | 4 ++ ui/src/i18n/locales/en/nls.access.json | 3 + ui/src/i18n/locales/en/nls.provider.json | 1 + ui/src/i18n/locales/zh/nls.access.json | 3 + ui/src/i18n/locales/zh/nls.provider.json | 1 + 13 files changed, 135 insertions(+) create mode 100644 internal/pkg/core/applicant/acme-dns-01/lego-providers/digitalocean/digitalocean.go create mode 100644 ui/public/imgs/providers/digitalocean.svg create mode 100644 ui/src/components/access/AccessFormDigitalOceanConfig.tsx diff --git a/internal/applicant/providers.go b/internal/applicant/providers.go index f967aef9..e35aee3e 100644 --- a/internal/applicant/providers.go +++ b/internal/applicant/providers.go @@ -17,6 +17,7 @@ import ( pClouDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns" pCMCCCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud" pDeSEC "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/desec" + pDigitalOcean "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/digitalocean" pDNSLA "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla" pDynv6 "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/dynv6" pGcore "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore" @@ -247,6 +248,21 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi return applicant, err } + case domain.ACMEDns01ProviderTypeDigitalOcean: + { + access := domain.AccessConfigForDigitalOcean{} + if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + applicant, err := pDigitalOcean.NewChallengeProvider(&pDigitalOcean.ChallengeProviderConfig{ + AccessToken: access.AccessToken, + DnsPropagationTimeout: options.DnsPropagationTimeout, + DnsTTL: options.DnsTTL, + }) + return applicant, err + } + case domain.ACMEDns01ProviderTypeDNSLA: { access := domain.AccessConfigForDNSLA{} diff --git a/internal/domain/access.go b/internal/domain/access.go index 30088bdf..c3530a4f 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -112,6 +112,10 @@ type AccessConfigForDeSEC struct { Token string `json:"token"` } +type AccessConfigForDigitalOcean struct { + AccessToken string `json:"accessToken"` +} + type AccessConfigForDingTalkBot struct { WebhookUrl string `json:"webhookUrl"` Secret string `json:"secret"` diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 4552553d..52a71e64 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -31,6 +31,7 @@ const ( AccessProviderTypeCTCCCloud = AccessProviderType("ctcccloud") // 天翼云(预留) AccessProviderTypeCUCCCloud = AccessProviderType("cucccloud") // 联通云(预留) AccessProviderTypeDeSEC = AccessProviderType("desec") + AccessProviderTypeDigitalOcean = AccessProviderType("digitalocean") AccessProviderTypeDingTalkBot = AccessProviderType("dingtalkbot") AccessProviderTypeDNSLA = AccessProviderType("dnsla") AccessProviderTypeDogeCloud = AccessProviderType("dogecloud") @@ -127,6 +128,7 @@ const ( ACMEDns01ProviderTypeClouDNS = ACMEDns01ProviderType(AccessProviderTypeClouDNS) ACMEDns01ProviderTypeCMCCCloud = ACMEDns01ProviderType(AccessProviderTypeCMCCCloud) ACMEDns01ProviderTypeDeSEC = ACMEDns01ProviderType(AccessProviderTypeDeSEC) + ACMEDns01ProviderTypeDigitalOcean = ACMEDns01ProviderType(AccessProviderTypeDigitalOcean) ACMEDns01ProviderTypeDNSLA = ACMEDns01ProviderType(AccessProviderTypeDNSLA) ACMEDns01ProviderTypeDynv6 = ACMEDns01ProviderType(AccessProviderTypeDynv6) ACMEDns01ProviderTypeGcore = ACMEDns01ProviderType(AccessProviderTypeGcore) diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/digitalocean/digitalocean.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/digitalocean/digitalocean.go new file mode 100644 index 00000000..0e3cb358 --- /dev/null +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/digitalocean/digitalocean.go @@ -0,0 +1,36 @@ +package namedotcom + +import ( + "time" + + "github.com/go-acme/lego/v4/challenge" + "github.com/go-acme/lego/v4/providers/dns/digitalocean" +) + +type ChallengeProviderConfig struct { + AccessToken string `json:"accessToken"` + DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` + DnsTTL int32 `json:"dnsTTL,omitempty"` +} + +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { + if config == nil { + panic("config is nil") + } + + providerConfig := digitalocean.NewDefaultConfig() + providerConfig.AuthToken = config.AccessToken + if config.DnsPropagationTimeout != 0 { + providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second + } + if config.DnsTTL != 0 { + providerConfig.TTL = int(config.DnsTTL) + } + + provider, err := digitalocean.NewDNSProviderConfig(providerConfig) + if err != nil { + return nil, err + } + + return provider, nil +} diff --git a/ui/public/imgs/providers/digitalocean.svg b/ui/public/imgs/providers/digitalocean.svg new file mode 100644 index 00000000..94b90bf9 --- /dev/null +++ b/ui/public/imgs/providers/digitalocean.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ui/src/components/access/AccessForm.tsx b/ui/src/components/access/AccessForm.tsx index 6f4d5086..4fd547e8 100644 --- a/ui/src/components/access/AccessForm.tsx +++ b/ui/src/components/access/AccessForm.tsx @@ -29,6 +29,7 @@ import AccessFormCloudflareConfig from "./AccessFormCloudflareConfig"; import AccessFormClouDNSConfig from "./AccessFormClouDNSConfig"; import AccessFormCMCCCloudConfig from "./AccessFormCMCCCloudConfig"; import AccessFormDeSECConfig from "./AccessFormDeSECConfig"; +import AccessFormDigitalOceanConfig from "./AccessFormDigitalOceanConfig"; import AccessFormDingTalkBotConfig from "./AccessFormDingTalkBotConfig"; import AccessFormDNSLAConfig from "./AccessFormDNSLAConfig"; import AccessFormDogeCloudConfig from "./AccessFormDogeCloudConfig"; @@ -216,6 +217,8 @@ const AccessForm = forwardRef(({ className, return ; case ACCESS_PROVIDERS.DESEC: return ; + case ACCESS_PROVIDERS.DIGITALOCEAN: + return ; case ACCESS_PROVIDERS.DINGTALKBOT: return ; case ACCESS_PROVIDERS.DNSLA: diff --git a/ui/src/components/access/AccessFormDigitalOceanConfig.tsx b/ui/src/components/access/AccessFormDigitalOceanConfig.tsx new file mode 100644 index 00000000..f4aafc4f --- /dev/null +++ b/ui/src/components/access/AccessFormDigitalOceanConfig.tsx @@ -0,0 +1,57 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForDigitalOcean } from "@/domain/access"; + +type AccessFormDigitalOceanConfigFieldValues = Nullish; + +export type AccessFormDigitalOceanConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormDigitalOceanConfigFieldValues; + onValuesChange?: (values: AccessFormDigitalOceanConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormDigitalOceanConfigFieldValues => { + return { + accessToken: "", + }; +}; + +const AccessFormDigitalOceanConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormDigitalOceanConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + accessToken: z.string().nonempty(t("access.form.digitalocean_access_token.placeholder")).trim(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + +
+ ); +}; + +export default AccessFormDigitalOceanConfig; diff --git a/ui/src/domain/access.ts b/ui/src/domain/access.ts index 1576fd67..32a1b128 100644 --- a/ui/src/domain/access.ts +++ b/ui/src/domain/access.ts @@ -170,6 +170,10 @@ export type AccessConfigForDeSEC = { token: string; }; +export type AccessConfigForDigitalOcean = { + accessToken: string; +}; + export type AccessConfigForDingTalkBot = { webhookUrl: string; secret?: string; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index 712530d7..6d1ad303 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -23,6 +23,7 @@ export const ACCESS_PROVIDERS = Object.freeze({ CLOUDNS: "cloudns", CMCCCLOUD: "cmcccloud", DESEC: "desec", + DIGITALOCEAN: "digitalocean", DINGTALKBOT: "dingtalkbot", DNSLA: "dnsla", DOGECLOUD: "dogecloud", @@ -139,6 +140,7 @@ export const accessProvidersMap: Maphttps://desec.readthedocs.io/en/latest/auth/tokens.html", + "access.form.digitalocean_access_token.label": "DigitalOcean access token", + "access.form.digitalocean_access_token.placeholder": "Please enter DigitalOcean access token", + "access.form.digitalocean_access_token.tooltip": "For more information, see https://docs.digitalocean.com/reference/api/create-personal-access-token/", "access.form.dingtalkbot_webhook_url.label": "DingTalk bot Webhook URL", "access.form.dingtalkbot_webhook_url.placeholder": "Please enter DingTalk bot Webhook URL", "access.form.dingtalkbot_webhook_url.tooltip": "For more information, see https://open.dingtalk.com/document/orgapp/obtain-the-webhook-address-of-a-custom-robot", diff --git a/ui/src/i18n/locales/en/nls.provider.json b/ui/src/i18n/locales/en/nls.provider.json index e9122149..c623bb27 100644 --- a/ui/src/i18n/locales/en/nls.provider.json +++ b/ui/src/i18n/locales/en/nls.provider.json @@ -58,6 +58,7 @@ "provider.ctcccloud": "China Telecom Cloud (State Cloud)", "provider.cucccloud": "China Unicom Cloud", "provider.desec": "deSEC", + "provider.digitalocean": "DigitalOcean", "provider.dingtalkbot": "DingTalk Bot", "provider.dnsla": "DNS.LA", "provider.dogecloud": "Doge Cloud", diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index e2cacc1f..f3a39ec2 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -146,6 +146,9 @@ "access.form.desec_token.label": "deSEC Token", "access.form.desec_token.placeholder": "请输入 deSEC Token", "access.form.desec_token.tooltip": "这是什么?请参阅 https://desec.readthedocs.io/en/latest/auth/tokens.html", + "access.form.digitalocean_access_token.label": "DigitalOcean Access Token", + "access.form.digitalocean_access_token.placeholder": "请输入 DigitalOcean Access Token", + "access.form.digitalocean_access_token.tooltip": "这是什么?请参阅 https://docs.digitalocean.com/reference/api/create-personal-access-token/", "access.form.dingtalkbot_webhook_url.label": "钉钉群机器人 Webhook 地址", "access.form.dingtalkbot_webhook_url.placeholder": "请输入钉钉群机器人 Webhook 地址", "access.form.dingtalkbot_webhook_url.tooltip": "这是什么?请参阅 https://open.dingtalk.com/document/orgapp/obtain-the-webhook-address-of-a-custom-robot", diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json index a6b94779..a68a1a09 100644 --- a/ui/src/i18n/locales/zh/nls.provider.json +++ b/ui/src/i18n/locales/zh/nls.provider.json @@ -58,6 +58,7 @@ "provider.ctcccloud": "联通云", "provider.cucccloud": "天翼云", "provider.desec": "deSEC", + "provider.digitalocean": "DigitalOcean", "provider.dingtalkbot": "钉钉群机器人", "provider.dnsla": "DNS.LA", "provider.dogecloud": "多吉云", From cd9dac776551db29ee8e3968e8dadcf5a0cd67fa Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Mon, 26 May 2025 13:59:00 +0800 Subject: [PATCH 06/11] feat: new acme dns-01 provider: duckdns --- internal/applicant/providers.go | 15 +++++ internal/domain/access.go | 4 ++ internal/domain/provider.go | 2 + .../lego-providers/duckdns/duckdns.go | 32 ++++++++++ ui/public/imgs/providers/duckdns.png | Bin 0 -> 6821 bytes ui/src/components/access/AccessForm.tsx | 3 + .../access/AccessFormDuckDNSConfig.tsx | 57 ++++++++++++++++++ ui/src/domain/access.ts | 6 ++ ui/src/domain/provider.ts | 4 ++ ui/src/i18n/locales/en/nls.access.json | 3 + ui/src/i18n/locales/en/nls.provider.json | 1 + ui/src/i18n/locales/zh/nls.access.json | 3 + ui/src/i18n/locales/zh/nls.provider.json | 1 + 13 files changed, 131 insertions(+) create mode 100644 internal/pkg/core/applicant/acme-dns-01/lego-providers/duckdns/duckdns.go create mode 100644 ui/public/imgs/providers/duckdns.png create mode 100644 ui/src/components/access/AccessFormDuckDNSConfig.tsx diff --git a/internal/applicant/providers.go b/internal/applicant/providers.go index e35aee3e..98561daf 100644 --- a/internal/applicant/providers.go +++ b/internal/applicant/providers.go @@ -19,6 +19,7 @@ import ( pDeSEC "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/desec" pDigitalOcean "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/digitalocean" pDNSLA "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla" + pDuckDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/duckdns" pDynv6 "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/dynv6" pGcore "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore" pGname "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname" @@ -279,6 +280,20 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi return applicant, err } + case domain.ACMEDns01ProviderTypeDuckDNS: + { + access := domain.AccessConfigForDuckDNS{} + if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + applicant, err := pDuckDNS.NewChallengeProvider(&pDuckDNS.ChallengeProviderConfig{ + Token: access.Token, + DnsPropagationTimeout: options.DnsPropagationTimeout, + }) + return applicant, err + } + case domain.ACMEDns01ProviderTypeDynv6: { access := domain.AccessConfigForDynv6{} diff --git a/internal/domain/access.go b/internal/domain/access.go index c3530a4f..dac85e31 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -131,6 +131,10 @@ type AccessConfigForDogeCloud struct { SecretKey string `json:"secretKey"` } +type AccessConfigForDuckDNS struct { + Token string `json:"token"` +} + type AccessConfigForDynv6 struct { HttpToken string `json:"httpToken"` } diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 52a71e64..14a107b6 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -35,6 +35,7 @@ const ( AccessProviderTypeDingTalkBot = AccessProviderType("dingtalkbot") AccessProviderTypeDNSLA = AccessProviderType("dnsla") AccessProviderTypeDogeCloud = AccessProviderType("dogecloud") + AccessProviderTypeDuckDNS = AccessProviderType("duckdns") AccessProviderTypeDynv6 = AccessProviderType("dynv6") AccessProviderTypeEdgio = AccessProviderType("edgio") AccessProviderTypeEmail = AccessProviderType("email") @@ -130,6 +131,7 @@ const ( ACMEDns01ProviderTypeDeSEC = ACMEDns01ProviderType(AccessProviderTypeDeSEC) ACMEDns01ProviderTypeDigitalOcean = ACMEDns01ProviderType(AccessProviderTypeDigitalOcean) ACMEDns01ProviderTypeDNSLA = ACMEDns01ProviderType(AccessProviderTypeDNSLA) + ACMEDns01ProviderTypeDuckDNS = ACMEDns01ProviderType(AccessProviderTypeDuckDNS) ACMEDns01ProviderTypeDynv6 = ACMEDns01ProviderType(AccessProviderTypeDynv6) ACMEDns01ProviderTypeGcore = ACMEDns01ProviderType(AccessProviderTypeGcore) ACMEDns01ProviderTypeGname = ACMEDns01ProviderType(AccessProviderTypeGname) diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/duckdns/duckdns.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/duckdns/duckdns.go new file mode 100644 index 00000000..6cc823d0 --- /dev/null +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/duckdns/duckdns.go @@ -0,0 +1,32 @@ +package namedotcom + +import ( + "time" + + "github.com/go-acme/lego/v4/challenge" + "github.com/go-acme/lego/v4/providers/dns/duckdns" +) + +type ChallengeProviderConfig struct { + Token string `json:"token"` + DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` +} + +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { + if config == nil { + panic("config is nil") + } + + providerConfig := duckdns.NewDefaultConfig() + providerConfig.Token = config.Token + if config.DnsPropagationTimeout != 0 { + providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second + } + + provider, err := duckdns.NewDNSProviderConfig(providerConfig) + if err != nil { + return nil, err + } + + return provider, nil +} diff --git a/ui/public/imgs/providers/duckdns.png b/ui/public/imgs/providers/duckdns.png new file mode 100644 index 0000000000000000000000000000000000000000..c80f4a9ed84ecf4545da1088eb305892504ef8e3 GIT binary patch literal 6821 zcmaJ`^;Zz&ZSF2x|Uc3=?-ZYrCDGJVdwjCp%GI2r|4+exwKD4TrU+31>AKkd@4L4^u#89G&F#qioA@T z-||tOe=6mC*P!(L%Gd?>v%}tkzE?Oh_WrR$yqxGs{t*JIAeI%+NXYs z@#+3x7EXW&dqsbgLTp%3K^R^|0kIH2_fIMQK*RalzYBN-Ygd;Sg8FM$o|<`CLcyJ7 zRVS?>_nkerojrtrB*o(C_rm`JaC)a0!*_?gKQmjQ@ssZ1dSS+g`%JjthOhNnSaBfn zf6RyxV6Cl<_0RMKzHGDqcK9HA(_ly|Dnnna5~G#nM$Qh9V7i)%nvu@Gueug=fw zJAM8wU0*9!$@h@7jkJ?YMm2jsm+JZyw%K{h+eOpPQ%zB2V!lH7l-=@0mh}+BwEhy9wBxt&(=Q|C8j4VnwV!OF$ zPq4q#r~vm_T{E|EYw)TZUU644>JXN-FJ(B{UYr=tM=wMF*AXbP!H~=QK8bL;GR0c@ z-mA9DUainITcO33shum)GewgLN8GllQwA!bd7AvCN53_@QPaous)$U?|#V<`%-}h8{8x9HZ6^g zY9@iKf$+@Am)qJFtu7HD#Y8+(yrwk;C1(E6kWa%Yhf9qdypInK@=yyxDZ+Lja0b~&7zstnz7P{zZ>yg!b}@!7>H%=jXwcl9VUED4UdOk-#y<@;!EO-}a;xt0&^y_FpuSK+HnWQ%3-4sVKj54fi;PUVeD{?%Cdw zt_m zS;#9Q>H!R)(Bx*9^WjmolfiD^y79WuwV?=XvZ^ZX>}+DmFa`-g&`F?_TgU7EPxvz1 zp4se)wA!P%jLHf7Azli6Ah%SD9YeZ&FKnvx`}WCQ!W37_8S@AhSp%i8BG)tC~kw07F){G%;U zz4Wejl4SV8?F@W|+9bhrqLQEm-FeKCg%V+5Y{Z(I<;XCR_M$Xnci=KPY-)PD3E*Ss ztcdP_kp7*P#^GxW&Cl}%Py8Os^dd?7{EQ9|{o&IOlF%dNM@vb$v$N3^_OSrU04G>^ zx|FhWb86c4n}2f`?5(0A1G^T_HIVc32fIV#BB{X-lqr#RfA|VSa!7Ya0P6YAS=Uq| z3%`&+NanMqSc3e*Y?G5F?JWJQ!)PqQpO@HUU-{=&q$Q!vD}}y(c7fL70xQRHB0zq^ zcReS2gyW*`jKu}1&86E1kH$#fooqbNCjzK8ydi!?$wkahUf3h?r9)zTf$WLWBDt&{ zrXiI!uA91pVVT4sUuBH5AQ$CPD|dfr3f=Kv^a^WmkM^Bhg|hg}3KzFopPKtRRVL?4 z5-n86J>)wSq}WDKlP+;U>t}e|qeQaELFa4H80vr2OtqK_er74*ziE z57{E&3kqqfYPPrcA|-6DGgA>-ME7gHMS(3LtUT@bV zw_F@-C)4GFWf9FO&x*jB_RN(LWx=S0S>uIXqJ#zsA7RwlsBFGp(bwI4mon&TQJJEh zMD)+8$`n|IHoDu>6+B*}xK-rjO>b5CrKrRHj{d$>oCh^`jTCU&Sm()b7P4239pxpg zcS;#}xCeg4qoj<*`oU|S=)TM*D-(W)EX`#y!F-HdeCr}%Gh3@A z`3iOU5!N|sJ2o7?-lglSfsKt5{jx86xJB4I-BKpJw zp`tgV?yb#m&*weRK#bizOz3g0V^hM7VaKcXBIZu+Ap26P*}hxSVcR&5;ERlP48V#B zvW{t(CONV(%$GEfusz(n0mo$_)0ho)_EF7wO@bX2KAHS**2TH2Tnev~nKM>r4}puu z@;f{Nk1h9ahD+60>_$09vH_;qa+a}uU~@`txRm_!$5&u9DX zoWIY-tVR!Lm67h@a^ZI|&^2fi@!TC@L=@I|+4IVesVi>s)muIQhmYf|KMxR%0xUi# ze900b;lW+&UURraI2^Z^$Hm7RM4eZKeJA^;H8X&=y8`4aEyX$fO*2(%?vT)3vK2NL z1359`&^J*{mjrYTGjn7XstfW2;kD^2AR=+Dd)R!!YR!qtG>J|JXs}nk4K-a1V7^M9 zcV#M%q`k%V5-MonWVf%oyKyS3GA;f!3SuP zyQenz<)wZx_--}$xT3QtqW+F6ok~EoJDll`aSVPrPt9S~bps09#dNpb_=7uyML)6H<0rDkz(EQw()zpSd8+@ zGJK=>l9o-x5}D7*#Mt}sK}IE`A8#LsF6jr(yRZ_OoS|LYa!~sE7)n<*RE&0}$P2NV zN$=m4hLwWPw6}H>_y}l0Z;sWvqAn10Hw51laEXY3$x_RyUn6?1EUtsS*$Xf>`FDqcG6@9=)8OPr~IHV~WS{OsLBYGYm*qzAc`HM<^g_7cH zCyN{GDaD$TM@w)Tz)51TSxsEU$dl62ioS^WO^Bgegi7W%bt$*HHNUyP5U;9A{h2{s zq`C;DynM`2=KLBZiyRa3SI?%rfG+M%h|o!Q8>m>pe(E`sDG6N3<;ExztM!pe2;^h) zCe1U^eiB{B6Y>Fnq%qXjGs^X~U^x8EmC!vxN8+mb73YSz#VpysxGNwI=GW@Bo;2#d z;xJo07_O(3&)h2r=Y)^i9b zQNw@3R&>0?*gd2PRMeliWxXuy9{(^QL7ycpZBOCk5-!lY6uW0Q^Qi5Dy@44uKs#H8 zy}v5foRx>`+Xa&g1*5#LCh zWS;5L^8VHO+EjVUL_|}Dn&h_JdzdZu zI*WPGgc0lVrEI%tI6*)8M3aV2)35dk1#qv+5VKJ5O-Y^RfK&Ok|J54*&*;~s3M6ko zaWaAs?hN67$=dHY-bC=olz8|mg575uUS^ODyl(=}(i*hKc8KSU^3^$>J0xt}v1hbY z$yM6WoU|2dx37bko4V&tnSx@16&I{w*}#qz)P8jJq6S)ihHD3qN z%i)s)r_8k1u!(%I3Cpk~rtq-lX?t2(!1lnX+iZ9?lX!J=!M$n$g_KSgdBy46$@8wZ zN2(unI#NYHgAAFB|veA1JkL70Vs;a&I z+i?h}sPTrFQsDLLrR=ZWs$U6jjANN)r>gltIpTKxVnc-_8y;EJJu*b5ica7 z8rJ0W^7rbhYwI>CaiGgbj`i{WnV9j5eX%Mvs?aR_h?6+HSp_!f4XeF(SE*wR!b6jb z_3N)U15XEJK1;86qX69@8iHPhYaKCV+0PuBPjY1G$}<(0n)YMor!4 ze{~t3Y*JFk59wML%DC0a)C$d0`V<|7^n^Pt3j^cxL=FyN!ma>-JoaW+psSPhJR#pR zB=V=*=K;bAY3bgsD?r2Q1G)Upi3uNJH_0~>q5Iog^ZN18&5Ofb+wtt6XyO|Cll5X> zoymM04hW*$QH#;uo+n18)lCWmy)SC7W2XcI@!kTvRvT&rGheDV~T0{5w`1m`0 z`+D#1*p$oHv_TmY@XF<-`=tGXZcWWT~+<@({voz>#G^8APg*G-O3; z*e(<^+u52d8A#xN)Qo4^vZ!Z}ok&kpqQ%I#)^XjvUEcDd8Mmux?zWRvJrAHmcK53P z`Jj)ed1sZ_gwk9f-HRHTH(=zn()Gpu->4*XqTijwZsmbjm@}%jv5Cv3&^PaiUREN~ za@0&b9m$j4yeAi;6|xl6>-?F1}m_ zlaJFyD*Sc;6h{&t-xM_o92p5Bu&3CMknJm6!Lp=2RQNEv96AYHZWem8OMS)A* zEv3c8bRvJ#WN_c=YFBx=Xo%V?JI_oGebwRGNRwk@H|O))XLb~=_Lym6aLg@4EZF@j z5D_&blnSgDyZ2&)K{lyittnDuFV~Ki5^ZEw&@ITIO{#jM1WXz}9})Gc5hwdpuo&+Q zXB%r;RmHk7u80f=JSu8uMyZwkb#u4+M(Sg?=qm~p%9V_ZNAD)HDOiQJTuU|__F}uB%k)KnuoblI}Nz_oea2l*0wFRpy zHy#vtP>-us?*tomk}gHo*#vK780d}K#)heJDXAPhb8ZMzY#zTqfHI-R8*r$o%8pOD zIZW0j{01Z4NTFV)P#)7KfBRe_v}fKn(qNH%Gr#S=8R`3OTIn*wjxrH7E3bk}$6YT1 z<$}9P10@rdS~Qj)Edx}Lhjv6#_j-gDwA1GJSUu}9)MW1)-|uWM}fEU zeATJ$5ob?!yNG0YutD8INYEvb5f7DID>Y3CRX+<#k@ahK8M{%39--8VQGZ^OpVJhk*pW+UufZZU{`;gn`Xoh)+Iy+}GMXN;o zGn!@lcJ^PgJAjpYHBJuDSWkaH+@;q$6aW(5x}4b;Cf=4ZD*XkK&T zifW%u(##`$LU&9;`=sOUPO?0QFH78JwA$v&Vk;WI*Ro~RNrnMq5cdXm$P1_gFOHDI ztM=Nuj-wG%7Sy$Jkw{V!@bSj5aX}$k=c!=iQTXjK#F8Da8{Ln`AW|9Y>77y3@x$=1 zz~RI19!}#cPI#m`X;7o>wyo43Lh8)a43}2+*~R*wHtQg^!v_#^>XAPTlN-n9m-9PQ zmvcnpa?P-CI**WXtEThNLAY3(N9%#S>}x)Bnn7pym0WP}OIX3@MLU9GrQZ#H^>ZF| z7|~+K?utf!VJmh->J)CB8ZobgqDs{?sOmBA){<;E@Ku9|P$x!2A3wss*AeLX#7?#4 zu6L0%SVzv~iQ!RpPKRpE^I!-x13ARpM{JH#%S?+C$L{ z@_dq~Ow$#P`b%%!u=0aDQ?N8V_%^jW4uX*$xV`?($;Q=+1<6vNyiIg_xpa5r zKK?|M!jgWar-E5~dw@YpO%|{wT+B1|*|a9yneq~SR2~*Nl(Io$Mmm|p$>nO{SD4lA zsd0%2N5>4>+Sy?bA;2UhFKalnOk9c9h@?Y}(zpFf@rhlu+w{L!MG zp9j(djX?Ka6he-_@_v~UUdUR<41&o(v2hi~y~Fs))xlGBkYq9zjHlX&-Ov{_UiIcn zc|$&vxv^0`CBMhu6fJ2H{gEvOfii4fId0@z!UyFLVo=ynrwYP`=tF8M?W&(Gv2Gcb z({D}FV7h<*fFx3j{gB7i{)xPngW9EO6o<#xR>s@8Sz;802d{^^pcd#UW2*7u3kJ18 zj@N>{j;a{L@+4e2xp)%2gZ+D{Rj>-7z? z`SU*4zYKzoc{jo1&~VGr;qmVPPc1z&2pK+n^N$)5>QzC{KHMq{9lq zU&a6Q?Vcn^>ciGHT_WAz-J*nur)*rHmN8cUfJ?kMmPN72`1pS3DYhLPx^kZN@}|}G z-wfl9+x$`ZIdE@T|9PG` zo!6nm)c1_!7m`8G1FMr~bRum(pKhMh2?&2(R010VpU#kqih6tdNq|p5@F^142e$gv zRE?Ci0BhWqTw?K7I+d$*-@`bf8DC*N(6r$XX2uGjhl-~JG?B5-TV%)wyb1nO1p0X(b)Sy@b~eGkU)AfJk29lVkpk?CJo zr4J89<6}OvY{*y7PDkKfC~O@+LyyMjYOLTB6*mYHL$-T@XUQkcV2ql*Vg%uhq~4z0 zB&iNllE?C&h#rqnTerDG@t2jT~OprB2{ipY)AwE9c_#I+OGzF2KpHdKxCl3?a+jxO7wlH6@Za)!TK93UY6W5@L zP2Uhe%sn^SvINQ7!t=n-=iNcOSCMZiY<53Vya`)Wwy9&;2^fqwotQrBtc(({ className, return ; case ACCESS_PROVIDERS.DOGECLOUD: return ; + case ACCESS_PROVIDERS.DUCKDNS: + return ; case ACCESS_PROVIDERS.DYNV6: return ; case ACCESS_PROVIDERS.EDGIO: diff --git a/ui/src/components/access/AccessFormDuckDNSConfig.tsx b/ui/src/components/access/AccessFormDuckDNSConfig.tsx new file mode 100644 index 00000000..969f78f8 --- /dev/null +++ b/ui/src/components/access/AccessFormDuckDNSConfig.tsx @@ -0,0 +1,57 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForDuckDNS } from "@/domain/access"; + +type AccessFormDuckDNSConfigFieldValues = Nullish; + +export type AccessFormDuckDNSConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormDuckDNSConfigFieldValues; + onValuesChange?: (values: AccessFormDuckDNSConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormDuckDNSConfigFieldValues => { + return { + token: "", + }; +}; + +const AccessFormDuckDNSConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormDuckDNSConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + token: z.string().nonempty(t("access.form.duckdns_token.placeholder")).trim(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + +
+ ); +}; + +export default AccessFormDuckDNSConfig; diff --git a/ui/src/domain/access.ts b/ui/src/domain/access.ts index 32a1b128..9e2d4f70 100644 --- a/ui/src/domain/access.ts +++ b/ui/src/domain/access.ts @@ -24,9 +24,11 @@ export interface AccessModel extends BaseModel { | AccessConfigForClouDNS | AccessConfigForCMCCCloud | AccessConfigForDeSEC + | AccessConfigForDigitalOcean | AccessConfigForDingTalkBot | AccessConfigForDNSLA | AccessConfigForDogeCloud + | AccessConfigForDuckDNS | AccessConfigForDynv6 | AccessConfigForEdgio | AccessConfigForEmail @@ -189,6 +191,10 @@ export type AccessConfigForDogeCloud = { secretKey: string; }; +export type AccessConfigForDuckDNS = { + token: string; +}; + export type AccessConfigForDynv6 = { httpToken: string; }; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index 6d1ad303..6576aa94 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -27,6 +27,7 @@ export const ACCESS_PROVIDERS = Object.freeze({ DINGTALKBOT: "dingtalkbot", DNSLA: "dnsla", DOGECLOUD: "dogecloud", + DUCKDNS: "duckdns", DYNV6: "dynv6", EDGIO: "edgio", EMAIL: "email", @@ -142,6 +143,7 @@ export const accessProvidersMap: Maphttps://console.dogecloud.com/", + "access.form.duckdns_token.label": "DuckDNS token", + "access.form.duckdns_token.placeholder": "Please enter DuckDNS token", + "access.form.duckdns_token.tooltip": "For more information, see https://www.duckdns.org/spec.jsp", "access.form.dynv6_http_token.label": "dynv6 HTTP token", "access.form.dynv6_http_token.placeholder": "Please enter dynv6 HTTP token", "access.form.dynv6_http_token.tooltip": "For more information, see https://dynv6.com/keys", diff --git a/ui/src/i18n/locales/en/nls.provider.json b/ui/src/i18n/locales/en/nls.provider.json index c623bb27..80cb65cf 100644 --- a/ui/src/i18n/locales/en/nls.provider.json +++ b/ui/src/i18n/locales/en/nls.provider.json @@ -63,6 +63,7 @@ "provider.dnsla": "DNS.LA", "provider.dogecloud": "Doge Cloud", "provider.dogecloud.cdn": "Doge Cloud - CDN (Content Delivery Network)", + "provider.duckdns": "Duck DNS", "provider.dynv6": "dynv6", "provider.edgio": "Edgio", "provider.edgio.applications": "Edgio - Applications", diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index f3a39ec2..1f538ac5 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -167,6 +167,9 @@ "access.form.dogecloud_secret_key.label": "多吉云 SecretKey", "access.form.dogecloud_secret_key.placeholder": "请输入多吉云 SecretKey", "access.form.dogecloud_secret_key.tooltip": "这是什么?请参阅 https://console.dogecloud.com/", + "access.form.duckdns_token.label": "DuckDNS Token", + "access.form.duckdns_token.placeholder": "请输入 DuckDNS Token", + "access.form.duckdns_token.tooltip": "这是什么?请参阅 https://www.duckdns.org/spec.jsp", "access.form.dynv6_http_token.label": "dynv6 HTTP Token", "access.form.dynv6_http_token.placeholder": "请输入 dynv6 HTTP Token", "access.form.dynv6_http_token.tooltip": "这是什么?请参阅 https://dynv6.com/keys", diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json index a68a1a09..8de1ccf5 100644 --- a/ui/src/i18n/locales/zh/nls.provider.json +++ b/ui/src/i18n/locales/zh/nls.provider.json @@ -63,6 +63,7 @@ "provider.dnsla": "DNS.LA", "provider.dogecloud": "多吉云", "provider.dogecloud.cdn": "多吉云 - 内容分发网络 CDN", + "provider.duckdns": "Duck DNS", "provider.dynv6": "dynv6", "provider.edgio": "Edgio", "provider.edgio.applications": "Edgio - Applications", From 8e23b14bf37612aaa4f82255f1ce0b7cd2724fd6 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Mon, 26 May 2025 15:55:09 +0800 Subject: [PATCH 07/11] feat: new notification provider: discord bot --- internal/domain/access.go | 5 ++ internal/domain/provider.go | 2 + internal/notify/providers.go | 14 ++++ .../providers/discordbot/discordbot.go | 67 ++++++++++++++++++ .../providers/discordbot/discordbot_test.go | 64 +++++++++++++++++ .../providers/telegrambot/telegrambot_test.go | 8 +-- ui/public/imgs/providers/discord.svg | 1 + ui/src/components/access/AccessForm.tsx | 3 + .../access/AccessFormDiscordBotConfig.tsx | 70 +++++++++++++++++++ .../access/AccessFormTelegramBotConfig.tsx | 18 ++--- .../workflow/node/NotifyNodeConfigForm.tsx | 3 + .../NotifyNodeConfigFormDiscordBotConfig.tsx | 61 ++++++++++++++++ .../NotifyNodeConfigFormTelegramBotConfig.tsx | 8 +-- ui/src/domain/access.ts | 6 ++ ui/src/domain/provider.ts | 8 ++- ui/src/i18n/locales/en/nls.access.json | 20 ++++-- ui/src/i18n/locales/en/nls.provider.json | 1 + .../i18n/locales/en/nls.workflow.nodes.json | 11 +-- ui/src/i18n/locales/zh/nls.access.json | 20 ++++-- ui/src/i18n/locales/zh/nls.provider.json | 3 +- .../i18n/locales/zh/nls.workflow.nodes.json | 9 ++- 21 files changed, 361 insertions(+), 41 deletions(-) create mode 100644 internal/pkg/core/notifier/providers/discordbot/discordbot.go create mode 100644 internal/pkg/core/notifier/providers/discordbot/discordbot_test.go create mode 100644 ui/public/imgs/providers/discord.svg create mode 100644 ui/src/components/access/AccessFormDiscordBotConfig.tsx create mode 100644 ui/src/components/workflow/node/NotifyNodeConfigFormDiscordBotConfig.tsx diff --git a/internal/domain/access.go b/internal/domain/access.go index dac85e31..4e002ecf 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -121,6 +121,11 @@ type AccessConfigForDingTalkBot struct { Secret string `json:"secret"` } +type AccessConfigForDiscordBot struct { + BotToken string `json:"botToken"` + DefaultChannelId string `json:"defaultChannelId,omitempty"` +} + type AccessConfigForDNSLA struct { ApiId string `json:"apiId"` ApiSecret string `json:"apiSecret"` diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 14a107b6..8f5c959a 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -33,6 +33,7 @@ const ( AccessProviderTypeDeSEC = AccessProviderType("desec") AccessProviderTypeDigitalOcean = AccessProviderType("digitalocean") AccessProviderTypeDingTalkBot = AccessProviderType("dingtalkbot") + AccessProviderTypeDiscordBot = AccessProviderType("discordbot") AccessProviderTypeDNSLA = AccessProviderType("dnsla") AccessProviderTypeDogeCloud = AccessProviderType("dogecloud") AccessProviderTypeDuckDNS = AccessProviderType("duckdns") @@ -269,6 +270,7 @@ type NotificationProviderType string */ const ( NotificationProviderTypeDingTalkBot = NotificationProviderType(AccessProviderTypeDingTalkBot) + NotificationProviderTypeDiscordBot = NotificationProviderType(AccessProviderTypeDiscordBot) NotificationProviderTypeEmail = NotificationProviderType(AccessProviderTypeEmail) NotificationProviderTypeLarkBot = NotificationProviderType(AccessProviderTypeLarkBot) NotificationProviderTypeMattermost = NotificationProviderType(AccessProviderTypeMattermost) diff --git a/internal/notify/providers.go b/internal/notify/providers.go index 3a8c575d..23f5bb43 100644 --- a/internal/notify/providers.go +++ b/internal/notify/providers.go @@ -7,6 +7,7 @@ import ( "github.com/usual2970/certimate/internal/domain" "github.com/usual2970/certimate/internal/pkg/core/notifier" pDingTalkBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/dingtalkbot" + pDiscordBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/discordbot" pEmail "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email" pLarkBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/larkbot" pMattermost "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/mattermost" @@ -42,6 +43,19 @@ func createNotifierProvider(options *notifierProviderOptions) (notifier.Notifier }) } + case domain.NotificationProviderTypeDiscordBot: + { + access := domain.AccessConfigForDiscordBot{} + if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + return pDiscordBot.NewNotifier(&pDiscordBot.NotifierConfig{ + BotToken: access.BotToken, + ChannelId: maputil.GetOrDefaultString(options.ProviderServiceConfig, "channelId", access.DefaultChannelId), + }) + } + case domain.NotificationProviderTypeEmail: { access := domain.AccessConfigForEmail{} diff --git a/internal/pkg/core/notifier/providers/discordbot/discordbot.go b/internal/pkg/core/notifier/providers/discordbot/discordbot.go new file mode 100644 index 00000000..dbffaba7 --- /dev/null +++ b/internal/pkg/core/notifier/providers/discordbot/discordbot.go @@ -0,0 +1,67 @@ +package discordbot + +import ( + "context" + "fmt" + "log/slog" + + "github.com/go-resty/resty/v2" + + "github.com/usual2970/certimate/internal/pkg/core/notifier" +) + +type NotifierConfig struct { + // Discord Bot API Token。 + BotToken string `json:"botToken"` + // Discord Channel ID。 + ChannelId string `json:"channelId"` +} + +type NotifierProvider struct { + config *NotifierConfig + logger *slog.Logger + httpClient *resty.Client +} + +var _ notifier.Notifier = (*NotifierProvider)(nil) + +func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) { + if config == nil { + panic("config is nil") + } + + client := resty.New() + + return &NotifierProvider{ + config: config, + logger: slog.Default(), + httpClient: client, + }, nil +} + +func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier { + if logger == nil { + n.logger = slog.Default() + } else { + n.logger = logger + } + return n +} + +func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { + // REF: https://discord.com/developers/docs/resources/message#create-message + req := n.httpClient.R(). + SetHeader("Content-Type", "application/json"). + SetHeader("Authorization", "Bot "+n.config.BotToken). + SetBody(map[string]any{ + "content": subject + "\n" + message, + }) + resp, err := req.Post(fmt.Sprintf("https://discord.com/api/v9/channels/%s/messages", n.config.ChannelId)) + if err != nil { + return nil, fmt.Errorf("discord api error: failed to send request: %w", err) + } else if resp.IsError() { + return nil, fmt.Errorf("discord api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String()) + } + + return ¬ifier.NotifyResult{}, nil +} diff --git a/internal/pkg/core/notifier/providers/discordbot/discordbot_test.go b/internal/pkg/core/notifier/providers/discordbot/discordbot_test.go new file mode 100644 index 00000000..42edf95e --- /dev/null +++ b/internal/pkg/core/notifier/providers/discordbot/discordbot_test.go @@ -0,0 +1,64 @@ +package discordbot_test + +import ( + "context" + "flag" + "fmt" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/discordbot" +) + +const ( + mockSubject = "test_subject" + mockMessage = "test_message" +) + +var ( + fApiToken string + fChannelId string +) + +func init() { + argsPrefix := "CERTIMATE_NOTIFIER_DISCORDBOT_" + + flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "") + flag.StringVar(&fChannelId, argsPrefix+"CHANNELID", 0, "") +} + +/* +Shell command to run this test: + + go test -v ./discordbot_test.go -args \ + --CERTIMATE_NOTIFIER_DISCORDBOT_APITOKEN="your-bot-token" \ + --CERTIMATE_NOTIFIER_DISCORDBOT_CHANNELID="your-channel-id" +*/ +func TestNotify(t *testing.T) { + flag.Parse() + + t.Run("Notify", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("APITOKEN: %v", fApiToken), + fmt.Sprintf("CHANNELID: %v", fChannelId), + }, "\n")) + + notifier, err := provider.NewNotifier(&provider.NotifierConfig{ + BotToken: fApiToken, + ChannelId: fChannelId, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + res, err := notifier.Notify(context.Background(), mockSubject, mockMessage) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/internal/pkg/core/notifier/providers/telegrambot/telegrambot_test.go b/internal/pkg/core/notifier/providers/telegrambot/telegrambot_test.go index 3a207384..8dc18b95 100644 --- a/internal/pkg/core/notifier/providers/telegrambot/telegrambot_test.go +++ b/internal/pkg/core/notifier/providers/telegrambot/telegrambot_test.go @@ -17,14 +17,14 @@ const ( var ( fApiToken string - fChartId int64 + fChatId int64 ) func init() { argsPrefix := "CERTIMATE_NOTIFIER_TELEGRAMBOT_" flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "") - flag.Int64Var(&fChartId, argsPrefix+"CHATID", 0, "") + flag.Int64Var(&fChatId, argsPrefix+"CHATID", 0, "") } /* @@ -41,12 +41,12 @@ func TestNotify(t *testing.T) { t.Log(strings.Join([]string{ "args:", fmt.Sprintf("APITOKEN: %v", fApiToken), - fmt.Sprintf("CHATID: %v", fChartId), + fmt.Sprintf("CHATID: %v", fChatId), }, "\n")) notifier, err := provider.NewNotifier(&provider.NotifierConfig{ BotToken: fApiToken, - ChatId: fChartId, + ChatId: fChatId, }) if err != nil { t.Errorf("err: %+v", err) diff --git a/ui/public/imgs/providers/discord.svg b/ui/public/imgs/providers/discord.svg new file mode 100644 index 00000000..04f8f5e9 --- /dev/null +++ b/ui/public/imgs/providers/discord.svg @@ -0,0 +1 @@ + diff --git a/ui/src/components/access/AccessForm.tsx b/ui/src/components/access/AccessForm.tsx index baea8ed8..2a28aaac 100644 --- a/ui/src/components/access/AccessForm.tsx +++ b/ui/src/components/access/AccessForm.tsx @@ -31,6 +31,7 @@ import AccessFormCMCCCloudConfig from "./AccessFormCMCCCloudConfig"; import AccessFormDeSECConfig from "./AccessFormDeSECConfig"; import AccessFormDigitalOceanConfig from "./AccessFormDigitalOceanConfig"; import AccessFormDingTalkBotConfig from "./AccessFormDingTalkBotConfig"; +import AccessFormDiscordBotConfig from "./AccessFormDiscordBotConfig"; import AccessFormDNSLAConfig from "./AccessFormDNSLAConfig"; import AccessFormDogeCloudConfig from "./AccessFormDogeCloudConfig"; import AccessFormDuckDNSConfig from "./AccessFormDuckDNSConfig"; @@ -222,6 +223,8 @@ const AccessForm = forwardRef(({ className, return ; case ACCESS_PROVIDERS.DINGTALKBOT: return ; + case ACCESS_PROVIDERS.DISCORDBOT: + return ; case ACCESS_PROVIDERS.DNSLA: return ; case ACCESS_PROVIDERS.DOGECLOUD: diff --git a/ui/src/components/access/AccessFormDiscordBotConfig.tsx b/ui/src/components/access/AccessFormDiscordBotConfig.tsx new file mode 100644 index 00000000..5f844ccc --- /dev/null +++ b/ui/src/components/access/AccessFormDiscordBotConfig.tsx @@ -0,0 +1,70 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForDiscordBot } from "@/domain/access"; + +type AccessFormDiscordBotConfigFieldValues = Nullish; + +export type AccessFormDiscordBotConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormDiscordBotConfigFieldValues; + onValuesChange?: (values: AccessFormDiscordBotConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormDiscordBotConfigFieldValues => { + return { + botToken: "", + }; +}; + +const AccessFormDiscordBotConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormDiscordBotConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + botToken: z + .string({ message: t("access.form.discordbot_token.placeholder") }) + .min(1, t("access.form.discordbot_token.placeholder")) + .max(256, t("common.errmsg.string_max", { max: 256 })), + defaultChannelId: z.string().nullish(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + + } + > + + +
+ ); +}; + +export default AccessFormDiscordBotConfig; diff --git a/ui/src/components/access/AccessFormTelegramBotConfig.tsx b/ui/src/components/access/AccessFormTelegramBotConfig.tsx index 3181c71d..a347610f 100644 --- a/ui/src/components/access/AccessFormTelegramBotConfig.tsx +++ b/ui/src/components/access/AccessFormTelegramBotConfig.tsx @@ -26,8 +26,8 @@ const AccessFormTelegramBotConfig = ({ form: formInst, formName, disabled, initi const formSchema = z.object({ botToken: z - .string({ message: t("access.form.telegram_bot_token.placeholder") }) - .min(1, t("access.form.telegram_bot_token.placeholder")) + .string({ message: t("access.form.telegrambot_token.placeholder") }) + .min(1, t("access.form.telegrambot_token.placeholder")) .max(256, t("common.errmsg.string_max", { max: 256 })), defaultChatId: z .preprocess( @@ -38,7 +38,7 @@ const AccessFormTelegramBotConfig = ({ form: formInst, formName, disabled, initi .refine((v) => { if (v == null || v + "" === "") return true; return !Number.isNaN(+v!) && +v! !== 0; - }, t("access.form.telegram_bot_default_chat_id.placeholder")) + }, t("access.form.telegrambot_default_chat_id.placeholder")) ) .nullish(), }); @@ -59,20 +59,20 @@ const AccessFormTelegramBotConfig = ({ form: formInst, formName, disabled, initi > } + tooltip={} > - + } + tooltip={} > - + ); diff --git a/ui/src/components/workflow/node/NotifyNodeConfigForm.tsx b/ui/src/components/workflow/node/NotifyNodeConfigForm.tsx index d303c2ba..44a4a604 100644 --- a/ui/src/components/workflow/node/NotifyNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/NotifyNodeConfigForm.tsx @@ -17,6 +17,7 @@ import { useAntdForm, useAntdFormName, useZustandShallowSelector } from "@/hooks import { useAccessesStore } from "@/stores/access"; import { useNotifyChannelsStore } from "@/stores/notify"; +import NotifyNodeConfigFormDiscordBotConfig from "./NotifyNodeConfigFormDiscordBotConfig"; import NotifyNodeConfigFormEmailConfig from "./NotifyNodeConfigFormEmailConfig"; import NotifyNodeConfigFormMattermostConfig from "./NotifyNodeConfigFormMattermostConfig"; import NotifyNodeConfigFormTelegramBotConfig from "./NotifyNodeConfigFormTelegramBotConfig"; @@ -110,6 +111,8 @@ const NotifyNodeConfigForm = forwardRef; case NOTIFICATION_PROVIDERS.EMAIL: return ; case NOTIFICATION_PROVIDERS.MATTERMOST: diff --git a/ui/src/components/workflow/node/NotifyNodeConfigFormDiscordBotConfig.tsx b/ui/src/components/workflow/node/NotifyNodeConfigFormDiscordBotConfig.tsx new file mode 100644 index 00000000..200f2684 --- /dev/null +++ b/ui/src/components/workflow/node/NotifyNodeConfigFormDiscordBotConfig.tsx @@ -0,0 +1,61 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +type NotifyNodeConfigFormDiscordBotConfigFieldValues = Nullish<{ + channelId?: string; +}>; + +export type NotifyNodeConfigFormDiscordBotConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: NotifyNodeConfigFormDiscordBotConfigFieldValues; + onValuesChange?: (values: NotifyNodeConfigFormDiscordBotConfigFieldValues) => void; +}; + +const initFormModel = (): NotifyNodeConfigFormDiscordBotConfigFieldValues => { + return {}; +}; + +const NotifyNodeConfigFormDiscordBotConfig = ({ + form: formInst, + formName, + disabled, + initialValues, + onValuesChange, +}: NotifyNodeConfigFormDiscordBotConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + channelId: z.string().nullish(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + +
+ ); +}; + +export default NotifyNodeConfigFormDiscordBotConfig; diff --git a/ui/src/components/workflow/node/NotifyNodeConfigFormTelegramBotConfig.tsx b/ui/src/components/workflow/node/NotifyNodeConfigFormTelegramBotConfig.tsx index a40142ee..29eaa807 100644 --- a/ui/src/components/workflow/node/NotifyNodeConfigFormTelegramBotConfig.tsx +++ b/ui/src/components/workflow/node/NotifyNodeConfigFormTelegramBotConfig.tsx @@ -38,7 +38,7 @@ const NotifyNodeConfigFormTelegramBotConfig = ({ .refine((v) => { if (v == null || v + "" === "") return true; return !Number.isNaN(+v!) && +v! !== 0; - }, t("workflow_node.notify.form.telegram_bot_chat_id.placeholder")) + }, t("workflow_node.notify.form.telegrambot_chat_id.placeholder")) ) .nullish(), }); @@ -59,11 +59,11 @@ const NotifyNodeConfigFormTelegramBotConfig = ({ > } + tooltip={} > - + ); diff --git a/ui/src/domain/access.ts b/ui/src/domain/access.ts index 9e2d4f70..9e953963 100644 --- a/ui/src/domain/access.ts +++ b/ui/src/domain/access.ts @@ -26,6 +26,7 @@ export interface AccessModel extends BaseModel { | AccessConfigForDeSEC | AccessConfigForDigitalOcean | AccessConfigForDingTalkBot + | AccessConfigForDiscordBot | AccessConfigForDNSLA | AccessConfigForDogeCloud | AccessConfigForDuckDNS @@ -181,6 +182,11 @@ export type AccessConfigForDingTalkBot = { secret?: string; }; +export type AccessConfigForDiscordBot = { + botToken: string; + defaultChannelId?: string; +}; + export type AccessConfigForDNSLA = { apiId: string; apiSecret: string; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index 6576aa94..806c8283 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -25,6 +25,7 @@ export const ACCESS_PROVIDERS = Object.freeze({ DESEC: "desec", DIGITALOCEAN: "digitalocean", DINGTALKBOT: "dingtalkbot", + DISCORDBOT: "discordbot", DNSLA: "dnsla", DOGECLOUD: "dogecloud", DUCKDNS: "duckdns", @@ -172,8 +173,9 @@ export const accessProvidersMap: Map [ e[0] as string, { @@ -588,6 +590,7 @@ export const deploymentProvidersMap: Map [ type, { diff --git a/ui/src/i18n/locales/en/nls.access.json b/ui/src/i18n/locales/en/nls.access.json index 31772bf5..fe437f87 100644 --- a/ui/src/i18n/locales/en/nls.access.json +++ b/ui/src/i18n/locales/en/nls.access.json @@ -161,6 +161,12 @@ "access.form.dingtalkbot_secret.label": "DingTalk bot secret", "access.form.dingtalkbot_secret.placeholder": "Please enter DingTalk bot secret", "access.form.dingtalkbot_secret.tooltip": "For more information, see https://open.dingtalk.com/document/orgapp/customize-robot-security-settings", + "access.form.discordbot_token.label": "Discord bot token", + "access.form.discordbot_token.placeholder": "Please enter Discord bot token", + "access.form.discordbot_token.tooltip": "How to get it? Please refer to https://docs.discordbotstudio.org/setting-up-dbs/finding-your-bot-token", + "access.form.discordbot_default_channel_id.label": "Default Discord channel ID (Optional)", + "access.form.discordbot_default_channel_id.placeholder": "Please enter default Discord channel ID", + "access.form.discordbot_default_channel_id.tooltip": "For more information, see https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID", "access.form.dnsla_api_id.label": "DNS.LA API ID", "access.form.dnsla_api_id.placeholder": "Please enter DNS.LA API ID", "access.form.dnsla_api_id.tooltip": "For more information, see https://www.dns.la/docs/ApiDoc", @@ -284,7 +290,7 @@ "access.form.mattermost_password.placeholder": "Please enter Mattermost password", "access.form.mattermost_default_channel_id.label": "Default Mattermost channel ID (Optional)", "access.form.mattermost_default_channel_id.placeholder": "Please enter default Mattermost channel ID", - "access.form.mattermost_default_channel_id.tooltip": "How to get the channel ID? Select the target channel from the left sidebar, click on the channel name at the top, and choose ”Channel Details.” You can directly see the channel ID on the pop-up page.", + "access.form.mattermost_default_channel_id.tooltip": "How to get it? Select the target channel from the left sidebar, click on the channel name at the top, and choose ”Channel Details.” You can directly see the channel ID on the pop-up page.", "access.form.namecheap_username.label": "Namecheap username", "access.form.namecheap_username.placeholder": "Please enter Namecheap username", "access.form.namecheap_username.tooltip": "For more information, see https://www.namecheap.com/support/api/intro/", @@ -380,12 +386,12 @@ "access.form.sslcom_eab_hmac_key.label": "ACME EAB HMAC key", "access.form.sslcom_eab_hmac_key.placeholder": "Please enter ACME EAB HMAC key", "access.form.sslcom_eab_hmac_key.tooltip": "For more information, see https://www.ssl.com/how-to/generate-acme-credentials-for-reseller-customers/", - "access.form.telegram_bot_token.label": "Telegram bot token", - "access.form.telegram_bot_token.placeholder": "Please enter Telegram bot token", - "access.form.telegram_bot_token.tooltip": "How to get the bot token? Please refer to https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a", - "access.form.telegram_bot_default_chat_id.label": "Default Telegram chat ID (Optional)", - "access.form.telegram_bot_default_chat_id.placeholder": "Please enter default Telegram chat ID", - "access.form.telegram_bot_default_chat_id.tooltip": "How to get the chat ID? Please refer to https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a", + "access.form.telegrambot_token.label": "Telegram bot token", + "access.form.telegrambot_token.placeholder": "Please enter Telegram bot token", + "access.form.telegrambot_token.tooltip": "How to get it? Please refer to https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a", + "access.form.telegrambot_default_chat_id.label": "Default Telegram chat ID (Optional)", + "access.form.telegrambot_default_chat_id.placeholder": "Please enter default Telegram chat ID", + "access.form.telegrambot_default_chat_id.tooltip": "How to get it? Please refer to https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a", "access.form.tencentcloud_secret_id.label": "Tencent Cloud SecretId", "access.form.tencentcloud_secret_id.placeholder": "Please enter Tencent Cloud SecretId", "access.form.tencentcloud_secret_id.tooltip": "For more information, see https://cloud.tencent.com/document/product/598/40488?lang=en", diff --git a/ui/src/i18n/locales/en/nls.provider.json b/ui/src/i18n/locales/en/nls.provider.json index 80cb65cf..b34c92a7 100644 --- a/ui/src/i18n/locales/en/nls.provider.json +++ b/ui/src/i18n/locales/en/nls.provider.json @@ -60,6 +60,7 @@ "provider.desec": "deSEC", "provider.digitalocean": "DigitalOcean", "provider.dingtalkbot": "DingTalk Bot", + "provider.discordbot": "Discord Bot", "provider.dnsla": "DNS.LA", "provider.dogecloud": "Doge Cloud", "provider.dogecloud.cdn": "Doge Cloud - CDN (Content Delivery Network)", diff --git a/ui/src/i18n/locales/en/nls.workflow.nodes.json b/ui/src/i18n/locales/en/nls.workflow.nodes.json index e0602370..172d707b 100644 --- a/ui/src/i18n/locales/en/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/en/nls.workflow.nodes.json @@ -815,6 +815,9 @@ "workflow_node.notify.form.provider_access.placeholder": "Please select an authorization of notification provider", "workflow_node.notify.form.provider_access.button": "Create", "workflow_node.notify.form.params_config.label": "Parameter settings", + "workflow_node.notify.form.discordbot_channel_id.label": "Discord channel ID (Optional)", + "workflow_node.notify.form.discordbot_channel_id.placeholder": "Please enter Discord channel ID to override the default value", + "workflow_node.notify.form.discordbot_channel_id.tooltip": "Leave it blank to use the default channel ID provided by the authorization.", "workflow_node.notify.form.email_sender_address.label": "Sender email address (Optional)", "workflow_node.notify.form.email_sender_address.placeholder": "Please enter sender email address to override the default value", "workflow_node.notify.form.email_sender_address.tooltip": "Leave it blank to use the default sender email address provided by the authorization.", @@ -822,11 +825,11 @@ "workflow_node.notify.form.email_receiver_address.placeholder": "Please enter receiver email address to override the default value", "workflow_node.notify.form.email_receiver_address.tooltip": "Leave it blank to use the default receiver email address provided by the selected authorization.", "workflow_node.notify.form.mattermost_channel_id.label": "Mattermost channel ID (Optional)", - "workflow_node.notify.form.mattermost_channel_id.placeholder": "Please enter Mattermost channel ID to override the default value", + "workflow_node.notify.form.mattermost_channel_id.placeholder": "Please enter Mattermost channel ID to override the default value", "workflow_node.notify.form.mattermost_channel_id.tooltip": "Leave it blank to use the default channel ID provided by the authorization.", - "workflow_node.notify.form.telegram_bot_chat_id.label": "Telegram chat ID (Optional)", - "workflow_node.notify.form.telegram_bot_chat_id.placeholder": "Please enter Telegram chat ID to override the default value", - "workflow_node.notify.form.telegram_bot_chat_id.tooltip": "Leave it blank to use the default chat ID provided by the selected authorization.", + "workflow_node.notify.form.telegrambot_chat_id.label": "Telegram chat ID (Optional)", + "workflow_node.notify.form.telegrambot_chat_id.placeholder": "Please enter Telegram chat ID to override the default value", + "workflow_node.notify.form.telegrambot_chat_id.tooltip": "Leave it blank to use the default chat ID provided by the selected authorization.", "workflow_node.notify.form.webhook_data.label": "Webhook data (Optional)", "workflow_node.notify.form.webhook_data.placeholder": "Please enter Webhook data to override the default value", "workflow_node.notify.form.webhook_data.tooltip": "Leave it blank to use the default Webhook data provided by the authorization.", diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index 1f538ac5..21ad79c5 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -155,6 +155,12 @@ "access.form.dingtalkbot_secret.label": "钉钉群机器人加签密钥", "access.form.dingtalkbot_secret.placeholder": "请输入钉钉群机器人加签密钥", "access.form.dingtalkbot_secret.tooltip": "这是什么?请参阅 https://open.dingtalk.com/document/orgapp/customize-robot-security-settings", + "access.form.discordbot_token.label": "Discord 机器人 API Token", + "access.form.discordbot_token.placeholder": "请输入 Discord 机器人 API Token", + "access.form.discordbot_token.tooltip": "如何获取此参数?请参阅 https://docs.discordbotstudio.org/setting-up-dbs/finding-your-bot-token", + "access.form.discordbot_default_channel_id.label": "默认的 Discord 频道 ID(可选)", + "access.form.discordbot_default_channel_id.placeholder": "请输入默认的 Discord 频道 ID", + "access.form.discordbot_default_channel_id.tooltip": "这是什么?请参阅 https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID", "access.form.dnsla_api_id.label": "DNS.LA API ID", "access.form.dnsla_api_id.placeholder": "请输入 DNS.LA API ID", "access.form.dnsla_api_id.tooltip": "这是什么?请参阅 https://www.dns.la/docs/ApiDoc", @@ -278,7 +284,7 @@ "access.form.mattermost_password.placeholder": "请输入 Mattermost 密码", "access.form.mattermost_default_channel_id.label": "默认的 Mattermost 频道 ID(可选)", "access.form.mattermost_default_channel_id.placeholder": "请输入默认的 Mattermost 频道 ID", - "access.form.mattermost_default_channel_id.tooltip": "如何获取频道 ID?从左侧边栏中选择目标频道,点击顶部的频道名称,选择“频道详情”,即可在弹出页面中直接看到频道 ID。", + "access.form.mattermost_default_channel_id.tooltip": "如何获取此参数?从左侧边栏中选择目标频道,点击顶部的频道名称,选择“频道详情”,即可在弹出页面中直接看到频道 ID。", "access.form.namecheap_username.label": "Namecheap 用户名", "access.form.namecheap_username.placeholder": "请输入 Namecheap 用户名", "access.form.namecheap_username.tooltip": "这是什么?请参阅 https://www.namecheap.com/support/api/intro/", @@ -374,12 +380,12 @@ "access.form.sslcom_eab_hmac_key.label": "ACME EAB HMAC key", "access.form.sslcom_eab_hmac_key.placeholder": "请输入 ACME EAB HMAC key", "access.form.sslcom_eab_hmac_key.tooltip": "这是什么?请参阅 https://www.ssl.com/how-to/generate-acme-credentials-for-reseller-customers/", - "access.form.telegram_bot_token.label": "Telegram 群机器人 API Token", - "access.form.telegram_bot_token.placeholder": "请输入 Telegram 群机器人 API Token", - "access.form.telegram_bot_token.tooltip": "如何获取机器人 API Token?请参阅 https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a", - "access.form.telegram_bot_default_chat_id.label": "默认的 Telegram 会话 ID(可选)", - "access.form.telegram_bot_default_chat_id.placeholder": "请输入默认的 Telegram 会话 ID", - "access.form.telegram_bot_default_chat_id.tooltip": "如何获取会话 ID?请参阅 https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a", + "access.form.telegrambot_token.label": "Telegram 机器人 API Token", + "access.form.telegrambot_token.placeholder": "请输入 Telegram 机器人 API Token", + "access.form.telegrambot_token.tooltip": "如何获取此参数?请参阅 https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a", + "access.form.telegrambot_default_chat_id.label": "默认的 Telegram 会话 ID(可选)", + "access.form.telegrambot_default_chat_id.placeholder": "请输入默认的 Telegram 会话 ID", + "access.form.telegrambot_default_chat_id.tooltip": "如何获取此参数?请参阅 https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a", "access.form.tencentcloud_secret_id.label": "腾讯云 SecretId", "access.form.tencentcloud_secret_id.placeholder": "请输入腾讯云 SecretId", "access.form.tencentcloud_secret_id.tooltip": "这是什么?请参阅 https://cloud.tencent.com/document/product/598/40488", diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json index 8de1ccf5..dd12aa27 100644 --- a/ui/src/i18n/locales/zh/nls.provider.json +++ b/ui/src/i18n/locales/zh/nls.provider.json @@ -60,6 +60,7 @@ "provider.desec": "deSEC", "provider.digitalocean": "DigitalOcean", "provider.dingtalkbot": "钉钉群机器人", + "provider.discordbot": "Discord 机器人", "provider.dnsla": "DNS.LA", "provider.dogecloud": "多吉云", "provider.dogecloud.cdn": "多吉云 - 内容分发网络 CDN", @@ -119,7 +120,7 @@ "provider.safeline": "雷池", "provider.ssh": "SSH 部署", "provider.sslcom": "SSL.com", - "provider.telegrambot": "Telegram 群机器人", + "provider.telegrambot": "Telegram 机器人", "provider.tencentcloud": "腾讯云", "provider.tencentcloud.cdn": "腾讯云 - 内容分发网络 CDN", "provider.tencentcloud.clb": "腾讯云 - 负载均衡 CLB", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index 2dbcb3ca..b6d27dc7 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -814,6 +814,9 @@ "workflow_node.notify.form.provider_access.placeholder": "请选择通知渠道授权", "workflow_node.notify.form.provider_access.button": "新建", "workflow_node.notify.form.params_config.label": "参数设置", + "workflow_node.notify.form.discordbot_channel_id.label": "Discord 频道 ID(可选)", + "workflow_node.notify.form.discordbot_channel_id.placeholder": "请输入 Discord 频道 ID 以覆盖默认值", + "workflow_node.notify.form.discordbot_channel_id.tooltip": "不填写时,将使用所选通知渠道授权的默认频道 ID。", "workflow_node.notify.form.email_sender_address.label": "发送邮箱地址(可选)", "workflow_node.notify.form.email_sender_address.placeholder": "请输入发送邮箱地址以覆盖默认值", "workflow_node.notify.form.email_sender_address.tooltip": "不填写时,将使用所选通知渠道授权的默认发送邮箱地址。", @@ -823,9 +826,9 @@ "workflow_node.notify.form.mattermost_channel_id.label": "Mattermost 频道 ID(可选)", "workflow_node.notify.form.mattermost_channel_id.placeholder": "请输入 Mattermost 频道 ID 以覆盖默认值", "workflow_node.notify.form.mattermost_channel_id.tooltip": "不填写时,将使用所选通知渠道授权的默认频道 ID。", - "workflow_node.notify.form.telegram_bot_chat_id.label": "Telegram 会话 ID(可选)", - "workflow_node.notify.form.telegram_bot_chat_id.placeholder": "请输入 Telegram 会话 ID 以覆盖默认值", - "workflow_node.notify.form.telegram_bot_chat_id.tooltip": "不填写时,将使用所选通知渠道授权的默认会话 ID。", + "workflow_node.notify.form.telegrambot_chat_id.label": "Telegram 会话 ID(可选)", + "workflow_node.notify.form.telegrambot_chat_id.placeholder": "请输入 Telegram 会话 ID 以覆盖默认值", + "workflow_node.notify.form.telegrambot_chat_id.tooltip": "不填写时,将使用所选通知渠道授权的默认会话 ID。", "workflow_node.notify.form.webhook_data.label": "Webhook 回调数据(可选)", "workflow_node.notify.form.webhook_data.placeholder": "请输入 Webhook 回调数据以覆盖默认值", "workflow_node.notify.form.webhook_data.tooltip": "不填写时,将使用所选部署目标授权的默认 Webhook 回调数据。", From e82a59289b2537ee3ee31c24a1823c9e5bb4033e Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Mon, 26 May 2025 16:41:16 +0800 Subject: [PATCH 08/11] feat: new notification provider: slack bot --- internal/domain/access.go | 5 ++ internal/domain/provider.go | 2 + internal/notify/providers.go | 14 ++++ .../pkg/core/notifier/providers/bark/bark.go | 1 + .../providers/discordbot/discordbot.go | 1 + .../core/notifier/providers/gotify/gotify.go | 1 + .../providers/mattermost/mattermost.go | 2 + .../notifier/providers/pushover/pushover.go | 1 + .../notifier/providers/pushplus/pushplus.go | 1 + .../providers/serverchan/serverchan.go | 1 + .../notifier/providers/slackbot/slackbot.go | 70 ++++++++++++++++++ .../providers/slackbot/slackbot_test.go | 64 +++++++++++++++++ .../providers/telegrambot/telegrambot.go | 1 + .../notifier/providers/webhook/webhook.go | 2 +- .../notifier/providers/wecombot/wecombot.go | 1 + ui/public/imgs/providers/slack.svg | 1 + ui/src/components/access/AccessForm.tsx | 3 + .../access/AccessFormDiscordBotConfig.tsx | 3 +- .../access/AccessFormSlackBotConfig.tsx | 71 +++++++++++++++++++ .../access/AccessFormTelegramBotConfig.tsx | 3 +- .../workflow/node/NotifyNodeConfigForm.tsx | 3 + .../NotifyNodeConfigFormSlackBotConfig.tsx | 55 ++++++++++++++ ui/src/domain/access.ts | 6 ++ ui/src/domain/provider.ts | 4 ++ ui/src/i18n/locales/en/nls.access.json | 8 ++- ui/src/i18n/locales/en/nls.provider.json | 7 +- .../i18n/locales/en/nls.workflow.nodes.json | 3 + ui/src/i18n/locales/zh/nls.access.json | 8 ++- ui/src/i18n/locales/zh/nls.provider.json | 7 +- .../i18n/locales/zh/nls.workflow.nodes.json | 3 + 30 files changed, 341 insertions(+), 11 deletions(-) create mode 100644 internal/pkg/core/notifier/providers/slackbot/slackbot.go create mode 100644 internal/pkg/core/notifier/providers/slackbot/slackbot_test.go create mode 100644 ui/public/imgs/providers/slack.svg create mode 100644 ui/src/components/access/AccessFormSlackBotConfig.tsx create mode 100644 ui/src/components/workflow/node/NotifyNodeConfigFormSlackBotConfig.tsx diff --git a/internal/domain/access.go b/internal/domain/access.go index 4e002ecf..482f753a 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -300,6 +300,11 @@ type AccessConfigForSafeLine struct { AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` } +type AccessConfigForSlackBot struct { + BotToken string `json:"botToken"` + DefaultChannelId string `json:"defaultChannelId,omitempty"` +} + type AccessConfigForSSH struct { Host string `json:"host"` Port int32 `json:"port"` diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 8f5c959a..c8cb37d5 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -71,6 +71,7 @@ const ( AccessProviderTypeRainYun = AccessProviderType("rainyun") AccessProviderTypeRatPanel = AccessProviderType("ratpanel") AccessProviderTypeSafeLine = AccessProviderType("safeline") + AccessProviderTypeSlackBot = AccessProviderType("slackbot") AccessProviderTypeSSH = AccessProviderType("ssh") AccessProviderTypeSSLCOM = AccessProviderType("sslcom") AccessProviderTypeTelegramBot = AccessProviderType("telegrambot") @@ -274,6 +275,7 @@ const ( NotificationProviderTypeEmail = NotificationProviderType(AccessProviderTypeEmail) NotificationProviderTypeLarkBot = NotificationProviderType(AccessProviderTypeLarkBot) NotificationProviderTypeMattermost = NotificationProviderType(AccessProviderTypeMattermost) + NotificationProviderTypeSlackBot = NotificationProviderType(AccessProviderTypeSlackBot) NotificationProviderTypeTelegramBot = NotificationProviderType(AccessProviderTypeTelegramBot) NotificationProviderTypeWebhook = NotificationProviderType(AccessProviderTypeWebhook) NotificationProviderTypeWeComBot = NotificationProviderType(AccessProviderTypeWeComBot) diff --git a/internal/notify/providers.go b/internal/notify/providers.go index 23f5bb43..7dc63465 100644 --- a/internal/notify/providers.go +++ b/internal/notify/providers.go @@ -11,6 +11,7 @@ import ( pEmail "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email" pLarkBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/larkbot" pMattermost "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/mattermost" + pSlackBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/slackbot" pTelegramBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/telegrambot" pWebhook "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/webhook" pWeComBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/wecombot" @@ -101,6 +102,19 @@ func createNotifierProvider(options *notifierProviderOptions) (notifier.Notifier }) } + case domain.NotificationProviderTypeSlackBot: + { + access := domain.AccessConfigForSlackBot{} + if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + return pSlackBot.NewNotifier(&pSlackBot.NotifierConfig{ + BotToken: access.BotToken, + ChannelId: maputil.GetOrDefaultString(options.ProviderServiceConfig, "channelId", access.DefaultChannelId), + }) + } + case domain.NotificationProviderTypeTelegramBot: { access := domain.AccessConfigForTelegramBot{} diff --git a/internal/pkg/core/notifier/providers/bark/bark.go b/internal/pkg/core/notifier/providers/bark/bark.go index 97ece0be..ec0d44f3 100644 --- a/internal/pkg/core/notifier/providers/bark/bark.go +++ b/internal/pkg/core/notifier/providers/bark/bark.go @@ -58,6 +58,7 @@ func (n *NotifierProvider) Notify(ctx context.Context, subject string, message s // REF: https://bark.day.app/#/tutorial req := n.httpClient.R(). + SetContext(ctx). SetHeader("Content-Type", "application/json"). SetBody(map[string]any{ "title": subject, diff --git a/internal/pkg/core/notifier/providers/discordbot/discordbot.go b/internal/pkg/core/notifier/providers/discordbot/discordbot.go index dbffaba7..3ed0cab7 100644 --- a/internal/pkg/core/notifier/providers/discordbot/discordbot.go +++ b/internal/pkg/core/notifier/providers/discordbot/discordbot.go @@ -51,6 +51,7 @@ func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier { func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { // REF: https://discord.com/developers/docs/resources/message#create-message req := n.httpClient.R(). + SetContext(ctx). SetHeader("Content-Type", "application/json"). SetHeader("Authorization", "Bot "+n.config.BotToken). SetBody(map[string]any{ diff --git a/internal/pkg/core/notifier/providers/gotify/gotify.go b/internal/pkg/core/notifier/providers/gotify/gotify.go index 81dcb8ad..c82cd5a5 100644 --- a/internal/pkg/core/notifier/providers/gotify/gotify.go +++ b/internal/pkg/core/notifier/providers/gotify/gotify.go @@ -56,6 +56,7 @@ func (n *NotifierProvider) Notify(ctx context.Context, subject string, message s // REF: https://gotify.net/api-docs#/message/createMessage req := n.httpClient.R(). + SetContext(ctx). SetHeader("Content-Type", "application/json"). SetHeader("Authorization", "Bearer "+n.config.Token). SetBody(map[string]any{ diff --git a/internal/pkg/core/notifier/providers/mattermost/mattermost.go b/internal/pkg/core/notifier/providers/mattermost/mattermost.go index 8e4fb24d..81283f7c 100644 --- a/internal/pkg/core/notifier/providers/mattermost/mattermost.go +++ b/internal/pkg/core/notifier/providers/mattermost/mattermost.go @@ -58,6 +58,7 @@ func (n *NotifierProvider) Notify(ctx context.Context, subject string, message s // REF: https://developers.mattermost.com/api-documentation/#/operations/Login loginReq := n.httpClient.R(). + SetContext(ctx). SetHeader("Content-Type", "application/json"). SetBody(map[string]any{ "login_id": n.config.Username, @@ -74,6 +75,7 @@ func (n *NotifierProvider) Notify(ctx context.Context, subject string, message s // REF: https://developers.mattermost.com/api-documentation/#/operations/CreatePost postReq := n.httpClient.R(). + SetContext(ctx). SetHeader("Content-Type", "application/json"). SetHeader("Authorization", "Bearer "+loginResp.Header().Get("Token")). SetBody(map[string]any{ diff --git a/internal/pkg/core/notifier/providers/pushover/pushover.go b/internal/pkg/core/notifier/providers/pushover/pushover.go index b7f74bba..827a45d6 100644 --- a/internal/pkg/core/notifier/providers/pushover/pushover.go +++ b/internal/pkg/core/notifier/providers/pushover/pushover.go @@ -51,6 +51,7 @@ func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier { func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { // REF: https://pushover.net/api req := n.httpClient.R(). + SetContext(ctx). SetHeader("Content-Type", "application/json"). SetBody(map[string]any{ "title": subject, diff --git a/internal/pkg/core/notifier/providers/pushplus/pushplus.go b/internal/pkg/core/notifier/providers/pushplus/pushplus.go index 834f9683..79a27d49 100644 --- a/internal/pkg/core/notifier/providers/pushplus/pushplus.go +++ b/internal/pkg/core/notifier/providers/pushplus/pushplus.go @@ -50,6 +50,7 @@ func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier { func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { // REF: https://pushplus.plus/doc/guide/api.html#%E4%B8%80%E3%80%81%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF%E6%8E%A5%E5%8F%A3 req := n.httpClient.R(). + SetContext(ctx). SetHeader("Content-Type", "application/json"). SetBody(map[string]any{ "title": subject, diff --git a/internal/pkg/core/notifier/providers/serverchan/serverchan.go b/internal/pkg/core/notifier/providers/serverchan/serverchan.go index d74b2fcc..d1897ab4 100644 --- a/internal/pkg/core/notifier/providers/serverchan/serverchan.go +++ b/internal/pkg/core/notifier/providers/serverchan/serverchan.go @@ -49,6 +49,7 @@ func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier { func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { // REF: https://sct.ftqq.com/ req := n.httpClient.R(). + SetContext(ctx). SetHeader("Content-Type", "application/json"). SetBody(map[string]any{ "text": subject, diff --git a/internal/pkg/core/notifier/providers/slackbot/slackbot.go b/internal/pkg/core/notifier/providers/slackbot/slackbot.go new file mode 100644 index 00000000..7b16ad25 --- /dev/null +++ b/internal/pkg/core/notifier/providers/slackbot/slackbot.go @@ -0,0 +1,70 @@ +package discordbot + +import ( + "context" + "fmt" + "log/slog" + + "github.com/go-resty/resty/v2" + + "github.com/usual2970/certimate/internal/pkg/core/notifier" +) + +type NotifierConfig struct { + // Slack Bot API Token。 + BotToken string `json:"botToken"` + // Slack Channel ID。 + ChannelId string `json:"channelId"` +} + +type NotifierProvider struct { + config *NotifierConfig + logger *slog.Logger + httpClient *resty.Client +} + +var _ notifier.Notifier = (*NotifierProvider)(nil) + +func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) { + if config == nil { + panic("config is nil") + } + + client := resty.New() + + return &NotifierProvider{ + config: config, + logger: slog.Default(), + httpClient: client, + }, nil +} + +func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier { + if logger == nil { + n.logger = slog.Default() + } else { + n.logger = logger + } + return n +} + +func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { + // REF: https://docs.slack.dev/messaging/sending-and-scheduling-messages#publishing + req := n.httpClient.R(). + SetContext(ctx). + SetHeader("Content-Type", "application/json"). + SetHeader("Authorization", "Bearer "+n.config.BotToken). + SetBody(map[string]any{ + "token": n.config.BotToken, + "channel": n.config.ChannelId, + "text": subject + "\n" + message, + }) + resp, err := req.Post("https://slack.com/api/chat.postMessage") + if err != nil { + return nil, fmt.Errorf("slack api error: failed to send request: %w", err) + } else if resp.IsError() { + return nil, fmt.Errorf("slack api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String()) + } + + return ¬ifier.NotifyResult{}, nil +} diff --git a/internal/pkg/core/notifier/providers/slackbot/slackbot_test.go b/internal/pkg/core/notifier/providers/slackbot/slackbot_test.go new file mode 100644 index 00000000..356ef71f --- /dev/null +++ b/internal/pkg/core/notifier/providers/slackbot/slackbot_test.go @@ -0,0 +1,64 @@ +package discordbot_test + +import ( + "context" + "flag" + "fmt" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/slackbot" +) + +const ( + mockSubject = "test_subject" + mockMessage = "test_message" +) + +var ( + fApiToken string + fChannelId string +) + +func init() { + argsPrefix := "CERTIMATE_NOTIFIER_SLACKBOT_" + + flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "") + flag.StringVar(&fChannelId, argsPrefix+"CHANNELID", 0, "") +} + +/* +Shell command to run this test: + + go test -v ./slackbot_test.go -args \ + --CERTIMATE_NOTIFIER_SLACKBOT_APITOKEN="your-bot-token" \ + --CERTIMATE_NOTIFIER_SLACKBOT_CHANNELID="your-channel-id" +*/ +func TestNotify(t *testing.T) { + flag.Parse() + + t.Run("Notify", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("APITOKEN: %v", fApiToken), + fmt.Sprintf("CHANNELID: %v", fChannelId), + }, "\n")) + + notifier, err := provider.NewNotifier(&provider.NotifierConfig{ + BotToken: fApiToken, + ChannelId: fChannelId, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + res, err := notifier.Notify(context.Background(), mockSubject, mockMessage) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/internal/pkg/core/notifier/providers/telegrambot/telegrambot.go b/internal/pkg/core/notifier/providers/telegrambot/telegrambot.go index 99b86a38..39e1f705 100644 --- a/internal/pkg/core/notifier/providers/telegrambot/telegrambot.go +++ b/internal/pkg/core/notifier/providers/telegrambot/telegrambot.go @@ -51,6 +51,7 @@ func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier { func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { // REF: https://core.telegram.org/bots/api#sendmessage req := n.httpClient.R(). + SetContext(ctx). SetHeader("Content-Type", "application/json"). SetBody(map[string]any{ "chat_id": n.config.ChatId, diff --git a/internal/pkg/core/notifier/providers/webhook/webhook.go b/internal/pkg/core/notifier/providers/webhook/webhook.go index 5f62f170..8850ea73 100644 --- a/internal/pkg/core/notifier/providers/webhook/webhook.go +++ b/internal/pkg/core/notifier/providers/webhook/webhook.go @@ -139,7 +139,7 @@ func (n *NotifierProvider) Notify(ctx context.Context, subject string, message s // 生成请求 // 其中 GET 请求需转换为查询参数 - req := n.httpClient.R().SetHeaderMultiValues(webhookHeaders) + req := n.httpClient.R().SetContext(ctx).SetHeaderMultiValues(webhookHeaders) req.URL = webhookUrl.String() req.Method = webhookMethod if webhookMethod == http.MethodGet { diff --git a/internal/pkg/core/notifier/providers/wecombot/wecombot.go b/internal/pkg/core/notifier/providers/wecombot/wecombot.go index 36c179d4..8f51a70a 100644 --- a/internal/pkg/core/notifier/providers/wecombot/wecombot.go +++ b/internal/pkg/core/notifier/providers/wecombot/wecombot.go @@ -49,6 +49,7 @@ func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier { func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { // REF: https://developer.work.weixin.qq.com/document/path/91770 req := n.httpClient.R(). + SetContext(ctx). SetHeader("Content-Type", "application/json"). SetBody(map[string]any{ "msgtype": "text", diff --git a/ui/public/imgs/providers/slack.svg b/ui/public/imgs/providers/slack.svg new file mode 100644 index 00000000..100af3d4 --- /dev/null +++ b/ui/public/imgs/providers/slack.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ui/src/components/access/AccessForm.tsx b/ui/src/components/access/AccessForm.tsx index 2a28aaac..c8c03290 100644 --- a/ui/src/components/access/AccessForm.tsx +++ b/ui/src/components/access/AccessForm.tsx @@ -64,6 +64,7 @@ import AccessFormQiniuConfig from "./AccessFormQiniuConfig"; import AccessFormRainYunConfig from "./AccessFormRainYunConfig"; import AccessFormRatPanelConfig from "./AccessFormRatPanelConfig"; import AccessFormSafeLineConfig from "./AccessFormSafeLineConfig"; +import AccessFormSlackBotConfig from "./AccessFormSlackBotConfig"; import AccessFormSSHConfig from "./AccessFormSSHConfig"; import AccessFormSSLComConfig from "./AccessFormSSLComConfig"; import AccessFormTelegramBotConfig from "./AccessFormTelegramBotConfig"; @@ -289,6 +290,8 @@ const AccessForm = forwardRef(({ className, return ; case ACCESS_PROVIDERS.SAFELINE: return ; + case ACCESS_PROVIDERS.SLACKBOT: + return ; case ACCESS_PROVIDERS.SSH: return ; case ACCESS_PROVIDERS.TELEGRAMBOT: diff --git a/ui/src/components/access/AccessFormDiscordBotConfig.tsx b/ui/src/components/access/AccessFormDiscordBotConfig.tsx index 5f844ccc..16848686 100644 --- a/ui/src/components/access/AccessFormDiscordBotConfig.tsx +++ b/ui/src/components/access/AccessFormDiscordBotConfig.tsx @@ -28,7 +28,8 @@ const AccessFormDiscordBotConfig = ({ form: formInst, formName, disabled, initia botToken: z .string({ message: t("access.form.discordbot_token.placeholder") }) .min(1, t("access.form.discordbot_token.placeholder")) - .max(256, t("common.errmsg.string_max", { max: 256 })), + .max(256, t("common.errmsg.string_max", { max: 256 })) + .trim(), defaultChannelId: z.string().nullish(), }); const formRule = createSchemaFieldRule(formSchema); diff --git a/ui/src/components/access/AccessFormSlackBotConfig.tsx b/ui/src/components/access/AccessFormSlackBotConfig.tsx new file mode 100644 index 00000000..3bea5f58 --- /dev/null +++ b/ui/src/components/access/AccessFormSlackBotConfig.tsx @@ -0,0 +1,71 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForSlackBot } from "@/domain/access"; + +type AccessFormSlackBotConfigFieldValues = Nullish; + +export type AccessFormSlackBotConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormSlackBotConfigFieldValues; + onValuesChange?: (values: AccessFormSlackBotConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormSlackBotConfigFieldValues => { + return { + botToken: "", + }; +}; + +const AccessFormSlackBotConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormSlackBotConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + botToken: z + .string({ message: t("access.form.slackbot_token.placeholder") }) + .min(1, t("access.form.slackbot_token.placeholder")) + .max(256, t("common.errmsg.string_max", { max: 256 })) + .trim(), + defaultChannelId: z.string().nullish(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + + } + > + + +
+ ); +}; + +export default AccessFormSlackBotConfig; diff --git a/ui/src/components/access/AccessFormTelegramBotConfig.tsx b/ui/src/components/access/AccessFormTelegramBotConfig.tsx index a347610f..82747694 100644 --- a/ui/src/components/access/AccessFormTelegramBotConfig.tsx +++ b/ui/src/components/access/AccessFormTelegramBotConfig.tsx @@ -28,7 +28,8 @@ const AccessFormTelegramBotConfig = ({ form: formInst, formName, disabled, initi botToken: z .string({ message: t("access.form.telegrambot_token.placeholder") }) .min(1, t("access.form.telegrambot_token.placeholder")) - .max(256, t("common.errmsg.string_max", { max: 256 })), + .max(256, t("common.errmsg.string_max", { max: 256 })) + .trim(), defaultChatId: z .preprocess( (v) => (v == null || v === "" ? undefined : Number(v)), diff --git a/ui/src/components/workflow/node/NotifyNodeConfigForm.tsx b/ui/src/components/workflow/node/NotifyNodeConfigForm.tsx index 44a4a604..3c612df8 100644 --- a/ui/src/components/workflow/node/NotifyNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/NotifyNodeConfigForm.tsx @@ -20,6 +20,7 @@ import { useNotifyChannelsStore } from "@/stores/notify"; import NotifyNodeConfigFormDiscordBotConfig from "./NotifyNodeConfigFormDiscordBotConfig"; import NotifyNodeConfigFormEmailConfig from "./NotifyNodeConfigFormEmailConfig"; import NotifyNodeConfigFormMattermostConfig from "./NotifyNodeConfigFormMattermostConfig"; +import NotifyNodeConfigFormSlackBotConfig from "./NotifyNodeConfigFormSlackBotConfig"; import NotifyNodeConfigFormTelegramBotConfig from "./NotifyNodeConfigFormTelegramBotConfig"; import NotifyNodeConfigFormWebhookConfig from "./NotifyNodeConfigFormWebhookConfig"; @@ -117,6 +118,8 @@ const NotifyNodeConfigForm = forwardRef; case NOTIFICATION_PROVIDERS.MATTERMOST: return ; + case NOTIFICATION_PROVIDERS.SLACKBOT: + return ; case NOTIFICATION_PROVIDERS.TELEGRAMBOT: return ; case NOTIFICATION_PROVIDERS.WEBHOOK: diff --git a/ui/src/components/workflow/node/NotifyNodeConfigFormSlackBotConfig.tsx b/ui/src/components/workflow/node/NotifyNodeConfigFormSlackBotConfig.tsx new file mode 100644 index 00000000..5c304060 --- /dev/null +++ b/ui/src/components/workflow/node/NotifyNodeConfigFormSlackBotConfig.tsx @@ -0,0 +1,55 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +type NotifyNodeConfigFormSlackBotConfigFieldValues = Nullish<{ + channelId?: string; +}>; + +export type NotifyNodeConfigFormSlackBotConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: NotifyNodeConfigFormSlackBotConfigFieldValues; + onValuesChange?: (values: NotifyNodeConfigFormSlackBotConfigFieldValues) => void; +}; + +const initFormModel = (): NotifyNodeConfigFormSlackBotConfigFieldValues => { + return {}; +}; + +const NotifyNodeConfigFormSlackBotConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: NotifyNodeConfigFormSlackBotConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + channelId: z.string().nullish(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + +
+ ); +}; + +export default NotifyNodeConfigFormSlackBotConfig; diff --git a/ui/src/domain/access.ts b/ui/src/domain/access.ts index 9e953963..3582b071 100644 --- a/ui/src/domain/access.ts +++ b/ui/src/domain/access.ts @@ -58,6 +58,7 @@ export interface AccessModel extends BaseModel { | AccessConfigForRainYun | AccessConfigForRatPanel | AccessConfigForSafeLine + | AccessConfigForSlackBot | AccessConfigForSSH | AccessConfigForSSLCom | AccessConfigForTelegramBot @@ -361,6 +362,11 @@ export type AccessConfigForSafeLine = { allowInsecureConnections?: boolean; }; +export type AccessConfigForSlackBot = { + botToken: string; + defaultChannelId?: string; +}; + export type AccessConfigForSSH = { host: string; port: number; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index 806c8283..2d288a3c 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -61,6 +61,7 @@ export const ACCESS_PROVIDERS = Object.freeze({ RAINYUN: "rainyun", RATPANEL: "ratpanel", SAFELINE: "safeline", + SLACKBOT: "slackbot", SSH: "ssh", SSLCOM: "sslcom", TELEGRAMBOT: "telegrambot", @@ -174,6 +175,7 @@ export const accessProvidersMap: Map [ @@ -594,6 +596,7 @@ export const NOTIFICATION_PROVIDERS = Object.freeze({ EMAIL: `${ACCESS_PROVIDERS.EMAIL}`, LARKBOT: `${ACCESS_PROVIDERS.LARKBOT}`, MATTERMOST: `${ACCESS_PROVIDERS.MATTERMOST}`, + SLACKBOT: `${ACCESS_PROVIDERS.SLACKBOT}`, TELEGRAMBOT: `${ACCESS_PROVIDERS.TELEGRAMBOT}`, WEBHOOK: `${ACCESS_PROVIDERS.WEBHOOK}`, WECOMBOT: `${ACCESS_PROVIDERS.WECOMBOT}`, @@ -620,6 +623,7 @@ export const notificationProvidersMap: Map [ diff --git a/ui/src/i18n/locales/en/nls.access.json b/ui/src/i18n/locales/en/nls.access.json index fe437f87..98717976 100644 --- a/ui/src/i18n/locales/en/nls.access.json +++ b/ui/src/i18n/locales/en/nls.access.json @@ -163,7 +163,7 @@ "access.form.dingtalkbot_secret.tooltip": "For more information, see https://open.dingtalk.com/document/orgapp/customize-robot-security-settings", "access.form.discordbot_token.label": "Discord bot token", "access.form.discordbot_token.placeholder": "Please enter Discord bot token", - "access.form.discordbot_token.tooltip": "How to get it? Please refer to https://docs.discordbotstudio.org/setting-up-dbs/finding-your-bot-token", + "access.form.discordbot_token.tooltip": "For more information, see https://docs.discordbotstudio.org/setting-up-dbs/finding-your-bot-token", "access.form.discordbot_default_channel_id.label": "Default Discord channel ID (Optional)", "access.form.discordbot_default_channel_id.placeholder": "Please enter default Discord channel ID", "access.form.discordbot_default_channel_id.tooltip": "For more information, see https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID", @@ -362,6 +362,12 @@ "access.form.safeline_api_token.label": "SafeLine API token", "access.form.safeline_api_token.placeholder": "Please enter SafeLine API token", "access.form.safeline_api_token.tooltip": "For more information, see https://docs.waf.chaitin.com/en/reference/articles/openapi", + "access.form.slackbot_token.label": "Slack bot token", + "access.form.slackbot_token.placeholder": "Please enter Slack bot token", + "access.form.slackbot_token.tooltip": "For more information, see https://docs.slack.dev/authentication/tokens#bot", + "access.form.slackbot_default_channel_id.label": "Default Slack channel ID (Optional)", + "access.form.slackbot_default_channel_id.placeholder": "Please enter default Slack channel ID", + "access.form.slackbot_default_channel_id.tooltip": "How to get it? Please refer to https://www.youtube.com/watch?v=Uz5Yi5C2pwQ", "access.form.ssh_host.label": "Server host", "access.form.ssh_host.placeholder": "Please enter server host", "access.form.ssh_port.label": "Server port", diff --git a/ui/src/i18n/locales/en/nls.provider.json b/ui/src/i18n/locales/en/nls.provider.json index b34c92a7..85966786 100644 --- a/ui/src/i18n/locales/en/nls.provider.json +++ b/ui/src/i18n/locales/en/nls.provider.json @@ -68,7 +68,7 @@ "provider.dynv6": "dynv6", "provider.edgio": "Edgio", "provider.edgio.applications": "Edgio - Applications", - "provider.email": "Email", + "provider.email": "Email (SMTP)", "provider.fastly": "Fastly", "provider.flexcdn": "FlexCDN", "provider.gcore": "Gcore", @@ -96,7 +96,7 @@ "provider.lecdn": "LeCDN", "provider.letsencrypt": "Let's Encrypt", "provider.letsencryptstaging": "Let's Encrypt Staging Environment", - "provider.local": "Local deployment", + "provider.local": "Local host", "provider.mattermost": "Mattermost", "provider.namecheap": "Namecheap", "provider.namedotcom": "Name.com", @@ -118,7 +118,8 @@ "provider.ratpanel.console": "RatPanel - Console", "provider.ratpanel.site": "RatPanel - Website", "provider.safeline": "SafeLine", - "provider.ssh": "SSH deployment", + "provider.slackbot": "Slack Bot", + "provider.ssh": "Remote host (SSH)", "provider.sslcom": "SSL.com", "provider.telegrambot": "Telegram Bot", "provider.tencentcloud": "Tencent Cloud", diff --git a/ui/src/i18n/locales/en/nls.workflow.nodes.json b/ui/src/i18n/locales/en/nls.workflow.nodes.json index 172d707b..92989ac2 100644 --- a/ui/src/i18n/locales/en/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/en/nls.workflow.nodes.json @@ -827,6 +827,9 @@ "workflow_node.notify.form.mattermost_channel_id.label": "Mattermost channel ID (Optional)", "workflow_node.notify.form.mattermost_channel_id.placeholder": "Please enter Mattermost channel ID to override the default value", "workflow_node.notify.form.mattermost_channel_id.tooltip": "Leave it blank to use the default channel ID provided by the authorization.", + "workflow_node.notify.form.slackbot_channel_id.label": "Slack channel ID (Optional)", + "workflow_node.notify.form.slackbot_channel_id.placeholder": "Please enter Slack channel ID to override the default value", + "workflow_node.notify.form.slackbot_channel_id.tooltip": "Leave it blank to use the default channel ID provided by the authorization.", "workflow_node.notify.form.telegrambot_chat_id.label": "Telegram chat ID (Optional)", "workflow_node.notify.form.telegrambot_chat_id.placeholder": "Please enter Telegram chat ID to override the default value", "workflow_node.notify.form.telegrambot_chat_id.tooltip": "Leave it blank to use the default chat ID provided by the selected authorization.", diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index 21ad79c5..7e184d55 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -157,7 +157,7 @@ "access.form.dingtalkbot_secret.tooltip": "这是什么?请参阅 https://open.dingtalk.com/document/orgapp/customize-robot-security-settings", "access.form.discordbot_token.label": "Discord 机器人 API Token", "access.form.discordbot_token.placeholder": "请输入 Discord 机器人 API Token", - "access.form.discordbot_token.tooltip": "如何获取此参数?请参阅 https://docs.discordbotstudio.org/setting-up-dbs/finding-your-bot-token", + "access.form.discordbot_token.tooltip": "这是什么?请参阅 https://docs.discordbotstudio.org/setting-up-dbs/finding-your-bot-token", "access.form.discordbot_default_channel_id.label": "默认的 Discord 频道 ID(可选)", "access.form.discordbot_default_channel_id.placeholder": "请输入默认的 Discord 频道 ID", "access.form.discordbot_default_channel_id.tooltip": "这是什么?请参阅 https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID", @@ -356,6 +356,12 @@ "access.form.safeline_api_token.label": "雷池 API Token", "access.form.safeline_api_token.placeholder": "请输入雷池 API Token", "access.form.safeline_api_token.tooltip": "这是什么?请参阅 https://docs.waf-ce.chaitin.cn/zh/更多技术文档/OPENAPI", + "access.form.slackbot_token.label": "Slack 机器人 Token", + "access.form.slackbot_token.placeholder": "请输入 Slack 机器人 Token", + "access.form.slackbot_token.tooltip": "这是什么?请参阅 https://docs.slack.dev/authentication/tokens#bot", + "access.form.slackbot_default_channel_id.label": "默认的 Slack 频道 ID(可选)", + "access.form.slackbot_default_channel_id.placeholder": "请输入默认的 Slack 频道 ID", + "access.form.slackbot_default_channel_id.tooltip": "如何获取此参数?请参阅 https://www.youtube.com/watch?v=Uz5Yi5C2pwQ", "access.form.ssh_host.label": "服务器地址", "access.form.ssh_host.placeholder": "请输入服务器地址", "access.form.ssh_port.label": "服务器端口", diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json index dd12aa27..c4e126e0 100644 --- a/ui/src/i18n/locales/zh/nls.provider.json +++ b/ui/src/i18n/locales/zh/nls.provider.json @@ -68,7 +68,7 @@ "provider.dynv6": "dynv6", "provider.edgio": "Edgio", "provider.edgio.applications": "Edgio - Applications", - "provider.email": "邮件", + "provider.email": "邮件(SMTP)", "provider.fastly": "Fastly", "provider.flexcdn": "FlexCDN", "provider.gcore": "Gcore", @@ -96,7 +96,7 @@ "provider.lecdn": "LeCDN", "provider.letsencrypt": "Let's Encrypt", "provider.letsencryptstaging": "Let's Encrypt 测试环境", - "provider.local": "本地部署", + "provider.local": "本地主机", "provider.mattermost": "Mattermost", "provider.namecheap": "Namecheap", "provider.namedotcom": "Name.com", @@ -118,7 +118,8 @@ "provider.ratpanel.console": "耗子面板 - 控制台", "provider.ratpanel.site": "耗子面板 - 网站", "provider.safeline": "雷池", - "provider.ssh": "SSH 部署", + "provider.slackbot": "Slack 机器人", + "provider.ssh": "远程主机(SSH)", "provider.sslcom": "SSL.com", "provider.telegrambot": "Telegram 机器人", "provider.tencentcloud": "腾讯云", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index b6d27dc7..87f0076b 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -826,6 +826,9 @@ "workflow_node.notify.form.mattermost_channel_id.label": "Mattermost 频道 ID(可选)", "workflow_node.notify.form.mattermost_channel_id.placeholder": "请输入 Mattermost 频道 ID 以覆盖默认值", "workflow_node.notify.form.mattermost_channel_id.tooltip": "不填写时,将使用所选通知渠道授权的默认频道 ID。", + "workflow_node.notify.form.slackbot_channel_id.label": "Slack 频道 ID(可选)", + "workflow_node.notify.form.slackbot_channel_id.placeholder": "请输入 Slack 频道 ID 以覆盖默认值", + "workflow_node.notify.form.slackbot_channel_id.tooltip": "不填写时,将使用所选通知渠道授权的默认频道 ID。", "workflow_node.notify.form.telegrambot_chat_id.label": "Telegram 会话 ID(可选)", "workflow_node.notify.form.telegrambot_chat_id.placeholder": "请输入 Telegram 会话 ID 以覆盖默认值", "workflow_node.notify.form.telegrambot_chat_id.tooltip": "不填写时,将使用所选通知渠道授权的默认会话 ID。", From b0eb71421f8e50fb7e6120454581e48fdf4719a7 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Mon, 26 May 2025 16:55:15 +0800 Subject: [PATCH 09/11] chore(deps): upgrade go mod dependencies --- go.mod | 46 +++++++++++------------ go.sum | 117 +++++++++++++++++++++++++++++---------------------------- 2 files changed, 82 insertions(+), 81 deletions(-) diff --git a/go.mod b/go.mod index 37686d8c..0f12bd45 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ toolchain go1.24.3 require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates v1.3.1 github.com/Edgio/edgio-api v0.0.0-workspace github.com/G-Core/gcorelabscdn-go v1.0.31 @@ -14,10 +14,10 @@ require ( github.com/alibabacloud-go/apig-20240327/v3 v3.2.2 github.com/alibabacloud-go/cas-20200407/v3 v3.0.4 github.com/alibabacloud-go/cdn-20180510/v5 v5.2.2 - github.com/alibabacloud-go/cloudapi-20160714/v5 v5.7.3 + github.com/alibabacloud-go/cloudapi-20160714/v5 v5.7.4 github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.7 github.com/alibabacloud-go/ddoscoo-20200101/v4 v4.0.0 - github.com/alibabacloud-go/esa-20240910/v2 v2.32.0 + github.com/alibabacloud-go/esa-20240910/v2 v2.33.0 github.com/alibabacloud-go/fc-20230330/v4 v4.3.5 github.com/alibabacloud-go/fc-open-20210406/v2 v2.0.12 github.com/alibabacloud-go/ga-20191120/v3 v3.1.8 @@ -26,18 +26,18 @@ require ( github.com/alibabacloud-go/slb-20140515/v4 v4.0.10 github.com/alibabacloud-go/tea v1.3.9 github.com/alibabacloud-go/vod-20170321/v4 v4.8.4 - github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.2 + github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.3 github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible github.com/aws/aws-sdk-go-v2/service/acm v1.32.0 github.com/aws/aws-sdk-go-v2/service/cloudfront v1.46.1 - github.com/baidubce/bce-sdk-go v0.9.226 + github.com/baidubce/bce-sdk-go v0.9.228 github.com/blinkbean/dingtalk v1.1.3 github.com/byteplus-sdk/byteplus-sdk-golang v1.0.46 github.com/go-acme/lego/v4 v4.23.1 github.com/go-lark/lark v1.16.0 github.com/go-resty/resty/v2 v2.16.5 github.com/go-viper/mapstructure/v2 v2.2.1 - github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.148 + github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.150 github.com/jdcloud-api/jdcloud-sdk-go v1.64.0 github.com/libdns/dynv6 v1.0.0 github.com/libdns/libdns v0.2.3 @@ -45,29 +45,29 @@ require ( github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0 github.com/pkg/sftp v1.13.9 github.com/pocketbase/dbx v1.11.0 - github.com/pocketbase/pocketbase v0.28.0 + github.com/pocketbase/pocketbase v0.28.2 github.com/povsister/scp v0.0.0-20250504051308-e467f71ea63c github.com/qiniu/go-sdk/v7 v7.25.3 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1155 - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1161 - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1162 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1166 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1173 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1150 - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1120 - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1124 - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1162 - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1160 - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1162 - github.com/ucloud/ucloud-sdk-go v0.22.35 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1172 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1169 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1166 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1164 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1170 + github.com/ucloud/ucloud-sdk-go v0.22.41 github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.12 - github.com/volcengine/volc-sdk-golang v1.0.207 - github.com/volcengine/volcengine-go-sdk v1.1.7 + github.com/volcengine/volc-sdk-golang v1.0.208 + github.com/volcengine/volcengine-go-sdk v1.1.8 gitlab.ecloud.com/ecloud/ecloudsdkclouddns v1.0.1 gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0 golang.org/x/crypto v0.38.0 golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 - k8s.io/api v0.33.0 - k8s.io/apimachinery v0.33.0 - k8s.io/client-go v0.33.0 + k8s.io/api v0.33.1 + k8s.io/apimachinery v0.33.1 + k8s.io/client-go v0.33.1 software.sslmate.com/src/go-pkcs12 v0.5.0 ) @@ -211,10 +211,10 @@ require ( google.golang.org/protobuf v1.36.5 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - modernc.org/libc v1.62.1 // indirect + modernc.org/libc v1.65.7 // indirect modernc.org/mathutil v1.7.1 // indirect - modernc.org/memory v1.9.1 // indirect - modernc.org/sqlite v1.37.0 // indirect + modernc.org/memory v1.11.0 // indirect + modernc.org/sqlite v1.37.1 // indirect ) replace github.com/Edgio/edgio-api v0.0.0-workspace => ./internal/pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace diff --git a/go.sum b/go.sum index 5a64f77a..7bbf5848 100644 --- a/go.sum +++ b/go.sum @@ -36,8 +36,8 @@ filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4 github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 h1:OVoM452qUFBrX+URdH3VpR299ma4kfom0yB0URYky9g= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0/go.mod h1:kUjrAo8bgEwLeZ/CmHqNl3Z/kPm7y6FKfxxK0izYUg4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 h1:j8BorDEigD8UFOSZQiSqAMOOleyQOOQPnUAwV+Ls1gA= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4= @@ -101,8 +101,8 @@ github.com/alibabacloud-go/cas-20200407/v3 v3.0.4 h1:ngRlctbt135zoujwX0lXSv9m4h1 github.com/alibabacloud-go/cas-20200407/v3 v3.0.4/go.mod h1:6n9MZ9SH3HlSzfe2oKwjOqhJx3dxvW2gMDO+lq8t9U4= github.com/alibabacloud-go/cdn-20180510/v5 v5.2.2 h1:+KJOPukTM+xMyiLOW5qBwYKG2df3Ar7coRsqc1juKO8= github.com/alibabacloud-go/cdn-20180510/v5 v5.2.2/go.mod h1:GnPiPL3HlzCi8SGiLiVgKrAFkP1vTtcF4yGtjsl4wfo= -github.com/alibabacloud-go/cloudapi-20160714/v5 v5.7.3 h1:OTLn0ShbE0jJj+5Z+P76zeHsZYxZjO7YVThQoeaBM9M= -github.com/alibabacloud-go/cloudapi-20160714/v5 v5.7.3/go.mod h1:eUmD1G4BjEBOAHIeJrHJL7pyLGgXSRTPLjBmYY7uPEg= +github.com/alibabacloud-go/cloudapi-20160714/v5 v5.7.4 h1:SsyAoXM1R4J3I4xQdPW/rRW8cTo2KN440/4h/pGiwRQ= +github.com/alibabacloud-go/cloudapi-20160714/v5 v5.7.4/go.mod h1:eUmD1G4BjEBOAHIeJrHJL7pyLGgXSRTPLjBmYY7uPEg= github.com/alibabacloud-go/darabonba-array v0.1.0 h1:vR8s7b1fWAQIjEjWnuF0JiKsCvclSRTfDzZHTYqfufY= github.com/alibabacloud-go/darabonba-array v0.1.0/go.mod h1:BLKxr0brnggqOJPqT09DFJ8g3fsDshapUD3C3aOEFaI= github.com/alibabacloud-go/darabonba-encode-util v0.0.2 h1:1uJGrbsGEVqWcWxrS9MyC2NG0Ax+GpOM5gtupki31XE= @@ -132,8 +132,8 @@ github.com/alibabacloud-go/debug v1.0.1/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/ql github.com/alibabacloud-go/endpoint-util v1.1.0/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE= github.com/alibabacloud-go/endpoint-util v1.1.1 h1:ZkBv2/jnghxtU0p+upSU0GGzW1VL9GQdZO3mcSUTUy8= github.com/alibabacloud-go/endpoint-util v1.1.1/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE= -github.com/alibabacloud-go/esa-20240910/v2 v2.32.0 h1:eudSgNIkCg6huIu3HuF16BJG6+CA6bIuIddxpuPydpg= -github.com/alibabacloud-go/esa-20240910/v2 v2.32.0/go.mod h1:HZS5PmYJvcmH4vrJYuCvK3AnYzD9hLlO8CT0hgRyDXo= +github.com/alibabacloud-go/esa-20240910/v2 v2.33.0 h1:10IWxrMcF1W6/7BUJIJifrofduSG0wRFqDbRfIsR3Zw= +github.com/alibabacloud-go/esa-20240910/v2 v2.33.0/go.mod h1:HZS5PmYJvcmH4vrJYuCvK3AnYzD9hLlO8CT0hgRyDXo= github.com/alibabacloud-go/fc-20230330/v4 v4.3.5 h1:nDNjVzGwkQPbQnAuxAmxvS9x8QGLph8j0ptEdZDPGBA= github.com/alibabacloud-go/fc-20230330/v4 v4.3.5/go.mod h1:vEJimQ6E/e+m2z0/oXdeQWlFw/Pi/Ar6NKcMrSvcILE= github.com/alibabacloud-go/fc-open-20210406/v2 v2.0.12 h1:A3D8Mp6qf8DfR6Dt5MpS8aDVaWfS4N85T5CvGUvgrjM= @@ -190,8 +190,8 @@ github.com/alibabacloud-go/tea-xml v1.1.3 h1:7LYnm+JbOq2B+T/B0fHC4Ies4/FofC4zHzY github.com/alibabacloud-go/tea-xml v1.1.3/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8= github.com/alibabacloud-go/vod-20170321/v4 v4.8.4 h1:MYP2xfrcud8vlWljQ4lhemNgAgi9/AUAa450n8TUXZo= github.com/alibabacloud-go/vod-20170321/v4 v4.8.4/go.mod h1:5ocQ6hIc9tpGixD2iy099aOGwIgpzjT2le4Krd4aLn8= -github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.2 h1:CmhJzCZ5RiSiWU6BV2XJUtIMD2LDo9FFfqlYGtx1aAw= -github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.2/go.mod h1:9itYSTzipL3NlvhvNYfTjFaapoZzG68nlu/KUdh9SpA= +github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.3 h1:25tmcJxIitrk55crBGssPlqRzmFcpGVW5TEFxdUvfg0= +github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.3/go.mod h1:9itYSTzipL3NlvhvNYfTjFaapoZzG68nlu/KUdh9SpA= github.com/aliyun/alibaba-cloud-sdk-go v1.63.100 h1:yUkCbrSM1cWtgBfRVKMQtdt22KhDvKY7g4V+92eG9wA= github.com/aliyun/alibaba-cloud-sdk-go v1.63.100/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ= github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible h1:8psS8a+wKfiLt1iVDX79F7Y6wUM49Lcha2FMXt4UM8g= @@ -250,8 +250,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.33.17/go.mod h1:cQnB8CUnxbMU82JvlqjK github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ= github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= -github.com/baidubce/bce-sdk-go v0.9.226 h1:VKEKcJC9P33yIfYJZr12Q/4Bvj18RFbgO8w8XOfU8AI= -github.com/baidubce/bce-sdk-go v0.9.226/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg= +github.com/baidubce/bce-sdk-go v0.9.228 h1:XEY3/oAxXcsi7+3atib9fMI6YNE9sL5qo+WMZ+iqmNE= +github.com/baidubce/bce-sdk-go v0.9.228/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -545,8 +545,8 @@ github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.148 h1:PdWSbniKnPhKe1B19KUHW/9ahYbFH2EY6Iq6sxOnomo= -github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.148/go.mod h1:Y/+YLCFCJtS29i2MbYPTUlNNfwXvkzEsZKR0imY/2aY= +github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.150 h1:Ih+z79Ko1ClH4dlv7O1lyHRiVCjkb2NZYYk+1cSZbU8= +github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.150/go.mod h1:Y/+YLCFCJtS29i2MbYPTUlNNfwXvkzEsZKR0imY/2aY= github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -737,8 +737,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pocketbase/dbx v1.11.0 h1:LpZezioMfT3K4tLrqA55wWFw1EtH1pM4tzSVa7kgszU= github.com/pocketbase/dbx v1.11.0/go.mod h1:xXRCIAKTHMgUCyCKZm55pUOdvFziJjQfXaWKhu2vhMs= -github.com/pocketbase/pocketbase v0.28.0 h1:dnMHSO0wuYpKs6oP3X5buw1lY9ptd8zy1fTjN+Ae+mA= -github.com/pocketbase/pocketbase v0.28.0/go.mod h1:WE6xMM4+pxKIVNl4B1mcOEZXlDvPGl7cZ64TW2iXHdI= +github.com/pocketbase/pocketbase v0.28.2 h1:b6cfUfr5d4whvUFGFhI8oHRzx/eB76GCUQGftqgv9lM= +github.com/pocketbase/pocketbase v0.28.2/go.mod h1:ElwIYS1b5xS9w0U7AK7tsm6FuC0lzw57H8p/118Cu7g= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/povsister/scp v0.0.0-20250504051308-e467f71ea63c h1:1+j5JHz9mUzYSp0scuF6hzvJP28EDBFe5eBJb0xnGk4= @@ -771,8 +771,8 @@ github.com/qiniu/x v1.10.5 h1:7V/CYWEmo9axJULvrJN6sMYh2FdY+esN5h8jwDkA4b0= github.com/qiniu/x v1.10.5/go.mod h1:03Ni9tj+N2h2aKnAz+6N0Xfl8FwMEDRC2PAlxekASDs= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM= -github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA= +github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI= +github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= @@ -829,31 +829,32 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1155 h1:ildxJtjnqiKZxWDVKHT/ncIknGDijtg60MuFELON8bY= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1155/go.mod h1:iLASpooTdyXtx642E5Ws7cfWENsp4/uZ/78TFoln7OI= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1161 h1:yGFg9/6j3NP10r9PfSWHfekuq4SwPyqblWnfISfKANo= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1161/go.mod h1:9MzQSEULYm5wHAKz8R3oQ8ovg4vWeLFzn0DmRWTc6zg= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1120/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1124/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1166 h1:cEoDsBt7vGh7YtfVHVmgXKQURZANBE8UKK/So84QUdU= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1166/go.mod h1:0o5Cfgdh+bAx7kpQ5a5wce/ZUiDvy4Md8NcbrLtk6i8= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1128/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1150/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1155/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1160/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1161/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1162 h1:bscCBygP9JRl6iNabF+vmBOhY+xayFFGYV5Wa0NzH0A= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1162/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1164/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1166/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1169/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1170/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1172/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1173 h1:W5bzEWiJwiwRZR0/P1l78OYWUXYsXLjhBaQ64c+9+fk= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1173/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1128 h1:mrJ5Fbkd7sZIJ5F6oRfh5zebPQaudPH9Y0+GUmFytYU= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1128/go.mod h1:zbsYIBT+VTX4z4ocjTAdLBIWyNYj3z0BRqd0iPdnjsk= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1150 h1:RQQYfZOFYlkxKR2+xp8el3+8xs9DhxBy+ajlHtapqtQ= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1150/go.mod h1:zpfr6EBWy7ClASTGUgIy01Gn4R79UXf+2QGQeyR124A= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1120 h1:z0t0lb5h1mZirXftO8MRg25COYZHx0ubQjSPhZT/LY0= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1120/go.mod h1:IFZL44Keyl+MHrhpFwUaQmJvMDwGr+t+cUfFAC+74lU= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1124 h1:LQKAlxFb0sYiE8ojK5h9+seuFzogoJtYnXmiRF+4F4Q= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1124/go.mod h1:tYbK0FbHVG+78od7eZpzczE8qk0JWKO/osTQWuiJ3Fo= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1162 h1:z/JF+JGi6bGf8vnK9ZeVXz+1Q3ih8nF6KjThxhtIrNc= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1162/go.mod h1:rsO8JCP+WQeLQ32wAB4oRRjsEz0O+kvCGDqc7Ze1jc4= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1160 h1:aNVEDS1yQ7sLfXOOQ/bF3eljFjyvHoJ/J8qSC9mC9gw= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1160/go.mod h1:kf6NQmKK6sh1ACwh8iliBy7I/burd+AWusNz6zbDvLM= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1162 h1:gnmuUaoFAShc9FKj3Omswu3n08bHM/sGsl8xjFAkFNs= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1162/go.mod h1:bu3KAFeoJ1xDGQp72h9Le3FqbOcCcdomOUig3OqgcE4= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1172 h1:6SUO0hTie3zxnUEMxmhnS1iRIXpAukSZV27Nrx4NwIk= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1172/go.mod h1:tmN4zfu70SD0iee3qfpc09NRLel30zGoAuzIs4X0Kfs= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1169 h1:oBymtJEmKDnS2NIR0PDLd+xCGQ+7uMoEt7zEB5Q3x8U= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1169/go.mod h1:K27PNEgRJ602ESXUNnlRnCkf1+XYHI6RVP/ylIe/Aro= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1166 h1:+kIsoG2If/0y15PpZsXfT0QqTuwec9nMgo1JP8KQMkw= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1166/go.mod h1:lGmBMXqe3vBg6Bi9h4mVpWLKd7jQIMRbndr8KNHBqSw= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1164 h1:caaIGWOs/JtWOK5ptVMEiiGgzU7Jf6UpMv+9IbIa4vs= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1164/go.mod h1:SJI2mc77gDC7Tw1QoF/4d5SwLvz8HQFUecWtIXb+r/Q= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1170 h1:kcQCWuI9zOkZgL5CK66HNAJmSWCSJxRrDxXT+j02CeE= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1170/go.mod h1:vTukVfThbBIc4lOf4eq/q51eEk78oZUJd2lAoJBOJwI= github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho= github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= @@ -862,18 +863,18 @@ github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaO github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -github.com/ucloud/ucloud-sdk-go v0.22.35 h1:Q4CY3Ae5813jmNUrGdCjc8tlyleL5Lyl0APnpK5L4sk= -github.com/ucloud/ucloud-sdk-go v0.22.35/go.mod h1:dyLmFHmUfgb4RZKYQP9IArlvQ2pxzFthfhwxRzOEPIw= +github.com/ucloud/ucloud-sdk-go v0.22.41 h1:JndTJhCx7A1wggZfVb4KMm7D0Wfvd/HkmQVfSNjClQA= +github.com/ucloud/ucloud-sdk-go v0.22.41/go.mod h1:dyLmFHmUfgb4RZKYQP9IArlvQ2pxzFthfhwxRzOEPIw= github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.12 h1:u9+32DXQIOFPG8oQ3xrjSAUSyAcaq5bqO4cEBom/6lA= github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.12/go.mod h1:IrjK84IJJTuOZOTMv/P18Ydjy/x+ow7fF7q11jAxXLM= github.com/volcengine/volc-sdk-golang v1.0.23/go.mod h1:AfG/PZRUkHJ9inETvbjNifTDgut25Wbkm2QoYBTbvyU= -github.com/volcengine/volc-sdk-golang v1.0.207 h1:1OJ/nC92dF1URRoyO1AHSghCob12NT1PAA/GoK8uU18= -github.com/volcengine/volc-sdk-golang v1.0.207/go.mod h1:stZX+EPgv1vF4nZwOlEe8iGcriUPRBKX8zA19gXycOQ= -github.com/volcengine/volcengine-go-sdk v1.1.7 h1:5ElF1inqX1QUKX8/XGk+HGpG+F01W+m73cLQH+0x50s= -github.com/volcengine/volcengine-go-sdk v1.1.7/go.mod h1:EyKoi6t6eZxoPNGr2GdFCZti2Skd7MO3eUzx7TtSvNo= +github.com/volcengine/volc-sdk-golang v1.0.208 h1:DyGUPjEKhWS08BkptfqenXTuUq+LKb7+gX/RBAtNl8w= +github.com/volcengine/volc-sdk-golang v1.0.208/go.mod h1:stZX+EPgv1vF4nZwOlEe8iGcriUPRBKX8zA19gXycOQ= +github.com/volcengine/volcengine-go-sdk v1.1.8 h1:/T2p7qeeLWWhGrhtB00b8VNlE32S266LcO+jqFUYwzY= +github.com/volcengine/volcengine-go-sdk v1.1.8/go.mod h1:EyKoi6t6eZxoPNGr2GdFCZti2Skd7MO3eUzx7TtSvNo= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= @@ -1394,39 +1395,39 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.33.0 h1:yTgZVn1XEe6opVpP1FylmNrIFWuDqe2H0V8CT5gxfIU= -k8s.io/api v0.33.0/go.mod h1:CTO61ECK/KU7haa3qq8sarQ0biLq2ju405IZAd9zsiM= -k8s.io/apimachinery v0.33.0 h1:1a6kHrJxb2hs4t8EE5wuR/WxKDwGN1FKH3JvDtA0CIQ= -k8s.io/apimachinery v0.33.0/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= -k8s.io/client-go v0.33.0 h1:UASR0sAYVUzs2kYuKn/ZakZlcs2bEHaizrrHUZg0G98= -k8s.io/client-go v0.33.0/go.mod h1:kGkd+l/gNGg8GYWAPr0xF1rRKvVWvzh9vmZAMXtaKOg= +k8s.io/api v0.33.1 h1:tA6Cf3bHnLIrUK4IqEgb2v++/GYUtqiu9sRVk3iBXyw= +k8s.io/api v0.33.1/go.mod h1:87esjTn9DRSRTD4fWMXamiXxJhpOIREjWOSjsW1kEHw= +k8s.io/apimachinery v0.33.1 h1:mzqXWV8tW9Rw4VeW9rEkqvnxj59k1ezDUl20tFK/oM4= +k8s.io/apimachinery v0.33.1/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= +k8s.io/client-go v0.33.1 h1:ZZV/Ks2g92cyxWkRRnfUDsnhNn28eFpt26aGc8KbXF4= +k8s.io/client-go v0.33.1/go.mod h1:JAsUrl1ArO7uRVFWfcj6kOomSlCv+JpvIsp6usAGefA= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4= k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0= k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -modernc.org/cc/v4 v4.25.2 h1:T2oH7sZdGvTaie0BRNFbIYsabzCxUQg8nLqCdQ2i0ic= -modernc.org/cc/v4 v4.25.2/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= -modernc.org/ccgo/v4 v4.25.1 h1:TFSzPrAGmDsdnhT9X2UrcPMI3N/mJ9/X9ykKXwLhDsU= -modernc.org/ccgo/v4 v4.25.1/go.mod h1:njjuAYiPflywOOrm3B7kCB444ONP5pAVr8PIEoE0uDw= +modernc.org/cc/v4 v4.26.1 h1:+X5NtzVBn0KgsBCBe+xkDC7twLb/jNVj9FPgiwSQO3s= +modernc.org/cc/v4 v4.26.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= +modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU= +modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE= modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8= -modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= -modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= +modernc.org/fileutil v1.3.1 h1:8vq5fe7jdtEvoCf3Zf9Nm0Q05sH6kGx0Op2CPx1wTC8= +modernc.org/fileutil v1.3.1/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc= modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= -modernc.org/libc v1.62.1 h1:s0+fv5E3FymN8eJVmnk0llBe6rOxCu/DEU+XygRbS8s= -modernc.org/libc v1.62.1/go.mod h1:iXhATfJQLjG3NWy56a6WVU73lWOcdYVxsvwCgoPljuo= +modernc.org/libc v1.65.7 h1:Ia9Z4yzZtWNtUIuiPuQ7Qf7kxYrxP1/jeHZzG8bFu00= +modernc.org/libc v1.65.7/go.mod h1:011EQibzzio/VX3ygj1qGFt5kMjP0lHb0qCW5/D/pQU= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= -modernc.org/memory v1.9.1 h1:V/Z1solwAVmMW1yttq3nDdZPJqV1rM05Ccq6KMSZ34g= -modernc.org/memory v1.9.1/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= +modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= +modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8= modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= -modernc.org/sqlite v1.37.0 h1:s1TMe7T3Q3ovQiK2Ouz4Jwh7dw4ZDqbebSDTlSJdfjI= -modernc.org/sqlite v1.37.0/go.mod h1:5YiWv+YviqGMuGw4V+PNplcyaJ5v+vQd7TQOgkACoJM= +modernc.org/sqlite v1.37.1 h1:EgHJK/FPoqC+q2YBXg7fUmES37pCHFc97sI7zSayBEs= +modernc.org/sqlite v1.37.1/go.mod h1:XwdRtsE1MpiBcL54+MbKcaDvcuej+IYSMfLN6gSKV8g= modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= From 3bb88d9f93f058a1f812c3a0d532012378372a32 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Mon, 26 May 2025 17:04:40 +0800 Subject: [PATCH 10/11] chore(deps): upgrade npm dependencies --- ui/package-lock.json | 226 +++++++++++++++++++++++-------------------- ui/package.json | 22 ++--- 2 files changed, 131 insertions(+), 117 deletions(-) diff --git a/ui/package-lock.json b/ui/package-lock.json index 44a4d2b6..e1bbb340 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -17,27 +17,27 @@ "@uiw/codemirror-extensions-basic-setup": "^4.23.12", "@uiw/codemirror-theme-vscode": "^4.23.12", "@uiw/react-codemirror": "^4.23.12", - "ahooks": "^3.8.4", - "antd": "^5.25.1", + "ahooks": "^3.8.5", + "antd": "^5.25.3", "antd-zod": "^6.1.0", "clsx": "^2.1.1", "cron-parser": "^5.2.0", "file-saver": "^2.0.5", - "i18next": "^25.1.2", + "i18next": "^25.2.1", "i18next-browser-languagedetector": "^8.1.0", "immer": "^10.1.1", - "lucide-react": "^0.509.0", + "lucide-react": "^0.511.0", "nanoid": "^5.1.5", "pocketbase": "^0.26.0", "radash": "^12.1.0", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", - "react-i18next": "^15.5.1", - "react-router-dom": "^7.6.0", + "react-i18next": "^15.5.2", + "react-router-dom": "^7.6.1", "tailwind-merge": "^2.6.0", - "zod": "^3.24.4", - "zustand": "^5.0.4" + "zod": "^3.25.28", + "zustand": "^5.0.5" }, "devDependencies": { "@types/file-saver": "^2.0.7", @@ -46,10 +46,10 @@ "@types/react": "^18.3.12", "@types/react-copy-to-clipboard": "^5.0.7", "@types/react-dom": "^18.3.1", - "@typescript-eslint/eslint-plugin": "^8.32.0", - "@typescript-eslint/parser": "^8.32.0", + "@typescript-eslint/eslint-plugin": "^8.32.1", + "@typescript-eslint/parser": "^8.32.1", "@vitejs/plugin-legacy": "^6.1.1", - "@vitejs/plugin-react": "^4.4.1", + "@vitejs/plugin-react": "^4.5.0", "autoprefixer": "^10.4.21", "eslint": "^8.57.0", "eslint-config-prettier": "^10.1.5", @@ -94,9 +94,9 @@ } }, "node_modules/@ant-design/colors": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/@ant-design/colors/-/colors-7.2.0.tgz", - "integrity": "sha512-bjTObSnZ9C/O8MB/B4OUtd/q9COomuJAR2SYfhxLyHvCKn4EKwCN3e+fWGMo7H5InAyV0wL17jdE9ALrdOW/6A==", + "version": "7.2.1", + "resolved": "https://registry.npmmirror.com/@ant-design/colors/-/colors-7.2.1.tgz", + "integrity": "sha512-lCHDcEzieu4GA3n8ELeZ5VQ8pKQAWcGGLRTQ50aQM2iqPpq2evTxER84jfdPvsPAtEcZ7m44NI45edFMo8oOYQ==", "dependencies": { "@ant-design/fast-color": "^2.0.6" } @@ -2047,12 +2047,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.26.10", - "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.26.10.tgz", - "integrity": "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.27.1.tgz", + "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", "engines": { "node": ">=6.9.0" } @@ -3225,6 +3222,12 @@ "react-dom": ">=18.0.0" } }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.9", + "resolved": "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.9.tgz", + "integrity": "sha512-e9MeMtVWo186sgvFFJOPGy7/d2j2mZhLJIdVW0C/xDluuOvymEATqz6zKsP0ZmXGzQtqlyjz5sC1sYQUoJG98w==", + "dev": true + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.40.0", "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.0.tgz", @@ -3613,18 +3616,18 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.32.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.0.tgz", - "integrity": "sha512-/jU9ettcntkBFmWUzzGgsClEi2ZFiikMX5eEQsmxIAWMOn4H3D4rvHssstmAHGVvrYnaMqdWWWg0b5M6IN/MTQ==", + "version": "8.32.1", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.1.tgz", + "integrity": "sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.32.0", - "@typescript-eslint/type-utils": "8.32.0", - "@typescript-eslint/utils": "8.32.0", - "@typescript-eslint/visitor-keys": "8.32.0", + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/type-utils": "8.32.1", + "@typescript-eslint/utils": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", "graphemer": "^1.4.0", - "ignore": "^5.3.1", + "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, @@ -3641,16 +3644,25 @@ "typescript": ">=4.8.4 <5.9.0" } }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.4", + "resolved": "https://registry.npmmirror.com/ignore/-/ignore-7.0.4.tgz", + "integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/@typescript-eslint/parser": { - "version": "8.32.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.32.0.tgz", - "integrity": "sha512-B2MdzyWxCE2+SqiZHAjPphft+/2x2FlO9YBx7eKE1BCb+rqBlQdhtAEhzIEdozHd55DXPmxBdpMygFJjfjjA9A==", + "version": "8.32.1", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.32.1.tgz", + "integrity": "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.32.0", - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/typescript-estree": "8.32.0", - "@typescript-eslint/visitor-keys": "8.32.0", + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/typescript-estree": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", "debug": "^4.3.4" }, "engines": { @@ -3666,13 +3678,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.32.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.32.0.tgz", - "integrity": "sha512-jc/4IxGNedXkmG4mx4nJTILb6TMjL66D41vyeaPWvDUmeYQzF3lKtN15WsAeTr65ce4mPxwopPSo1yUUAWw0hQ==", + "version": "8.32.1", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz", + "integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/visitor-keys": "8.32.0" + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3683,13 +3695,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.32.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.32.0.tgz", - "integrity": "sha512-t2vouuYQKEKSLtJaa5bB4jHeha2HJczQ6E5IXPDPgIty9EqcJxpr1QHQ86YyIPwDwxvUmLfP2YADQ5ZY4qddZg==", + "version": "8.32.1", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.32.1.tgz", + "integrity": "sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.32.0", - "@typescript-eslint/utils": "8.32.0", + "@typescript-eslint/typescript-estree": "8.32.1", + "@typescript-eslint/utils": "8.32.1", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -3706,9 +3718,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.32.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.32.0.tgz", - "integrity": "sha512-O5Id6tGadAZEMThM6L9HmVf5hQUXNSxLVKeGJYWNhhVseps/0LddMkp7//VDkzwJ69lPL0UmZdcZwggj9akJaA==", + "version": "8.32.1", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.32.1.tgz", + "integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3719,13 +3731,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.32.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.0.tgz", - "integrity": "sha512-pU9VD7anSCOIoBFnhTGfOzlVFQIA1XXiQpH/CezqOBaDppRwTglJzCC6fUQGpfwey4T183NKhF1/mfatYmjRqQ==", + "version": "8.32.1", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz", + "integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/visitor-keys": "8.32.0", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -3745,15 +3757,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.32.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.32.0.tgz", - "integrity": "sha512-8S9hXau6nQ/sYVtC3D6ISIDoJzS1NsCK+gluVhLN2YkBPX+/1wkwyUiDKnxRh15579WoOIyVWnoyIf3yGI9REw==", + "version": "8.32.1", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.32.1.tgz", + "integrity": "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.32.0", - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/typescript-estree": "8.32.0" + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/typescript-estree": "8.32.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3768,12 +3780,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.32.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.0.tgz", - "integrity": "sha512-1rYQTCLFFzOI5Nl0c8LUpJT8HxpwVRn9E4CkMsYfuN6ctmQqExjSTzzSk0Tz2apmXy7WU6/6fyaZVVA/thPN+w==", + "version": "8.32.1", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz", + "integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.32.0", + "@typescript-eslint/types": "8.32.1", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -3922,14 +3934,15 @@ } }, "node_modules/@vitejs/plugin-react": { - "version": "4.4.1", - "resolved": "https://registry.npmmirror.com/@vitejs/plugin-react/-/plugin-react-4.4.1.tgz", - "integrity": "sha512-IpEm5ZmeXAP/osiBXVVP5KjFMzbWOonMs0NaQQl+xYnUAcq4oHUBsF2+p4MgKWG4YMmFYJU8A6sxRPuowllm6w==", + "version": "4.5.0", + "resolved": "https://registry.npmmirror.com/@vitejs/plugin-react/-/plugin-react-4.5.0.tgz", + "integrity": "sha512-JuLWaEqypaJmOJPLWwO335Ig6jSgC1FTONCWAxnqcQthLTK/Yc9aH6hr9z/87xciejbQcnP3GnA1FWUSWeXaeg==", "dev": true, "dependencies": { "@babel/core": "^7.26.10", "@babel/plugin-transform-react-jsx-self": "^7.25.9", "@babel/plugin-transform-react-jsx-source": "^7.25.9", + "@rolldown/pluginutils": "1.0.0-beta.9", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, @@ -3970,9 +3983,9 @@ } }, "node_modules/ahooks": { - "version": "3.8.4", - "resolved": "https://registry.npmmirror.com/ahooks/-/ahooks-3.8.4.tgz", - "integrity": "sha512-39wDEw2ZHvypaT14EpMMk4AzosHWt0z9bulY0BeDsvc9PqJEV+Kjh/4TZfftSsotBMq52iYIOFPd3PR56e0ZJg==", + "version": "3.8.5", + "resolved": "https://registry.npmmirror.com/ahooks/-/ahooks-3.8.5.tgz", + "integrity": "sha512-Y+MLoJpBXVdjsnnBjE5rOSPkQ4DK+8i5aPDzLJdIOsCpo/fiAeXcBY1Y7oWgtOK0TpOz0gFa/XcyO1UGdoqLcw==", "dependencies": { "@babel/runtime": "^7.21.0", "dayjs": "^1.9.1", @@ -3988,7 +4001,7 @@ "node": ">=8.0.0" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/ajv": { @@ -4017,11 +4030,11 @@ } }, "node_modules/antd": { - "version": "5.25.1", - "resolved": "https://registry.npmmirror.com/antd/-/antd-5.25.1.tgz", - "integrity": "sha512-4KC7KuPCjr0z3Vuw9DsF+ceqJaPLbuUI3lOX1sY8ix25ceamp+P8yxOmk3Y2JHCD2ZAhq+5IQ/DTJRN2adWYKQ==", + "version": "5.25.3", + "resolved": "https://registry.npmmirror.com/antd/-/antd-5.25.3.tgz", + "integrity": "sha512-tBBcAFRjmWM3sitxrL/FEbQL+MTQntYY5bGa5c1ZZZHXWCynkhS3Ch/gy25mGMUY1M/9Uw3pH029v/RGht1x3w==", "dependencies": { - "@ant-design/colors": "^7.2.0", + "@ant-design/colors": "^7.2.1", "@ant-design/cssinjs": "^1.23.0", "@ant-design/cssinjs-utils": "^1.1.3", "@ant-design/fast-color": "^2.0.6", @@ -4056,11 +4069,11 @@ "rc-rate": "~2.13.1", "rc-resize-observer": "^1.4.3", "rc-segmented": "~2.7.0", - "rc-select": "~14.16.7", + "rc-select": "~14.16.8", "rc-slider": "~11.1.8", "rc-steps": "~6.0.1", "rc-switch": "~4.1.0", - "rc-table": "~7.50.4", + "rc-table": "~7.50.5", "rc-tabs": "~15.6.1", "rc-textarea": "~1.10.0", "rc-tooltip": "~6.4.0", @@ -6081,9 +6094,9 @@ } }, "node_modules/i18next": { - "version": "25.1.2", - "resolved": "https://registry.npmmirror.com/i18next/-/i18next-25.1.2.tgz", - "integrity": "sha512-SP63m8LzdjkrAjruH7SCI3ndPSgjt4/wX7ouUUOzCW/eY+HzlIo19IQSfYA9X3qRiRP1SYtaTsg/Oz/PGsfD8w==", + "version": "25.2.1", + "resolved": "https://registry.npmmirror.com/i18next/-/i18next-25.2.1.tgz", + "integrity": "sha512-+UoXK5wh+VlE1Zy5p6MjcvctHXAhRwQKCxiJD8noKZzIXmnAX8gdHX5fLPA3MEVxEN4vbZkQFy8N0LyD9tUqPw==", "funding": [ { "type": "individual", @@ -6099,7 +6112,7 @@ } ], "dependencies": { - "@babel/runtime": "^7.26.10" + "@babel/runtime": "^7.27.1" }, "peerDependencies": { "typescript": "^5" @@ -6797,9 +6810,9 @@ } }, "node_modules/lucide-react": { - "version": "0.509.0", - "resolved": "https://registry.npmmirror.com/lucide-react/-/lucide-react-0.509.0.tgz", - "integrity": "sha512-xCJHn6Uh5qF6PGml25vveCTrHJZcqS1G1MVzWZK54ZQsOiCVJk4fwY3oyo5EXS2S+aqvTpWYIfJN+PesJ0quxg==", + "version": "0.511.0", + "resolved": "https://registry.npmmirror.com/lucide-react/-/lucide-react-0.511.0.tgz", + "integrity": "sha512-VK5a2ydJ7xm8GvBeKLS9mu1pVK6ucef9780JVUjw6bAjJL/QXnd4Y0p7SPeOUMC27YhzNCZvm5d/QX0Tp3rc0w==", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } @@ -7874,9 +7887,9 @@ } }, "node_modules/rc-select": { - "version": "14.16.7", - "resolved": "https://registry.npmmirror.com/rc-select/-/rc-select-14.16.7.tgz", - "integrity": "sha512-lT9kO5gFHQdJzu9a0btcOtNaJHkhenSl8H5mcpgXN9VIMXP59rnkpbdHmPrteixWs1D5zFOTyoTYX3b7joADIQ==", + "version": "14.16.8", + "resolved": "https://registry.npmmirror.com/rc-select/-/rc-select-14.16.8.tgz", + "integrity": "sha512-NOV5BZa1wZrsdkKaiK7LHRuo5ZjZYMDxPP6/1+09+FB4KoNi8jcG1ZqLE3AVCxEsYMBe65OBx71wFoHRTP3LRg==", "dependencies": { "@babel/runtime": "^7.10.1", "@rc-component/trigger": "^2.1.1", @@ -7943,9 +7956,9 @@ } }, "node_modules/rc-table": { - "version": "7.50.4", - "resolved": "https://registry.npmmirror.com/rc-table/-/rc-table-7.50.4.tgz", - "integrity": "sha512-Y+YuncnQqoS5e7yHvfvlv8BmCvwDYDX/2VixTBEhkMDk9itS9aBINp4nhzXFKiBP/frG4w0pS9d9Rgisl0T1Bw==", + "version": "7.50.5", + "resolved": "https://registry.npmmirror.com/rc-table/-/rc-table-7.50.5.tgz", + "integrity": "sha512-FDZu8aolhSYd3v9KOc3lZOVAU77wmRRu44R0Wfb8Oj1dXRUsloFaXMSl6f7yuWZUxArJTli7k8TEOX2mvhDl4A==", "dependencies": { "@babel/runtime": "^7.10.1", "@rc-component/context": "^1.4.0", @@ -8135,9 +8148,9 @@ "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" }, "node_modules/react-i18next": { - "version": "15.5.1", - "resolved": "https://registry.npmmirror.com/react-i18next/-/react-i18next-15.5.1.tgz", - "integrity": "sha512-C8RZ7N7H0L+flitiX6ASjq9p5puVJU1Z8VyL3OgM/QOMRf40BMZX+5TkpxzZVcTmOLPX5zlti4InEX5pFyiVeA==", + "version": "15.5.2", + "resolved": "https://registry.npmmirror.com/react-i18next/-/react-i18next-15.5.2.tgz", + "integrity": "sha512-ePODyXgmZQAOYTbZXQn5rRsSBu3Gszo69jxW6aKmlSgxKAI1fOhDwSu6bT4EKHciWPKQ7v7lPrjeiadR6Gi+1A==", "dependencies": { "@babel/runtime": "^7.25.0", "html-parse-stringify": "^3.0.1" @@ -8179,9 +8192,9 @@ } }, "node_modules/react-router": { - "version": "7.6.0", - "resolved": "https://registry.npmmirror.com/react-router/-/react-router-7.6.0.tgz", - "integrity": "sha512-GGufuHIVCJDbnIAXP3P9Sxzq3UUsddG3rrI3ut1q6m0FI6vxVBF3JoPQ38+W/blslLH4a5Yutp8drkEpXoddGQ==", + "version": "7.6.1", + "resolved": "https://registry.npmmirror.com/react-router/-/react-router-7.6.1.tgz", + "integrity": "sha512-hPJXXxHJZEsPFNVbtATH7+MMX43UDeOauz+EAU4cgqTn7ojdI9qQORqS8Z0qmDlL1TclO/6jLRYUEtbWidtdHQ==", "dependencies": { "cookie": "^1.0.1", "set-cookie-parser": "^2.6.0" @@ -8200,11 +8213,11 @@ } }, "node_modules/react-router-dom": { - "version": "7.6.0", - "resolved": "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-7.6.0.tgz", - "integrity": "sha512-DYgm6RDEuKdopSyGOWZGtDfSm7Aofb8CCzgkliTjtu/eDuB0gcsv6qdFhhi8HdtmA+KHkt5MfZ5K2PdzjugYsA==", + "version": "7.6.1", + "resolved": "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-7.6.1.tgz", + "integrity": "sha512-vxU7ei//UfPYQ3iZvHuO1D/5fX3/JOqhNTbRR+WjSBWxf9bIvpWK+ftjmdfJHzPOuMQKe2fiEdG+dZX6E8uUpA==", "dependencies": { - "react-router": "7.6.0" + "react-router": "7.6.1" }, "engines": { "node": ">=20.0.0" @@ -8286,7 +8299,8 @@ "node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true }, "node_modules/regenerator-transform": { "version": "0.15.2", @@ -9926,17 +9940,17 @@ } }, "node_modules/zod": { - "version": "3.24.4", - "resolved": "https://registry.npmmirror.com/zod/-/zod-3.24.4.tgz", - "integrity": "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==", + "version": "3.25.28", + "resolved": "https://registry.npmmirror.com/zod/-/zod-3.25.28.tgz", + "integrity": "sha512-/nt/67WYKnr5by3YS7LroZJbtcCBurDKKPBPWWzaxvVCGuG/NOsiKkrjoOhI8mJ+SQUXEbUzeB3S+6XDUEEj7Q==", "funding": { "url": "https://github.com/sponsors/colinhacks" } }, "node_modules/zustand": { - "version": "5.0.4", - "resolved": "https://registry.npmmirror.com/zustand/-/zustand-5.0.4.tgz", - "integrity": "sha512-39VFTN5InDtMd28ZhjLyuTnlytDr9HfwO512Ai4I8ZABCoyAj4F1+sr7sD1jP/+p7k77Iko0Pb5NhgBFDCX0kQ==", + "version": "5.0.5", + "resolved": "https://registry.npmmirror.com/zustand/-/zustand-5.0.5.tgz", + "integrity": "sha512-mILtRfKW9xM47hqxGIxCv12gXusoY/xTSHBYApXozR0HmQv299whhBeeAcRy+KrPPybzosvJBCOmVjq6x12fCg==", "engines": { "node": ">=12.20.0" }, diff --git a/ui/package.json b/ui/package.json index bec7eda9..b8383a99 100644 --- a/ui/package.json +++ b/ui/package.json @@ -19,27 +19,27 @@ "@uiw/codemirror-extensions-basic-setup": "^4.23.12", "@uiw/codemirror-theme-vscode": "^4.23.12", "@uiw/react-codemirror": "^4.23.12", - "ahooks": "^3.8.4", - "antd": "^5.25.1", + "ahooks": "^3.8.5", + "antd": "^5.25.3", "antd-zod": "^6.1.0", "clsx": "^2.1.1", "cron-parser": "^5.2.0", "file-saver": "^2.0.5", - "i18next": "^25.1.2", + "i18next": "^25.2.1", "i18next-browser-languagedetector": "^8.1.0", "immer": "^10.1.1", - "lucide-react": "^0.509.0", + "lucide-react": "^0.511.0", "nanoid": "^5.1.5", "pocketbase": "^0.26.0", "radash": "^12.1.0", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", - "react-i18next": "^15.5.1", - "react-router-dom": "^7.6.0", + "react-i18next": "^15.5.2", + "react-router-dom": "^7.6.1", "tailwind-merge": "^2.6.0", - "zod": "^3.24.4", - "zustand": "^5.0.4" + "zod": "^3.25.28", + "zustand": "^5.0.5" }, "devDependencies": { "@types/file-saver": "^2.0.7", @@ -48,10 +48,10 @@ "@types/react": "^18.3.12", "@types/react-copy-to-clipboard": "^5.0.7", "@types/react-dom": "^18.3.1", - "@typescript-eslint/eslint-plugin": "^8.32.0", - "@typescript-eslint/parser": "^8.32.0", + "@typescript-eslint/eslint-plugin": "^8.32.1", + "@typescript-eslint/parser": "^8.32.1", "@vitejs/plugin-legacy": "^6.1.1", - "@vitejs/plugin-react": "^4.4.1", + "@vitejs/plugin-react": "^4.5.0", "autoprefixer": "^10.4.21", "eslint": "^8.57.0", "eslint-config-prettier": "^10.1.5", From bf1d03a30efda4f84e7915fe02b17129bbf54ddd Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Mon, 26 May 2025 21:49:37 +0800 Subject: [PATCH 11/11] feat(migration): tracer --- migrations/1739462400_collections_snapshot.go | 15 +- migrations/1740050400_upgrade.go | 34 ++-- migrations/1742209200_upgrade.go | 14 ++ migrations/1742392800_upgrade.go | 144 ++++++++------- migrations/1742644800_upgrade.go | 12 ++ migrations/1743264000_upgrade.go | 11 +- migrations/1744192800_upgrade.go | 164 +++++++++-------- migrations/1744459000_upgrade.go | 166 ++++++++++-------- migrations/1745308800_upgrade.go | 161 +++++++++-------- migrations/1745726400_upgrade.go | 42 +++-- migrations/1747314000_upgrade.go | 24 ++- migrations/1747389600_upgrade.go | 26 ++- migrations/1748178000_upgrade.go | 32 ++-- migrations/1748228400_upgrade.go | 6 + migrations/tracer.go | 22 +++ 15 files changed, 518 insertions(+), 355 deletions(-) create mode 100644 migrations/tracer.go diff --git a/migrations/1739462400_collections_snapshot.go b/migrations/1739462400_collections_snapshot.go index 25564526..2f78e7b9 100644 --- a/migrations/1739462400_collections_snapshot.go +++ b/migrations/1739462400_collections_snapshot.go @@ -2,7 +2,6 @@ package migrations import ( x509 "crypto/x509" - "log/slog" "strings" "github.com/pocketbase/pocketbase/core" @@ -12,7 +11,8 @@ import ( func init() { m.Register(func(app core.App) error { - slog.Info("[CERTIMATE] migration: ready ...") + tracer := NewTracer("to v0.3") + tracer.Printf("go ...") // backup collection records collectionRecords := make([]*core.Record, 0) @@ -30,7 +30,7 @@ func init() { } collectionRecords = append(collectionRecords, records...) - slog.Info("[CERTIMATE] migration: collection '" + collection.Name + "' backed up") + tracer.Printf("collection '%s' backed up", collection.Name) if collection.Name == "access" { collection.Fields.RemoveByName("usage") @@ -107,7 +107,7 @@ func init() { { app.Delete(collection) - slog.Info("[CERTIMATE] migration: collection '" + collection.Name + "' truncated") + tracer.Printf("collection '%s' truncated", collection.Name) } } } @@ -1729,7 +1729,7 @@ func init() { return err } - slog.Info("[CERTIMATE] migration: collections imported") + tracer.Printf("collections imported") // restore records for _, record := range collectionRecords { @@ -1795,12 +1795,11 @@ func init() { return err } - slog.Info("[CERTIMATE] migration: collection '" + record.Collection().Name + "' record #" + record.Id + " updated") + tracer.Printf("record #%s in collection '%s' updated", record.Id, record.Collection().Name) } } - slog.Info("[CERTIMATE] migration: done") - + tracer.Printf("done") return nil }, func(app core.App) error { return nil diff --git a/migrations/1740050400_upgrade.go b/migrations/1740050400_upgrade.go index 93bc3f33..261169f8 100644 --- a/migrations/1740050400_upgrade.go +++ b/migrations/1740050400_upgrade.go @@ -7,14 +7,17 @@ import ( func init() { m.Register(func(app core.App) error { + tracer := NewTracer("(v0.3)1740050400") + tracer.Printf("go ...") + // update collection `certificate` { - certimateCollection, err := app.FindCollectionByNameOrId("4szxr9x43tpj6np") + collection, err := app.FindCollectionByNameOrId("4szxr9x43tpj6np") if err != nil { return err } - if err := certimateCollection.Fields.AddMarshaledJSONAt(4, []byte(`{ + if err := collection.Fields.AddMarshaledJSONAt(4, []byte(`{ "autogeneratePattern": "", "hidden": false, "id": "plmambpz", @@ -31,7 +34,7 @@ func init() { return err } - if err := certimateCollection.Fields.AddMarshaledJSONAt(5, []byte(`{ + if err := collection.Fields.AddMarshaledJSONAt(5, []byte(`{ "autogeneratePattern": "", "hidden": false, "id": "49qvwxcg", @@ -48,7 +51,7 @@ func init() { return err } - if err := certimateCollection.Fields.AddMarshaledJSONAt(7, []byte(`{ + if err := collection.Fields.AddMarshaledJSONAt(7, []byte(`{ "autogeneratePattern": "", "hidden": false, "id": "agt7n5bb", @@ -65,19 +68,21 @@ func init() { return err } - if err := app.Save(certimateCollection); err != nil { + if err := app.Save(collection); err != nil { return err } + + tracer.Printf("collection '%s' updated", collection.Name) } // update collection `workflow` { - workflowCollection, err := app.FindCollectionByNameOrId("tovyif5ax6j62ur") + collection, err := app.FindCollectionByNameOrId("tovyif5ax6j62ur") if err != nil { return err } - if err := workflowCollection.Fields.AddMarshaledJSONAt(6, []byte(`{ + if err := collection.Fields.AddMarshaledJSONAt(6, []byte(`{ "hidden": false, "id": "awlphkfe", "maxSize": 5000000, @@ -90,7 +95,7 @@ func init() { return err } - if err := workflowCollection.Fields.AddMarshaledJSONAt(7, []byte(`{ + if err := collection.Fields.AddMarshaledJSONAt(7, []byte(`{ "hidden": false, "id": "g9ohkk5o", "maxSize": 5000000, @@ -103,19 +108,21 @@ func init() { return err } - if err := app.Save(workflowCollection); err != nil { + if err := app.Save(collection); err != nil { return err } + + tracer.Printf("collection '%s' updated", collection.Name) } // update collection `workflow_output` { - workflowOutputCollection, err := app.FindCollectionByNameOrId("bqnxb95f2cooowp") + collection, err := app.FindCollectionByNameOrId("bqnxb95f2cooowp") if err != nil { return err } - if err := workflowOutputCollection.Fields.AddMarshaledJSONAt(4, []byte(`{ + if err := collection.Fields.AddMarshaledJSONAt(4, []byte(`{ "hidden": false, "id": "c2rm9omj", "maxSize": 5000000, @@ -128,11 +135,14 @@ func init() { return err } - if err := app.Save(workflowOutputCollection); err != nil { + if err := app.Save(collection); err != nil { return err } + + tracer.Printf("collection '%s' updated", collection.Name) } + tracer.Printf("done") return nil }, func(app core.App) error { return nil diff --git a/migrations/1742209200_upgrade.go b/migrations/1742209200_upgrade.go index 5cda0c35..1bc0d482 100644 --- a/migrations/1742209200_upgrade.go +++ b/migrations/1742209200_upgrade.go @@ -11,6 +11,9 @@ import ( func init() { m.Register(func(app core.App) error { + tracer := NewTracer("(v0.3)1742209200") + tracer.Printf("go ...") + // create collection `workflow_logs` { jsonData := `{ @@ -167,6 +170,8 @@ func init() { if err := app.Save(collection); err != nil { return err } + + tracer.Printf("collection '%s' created", collection.Name) } // migrate data @@ -215,6 +220,8 @@ func init() { if err := app.Save(record); err != nil { return err } + + tracer.Printf("record #%s in collection '%s' updated", record.Id, collection.Name) } } } @@ -243,6 +250,8 @@ func init() { if err := app.Save(collection); err != nil { return err } + + tracer.Printf("collection '%s' updated", collection.Name) } // migrate data @@ -321,6 +330,8 @@ func init() { if err := app.Save(workflowRun); err != nil { return err } + + tracer.Printf("record #%s in collection '%s' updated", workflowRun.Id, workflowRun.Collection().Name) } } @@ -336,8 +347,11 @@ func init() { if err := app.Save(collection); err != nil { return err } + + tracer.Printf("collection '%s' updated", collection.Name) } + tracer.Printf("done") return nil }, func(app core.App) error { return nil diff --git a/migrations/1742392800_upgrade.go b/migrations/1742392800_upgrade.go index a06bdc75..4416936a 100644 --- a/migrations/1742392800_upgrade.go +++ b/migrations/1742392800_upgrade.go @@ -7,74 +7,86 @@ import ( func init() { m.Register(func(app core.App) error { - collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") - if err != nil { - return err + tracer := NewTracer("(v0.3)1742392800") + tracer.Printf("go ...") + + // update collection `access` + { + collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") + if err != nil { + return err + } + + if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{ + "hidden": false, + "id": "hwy7m03o", + "maxSelect": 1, + "name": "provider", + "presentable": false, + "required": false, + "system": false, + "type": "select", + "values": [ + "1panel", + "acmehttpreq", + "akamai", + "aliyun", + "aws", + "azure", + "baiducloud", + "baishan", + "baotapanel", + "byteplus", + "cachefly", + "cdnfly", + "cloudflare", + "cloudns", + "cmcccloud", + "ctcccloud", + "cucccloud", + "dnsla", + "dogecloud", + "dynv6", + "edgio", + "fastly", + "gname", + "gcore", + "godaddy", + "goedge", + "huaweicloud", + "jdcloud", + "k8s", + "local", + "namecheap", + "namedotcom", + "namesilo", + "ns1", + "powerdns", + "qiniu", + "qingcloud", + "rainyun", + "safeline", + "ssh", + "tencentcloud", + "ucloud", + "upyun", + "volcengine", + "webhook", + "westcn" + ] + }`)); err != nil { + return err + } + + if err := app.Save(collection); err != nil { + return err + } + + tracer.Printf("collection '%s' updated", collection.Name) } - // update field - if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{ - "hidden": false, - "id": "hwy7m03o", - "maxSelect": 1, - "name": "provider", - "presentable": false, - "required": false, - "system": false, - "type": "select", - "values": [ - "1panel", - "acmehttpreq", - "akamai", - "aliyun", - "aws", - "azure", - "baiducloud", - "baishan", - "baotapanel", - "byteplus", - "cachefly", - "cdnfly", - "cloudflare", - "cloudns", - "cmcccloud", - "ctcccloud", - "cucccloud", - "dnsla", - "dogecloud", - "dynv6", - "edgio", - "fastly", - "gname", - "gcore", - "godaddy", - "goedge", - "huaweicloud", - "jdcloud", - "k8s", - "local", - "namecheap", - "namedotcom", - "namesilo", - "ns1", - "powerdns", - "qiniu", - "qingcloud", - "rainyun", - "safeline", - "ssh", - "tencentcloud", - "ucloud", - "upyun", - "volcengine", - "webhook", - "westcn" - ] - }`)); err != nil { - return err - } - - return app.Save(collection) + tracer.Printf("done") + return nil }, func(app core.App) error { return nil }) diff --git a/migrations/1742644800_upgrade.go b/migrations/1742644800_upgrade.go index b28634a1..228a70fc 100644 --- a/migrations/1742644800_upgrade.go +++ b/migrations/1742644800_upgrade.go @@ -7,6 +7,9 @@ import ( func init() { m.Register(func(app core.App) error { + tracer := NewTracer("(v0.3)1742644800") + tracer.Printf("go ...") + // update collection `workflow_run` { collection, err := app.FindCollectionByNameOrId("qjp8lygssgwyqyz") @@ -35,6 +38,8 @@ func init() { if err := app.Save(collection); err != nil { return err } + + tracer.Printf("collection '%s' updated", collection.Name) } // update collection `workflow_output` @@ -61,6 +66,8 @@ func init() { if err := app.Save(collection); err != nil { return err } + + tracer.Printf("collection '%s' updated", collection.Name) } // update collection `workflow_logs` @@ -105,6 +112,8 @@ func init() { if err := app.Save(collection); err != nil { return err } + + tracer.Printf("collection '%s' updated", collection.Name) } // update collection `access` @@ -182,8 +191,11 @@ func init() { if err := app.Save(collection); err != nil { return err } + + tracer.Printf("collection '%s' updated", collection.Name) } + tracer.Printf("done") return nil }, func(app core.App) error { return nil diff --git a/migrations/1743264000_upgrade.go b/migrations/1743264000_upgrade.go index 75f98b30..22738be2 100644 --- a/migrations/1743264000_upgrade.go +++ b/migrations/1743264000_upgrade.go @@ -7,6 +7,9 @@ import ( func init() { m.Register(func(app core.App) error { + tracer := NewTracer("(v0.3)1743264000") + tracer.Printf("go ...") + // update collection `settings` { collection, err := app.FindCollectionByNameOrId("dy6ccjb60spfy6p") @@ -52,6 +55,8 @@ func init() { if err := app.Save(record); err != nil { return err } + + tracer.Printf("record #%s in collection '%s' updated", record.Id, collection.Name) } } @@ -62,7 +67,6 @@ func init() { return err } - // update field if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{ "hidden": false, "id": "hwy7m03o", @@ -136,6 +140,8 @@ func init() { if err := app.Save(collection); err != nil { return err } + + tracer.Printf("collection '%s' updated", collection.Name) } // update collection `acme_accounts` @@ -163,9 +169,12 @@ func init() { if err := app.Save(record); err != nil { return err } + + tracer.Printf("record #%s in collection '%s' updated", record.Id, collection.Name) } } + tracer.Printf("done") return nil }, func(app core.App) error { return nil diff --git a/migrations/1744192800_upgrade.go b/migrations/1744192800_upgrade.go index 83e83ee6..eb4c6d06 100644 --- a/migrations/1744192800_upgrade.go +++ b/migrations/1744192800_upgrade.go @@ -7,84 +7,96 @@ import ( func init() { m.Register(func(app core.App) error { - collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") - if err != nil { - return err + tracer := NewTracer("(v0.3)1744192800") + tracer.Printf("go ...") + + // update collection `access` + { + collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") + if err != nil { + return err + } + + if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{ + "hidden": false, + "id": "hwy7m03o", + "maxSelect": 1, + "name": "provider", + "presentable": false, + "required": false, + "system": false, + "type": "select", + "values": [ + "1panel", + "acmehttpreq", + "akamai", + "aliyun", + "aws", + "azure", + "baiducloud", + "baishan", + "baotapanel", + "byteplus", + "buypass", + "cachefly", + "cdnfly", + "cloudflare", + "cloudns", + "cmcccloud", + "ctcccloud", + "cucccloud", + "desec", + "dnsla", + "dogecloud", + "dynv6", + "edgio", + "fastly", + "gname", + "gcore", + "godaddy", + "goedge", + "googletrustservices", + "huaweicloud", + "jdcloud", + "k8s", + "letsencrypt", + "letsencryptstaging", + "local", + "namecheap", + "namedotcom", + "namesilo", + "ns1", + "porkbun", + "powerdns", + "qiniu", + "qingcloud", + "rainyun", + "safeline", + "ssh", + "sslcom", + "tencentcloud", + "ucloud", + "upyun", + "vercel", + "volcengine", + "wangsu", + "webhook", + "westcn", + "zerossl" + ] + }`)); err != nil { + return err + } + + if err := app.Save(collection); err != nil { + return nil + } + + tracer.Printf("collection '%s' updated", collection.Name) } - // update field - if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{ - "hidden": false, - "id": "hwy7m03o", - "maxSelect": 1, - "name": "provider", - "presentable": false, - "required": false, - "system": false, - "type": "select", - "values": [ - "1panel", - "acmehttpreq", - "akamai", - "aliyun", - "aws", - "azure", - "baiducloud", - "baishan", - "baotapanel", - "byteplus", - "buypass", - "cachefly", - "cdnfly", - "cloudflare", - "cloudns", - "cmcccloud", - "ctcccloud", - "cucccloud", - "desec", - "dnsla", - "dogecloud", - "dynv6", - "edgio", - "fastly", - "gname", - "gcore", - "godaddy", - "goedge", - "googletrustservices", - "huaweicloud", - "jdcloud", - "k8s", - "letsencrypt", - "letsencryptstaging", - "local", - "namecheap", - "namedotcom", - "namesilo", - "ns1", - "porkbun", - "powerdns", - "qiniu", - "qingcloud", - "rainyun", - "safeline", - "ssh", - "sslcom", - "tencentcloud", - "ucloud", - "upyun", - "vercel", - "volcengine", - "wangsu", - "webhook", - "westcn", - "zerossl" - ] - }`)); err != nil { - return err - } - - return app.Save(collection) + tracer.Printf("done") + return nil }, func(app core.App) error { return nil }) diff --git a/migrations/1744459000_upgrade.go b/migrations/1744459000_upgrade.go index 4b2bbba9..82ecbcf6 100644 --- a/migrations/1744459000_upgrade.go +++ b/migrations/1744459000_upgrade.go @@ -7,85 +7,97 @@ import ( func init() { m.Register(func(app core.App) error { - collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") - if err != nil { - return err + tracer := NewTracer("(v0.3)1744459000") + tracer.Printf("go ...") + + // update collection `access` + { + collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") + if err != nil { + return err + } + + if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{ + "hidden": false, + "id": "hwy7m03o", + "maxSelect": 1, + "name": "provider", + "presentable": false, + "required": false, + "system": false, + "type": "select", + "values": [ + "1panel", + "acmehttpreq", + "akamai", + "aliyun", + "aws", + "azure", + "baiducloud", + "baishan", + "baotapanel", + "bunny", + "byteplus", + "buypass", + "cachefly", + "cdnfly", + "cloudflare", + "cloudns", + "cmcccloud", + "ctcccloud", + "cucccloud", + "desec", + "dnsla", + "dogecloud", + "dynv6", + "edgio", + "fastly", + "gname", + "gcore", + "godaddy", + "goedge", + "googletrustservices", + "huaweicloud", + "jdcloud", + "k8s", + "letsencrypt", + "letsencryptstaging", + "local", + "namecheap", + "namedotcom", + "namesilo", + "ns1", + "porkbun", + "powerdns", + "qiniu", + "qingcloud", + "rainyun", + "safeline", + "ssh", + "sslcom", + "tencentcloud", + "ucloud", + "upyun", + "vercel", + "volcengine", + "wangsu", + "webhook", + "westcn", + "zerossl" + ] + }`)); err != nil { + return err + } + + if err := app.Save(collection); err != nil { + return err + } + + tracer.Printf("collection '%s' updated", collection.Name) } - // update field - if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{ - "hidden": false, - "id": "hwy7m03o", - "maxSelect": 1, - "name": "provider", - "presentable": false, - "required": false, - "system": false, - "type": "select", - "values": [ - "1panel", - "acmehttpreq", - "akamai", - "aliyun", - "aws", - "azure", - "baiducloud", - "baishan", - "baotapanel", - "bunny", - "byteplus", - "buypass", - "cachefly", - "cdnfly", - "cloudflare", - "cloudns", - "cmcccloud", - "ctcccloud", - "cucccloud", - "desec", - "dnsla", - "dogecloud", - "dynv6", - "edgio", - "fastly", - "gname", - "gcore", - "godaddy", - "goedge", - "googletrustservices", - "huaweicloud", - "jdcloud", - "k8s", - "letsencrypt", - "letsencryptstaging", - "local", - "namecheap", - "namedotcom", - "namesilo", - "ns1", - "porkbun", - "powerdns", - "qiniu", - "qingcloud", - "rainyun", - "safeline", - "ssh", - "sslcom", - "tencentcloud", - "ucloud", - "upyun", - "vercel", - "volcengine", - "wangsu", - "webhook", - "westcn", - "zerossl" - ] - }`)); err != nil { - return err - } - - return app.Save(collection) + tracer.Printf("done") + return nil }, func(app core.App) error { return nil }) diff --git a/migrations/1745308800_upgrade.go b/migrations/1745308800_upgrade.go index 989664fb..68d025fd 100644 --- a/migrations/1745308800_upgrade.go +++ b/migrations/1745308800_upgrade.go @@ -9,84 +9,93 @@ import ( func init() { m.Register(func(app core.App) error { - collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") - if err != nil { - return err - } - - // add temp field `providerTmp` - if err := collection.Fields.AddMarshaledJSONAt(3, []byte(`{ - "autogeneratePattern": "", - "hidden": false, - "id": "text2024822322", - "max": 0, - "min": 0, - "name": "providerTmp", - "pattern": "", - "presentable": false, - "primaryKey": false, - "required": false, - "system": false, - "type": "text" - }`)); err != nil { - return err - } - if err := app.Save(collection); err != nil { - return err - } - - // copy `provider` to `providerTmp` - if _, err := app.DB().NewQuery("UPDATE access SET providerTmp = provider").Execute(); err != nil { - return err - } - - // remove old field `provider` - collection.Fields.RemoveById("hwy7m03o") - if err := json.Unmarshal([]byte(`{ - "indexes": [ - "CREATE INDEX `+"`"+`idx_wkoST0j`+"`"+` ON `+"`"+`access`+"`"+` (`+"`"+`name`+"`"+`)" - ] - }`), &collection); err != nil { - return err - } - if err := app.Save(collection); err != nil { - return err - } - - // rename field `providerTmp` to `provider` - if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{ - "autogeneratePattern": "", - "hidden": false, - "id": "text2024822322", - "max": 0, - "min": 0, - "name": "provider", - "pattern": "", - "presentable": false, - "primaryKey": false, - "required": false, - "system": false, - "type": "text" - }`)); err != nil { - return err - } - if err := app.Save(collection); err != nil { - return err - } - - // rebuild indexes - if err := json.Unmarshal([]byte(`{ - "indexes": [ - "CREATE INDEX `+"`"+`idx_wkoST0j`+"`"+` ON `+"`"+`access`+"`"+` (`+"`"+`name`+"`"+`)", - "CREATE INDEX `+"`"+`idx_frh0JT1Aqx`+"`"+` ON `+"`"+`access`+"`"+` (`+"`"+`provider`+"`"+`)" - ] - }`), &collection); err != nil { - return err - } - if err := app.Save(collection); err != nil { - return err + tracer := NewTracer("(v0.3)1745308800") + tracer.Printf("go ...") + + // update collection `access` + { + collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") + if err != nil { + return err + } + + // add temp field `providerTmp` + if err := collection.Fields.AddMarshaledJSONAt(3, []byte(`{ + "autogeneratePattern": "", + "hidden": false, + "id": "text2024822322", + "max": 0, + "min": 0, + "name": "providerTmp", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": false, + "system": false, + "type": "text" + }`)); err != nil { + return err + } + if err := app.Save(collection); err != nil { + return err + } + + // copy `provider` to `providerTmp` + if _, err := app.DB().NewQuery("UPDATE access SET providerTmp = provider").Execute(); err != nil { + return err + } + + // remove old field `provider` + collection.Fields.RemoveById("hwy7m03o") + if err := json.Unmarshal([]byte(`{ + "indexes": [ + "CREATE INDEX `+"`"+`idx_wkoST0j`+"`"+` ON `+"`"+`access`+"`"+` (`+"`"+`name`+"`"+`)" + ] + }`), &collection); err != nil { + return err + } + if err := app.Save(collection); err != nil { + return err + } + + // rename field `providerTmp` to `provider` + if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{ + "autogeneratePattern": "", + "hidden": false, + "id": "text2024822322", + "max": 0, + "min": 0, + "name": "provider", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": false, + "system": false, + "type": "text" + }`)); err != nil { + return err + } + if err := app.Save(collection); err != nil { + return err + } + + // rebuild indexes + if err := json.Unmarshal([]byte(`{ + "indexes": [ + "CREATE INDEX `+"`"+`idx_wkoST0j`+"`"+` ON `+"`"+`access`+"`"+` (`+"`"+`name`+"`"+`)", + "CREATE INDEX `+"`"+`idx_frh0JT1Aqx`+"`"+` ON `+"`"+`access`+"`"+` (`+"`"+`provider`+"`"+`)" + ] + }`), &collection); err != nil { + return err + } + if err := app.Save(collection); err != nil { + return err + } + + tracer.Printf("collection '%s' updated", collection.Name) } + tracer.Printf("done") return nil }, func(app core.App) error { return nil diff --git a/migrations/1745726400_upgrade.go b/migrations/1745726400_upgrade.go index e4449f36..0513dac4 100644 --- a/migrations/1745726400_upgrade.go +++ b/migrations/1745726400_upgrade.go @@ -7,6 +7,9 @@ import ( func init() { m.Register(func(app core.App) error { + tracer := NewTracer("(v0.3)1745726400") + tracer.Printf("go ...") + // update collection `access` { collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") @@ -34,53 +37,62 @@ func init() { if err := app.Save(collection); err != nil { return err } + + tracer.Printf("collection '%s' updated", collection.Name) } // migrate data { - accesses, err := app.FindAllRecords("access") + collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") if err != nil { return err } - for _, access := range accesses { + records, err := app.FindAllRecords(collection) + if err != nil { + return err + } + + for _, record := range records { changed := false - if access.GetString("provider") == "buypass" { - access.Set("reserve", "ca") + if record.GetString("provider") == "buypass" { + record.Set("reserve", "ca") changed = true - } else if access.GetString("provider") == "googletrustservices" { - access.Set("reserve", "ca") + } else if record.GetString("provider") == "googletrustservices" { + record.Set("reserve", "ca") changed = true - } else if access.GetString("provider") == "sslcom" { - access.Set("reserve", "ca") + } else if record.GetString("provider") == "sslcom" { + record.Set("reserve", "ca") changed = true - } else if access.GetString("provider") == "zerossl" { - access.Set("reserve", "ca") + } else if record.GetString("provider") == "zerossl" { + record.Set("reserve", "ca") changed = true } - if access.GetString("provider") == "webhook" { + if record.GetString("provider") == "webhook" { config := make(map[string]any) - if err := access.UnmarshalJSONField("config", &config); err != nil { + if err := record.UnmarshalJSONField("config", &config); err != nil { return err } config["method"] = "POST" config["headers"] = "Content-Type: application/json" - access.Set("config", config) + record.Set("config", config) changed = true } if changed { - err = app.Save(access) - if err != nil { + if err := app.Save(record); err != nil { return err } + + tracer.Printf("record #%s in collection '%s' updated", record.Id, collection.Name) } } } + tracer.Printf("done") return nil }, func(app core.App) error { return nil diff --git a/migrations/1747314000_upgrade.go b/migrations/1747314000_upgrade.go index 19a25bb2..2c3ecdc4 100644 --- a/migrations/1747314000_upgrade.go +++ b/migrations/1747314000_upgrade.go @@ -7,36 +7,46 @@ import ( func init() { m.Register(func(app core.App) error { + tracer := NewTracer("(v0.3)1747314000") + tracer.Printf("go ...") + // migrate data { - accesses, err := app.FindAllRecords("access") + collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") if err != nil { return err } - for _, access := range accesses { + records, err := app.FindAllRecords(collection) + if err != nil { + return err + } + + for _, record := range records { changed := false - if access.GetString("provider") == "goedge" { + if record.GetString("provider") == "goedge" { config := make(map[string]any) - if err := access.UnmarshalJSONField("config", &config); err != nil { + if err := record.UnmarshalJSONField("config", &config); err != nil { return err } config["apiRole"] = "user" - access.Set("config", config) + record.Set("config", config) changed = true } if changed { - err = app.Save(access) - if err != nil { + if err := app.Save(record); err != nil { return err } + + tracer.Printf("record #%s in collection '%s' updated", record.Id, collection.Name) } } } + tracer.Printf("done") return nil }, func(app core.App) error { return nil diff --git a/migrations/1747389600_upgrade.go b/migrations/1747389600_upgrade.go index a145679a..fabc562c 100644 --- a/migrations/1747389600_upgrade.go +++ b/migrations/1747389600_upgrade.go @@ -7,6 +7,9 @@ import ( func init() { m.Register(func(app core.App) error { + tracer := NewTracer("(v0.3)1747389600") + tracer.Printf("go ...") + // update collection `certificate` { collection, err := app.FindCollectionByNameOrId("4szxr9x43tpj6np") @@ -34,38 +37,47 @@ func init() { if err := app.Save(collection); err != nil { return err } + + tracer.Printf("collection '%s' updated", collection.Name) } // migrate data { - accesses, err := app.FindAllRecords("access") + collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") if err != nil { return err } - for _, access := range accesses { + records, err := app.FindAllRecords(collection) + if err != nil { + return err + } + + for _, record := range records { changed := false - if access.GetString("provider") == "1panel" { + if record.GetString("provider") == "1panel" { config := make(map[string]any) - if err := access.UnmarshalJSONField("config", &config); err != nil { + if err := record.UnmarshalJSONField("config", &config); err != nil { return err } config["apiVersion"] = "v1" - access.Set("config", config) + record.Set("config", config) changed = true } if changed { - err = app.Save(access) - if err != nil { + if err := app.Save(record); err != nil { return err } + + tracer.Printf("record #%s in collection '%s' updated", record.Id, collection.Name) } } } + tracer.Printf("done") return nil }, func(app core.App) error { return nil diff --git a/migrations/1748178000_upgrade.go b/migrations/1748178000_upgrade.go index 719ed64f..44783448 100644 --- a/migrations/1748178000_upgrade.go +++ b/migrations/1748178000_upgrade.go @@ -9,9 +9,17 @@ import ( func init() { m.Register(func(app core.App) error { + tracer := NewTracer("(v0.3)1748178000") + tracer.Printf("go ...") + // migrate data { - accesses, err := app.FindAllRecords("access") + collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") + if err != nil { + return err + } + + records, err := app.FindAllRecords(collection) if err != nil { return err } @@ -29,30 +37,34 @@ func init() { "ratpanel", "safeline", } - for _, access := range accesses { + for _, record := range records { changed := false - if slices.Contains(providersToUpdate, access.GetString("provider")) { + if slices.Contains(providersToUpdate, record.GetString("provider")) { config := make(map[string]any) - if err := access.UnmarshalJSONField("config", &config); err != nil { + if err := record.UnmarshalJSONField("config", &config); err != nil { return err } - config["serverUrl"] = config["apiUrl"] - delete(config, "apiUrl") - access.Set("config", config) - changed = true + if config["apiUrl"] != nil { + config["serverUrl"] = config["apiUrl"] + delete(config, "apiUrl") + record.Set("config", config) + changed = true + } } if changed { - err = app.Save(access) - if err != nil { + if err := app.Save(record); err != nil { return err } + + tracer.Printf("record #%s in collection '%s' updated", record.Id, collection.Name) } } } + tracer.Printf("done") return nil }, func(app core.App) error { return nil diff --git a/migrations/1748228400_upgrade.go b/migrations/1748228400_upgrade.go index b6f954d2..afdfd850 100644 --- a/migrations/1748228400_upgrade.go +++ b/migrations/1748228400_upgrade.go @@ -7,6 +7,9 @@ import ( func init() { m.Register(func(app core.App) error { + tracer := NewTracer("(v0.3)1748228400") + tracer.Printf("go ...") + // update collection `certificate` { collection, err := app.FindCollectionByNameOrId("4szxr9x43tpj6np") @@ -30,8 +33,11 @@ func init() { if err := app.Save(collection); err != nil { return err } + + tracer.Printf("collection '%s' updated", collection.Name) } + tracer.Printf("done") return nil }, func(app core.App) error { return nil diff --git a/migrations/tracer.go b/migrations/tracer.go new file mode 100644 index 00000000..04f58e54 --- /dev/null +++ b/migrations/tracer.go @@ -0,0 +1,22 @@ +package migrations + +import ( + "fmt" + "log/slog" +) + +type Tracer struct { + logger *slog.Logger + flag string +} + +func NewTracer(flag string) *Tracer { + return &Tracer{ + logger: slog.Default(), + flag: flag, + } +} + +func (l *Tracer) Printf(format string, args ...any) { + l.logger.Info("[CERTIMATE] migration " + l.flag + ": " + fmt.Sprintf(format, args...)) +}