From 7478dd7f471b69eeca0a3cd499389dd48473acb4 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Thu, 24 Apr 2025 20:27:20 +0800 Subject: [PATCH] feat: deprecate old notification module and introduce new notifier module --- internal/domain/notify.go | 1 + internal/domain/provider.go | 250 +++++++++--------- internal/domain/settings.go | 3 + internal/domain/workflow.go | 26 +- internal/notify/notifier.go | 72 +++++ internal/notify/notify.go | 7 +- internal/notify/providers.go | 98 +------ internal/notify/providers_deprecated.go | 108 ++++++++ internal/notify/service.go | 5 + internal/pkg/utils/map/getter.go | 2 +- .../workflow/node-processor/apply_node.go | 7 +- .../workflow/node-processor/deploy_node.go | 11 +- .../workflow/node-processor/notify_node.go | 51 +++- .../provider/NotifyProviderSelect.tsx | 67 +++++ .../components/workflow/WorkflowRunDetail.tsx | 6 +- .../components/workflow/node/NotifyNode.tsx | 7 +- .../workflow/node/NotifyNodeConfigForm.tsx | 118 ++++++++- ui/src/domain/provider.ts | 53 +++- ui/src/domain/settings.ts | 17 +- ui/src/domain/workflow.ts | 8 +- .../i18n/locales/en/nls.workflow.nodes.json | 7 +- .../i18n/locales/zh/nls.workflow.nodes.json | 9 +- ui/src/pages/accesses/AccessList.tsx | 10 +- ui/src/pages/certificates/CertificateList.tsx | 1 + .../pages/settings/SettingsNotification.tsx | 6 +- ui/src/pages/workflows/WorkflowList.tsx | 1 + ui/src/stores/notify/index.ts | 6 + 27 files changed, 692 insertions(+), 265 deletions(-) create mode 100644 internal/notify/notifier.go create mode 100644 internal/notify/providers_deprecated.go create mode 100644 ui/src/components/provider/NotifyProviderSelect.tsx diff --git a/internal/domain/notify.go b/internal/domain/notify.go index 6142dae5..1a244e9b 100644 --- a/internal/domain/notify.go +++ b/internal/domain/notify.go @@ -8,6 +8,7 @@ type NotifyChannelType string 注意:如果追加新的常量值,请保持以 ASCII 排序。 NOTICE: If you add new constant, please keep ASCII order. */ +// Deprecated: v0.4.x 将废弃 const ( NotifyChannelTypeBark = NotifyChannelType("bark") NotifyChannelTypeDingTalk = NotifyChannelType("dingtalk") diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 267adc12..5345215a 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -19,6 +19,7 @@ const ( AccessProviderTypeBaishan = AccessProviderType("baishan") AccessProviderTypeBaotaPanel = AccessProviderType("baotapanel") AccessProviderTypeBytePlus = AccessProviderType("byteplus") + AccessProviderTypeBunny = AccessProviderType("bunny") AccessProviderTypeBuypass = AccessProviderType("buypass") AccessProviderTypeCacheFly = AccessProviderType("cachefly") AccessProviderTypeCdnfly = AccessProviderType("cdnfly") @@ -71,18 +72,18 @@ type ApplyCAProviderType string /* 申请证书 CA 提供商常量值。 -始终等于授权提供商类型。 +短横线前的部分始终等于授权提供商类型。 注意:如果追加新的常量值,请保持以 ASCII 排序。 NOTICE: If you add new constant, please keep ASCII order. */ const ( - ApplyCAProviderTypeBuypass = ApplyCAProviderType(string(AccessProviderTypeBuypass)) - ApplyCAProviderTypeGoogleTrustServices = ApplyCAProviderType(string(AccessProviderTypeGoogleTrustServices)) - ApplyCAProviderTypeLetsEncrypt = ApplyCAProviderType(string(AccessProviderTypeLetsEncrypt)) - ApplyCAProviderTypeLetsEncryptStaging = ApplyCAProviderType(string(AccessProviderTypeLetsEncryptStaging)) - ApplyCAProviderTypeSSLCom = ApplyCAProviderType(string(AccessProviderTypeSSLCOM)) - ApplyCAProviderTypeZeroSSL = ApplyCAProviderType(string(AccessProviderTypeZeroSSL)) + ApplyCAProviderTypeBuypass = ApplyCAProviderType(AccessProviderTypeBuypass) + ApplyCAProviderTypeGoogleTrustServices = ApplyCAProviderType(AccessProviderTypeGoogleTrustServices) + ApplyCAProviderTypeLetsEncrypt = ApplyCAProviderType(AccessProviderTypeLetsEncrypt) + ApplyCAProviderTypeLetsEncryptStaging = ApplyCAProviderType(AccessProviderTypeLetsEncryptStaging) + ApplyCAProviderTypeSSLCom = ApplyCAProviderType(AccessProviderTypeSSLCOM) + ApplyCAProviderTypeZeroSSL = ApplyCAProviderType(AccessProviderTypeZeroSSL) ) type ApplyDNSProviderType string @@ -95,43 +96,43 @@ type ApplyDNSProviderType string NOTICE: If you add new constant, please keep ASCII order. */ const ( - ApplyDNSProviderTypeACMEHttpReq = ApplyDNSProviderType("acmehttpreq") - ApplyDNSProviderTypeAliyun = ApplyDNSProviderType("aliyun") // 兼容旧值,等同于 [ApplyDNSProviderTypeAliyunDNS] - ApplyDNSProviderTypeAliyunDNS = ApplyDNSProviderType("aliyun-dns") - ApplyDNSProviderTypeAWS = ApplyDNSProviderType("aws") // 兼容旧值,等同于 [ApplyDNSProviderTypeAWSRoute53] - ApplyDNSProviderTypeAWSRoute53 = ApplyDNSProviderType("aws-route53") - ApplyDNSProviderTypeAzure = ApplyDNSProviderType("azure") // 兼容旧值,等同于 [ApplyDNSProviderTypeAzure] - ApplyDNSProviderTypeAzureDNS = ApplyDNSProviderType("azure-dns") - ApplyDNSProviderTypeBaiduCloud = ApplyDNSProviderType("baiducloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeBaiduCloudDNS] - ApplyDNSProviderTypeBaiduCloudDNS = ApplyDNSProviderType("baiducloud-dns") - ApplyDNSProviderTypeBunny = ApplyDNSProviderType("bunny") - ApplyDNSProviderTypeCloudflare = ApplyDNSProviderType("cloudflare") - ApplyDNSProviderTypeClouDNS = ApplyDNSProviderType("cloudns") - ApplyDNSProviderTypeCMCCCloud = ApplyDNSProviderType("cmcccloud") - ApplyDNSProviderTypeDeSEC = ApplyDNSProviderType("desec") - ApplyDNSProviderTypeDNSLA = ApplyDNSProviderType("dnsla") - ApplyDNSProviderTypeDynv6 = ApplyDNSProviderType("dynv6") - ApplyDNSProviderTypeGcore = ApplyDNSProviderType("gcore") - ApplyDNSProviderTypeGname = ApplyDNSProviderType("gname") - ApplyDNSProviderTypeGoDaddy = ApplyDNSProviderType("godaddy") - ApplyDNSProviderTypeHuaweiCloud = ApplyDNSProviderType("huaweicloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeHuaweiCloudDNS] - ApplyDNSProviderTypeHuaweiCloudDNS = ApplyDNSProviderType("huaweicloud-dns") - ApplyDNSProviderTypeJDCloud = ApplyDNSProviderType("jdcloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeJDCloudDNS] - ApplyDNSProviderTypeJDCloudDNS = ApplyDNSProviderType("jdcloud-dns") - ApplyDNSProviderTypeNamecheap = ApplyDNSProviderType("namecheap") - ApplyDNSProviderTypeNameDotCom = ApplyDNSProviderType("namedotcom") - ApplyDNSProviderTypeNameSilo = ApplyDNSProviderType("namesilo") - ApplyDNSProviderTypeNS1 = ApplyDNSProviderType("ns1") - ApplyDNSProviderTypePorkbun = ApplyDNSProviderType("porkbun") - ApplyDNSProviderTypePowerDNS = ApplyDNSProviderType("powerdns") - ApplyDNSProviderTypeRainYun = ApplyDNSProviderType("rainyun") - ApplyDNSProviderTypeTencentCloud = ApplyDNSProviderType("tencentcloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeTencentCloudDNS] - ApplyDNSProviderTypeTencentCloudDNS = ApplyDNSProviderType("tencentcloud-dns") - ApplyDNSProviderTypeTencentCloudEO = ApplyDNSProviderType("tencentcloud-eo") - ApplyDNSProviderTypeVercel = ApplyDNSProviderType("vercel") - ApplyDNSProviderTypeVolcEngine = ApplyDNSProviderType("volcengine") // 兼容旧值,等同于 [ApplyDNSProviderTypeVolcEngineDNS] - ApplyDNSProviderTypeVolcEngineDNS = ApplyDNSProviderType("volcengine-dns") - ApplyDNSProviderTypeWestcn = ApplyDNSProviderType("westcn") + ApplyDNSProviderTypeACMEHttpReq = ApplyDNSProviderType(AccessProviderTypeACMEHttpReq) + ApplyDNSProviderTypeAliyun = ApplyDNSProviderType(AccessProviderTypeAliyun) // 兼容旧值,等同于 [ApplyDNSProviderTypeAliyunDNS] + ApplyDNSProviderTypeAliyunDNS = ApplyDNSProviderType(AccessProviderTypeAliyun + "-dns") + ApplyDNSProviderTypeAWS = ApplyDNSProviderType(AccessProviderTypeAWS) // 兼容旧值,等同于 [ApplyDNSProviderTypeAWSRoute53] + ApplyDNSProviderTypeAWSRoute53 = ApplyDNSProviderType(AccessProviderTypeAWS + "-route53") + ApplyDNSProviderTypeAzure = ApplyDNSProviderType(AccessProviderTypeAzure) // 兼容旧值,等同于 [ApplyDNSProviderTypeAzure] + ApplyDNSProviderTypeAzureDNS = ApplyDNSProviderType(AccessProviderTypeAzure + "-dns") + ApplyDNSProviderTypeBaiduCloud = ApplyDNSProviderType(AccessProviderTypeBaiduCloud) // 兼容旧值,等同于 [ApplyDNSProviderTypeBaiduCloudDNS] + ApplyDNSProviderTypeBaiduCloudDNS = ApplyDNSProviderType(AccessProviderTypeBaiduCloud + "-dns") + ApplyDNSProviderTypeBunny = ApplyDNSProviderType(AccessProviderTypeBunny) + ApplyDNSProviderTypeCloudflare = ApplyDNSProviderType(AccessProviderTypeCloudflare) + ApplyDNSProviderTypeClouDNS = ApplyDNSProviderType(AccessProviderTypeClouDNS) + ApplyDNSProviderTypeCMCCCloud = ApplyDNSProviderType(AccessProviderTypeCMCCCloud) + ApplyDNSProviderTypeDeSEC = ApplyDNSProviderType(AccessProviderTypeDeSEC) + ApplyDNSProviderTypeDNSLA = ApplyDNSProviderType(AccessProviderTypeDNSLA) + ApplyDNSProviderTypeDynv6 = ApplyDNSProviderType(AccessProviderTypeDynv6) + ApplyDNSProviderTypeGcore = ApplyDNSProviderType(AccessProviderTypeGcore) + ApplyDNSProviderTypeGname = ApplyDNSProviderType(AccessProviderTypeGname) + ApplyDNSProviderTypeGoDaddy = ApplyDNSProviderType(AccessProviderTypeGoDaddy) + ApplyDNSProviderTypeHuaweiCloud = ApplyDNSProviderType(AccessProviderTypeHuaweiCloud) // 兼容旧值,等同于 [ApplyDNSProviderTypeHuaweiCloudDNS] + ApplyDNSProviderTypeHuaweiCloudDNS = ApplyDNSProviderType(AccessProviderTypeHuaweiCloud + "-dns") + ApplyDNSProviderTypeJDCloud = ApplyDNSProviderType(AccessProviderTypeJDCloud) // 兼容旧值,等同于 [ApplyDNSProviderTypeJDCloudDNS] + ApplyDNSProviderTypeJDCloudDNS = ApplyDNSProviderType(AccessProviderTypeJDCloud + "-dns") + ApplyDNSProviderTypeNamecheap = ApplyDNSProviderType(AccessProviderTypeNamecheap) + ApplyDNSProviderTypeNameDotCom = ApplyDNSProviderType(AccessProviderTypeNameDotCom) + ApplyDNSProviderTypeNameSilo = ApplyDNSProviderType(AccessProviderTypeNameSilo) + ApplyDNSProviderTypeNS1 = ApplyDNSProviderType(AccessProviderTypeNS1) + ApplyDNSProviderTypePorkbun = ApplyDNSProviderType(AccessProviderTypePorkbun) + ApplyDNSProviderTypePowerDNS = ApplyDNSProviderType(AccessProviderTypePowerDNS) + ApplyDNSProviderTypeRainYun = ApplyDNSProviderType(AccessProviderTypeRainYun) + ApplyDNSProviderTypeTencentCloud = ApplyDNSProviderType(AccessProviderTypeTencentCloud) // 兼容旧值,等同于 [ApplyDNSProviderTypeTencentCloudDNS] + ApplyDNSProviderTypeTencentCloudDNS = ApplyDNSProviderType(AccessProviderTypeTencentCloud + "-dns") + ApplyDNSProviderTypeTencentCloudEO = ApplyDNSProviderType(AccessProviderTypeTencentCloud + "-eo") + ApplyDNSProviderTypeVercel = ApplyDNSProviderType(AccessProviderTypeVercel) + ApplyDNSProviderTypeVolcEngine = ApplyDNSProviderType(AccessProviderTypeVolcEngine) // 兼容旧值,等同于 [ApplyDNSProviderTypeVolcEngineDNS] + ApplyDNSProviderTypeVolcEngineDNS = ApplyDNSProviderType(AccessProviderTypeVolcEngine + "-dns") + ApplyDNSProviderTypeWestcn = ApplyDNSProviderType(AccessProviderTypeWestcn) ) type DeployProviderType string @@ -144,78 +145,91 @@ type DeployProviderType string NOTICE: If you add new constant, please keep ASCII order. */ const ( - DeployProviderType1PanelConsole = DeployProviderType("1panel-console") - DeployProviderType1PanelSite = DeployProviderType("1panel-site") - DeployProviderTypeAliyunALB = DeployProviderType("aliyun-alb") - DeployProviderTypeAliyunAPIGW = DeployProviderType("aliyun-apigw") - DeployProviderTypeAliyunCAS = DeployProviderType("aliyun-cas") - DeployProviderTypeAliyunCASDeploy = DeployProviderType("aliyun-casdeploy") - DeployProviderTypeAliyunCDN = DeployProviderType("aliyun-cdn") - DeployProviderTypeAliyunCLB = DeployProviderType("aliyun-clb") - DeployProviderTypeAliyunDCDN = DeployProviderType("aliyun-dcdn") - DeployProviderTypeAliyunESA = DeployProviderType("aliyun-esa") - DeployProviderTypeAliyunFC = DeployProviderType("aliyun-fc") - DeployProviderTypeAliyunLive = DeployProviderType("aliyun-live") - DeployProviderTypeAliyunNLB = DeployProviderType("aliyun-nlb") - DeployProviderTypeAliyunOSS = DeployProviderType("aliyun-oss") - DeployProviderTypeAliyunVOD = DeployProviderType("aliyun-vod") - DeployProviderTypeAliyunWAF = DeployProviderType("aliyun-waf") - DeployProviderTypeAWSACM = DeployProviderType("aws-acm") - DeployProviderTypeAWSCloudFront = DeployProviderType("aws-cloudfront") - DeployProviderTypeAzureKeyVault = DeployProviderType("azure-keyvault") - DeployProviderTypeBaiduCloudAppBLB = DeployProviderType("baiducloud-appblb") - DeployProviderTypeBaiduCloudBLB = DeployProviderType("baiducloud-blb") - DeployProviderTypeBaiduCloudCDN = DeployProviderType("baiducloud-cdn") - DeployProviderTypeBaiduCloudCert = DeployProviderType("baiducloud-cert") - DeployProviderTypeBaishanCDN = DeployProviderType("baishan-cdn") - DeployProviderTypeBaotaPanelConsole = DeployProviderType("baotapanel-console") - DeployProviderTypeBaotaPanelSite = DeployProviderType("baotapanel-site") - DeployProviderTypeBunnyCDN = DeployProviderType("bunny-cdn") - DeployProviderTypeBytePlusCDN = DeployProviderType("byteplus-cdn") - DeployProviderTypeCacheFly = DeployProviderType("cachefly") - DeployProviderTypeCdnfly = DeployProviderType("cdnfly") - DeployProviderTypeDogeCloudCDN = DeployProviderType("dogecloud-cdn") - DeployProviderTypeEdgioApplications = DeployProviderType("edgio-applications") - DeployProviderTypeGcoreCDN = DeployProviderType("gcore-cdn") - DeployProviderTypeHuaweiCloudCDN = DeployProviderType("huaweicloud-cdn") - DeployProviderTypeHuaweiCloudELB = DeployProviderType("huaweicloud-elb") - DeployProviderTypeHuaweiCloudSCM = DeployProviderType("huaweicloud-scm") - DeployProviderTypeHuaweiCloudWAF = DeployProviderType("huaweicloud-waf") - DeployProviderTypeJDCloudALB = DeployProviderType("jdcloud-alb") - DeployProviderTypeJDCloudCDN = DeployProviderType("jdcloud-cdn") - DeployProviderTypeJDCloudLive = DeployProviderType("jdcloud-live") - DeployProviderTypeJDCloudVOD = DeployProviderType("jdcloud-vod") - DeployProviderTypeKubernetesSecret = DeployProviderType("k8s-secret") - DeployProviderTypeLocal = DeployProviderType("local") - DeployProviderTypeQiniuCDN = DeployProviderType("qiniu-cdn") - DeployProviderTypeQiniuKodo = DeployProviderType("qiniu-kodo") - DeployProviderTypeQiniuPili = DeployProviderType("qiniu-pili") - DeployProviderTypeRainYunRCDN = DeployProviderType("rainyun-rcdn") - DeployProviderTypeSafeLine = DeployProviderType("safeline") - DeployProviderTypeSSH = DeployProviderType("ssh") - DeployProviderTypeTencentCloudCDN = DeployProviderType("tencentcloud-cdn") - DeployProviderTypeTencentCloudCLB = DeployProviderType("tencentcloud-clb") - DeployProviderTypeTencentCloudCOS = DeployProviderType("tencentcloud-cos") - DeployProviderTypeTencentCloudCSS = DeployProviderType("tencentcloud-css") - DeployProviderTypeTencentCloudECDN = DeployProviderType("tencentcloud-ecdn") - DeployProviderTypeTencentCloudEO = DeployProviderType("tencentcloud-eo") - DeployProviderTypeTencentCloudSCF = DeployProviderType("tencentcloud-scf") - DeployProviderTypeTencentCloudSSL = DeployProviderType("tencentcloud-ssl") - DeployProviderTypeTencentCloudSSLDeploy = DeployProviderType("tencentcloud-ssldeploy") - DeployProviderTypeTencentCloudVOD = DeployProviderType("tencentcloud-vod") - DeployProviderTypeTencentCloudWAF = DeployProviderType("tencentcloud-waf") - DeployProviderTypeUCloudUCDN = DeployProviderType("ucloud-ucdn") - DeployProviderTypeUCloudUS3 = DeployProviderType("ucloud-us3") - DeployProviderTypeUpyunCDN = DeployProviderType("upyun-cdn") - DeployProviderTypeUpyunFile = DeployProviderType("upyun-file") - DeployProviderTypeVolcEngineALB = DeployProviderType("volcengine-alb") - DeployProviderTypeVolcEngineCDN = DeployProviderType("volcengine-cdn") - DeployProviderTypeVolcEngineCertCenter = DeployProviderType("volcengine-certcenter") - DeployProviderTypeVolcEngineCLB = DeployProviderType("volcengine-clb") - DeployProviderTypeVolcEngineDCDN = DeployProviderType("volcengine-dcdn") - DeployProviderTypeVolcEngineImageX = DeployProviderType("volcengine-imagex") - DeployProviderTypeVolcEngineLive = DeployProviderType("volcengine-live") - DeployProviderTypeVolcEngineTOS = DeployProviderType("volcengine-tos") - DeployProviderTypeWangsuCDNPro = DeployProviderType("wangsu-cdnpro") - DeployProviderTypeWebhook = DeployProviderType("webhook") + DeployProviderType1PanelConsole = DeployProviderType(AccessProviderType1Panel + "-console") + DeployProviderType1PanelSite = DeployProviderType(AccessProviderType1Panel + "-site") + DeployProviderTypeAliyunALB = DeployProviderType(AccessProviderTypeAliyun + "-alb") + DeployProviderTypeAliyunAPIGW = DeployProviderType(AccessProviderTypeAliyun + "-apigw") + DeployProviderTypeAliyunCAS = DeployProviderType(AccessProviderTypeAliyun + "-cas") + DeployProviderTypeAliyunCASDeploy = DeployProviderType(AccessProviderTypeAliyun + "-casdeploy") + DeployProviderTypeAliyunCDN = DeployProviderType(AccessProviderTypeAliyun + "-cdn") + DeployProviderTypeAliyunCLB = DeployProviderType(AccessProviderTypeAliyun + "-clb") + DeployProviderTypeAliyunDCDN = DeployProviderType(AccessProviderTypeAliyun + "-dcdn") + DeployProviderTypeAliyunESA = DeployProviderType(AccessProviderTypeAliyun + "-esa") + DeployProviderTypeAliyunFC = DeployProviderType(AccessProviderTypeAliyun + "-fc") + DeployProviderTypeAliyunLive = DeployProviderType(AccessProviderTypeAliyun + "-live") + DeployProviderTypeAliyunNLB = DeployProviderType(AccessProviderTypeAliyun + "-nlb") + DeployProviderTypeAliyunOSS = DeployProviderType(AccessProviderTypeAliyun + "-oss") + DeployProviderTypeAliyunVOD = DeployProviderType(AccessProviderTypeAliyun + "-vod") + DeployProviderTypeAliyunWAF = DeployProviderType(AccessProviderTypeAliyun + "-waf") + DeployProviderTypeAWSACM = DeployProviderType(AccessProviderTypeAWS + "-acm") + DeployProviderTypeAWSCloudFront = DeployProviderType(AccessProviderTypeAWS + "-cloudfront") + DeployProviderTypeAzureKeyVault = DeployProviderType(AccessProviderTypeAzure + "-keyvault") + DeployProviderTypeBaiduCloudAppBLB = DeployProviderType(AccessProviderTypeBaiduCloud + "-appblb") + DeployProviderTypeBaiduCloudBLB = DeployProviderType(AccessProviderTypeBaiduCloud + "-blb") + DeployProviderTypeBaiduCloudCDN = DeployProviderType(AccessProviderTypeBaiduCloud + "-cdn") + DeployProviderTypeBaiduCloudCert = DeployProviderType(AccessProviderTypeBaiduCloud + "-cert") + DeployProviderTypeBaishanCDN = DeployProviderType(AccessProviderTypeBaishan + "-cdn") + DeployProviderTypeBaotaPanelConsole = DeployProviderType(AccessProviderTypeBaotaPanel + "-console") + DeployProviderTypeBaotaPanelSite = DeployProviderType(AccessProviderTypeBaotaPanel + "-site") + DeployProviderTypeBunnyCDN = DeployProviderType(AccessProviderTypeBunny + "-cdn") + DeployProviderTypeBytePlusCDN = DeployProviderType(AccessProviderTypeBytePlus + "-cdn") + DeployProviderTypeCacheFly = DeployProviderType(AccessProviderTypeCacheFly) + DeployProviderTypeCdnfly = DeployProviderType(AccessProviderTypeCdnfly) + DeployProviderTypeDogeCloudCDN = DeployProviderType(AccessProviderTypeDogeCloud + "-cdn") + DeployProviderTypeEdgioApplications = DeployProviderType(AccessProviderTypeEdgio + "-applications") + DeployProviderTypeGcoreCDN = DeployProviderType(AccessProviderTypeGcore + "-cdn") + DeployProviderTypeHuaweiCloudCDN = DeployProviderType(AccessProviderTypeHuaweiCloud + "-cdn") + DeployProviderTypeHuaweiCloudELB = DeployProviderType(AccessProviderTypeHuaweiCloud + "-elb") + DeployProviderTypeHuaweiCloudSCM = DeployProviderType(AccessProviderTypeHuaweiCloud + "-scm") + DeployProviderTypeHuaweiCloudWAF = DeployProviderType(AccessProviderTypeHuaweiCloud + "-waf") + DeployProviderTypeJDCloudALB = DeployProviderType(AccessProviderTypeJDCloud + "-alb") + DeployProviderTypeJDCloudCDN = DeployProviderType(AccessProviderTypeJDCloud + "-cdn") + DeployProviderTypeJDCloudLive = DeployProviderType(AccessProviderTypeJDCloud + "-live") + DeployProviderTypeJDCloudVOD = DeployProviderType(AccessProviderTypeJDCloud + "-vod") + DeployProviderTypeKubernetesSecret = DeployProviderType(AccessProviderTypeKubernetes + "-secret") + DeployProviderTypeLocal = DeployProviderType(AccessProviderTypeLocal) + DeployProviderTypeQiniuCDN = DeployProviderType(AccessProviderTypeQiniu + "-cdn") + DeployProviderTypeQiniuKodo = DeployProviderType(AccessProviderTypeQiniu + "-kodo") + DeployProviderTypeQiniuPili = DeployProviderType(AccessProviderTypeQiniu + "-pili") + DeployProviderTypeRainYunRCDN = DeployProviderType(AccessProviderTypeRainYun + "-rcdn") + DeployProviderTypeSafeLine = DeployProviderType(AccessProviderTypeSafeLine) + DeployProviderTypeSSH = DeployProviderType(AccessProviderTypeSSH) + DeployProviderTypeTencentCloudCDN = DeployProviderType(AccessProviderTypeTencentCloud + "-cdn") + DeployProviderTypeTencentCloudCLB = DeployProviderType(AccessProviderTypeTencentCloud + "-clb") + DeployProviderTypeTencentCloudCOS = DeployProviderType(AccessProviderTypeTencentCloud + "-cos") + DeployProviderTypeTencentCloudCSS = DeployProviderType(AccessProviderTypeTencentCloud + "-css") + DeployProviderTypeTencentCloudECDN = DeployProviderType(AccessProviderTypeTencentCloud + "-ecdn") + DeployProviderTypeTencentCloudEO = DeployProviderType(AccessProviderTypeTencentCloud + "-eo") + DeployProviderTypeTencentCloudSCF = DeployProviderType(AccessProviderTypeTencentCloud + "-scf") + DeployProviderTypeTencentCloudSSL = DeployProviderType(AccessProviderTypeTencentCloud + "-ssl") + DeployProviderTypeTencentCloudSSLDeploy = DeployProviderType(AccessProviderTypeTencentCloud + "-ssldeploy") + DeployProviderTypeTencentCloudVOD = DeployProviderType(AccessProviderTypeTencentCloud + "-vod") + DeployProviderTypeTencentCloudWAF = DeployProviderType(AccessProviderTypeTencentCloud + "-waf") + DeployProviderTypeUCloudUCDN = DeployProviderType(AccessProviderTypeUCloud + "-ucdn") + DeployProviderTypeUCloudUS3 = DeployProviderType(AccessProviderTypeUCloud + "-us3") + DeployProviderTypeUpyunCDN = DeployProviderType(AccessProviderTypeUpyun + "-cdn") + DeployProviderTypeUpyunFile = DeployProviderType(AccessProviderTypeUpyun + "-file") + DeployProviderTypeVolcEngineALB = DeployProviderType(AccessProviderTypeVolcEngine + "-alb") + DeployProviderTypeVolcEngineCDN = DeployProviderType(AccessProviderTypeVolcEngine + "-cdn") + DeployProviderTypeVolcEngineCertCenter = DeployProviderType(AccessProviderTypeVolcEngine + "-certcenter") + DeployProviderTypeVolcEngineCLB = DeployProviderType(AccessProviderTypeVolcEngine + "-clb") + DeployProviderTypeVolcEngineDCDN = DeployProviderType(AccessProviderTypeVolcEngine + "-dcdn") + DeployProviderTypeVolcEngineImageX = DeployProviderType(AccessProviderTypeVolcEngine + "-imagex") + DeployProviderTypeVolcEngineLive = DeployProviderType(AccessProviderTypeVolcEngine + "-live") + DeployProviderTypeVolcEngineTOS = DeployProviderType(AccessProviderTypeVolcEngine + "-tos") + DeployProviderTypeWangsuCDNPro = DeployProviderType(AccessProviderTypeWangsu + "-cdnpro") + DeployProviderTypeWebhook = DeployProviderType(AccessProviderTypeWebhook) +) + +type NotifyProviderType string + +/* +消息通知提供商常量值。 +短横线前的部分始终等于授权提供商类型。 + + 注意:如果追加新的常量值,请保持以 ASCII 排序。 + NOTICE: If you add new constant, please keep ASCII order. +*/ +const ( + NotifyProviderTypeWebhook = NotifyProviderType(AccessProviderTypeWebhook) ) diff --git a/internal/domain/settings.go b/internal/domain/settings.go index ebe6b9d7..7063ed83 100644 --- a/internal/domain/settings.go +++ b/internal/domain/settings.go @@ -13,6 +13,7 @@ type Settings struct { Content string `json:"content" db:"content"` } +// Deprecated: v0.4.x 将废弃 type NotifyTemplatesSettingsContent struct { NotifyTemplates []struct { Subject string `json:"subject"` @@ -20,8 +21,10 @@ type NotifyTemplatesSettingsContent struct { } `json:"notifyTemplates"` } +// Deprecated: v0.4.x 将废弃 type NotifyChannelsSettingsContent map[string]map[string]any +// Deprecated: v0.4.x 将废弃 func (s *Settings) GetNotifyChannelConfig(channel string) (map[string]any, error) { conf := &NotifyChannelsSettingsContent{} if err := json.Unmarshal([]byte(s.Content), conf); err != nil { diff --git a/internal/domain/workflow.go b/internal/domain/workflow.go index cfa1c8cc..639a31ca 100644 --- a/internal/domain/workflow.go +++ b/internal/domain/workflow.go @@ -71,7 +71,7 @@ type WorkflowNodeConfigForApply struct { CAProvider string `json:"caProvider,omitempty"` // CA 提供商(零值将使用全局配置) CAProviderAccessId string `json:"caProviderAccessId,omitempty"` // CA 提供商授权记录 ID CAProviderConfig map[string]any `json:"caProviderConfig,omitempty"` // CA 提供商额外配置 - KeyAlgorithm string `json:"keyAlgorithm"` // 密钥算法 + KeyAlgorithm string `json:"keyAlgorithm"` // 证书算法 Nameservers string `json:"nameservers,omitempty"` // DNS 服务器列表,以半角分号分隔 DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` // DNS 传播超时时间(零值取决于提供商的默认值) DnsTTL int32 `json:"dnsTTL,omitempty"` // DNS TTL(零值取决于提供商的默认值) @@ -95,9 +95,12 @@ type WorkflowNodeConfigForDeploy struct { } type WorkflowNodeConfigForNotify struct { - Channel string `json:"channel"` // 通知渠道 - Subject string `json:"subject"` // 通知主题 - Message string `json:"message"` // 通知内容 + Channel string `json:"channel,omitempty"` // Deprecated: v0.4.x 将废弃 + Provider string `json:"provider"` // 通知提供商 + ProviderAccessId string `json:"providerAccessId"` // 通知提供商授权记录 ID + ProviderConfig map[string]any `json:"providerConfig,omitempty"` // 通知提供商额外配置 + Subject string `json:"subject"` // 通知主题 + Message string `json:"message"` // 通知内容 } func (n *WorkflowNode) GetConfigForApply() WorkflowNodeConfigForApply { @@ -111,10 +114,10 @@ func (n *WorkflowNode) GetConfigForApply() WorkflowNodeConfigForApply { ContactEmail: maputil.GetString(n.Config, "contactEmail"), Provider: maputil.GetString(n.Config, "provider"), ProviderAccessId: maputil.GetString(n.Config, "providerAccessId"), - ProviderConfig: maputil.GetAnyMap(n.Config, "providerConfig"), + ProviderConfig: maputil.GetMap(n.Config, "providerConfig"), CAProvider: maputil.GetString(n.Config, "caProvider"), CAProviderAccessId: maputil.GetString(n.Config, "caProviderAccessId"), - CAProviderConfig: maputil.GetAnyMap(n.Config, "caProviderConfig"), + CAProviderConfig: maputil.GetMap(n.Config, "caProviderConfig"), KeyAlgorithm: maputil.GetString(n.Config, "keyAlgorithm"), Nameservers: maputil.GetString(n.Config, "nameservers"), DnsPropagationTimeout: maputil.GetInt32(n.Config, "dnsPropagationTimeout"), @@ -138,16 +141,19 @@ func (n *WorkflowNode) GetConfigForDeploy() WorkflowNodeConfigForDeploy { Certificate: maputil.GetString(n.Config, "certificate"), Provider: maputil.GetString(n.Config, "provider"), ProviderAccessId: maputil.GetString(n.Config, "providerAccessId"), - ProviderConfig: maputil.GetAnyMap(n.Config, "providerConfig"), + ProviderConfig: maputil.GetMap(n.Config, "providerConfig"), SkipOnLastSucceeded: maputil.GetBool(n.Config, "skipOnLastSucceeded"), } } func (n *WorkflowNode) GetConfigForNotify() WorkflowNodeConfigForNotify { return WorkflowNodeConfigForNotify{ - Channel: maputil.GetString(n.Config, "channel"), - Subject: maputil.GetString(n.Config, "subject"), - Message: maputil.GetString(n.Config, "message"), + Channel: maputil.GetString(n.Config, "channel"), + Provider: maputil.GetString(n.Config, "provider"), + ProviderAccessId: maputil.GetString(n.Config, "providerAccessId"), + ProviderConfig: maputil.GetMap(n.Config, "providerConfig"), + Subject: maputil.GetString(n.Config, "subject"), + Message: maputil.GetString(n.Config, "message"), } } diff --git a/internal/notify/notifier.go b/internal/notify/notifier.go new file mode 100644 index 00000000..b8547e94 --- /dev/null +++ b/internal/notify/notifier.go @@ -0,0 +1,72 @@ +package notify + +import ( + "context" + "fmt" + "log/slog" + + "github.com/usual2970/certimate/internal/domain" + "github.com/usual2970/certimate/internal/pkg/core/notifier" + "github.com/usual2970/certimate/internal/repository" +) + +type Notifier interface { + Notify(ctx context.Context) error +} + +type NotifierWithWorkflowNodeConfig struct { + Node *domain.WorkflowNode + Logger *slog.Logger + Subject string + Message string +} + +func NewWithWorkflowNode(config NotifierWithWorkflowNodeConfig) (Notifier, error) { + if config.Node == nil { + return nil, fmt.Errorf("node is nil") + } + if config.Node.Type != domain.WorkflowNodeTypeNotify { + return nil, fmt.Errorf("node type is not '%s'", string(domain.WorkflowNodeTypeNotify)) + } + + nodeConfig := config.Node.GetConfigForNotify() + options := ¬ifierProviderOptions{ + Provider: domain.NotifyProviderType(nodeConfig.Provider), + ProviderAccessConfig: make(map[string]any), + ProviderNotifyConfig: nodeConfig.ProviderConfig, + } + + accessRepo := repository.NewAccessRepository() + if nodeConfig.ProviderAccessId != "" { + access, err := accessRepo.GetById(context.Background(), nodeConfig.ProviderAccessId) + if err != nil { + return nil, fmt.Errorf("failed to get access #%s record: %w", nodeConfig.ProviderAccessId, err) + } else { + options.ProviderAccessConfig = access.Config + } + } + + notifierProvider, err := createNotifierProvider(options) + if err != nil { + return nil, err + } + + return ¬ifierImpl{ + provider: notifierProvider.WithLogger(config.Logger), + subject: config.Subject, + message: config.Message, + }, nil +} + +type notifierImpl struct { + provider notifier.Notifier + subject string + message string +} + +var _ Notifier = (*notifierImpl)(nil) + +func (n *notifierImpl) Notify(ctx context.Context) error { + _, err := n.provider.Notify(ctx, n.subject, n.message) + return err +} diff --git a/internal/notify/notify.go b/internal/notify/notify.go index 3d447c05..92970341 100644 --- a/internal/notify/notify.go +++ b/internal/notify/notify.go @@ -13,6 +13,7 @@ import ( "github.com/usual2970/certimate/internal/repository" ) +// Deprecated: v0.4.x 将废弃 func SendToAllChannels(subject, message string) error { notifiers, err := getEnabledNotifiers() if err != nil { @@ -38,8 +39,9 @@ func SendToAllChannels(subject, message string) error { return err } +// Deprecated: v0.4.x 将废弃 func SendToChannel(subject, message string, channel string, channelConfig map[string]any) error { - notifier, err := createNotifier(domain.NotifyChannelType(channel), channelConfig) + notifier, err := createNotifierProviderUseGlobalSettings(domain.NotifyChannelType(channel), channelConfig) if err != nil { return err } @@ -48,6 +50,7 @@ func SendToChannel(subject, message string, channel string, channelConfig map[st return err } +// Deprecated: v0.4.x 将废弃 func getEnabledNotifiers() ([]notifier.Notifier, error) { settingsRepo := repository.NewSettingsRepository() settings, err := settingsRepo.GetByName(context.Background(), "notifyChannels") @@ -66,7 +69,7 @@ func getEnabledNotifiers() ([]notifier.Notifier, error) { continue } - notifier, err := createNotifier(domain.NotifyChannelType(k), v) + notifier, err := createNotifierProviderUseGlobalSettings(domain.NotifyChannelType(k), v) if err != nil { continue } diff --git a/internal/notify/providers.go b/internal/notify/providers.go index bae9ba72..dde87587 100644 --- a/internal/notify/providers.go +++ b/internal/notify/providers.go @@ -5,102 +5,28 @@ import ( "github.com/usual2970/certimate/internal/domain" "github.com/usual2970/certimate/internal/pkg/core/notifier" - pBark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/bark" - pDingTalk "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/dingtalk" - pEmail "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email" - pGotify "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/gotify" - pLark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/lark" - pMattermost "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/mattermost" - pPushover "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/pushover" - pPushPlus "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/pushplus" - pServerChan "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/serverchan" - pTelegram "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/telegram" pWebhook "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/webhook" - pWeCom "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/wecom" maputil "github.com/usual2970/certimate/internal/pkg/utils/map" ) -func createNotifier(channel domain.NotifyChannelType, channelConfig map[string]any) (notifier.Notifier, error) { +type notifierProviderOptions struct { + Provider domain.NotifyProviderType + ProviderAccessConfig map[string]any + ProviderNotifyConfig map[string]any +} + +func createNotifierProvider(options *notifierProviderOptions) (notifier.Notifier, error) { /* 注意:如果追加新的常量值,请保持以 ASCII 排序。 NOTICE: If you add new constant, please keep ASCII order. */ - switch channel { - case domain.NotifyChannelTypeBark: - return pBark.NewNotifier(&pBark.NotifierConfig{ - DeviceKey: maputil.GetString(channelConfig, "deviceKey"), - ServerUrl: maputil.GetString(channelConfig, "serverUrl"), - }) - - case domain.NotifyChannelTypeDingTalk: - return pDingTalk.NewNotifier(&pDingTalk.NotifierConfig{ - AccessToken: maputil.GetString(channelConfig, "accessToken"), - Secret: maputil.GetString(channelConfig, "secret"), - }) - - case domain.NotifyChannelTypeEmail: - return pEmail.NewNotifier(&pEmail.NotifierConfig{ - SmtpHost: maputil.GetString(channelConfig, "smtpHost"), - SmtpPort: maputil.GetInt32(channelConfig, "smtpPort"), - SmtpTLS: maputil.GetOrDefaultBool(channelConfig, "smtpTLS", true), - Username: maputil.GetOrDefaultString(channelConfig, "username", maputil.GetString(channelConfig, "senderAddress")), - Password: maputil.GetString(channelConfig, "password"), - SenderAddress: maputil.GetString(channelConfig, "senderAddress"), - ReceiverAddress: maputil.GetString(channelConfig, "receiverAddress"), - }) - - case domain.NotifyChannelTypeGotify: - return pGotify.NewNotifier(&pGotify.NotifierConfig{ - Url: maputil.GetString(channelConfig, "url"), - Token: maputil.GetString(channelConfig, "token"), - Priority: maputil.GetOrDefaultInt64(channelConfig, "priority", 1), - }) - - case domain.NotifyChannelTypeLark: - return pLark.NewNotifier(&pLark.NotifierConfig{ - WebhookUrl: maputil.GetString(channelConfig, "webhookUrl"), - }) - - case domain.NotifyChannelTypeMattermost: - return pMattermost.NewNotifier(&pMattermost.NotifierConfig{ - ServerUrl: maputil.GetString(channelConfig, "serverUrl"), - ChannelId: maputil.GetString(channelConfig, "channelId"), - Username: maputil.GetString(channelConfig, "username"), - Password: maputil.GetString(channelConfig, "password"), - }) - case domain.NotifyChannelTypePushover: - return pPushover.NewNotifier(&pPushover.NotifierConfig{ - Token: maputil.GetString(channelConfig, "token"), - User: maputil.GetString(channelConfig, "user"), - }) - - case domain.NotifyChannelTypePushPlus: - return pPushPlus.NewNotifier(&pPushPlus.NotifierConfig{ - Token: maputil.GetString(channelConfig, "token"), - }) - - case domain.NotifyChannelTypeServerChan: - return pServerChan.NewNotifier(&pServerChan.NotifierConfig{ - Url: maputil.GetString(channelConfig, "url"), - }) - - case domain.NotifyChannelTypeTelegram: - return pTelegram.NewNotifier(&pTelegram.NotifierConfig{ - ApiToken: maputil.GetString(channelConfig, "apiToken"), - ChatId: maputil.GetInt64(channelConfig, "chatId"), - }) - - case domain.NotifyChannelTypeWebhook: + switch options.Provider { + case domain.NotifyProviderTypeWebhook: return pWebhook.NewNotifier(&pWebhook.NotifierConfig{ - Url: maputil.GetString(channelConfig, "url"), - AllowInsecureConnections: maputil.GetBool(channelConfig, "allowInsecureConnections"), - }) - - case domain.NotifyChannelTypeWeCom: - return pWeCom.NewNotifier(&pWeCom.NotifierConfig{ - WebhookUrl: maputil.GetString(channelConfig, "webhookUrl"), + Url: maputil.GetString(options.ProviderAccessConfig, "url"), + AllowInsecureConnections: maputil.GetBool(options.ProviderAccessConfig, "allowInsecureConnections"), }) } - return nil, fmt.Errorf("unsupported notifier channel '%s'", channelConfig) + return nil, fmt.Errorf("unsupported notifier provider '%s'", options.Provider) } diff --git a/internal/notify/providers_deprecated.go b/internal/notify/providers_deprecated.go new file mode 100644 index 00000000..31e0071b --- /dev/null +++ b/internal/notify/providers_deprecated.go @@ -0,0 +1,108 @@ +package notify + +import ( + "fmt" + + "github.com/usual2970/certimate/internal/domain" + "github.com/usual2970/certimate/internal/pkg/core/notifier" + pBark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/bark" + pDingTalk "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/dingtalk" + pEmail "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email" + pGotify "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/gotify" + pLark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/lark" + pMattermost "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/mattermost" + pPushover "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/pushover" + pPushPlus "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/pushplus" + pServerChan "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/serverchan" + pTelegram "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/telegram" + pWebhook "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/webhook" + pWeCom "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/wecom" + maputil "github.com/usual2970/certimate/internal/pkg/utils/map" +) + +// Deprecated: v0.4.x 将废弃 +func createNotifierProviderUseGlobalSettings(channel domain.NotifyChannelType, channelConfig map[string]any) (notifier.Notifier, error) { + /* + 注意:如果追加新的常量值,请保持以 ASCII 排序。 + NOTICE: If you add new constant, please keep ASCII order. + */ + switch channel { + case domain.NotifyChannelTypeBark: + return pBark.NewNotifier(&pBark.NotifierConfig{ + DeviceKey: maputil.GetString(channelConfig, "deviceKey"), + ServerUrl: maputil.GetString(channelConfig, "serverUrl"), + }) + + case domain.NotifyChannelTypeDingTalk: + return pDingTalk.NewNotifier(&pDingTalk.NotifierConfig{ + AccessToken: maputil.GetString(channelConfig, "accessToken"), + Secret: maputil.GetString(channelConfig, "secret"), + }) + + case domain.NotifyChannelTypeEmail: + return pEmail.NewNotifier(&pEmail.NotifierConfig{ + SmtpHost: maputil.GetString(channelConfig, "smtpHost"), + SmtpPort: maputil.GetInt32(channelConfig, "smtpPort"), + SmtpTLS: maputil.GetOrDefaultBool(channelConfig, "smtpTLS", true), + Username: maputil.GetOrDefaultString(channelConfig, "username", maputil.GetString(channelConfig, "senderAddress")), + Password: maputil.GetString(channelConfig, "password"), + SenderAddress: maputil.GetString(channelConfig, "senderAddress"), + ReceiverAddress: maputil.GetString(channelConfig, "receiverAddress"), + }) + + case domain.NotifyChannelTypeGotify: + return pGotify.NewNotifier(&pGotify.NotifierConfig{ + Url: maputil.GetString(channelConfig, "url"), + Token: maputil.GetString(channelConfig, "token"), + Priority: maputil.GetOrDefaultInt64(channelConfig, "priority", 1), + }) + + case domain.NotifyChannelTypeLark: + return pLark.NewNotifier(&pLark.NotifierConfig{ + WebhookUrl: maputil.GetString(channelConfig, "webhookUrl"), + }) + + case domain.NotifyChannelTypeMattermost: + return pMattermost.NewNotifier(&pMattermost.NotifierConfig{ + ServerUrl: maputil.GetString(channelConfig, "serverUrl"), + ChannelId: maputil.GetString(channelConfig, "channelId"), + Username: maputil.GetString(channelConfig, "username"), + Password: maputil.GetString(channelConfig, "password"), + }) + + case domain.NotifyChannelTypePushover: + return pPushover.NewNotifier(&pPushover.NotifierConfig{ + Token: maputil.GetString(channelConfig, "token"), + User: maputil.GetString(channelConfig, "user"), + }) + + case domain.NotifyChannelTypePushPlus: + return pPushPlus.NewNotifier(&pPushPlus.NotifierConfig{ + Token: maputil.GetString(channelConfig, "token"), + }) + + case domain.NotifyChannelTypeServerChan: + return pServerChan.NewNotifier(&pServerChan.NotifierConfig{ + Url: maputil.GetString(channelConfig, "url"), + }) + + case domain.NotifyChannelTypeTelegram: + return pTelegram.NewNotifier(&pTelegram.NotifierConfig{ + ApiToken: maputil.GetString(channelConfig, "apiToken"), + ChatId: maputil.GetInt64(channelConfig, "chatId"), + }) + + case domain.NotifyChannelTypeWebhook: + return pWebhook.NewNotifier(&pWebhook.NotifierConfig{ + Url: maputil.GetString(channelConfig, "url"), + AllowInsecureConnections: maputil.GetBool(channelConfig, "allowInsecureConnections"), + }) + + case domain.NotifyChannelTypeWeCom: + return pWeCom.NewNotifier(&pWeCom.NotifierConfig{ + WebhookUrl: maputil.GetString(channelConfig, "webhookUrl"), + }) + } + + return nil, fmt.Errorf("unsupported notifier channel '%s'", channelConfig) +} diff --git a/internal/notify/service.go b/internal/notify/service.go index 9b7cc416..1d1f6c25 100644 --- a/internal/notify/service.go +++ b/internal/notify/service.go @@ -8,25 +8,30 @@ import ( "github.com/usual2970/certimate/internal/domain/dtos" ) +// Deprecated: v0.4.x 将废弃 const ( notifyTestTitle = "测试通知" notifyTestBody = "欢迎使用 Certimate ,这是一条测试通知。" ) +// Deprecated: v0.4.x 将废弃 type settingsRepository interface { GetByName(ctx context.Context, name string) (*domain.Settings, error) } +// Deprecated: v0.4.x 将废弃 type NotifyService struct { settingsRepo settingsRepository } +// Deprecated: v0.4.x 将废弃 func NewNotifyService(settingsRepo settingsRepository) *NotifyService { return &NotifyService{ settingsRepo: settingsRepo, } } +// Deprecated: v0.4.x 将废弃 func (n *NotifyService) Test(ctx context.Context, req *dtos.NotifyTestPushReq) error { settings, err := n.settingsRepo.GetByName(ctx, "notifyChannels") if err != nil { diff --git a/internal/pkg/utils/map/getter.go b/internal/pkg/utils/map/getter.go index c4e6fbe1..b4b654e3 100644 --- a/internal/pkg/utils/map/getter.go +++ b/internal/pkg/utils/map/getter.go @@ -207,7 +207,7 @@ func GetOrDefaultBool(dict map[string]any, key string, defaultValue bool) bool { // // 出参: // - 字典中键对应的 `map[string]any` 对象。 -func GetAnyMap(dict map[string]any, key string) map[string]any { +func GetMap(dict map[string]any, key string) map[string]any { if dict == nil { return make(map[string]any) } diff --git a/internal/workflow/node-processor/apply_node.go b/internal/workflow/node-processor/apply_node.go index d9415cb9..265437ea 100644 --- a/internal/workflow/node-processor/apply_node.go +++ b/internal/workflow/node-processor/apply_node.go @@ -49,14 +49,17 @@ func (n *applyNode) Process(ctx context.Context) error { } // 初始化申请器 - applicant, err := applicant.NewWithApplyNode(n.node) + applicant, err := applicant.NewWithWorkflowNode(applicant.ApplicantWithWorkflowNodeConfig{ + Node: n.node, + Logger: n.logger, + }) if err != nil { n.logger.Warn("failed to create applicant provider") return err } // 申请证书 - applyResult, err := applicant.Apply() + applyResult, err := applicant.Apply(ctx) if err != nil { n.logger.Warn("failed to apply") return err diff --git a/internal/workflow/node-processor/deploy_node.go b/internal/workflow/node-processor/deploy_node.go index edb3c53d..01d899a4 100644 --- a/internal/workflow/node-processor/deploy_node.go +++ b/internal/workflow/node-processor/deploy_node.go @@ -63,17 +63,18 @@ func (n *deployNode) Process(ctx context.Context) error { } // 初始化部署器 - deployer, err := deployer.NewWithDeployNode(n.node, struct { - Certificate string - PrivateKey string - }{Certificate: certificate.Certificate, PrivateKey: certificate.PrivateKey}) + deployer, err := deployer.NewWithWorkflowNode(deployer.DeployerWithWorkflowNodeConfig{ + Node: n.node, + Logger: n.logger, + CertificatePEM: certificate.Certificate, + PrivateKeyPEM: certificate.PrivateKey, + }) if err != nil { n.logger.Warn("failed to create deployer provider") return err } // 部署证书 - deployer.SetLogger(n.logger) if err := deployer.Deploy(ctx); err != nil { n.logger.Warn("failed to deploy") return err diff --git a/internal/workflow/node-processor/notify_node.go b/internal/workflow/node-processor/notify_node.go index 1c2b49d8..1840938b 100644 --- a/internal/workflow/node-processor/notify_node.go +++ b/internal/workflow/node-processor/notify_node.go @@ -30,25 +30,50 @@ func (n *notifyNode) Process(ctx context.Context) error { nodeConfig := n.node.GetConfigForNotify() - // 获取通知配置 - settings, err := n.settingsRepo.GetByName(ctx, "notifyChannels") + if nodeConfig.Provider == "" { + // Deprecated: v0.4.x 将废弃 + // 兼容旧版本的通知渠道 + n.logger.Warn("WARNING! you are using the notification channel from global settings, which will be deprecated in the future") + + // 获取通知配置 + settings, err := n.settingsRepo.GetByName(ctx, "notifyChannels") + if err != nil { + return err + } + + // 获取通知渠道 + channelConfig, err := settings.GetNotifyChannelConfig(nodeConfig.Channel) + if err != nil { + return err + } + + // 发送通知 + if err := notify.SendToChannel(nodeConfig.Subject, nodeConfig.Message, nodeConfig.Channel, channelConfig); err != nil { + n.logger.Warn("failed to notify", slog.String("channel", nodeConfig.Channel)) + return err + } + + n.logger.Info("notify completed") + return nil + } + + // 初始化通知器 + deployer, err := notify.NewWithWorkflowNode(notify.NotifierWithWorkflowNodeConfig{ + Node: n.node, + Logger: n.logger, + Subject: nodeConfig.Subject, + Message: nodeConfig.Message, + }) if err != nil { + n.logger.Warn("failed to create notifier provider") return err } - // 获取通知渠道 - channelConfig, err := settings.GetNotifyChannelConfig(nodeConfig.Channel) - if err != nil { + // 推送通知 + if err := deployer.Notify(ctx); err != nil { + n.logger.Warn("failed to notify") return err } - // 发送通知 - if err := notify.SendToChannel(nodeConfig.Subject, nodeConfig.Message, nodeConfig.Channel, channelConfig); err != nil { - n.logger.Warn("failed to notify", slog.String("channel", nodeConfig.Channel)) - return err - } - - n.logger.Info("notify completed") - return nil } diff --git a/ui/src/components/provider/NotifyProviderSelect.tsx b/ui/src/components/provider/NotifyProviderSelect.tsx new file mode 100644 index 00000000..409126f4 --- /dev/null +++ b/ui/src/components/provider/NotifyProviderSelect.tsx @@ -0,0 +1,67 @@ +import { memo, useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { Avatar, Select, type SelectProps, Space, Typography } from "antd"; + +import { type NotifyProvider, notifyProvidersMap } from "@/domain/provider"; + +export type NotifyProviderSelectProps = Omit< + SelectProps, + "filterOption" | "filterSort" | "labelRender" | "options" | "optionFilterProp" | "optionLabelProp" | "optionRender" +> & { + filter?: (record: NotifyProvider) => boolean; +}; + +const NotifyProviderSelect = ({ filter, ...props }: NotifyProviderSelectProps) => { + const { t } = useTranslation(); + + const [options, setOptions] = useState>([]); + useEffect(() => { + const allItems = Array.from(notifyProvidersMap.values()); + const filteredItems = filter != null ? allItems.filter(filter) : allItems; + setOptions( + filteredItems.map((item) => ({ + key: item.type, + value: item.type, + label: t(item.name), + data: item, + })) + ); + }, [filter]); + + const renderOption = (key: string) => { + const provider = notifyProvidersMap.get(key); + return ( + + + + {t(provider?.name ?? "")} + + + ); + }; + + return ( +