mirror of
https://github.com/woodchen-ink/certimate.git
synced 2025-07-18 17:31:55 +08:00
feat: deprecate old notification module and introduce new notifier module
This commit is contained in:
parent
2d17501072
commit
7478dd7f47
@ -8,6 +8,7 @@ type NotifyChannelType string
|
|||||||
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
||||||
NOTICE: If you add new constant, please keep ASCII order.
|
NOTICE: If you add new constant, please keep ASCII order.
|
||||||
*/
|
*/
|
||||||
|
// Deprecated: v0.4.x 将废弃
|
||||||
const (
|
const (
|
||||||
NotifyChannelTypeBark = NotifyChannelType("bark")
|
NotifyChannelTypeBark = NotifyChannelType("bark")
|
||||||
NotifyChannelTypeDingTalk = NotifyChannelType("dingtalk")
|
NotifyChannelTypeDingTalk = NotifyChannelType("dingtalk")
|
||||||
|
@ -19,6 +19,7 @@ const (
|
|||||||
AccessProviderTypeBaishan = AccessProviderType("baishan")
|
AccessProviderTypeBaishan = AccessProviderType("baishan")
|
||||||
AccessProviderTypeBaotaPanel = AccessProviderType("baotapanel")
|
AccessProviderTypeBaotaPanel = AccessProviderType("baotapanel")
|
||||||
AccessProviderTypeBytePlus = AccessProviderType("byteplus")
|
AccessProviderTypeBytePlus = AccessProviderType("byteplus")
|
||||||
|
AccessProviderTypeBunny = AccessProviderType("bunny")
|
||||||
AccessProviderTypeBuypass = AccessProviderType("buypass")
|
AccessProviderTypeBuypass = AccessProviderType("buypass")
|
||||||
AccessProviderTypeCacheFly = AccessProviderType("cachefly")
|
AccessProviderTypeCacheFly = AccessProviderType("cachefly")
|
||||||
AccessProviderTypeCdnfly = AccessProviderType("cdnfly")
|
AccessProviderTypeCdnfly = AccessProviderType("cdnfly")
|
||||||
@ -71,18 +72,18 @@ type ApplyCAProviderType string
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
申请证书 CA 提供商常量值。
|
申请证书 CA 提供商常量值。
|
||||||
始终等于授权提供商类型。
|
短横线前的部分始终等于授权提供商类型。
|
||||||
|
|
||||||
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
||||||
NOTICE: If you add new constant, please keep ASCII order.
|
NOTICE: If you add new constant, please keep ASCII order.
|
||||||
*/
|
*/
|
||||||
const (
|
const (
|
||||||
ApplyCAProviderTypeBuypass = ApplyCAProviderType(string(AccessProviderTypeBuypass))
|
ApplyCAProviderTypeBuypass = ApplyCAProviderType(AccessProviderTypeBuypass)
|
||||||
ApplyCAProviderTypeGoogleTrustServices = ApplyCAProviderType(string(AccessProviderTypeGoogleTrustServices))
|
ApplyCAProviderTypeGoogleTrustServices = ApplyCAProviderType(AccessProviderTypeGoogleTrustServices)
|
||||||
ApplyCAProviderTypeLetsEncrypt = ApplyCAProviderType(string(AccessProviderTypeLetsEncrypt))
|
ApplyCAProviderTypeLetsEncrypt = ApplyCAProviderType(AccessProviderTypeLetsEncrypt)
|
||||||
ApplyCAProviderTypeLetsEncryptStaging = ApplyCAProviderType(string(AccessProviderTypeLetsEncryptStaging))
|
ApplyCAProviderTypeLetsEncryptStaging = ApplyCAProviderType(AccessProviderTypeLetsEncryptStaging)
|
||||||
ApplyCAProviderTypeSSLCom = ApplyCAProviderType(string(AccessProviderTypeSSLCOM))
|
ApplyCAProviderTypeSSLCom = ApplyCAProviderType(AccessProviderTypeSSLCOM)
|
||||||
ApplyCAProviderTypeZeroSSL = ApplyCAProviderType(string(AccessProviderTypeZeroSSL))
|
ApplyCAProviderTypeZeroSSL = ApplyCAProviderType(AccessProviderTypeZeroSSL)
|
||||||
)
|
)
|
||||||
|
|
||||||
type ApplyDNSProviderType string
|
type ApplyDNSProviderType string
|
||||||
@ -95,43 +96,43 @@ type ApplyDNSProviderType string
|
|||||||
NOTICE: If you add new constant, please keep ASCII order.
|
NOTICE: If you add new constant, please keep ASCII order.
|
||||||
*/
|
*/
|
||||||
const (
|
const (
|
||||||
ApplyDNSProviderTypeACMEHttpReq = ApplyDNSProviderType("acmehttpreq")
|
ApplyDNSProviderTypeACMEHttpReq = ApplyDNSProviderType(AccessProviderTypeACMEHttpReq)
|
||||||
ApplyDNSProviderTypeAliyun = ApplyDNSProviderType("aliyun") // 兼容旧值,等同于 [ApplyDNSProviderTypeAliyunDNS]
|
ApplyDNSProviderTypeAliyun = ApplyDNSProviderType(AccessProviderTypeAliyun) // 兼容旧值,等同于 [ApplyDNSProviderTypeAliyunDNS]
|
||||||
ApplyDNSProviderTypeAliyunDNS = ApplyDNSProviderType("aliyun-dns")
|
ApplyDNSProviderTypeAliyunDNS = ApplyDNSProviderType(AccessProviderTypeAliyun + "-dns")
|
||||||
ApplyDNSProviderTypeAWS = ApplyDNSProviderType("aws") // 兼容旧值,等同于 [ApplyDNSProviderTypeAWSRoute53]
|
ApplyDNSProviderTypeAWS = ApplyDNSProviderType(AccessProviderTypeAWS) // 兼容旧值,等同于 [ApplyDNSProviderTypeAWSRoute53]
|
||||||
ApplyDNSProviderTypeAWSRoute53 = ApplyDNSProviderType("aws-route53")
|
ApplyDNSProviderTypeAWSRoute53 = ApplyDNSProviderType(AccessProviderTypeAWS + "-route53")
|
||||||
ApplyDNSProviderTypeAzure = ApplyDNSProviderType("azure") // 兼容旧值,等同于 [ApplyDNSProviderTypeAzure]
|
ApplyDNSProviderTypeAzure = ApplyDNSProviderType(AccessProviderTypeAzure) // 兼容旧值,等同于 [ApplyDNSProviderTypeAzure]
|
||||||
ApplyDNSProviderTypeAzureDNS = ApplyDNSProviderType("azure-dns")
|
ApplyDNSProviderTypeAzureDNS = ApplyDNSProviderType(AccessProviderTypeAzure + "-dns")
|
||||||
ApplyDNSProviderTypeBaiduCloud = ApplyDNSProviderType("baiducloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeBaiduCloudDNS]
|
ApplyDNSProviderTypeBaiduCloud = ApplyDNSProviderType(AccessProviderTypeBaiduCloud) // 兼容旧值,等同于 [ApplyDNSProviderTypeBaiduCloudDNS]
|
||||||
ApplyDNSProviderTypeBaiduCloudDNS = ApplyDNSProviderType("baiducloud-dns")
|
ApplyDNSProviderTypeBaiduCloudDNS = ApplyDNSProviderType(AccessProviderTypeBaiduCloud + "-dns")
|
||||||
ApplyDNSProviderTypeBunny = ApplyDNSProviderType("bunny")
|
ApplyDNSProviderTypeBunny = ApplyDNSProviderType(AccessProviderTypeBunny)
|
||||||
ApplyDNSProviderTypeCloudflare = ApplyDNSProviderType("cloudflare")
|
ApplyDNSProviderTypeCloudflare = ApplyDNSProviderType(AccessProviderTypeCloudflare)
|
||||||
ApplyDNSProviderTypeClouDNS = ApplyDNSProviderType("cloudns")
|
ApplyDNSProviderTypeClouDNS = ApplyDNSProviderType(AccessProviderTypeClouDNS)
|
||||||
ApplyDNSProviderTypeCMCCCloud = ApplyDNSProviderType("cmcccloud")
|
ApplyDNSProviderTypeCMCCCloud = ApplyDNSProviderType(AccessProviderTypeCMCCCloud)
|
||||||
ApplyDNSProviderTypeDeSEC = ApplyDNSProviderType("desec")
|
ApplyDNSProviderTypeDeSEC = ApplyDNSProviderType(AccessProviderTypeDeSEC)
|
||||||
ApplyDNSProviderTypeDNSLA = ApplyDNSProviderType("dnsla")
|
ApplyDNSProviderTypeDNSLA = ApplyDNSProviderType(AccessProviderTypeDNSLA)
|
||||||
ApplyDNSProviderTypeDynv6 = ApplyDNSProviderType("dynv6")
|
ApplyDNSProviderTypeDynv6 = ApplyDNSProviderType(AccessProviderTypeDynv6)
|
||||||
ApplyDNSProviderTypeGcore = ApplyDNSProviderType("gcore")
|
ApplyDNSProviderTypeGcore = ApplyDNSProviderType(AccessProviderTypeGcore)
|
||||||
ApplyDNSProviderTypeGname = ApplyDNSProviderType("gname")
|
ApplyDNSProviderTypeGname = ApplyDNSProviderType(AccessProviderTypeGname)
|
||||||
ApplyDNSProviderTypeGoDaddy = ApplyDNSProviderType("godaddy")
|
ApplyDNSProviderTypeGoDaddy = ApplyDNSProviderType(AccessProviderTypeGoDaddy)
|
||||||
ApplyDNSProviderTypeHuaweiCloud = ApplyDNSProviderType("huaweicloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeHuaweiCloudDNS]
|
ApplyDNSProviderTypeHuaweiCloud = ApplyDNSProviderType(AccessProviderTypeHuaweiCloud) // 兼容旧值,等同于 [ApplyDNSProviderTypeHuaweiCloudDNS]
|
||||||
ApplyDNSProviderTypeHuaweiCloudDNS = ApplyDNSProviderType("huaweicloud-dns")
|
ApplyDNSProviderTypeHuaweiCloudDNS = ApplyDNSProviderType(AccessProviderTypeHuaweiCloud + "-dns")
|
||||||
ApplyDNSProviderTypeJDCloud = ApplyDNSProviderType("jdcloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeJDCloudDNS]
|
ApplyDNSProviderTypeJDCloud = ApplyDNSProviderType(AccessProviderTypeJDCloud) // 兼容旧值,等同于 [ApplyDNSProviderTypeJDCloudDNS]
|
||||||
ApplyDNSProviderTypeJDCloudDNS = ApplyDNSProviderType("jdcloud-dns")
|
ApplyDNSProviderTypeJDCloudDNS = ApplyDNSProviderType(AccessProviderTypeJDCloud + "-dns")
|
||||||
ApplyDNSProviderTypeNamecheap = ApplyDNSProviderType("namecheap")
|
ApplyDNSProviderTypeNamecheap = ApplyDNSProviderType(AccessProviderTypeNamecheap)
|
||||||
ApplyDNSProviderTypeNameDotCom = ApplyDNSProviderType("namedotcom")
|
ApplyDNSProviderTypeNameDotCom = ApplyDNSProviderType(AccessProviderTypeNameDotCom)
|
||||||
ApplyDNSProviderTypeNameSilo = ApplyDNSProviderType("namesilo")
|
ApplyDNSProviderTypeNameSilo = ApplyDNSProviderType(AccessProviderTypeNameSilo)
|
||||||
ApplyDNSProviderTypeNS1 = ApplyDNSProviderType("ns1")
|
ApplyDNSProviderTypeNS1 = ApplyDNSProviderType(AccessProviderTypeNS1)
|
||||||
ApplyDNSProviderTypePorkbun = ApplyDNSProviderType("porkbun")
|
ApplyDNSProviderTypePorkbun = ApplyDNSProviderType(AccessProviderTypePorkbun)
|
||||||
ApplyDNSProviderTypePowerDNS = ApplyDNSProviderType("powerdns")
|
ApplyDNSProviderTypePowerDNS = ApplyDNSProviderType(AccessProviderTypePowerDNS)
|
||||||
ApplyDNSProviderTypeRainYun = ApplyDNSProviderType("rainyun")
|
ApplyDNSProviderTypeRainYun = ApplyDNSProviderType(AccessProviderTypeRainYun)
|
||||||
ApplyDNSProviderTypeTencentCloud = ApplyDNSProviderType("tencentcloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeTencentCloudDNS]
|
ApplyDNSProviderTypeTencentCloud = ApplyDNSProviderType(AccessProviderTypeTencentCloud) // 兼容旧值,等同于 [ApplyDNSProviderTypeTencentCloudDNS]
|
||||||
ApplyDNSProviderTypeTencentCloudDNS = ApplyDNSProviderType("tencentcloud-dns")
|
ApplyDNSProviderTypeTencentCloudDNS = ApplyDNSProviderType(AccessProviderTypeTencentCloud + "-dns")
|
||||||
ApplyDNSProviderTypeTencentCloudEO = ApplyDNSProviderType("tencentcloud-eo")
|
ApplyDNSProviderTypeTencentCloudEO = ApplyDNSProviderType(AccessProviderTypeTencentCloud + "-eo")
|
||||||
ApplyDNSProviderTypeVercel = ApplyDNSProviderType("vercel")
|
ApplyDNSProviderTypeVercel = ApplyDNSProviderType(AccessProviderTypeVercel)
|
||||||
ApplyDNSProviderTypeVolcEngine = ApplyDNSProviderType("volcengine") // 兼容旧值,等同于 [ApplyDNSProviderTypeVolcEngineDNS]
|
ApplyDNSProviderTypeVolcEngine = ApplyDNSProviderType(AccessProviderTypeVolcEngine) // 兼容旧值,等同于 [ApplyDNSProviderTypeVolcEngineDNS]
|
||||||
ApplyDNSProviderTypeVolcEngineDNS = ApplyDNSProviderType("volcengine-dns")
|
ApplyDNSProviderTypeVolcEngineDNS = ApplyDNSProviderType(AccessProviderTypeVolcEngine + "-dns")
|
||||||
ApplyDNSProviderTypeWestcn = ApplyDNSProviderType("westcn")
|
ApplyDNSProviderTypeWestcn = ApplyDNSProviderType(AccessProviderTypeWestcn)
|
||||||
)
|
)
|
||||||
|
|
||||||
type DeployProviderType string
|
type DeployProviderType string
|
||||||
@ -144,78 +145,91 @@ type DeployProviderType string
|
|||||||
NOTICE: If you add new constant, please keep ASCII order.
|
NOTICE: If you add new constant, please keep ASCII order.
|
||||||
*/
|
*/
|
||||||
const (
|
const (
|
||||||
DeployProviderType1PanelConsole = DeployProviderType("1panel-console")
|
DeployProviderType1PanelConsole = DeployProviderType(AccessProviderType1Panel + "-console")
|
||||||
DeployProviderType1PanelSite = DeployProviderType("1panel-site")
|
DeployProviderType1PanelSite = DeployProviderType(AccessProviderType1Panel + "-site")
|
||||||
DeployProviderTypeAliyunALB = DeployProviderType("aliyun-alb")
|
DeployProviderTypeAliyunALB = DeployProviderType(AccessProviderTypeAliyun + "-alb")
|
||||||
DeployProviderTypeAliyunAPIGW = DeployProviderType("aliyun-apigw")
|
DeployProviderTypeAliyunAPIGW = DeployProviderType(AccessProviderTypeAliyun + "-apigw")
|
||||||
DeployProviderTypeAliyunCAS = DeployProviderType("aliyun-cas")
|
DeployProviderTypeAliyunCAS = DeployProviderType(AccessProviderTypeAliyun + "-cas")
|
||||||
DeployProviderTypeAliyunCASDeploy = DeployProviderType("aliyun-casdeploy")
|
DeployProviderTypeAliyunCASDeploy = DeployProviderType(AccessProviderTypeAliyun + "-casdeploy")
|
||||||
DeployProviderTypeAliyunCDN = DeployProviderType("aliyun-cdn")
|
DeployProviderTypeAliyunCDN = DeployProviderType(AccessProviderTypeAliyun + "-cdn")
|
||||||
DeployProviderTypeAliyunCLB = DeployProviderType("aliyun-clb")
|
DeployProviderTypeAliyunCLB = DeployProviderType(AccessProviderTypeAliyun + "-clb")
|
||||||
DeployProviderTypeAliyunDCDN = DeployProviderType("aliyun-dcdn")
|
DeployProviderTypeAliyunDCDN = DeployProviderType(AccessProviderTypeAliyun + "-dcdn")
|
||||||
DeployProviderTypeAliyunESA = DeployProviderType("aliyun-esa")
|
DeployProviderTypeAliyunESA = DeployProviderType(AccessProviderTypeAliyun + "-esa")
|
||||||
DeployProviderTypeAliyunFC = DeployProviderType("aliyun-fc")
|
DeployProviderTypeAliyunFC = DeployProviderType(AccessProviderTypeAliyun + "-fc")
|
||||||
DeployProviderTypeAliyunLive = DeployProviderType("aliyun-live")
|
DeployProviderTypeAliyunLive = DeployProviderType(AccessProviderTypeAliyun + "-live")
|
||||||
DeployProviderTypeAliyunNLB = DeployProviderType("aliyun-nlb")
|
DeployProviderTypeAliyunNLB = DeployProviderType(AccessProviderTypeAliyun + "-nlb")
|
||||||
DeployProviderTypeAliyunOSS = DeployProviderType("aliyun-oss")
|
DeployProviderTypeAliyunOSS = DeployProviderType(AccessProviderTypeAliyun + "-oss")
|
||||||
DeployProviderTypeAliyunVOD = DeployProviderType("aliyun-vod")
|
DeployProviderTypeAliyunVOD = DeployProviderType(AccessProviderTypeAliyun + "-vod")
|
||||||
DeployProviderTypeAliyunWAF = DeployProviderType("aliyun-waf")
|
DeployProviderTypeAliyunWAF = DeployProviderType(AccessProviderTypeAliyun + "-waf")
|
||||||
DeployProviderTypeAWSACM = DeployProviderType("aws-acm")
|
DeployProviderTypeAWSACM = DeployProviderType(AccessProviderTypeAWS + "-acm")
|
||||||
DeployProviderTypeAWSCloudFront = DeployProviderType("aws-cloudfront")
|
DeployProviderTypeAWSCloudFront = DeployProviderType(AccessProviderTypeAWS + "-cloudfront")
|
||||||
DeployProviderTypeAzureKeyVault = DeployProviderType("azure-keyvault")
|
DeployProviderTypeAzureKeyVault = DeployProviderType(AccessProviderTypeAzure + "-keyvault")
|
||||||
DeployProviderTypeBaiduCloudAppBLB = DeployProviderType("baiducloud-appblb")
|
DeployProviderTypeBaiduCloudAppBLB = DeployProviderType(AccessProviderTypeBaiduCloud + "-appblb")
|
||||||
DeployProviderTypeBaiduCloudBLB = DeployProviderType("baiducloud-blb")
|
DeployProviderTypeBaiduCloudBLB = DeployProviderType(AccessProviderTypeBaiduCloud + "-blb")
|
||||||
DeployProviderTypeBaiduCloudCDN = DeployProviderType("baiducloud-cdn")
|
DeployProviderTypeBaiduCloudCDN = DeployProviderType(AccessProviderTypeBaiduCloud + "-cdn")
|
||||||
DeployProviderTypeBaiduCloudCert = DeployProviderType("baiducloud-cert")
|
DeployProviderTypeBaiduCloudCert = DeployProviderType(AccessProviderTypeBaiduCloud + "-cert")
|
||||||
DeployProviderTypeBaishanCDN = DeployProviderType("baishan-cdn")
|
DeployProviderTypeBaishanCDN = DeployProviderType(AccessProviderTypeBaishan + "-cdn")
|
||||||
DeployProviderTypeBaotaPanelConsole = DeployProviderType("baotapanel-console")
|
DeployProviderTypeBaotaPanelConsole = DeployProviderType(AccessProviderTypeBaotaPanel + "-console")
|
||||||
DeployProviderTypeBaotaPanelSite = DeployProviderType("baotapanel-site")
|
DeployProviderTypeBaotaPanelSite = DeployProviderType(AccessProviderTypeBaotaPanel + "-site")
|
||||||
DeployProviderTypeBunnyCDN = DeployProviderType("bunny-cdn")
|
DeployProviderTypeBunnyCDN = DeployProviderType(AccessProviderTypeBunny + "-cdn")
|
||||||
DeployProviderTypeBytePlusCDN = DeployProviderType("byteplus-cdn")
|
DeployProviderTypeBytePlusCDN = DeployProviderType(AccessProviderTypeBytePlus + "-cdn")
|
||||||
DeployProviderTypeCacheFly = DeployProviderType("cachefly")
|
DeployProviderTypeCacheFly = DeployProviderType(AccessProviderTypeCacheFly)
|
||||||
DeployProviderTypeCdnfly = DeployProviderType("cdnfly")
|
DeployProviderTypeCdnfly = DeployProviderType(AccessProviderTypeCdnfly)
|
||||||
DeployProviderTypeDogeCloudCDN = DeployProviderType("dogecloud-cdn")
|
DeployProviderTypeDogeCloudCDN = DeployProviderType(AccessProviderTypeDogeCloud + "-cdn")
|
||||||
DeployProviderTypeEdgioApplications = DeployProviderType("edgio-applications")
|
DeployProviderTypeEdgioApplications = DeployProviderType(AccessProviderTypeEdgio + "-applications")
|
||||||
DeployProviderTypeGcoreCDN = DeployProviderType("gcore-cdn")
|
DeployProviderTypeGcoreCDN = DeployProviderType(AccessProviderTypeGcore + "-cdn")
|
||||||
DeployProviderTypeHuaweiCloudCDN = DeployProviderType("huaweicloud-cdn")
|
DeployProviderTypeHuaweiCloudCDN = DeployProviderType(AccessProviderTypeHuaweiCloud + "-cdn")
|
||||||
DeployProviderTypeHuaweiCloudELB = DeployProviderType("huaweicloud-elb")
|
DeployProviderTypeHuaweiCloudELB = DeployProviderType(AccessProviderTypeHuaweiCloud + "-elb")
|
||||||
DeployProviderTypeHuaweiCloudSCM = DeployProviderType("huaweicloud-scm")
|
DeployProviderTypeHuaweiCloudSCM = DeployProviderType(AccessProviderTypeHuaweiCloud + "-scm")
|
||||||
DeployProviderTypeHuaweiCloudWAF = DeployProviderType("huaweicloud-waf")
|
DeployProviderTypeHuaweiCloudWAF = DeployProviderType(AccessProviderTypeHuaweiCloud + "-waf")
|
||||||
DeployProviderTypeJDCloudALB = DeployProviderType("jdcloud-alb")
|
DeployProviderTypeJDCloudALB = DeployProviderType(AccessProviderTypeJDCloud + "-alb")
|
||||||
DeployProviderTypeJDCloudCDN = DeployProviderType("jdcloud-cdn")
|
DeployProviderTypeJDCloudCDN = DeployProviderType(AccessProviderTypeJDCloud + "-cdn")
|
||||||
DeployProviderTypeJDCloudLive = DeployProviderType("jdcloud-live")
|
DeployProviderTypeJDCloudLive = DeployProviderType(AccessProviderTypeJDCloud + "-live")
|
||||||
DeployProviderTypeJDCloudVOD = DeployProviderType("jdcloud-vod")
|
DeployProviderTypeJDCloudVOD = DeployProviderType(AccessProviderTypeJDCloud + "-vod")
|
||||||
DeployProviderTypeKubernetesSecret = DeployProviderType("k8s-secret")
|
DeployProviderTypeKubernetesSecret = DeployProviderType(AccessProviderTypeKubernetes + "-secret")
|
||||||
DeployProviderTypeLocal = DeployProviderType("local")
|
DeployProviderTypeLocal = DeployProviderType(AccessProviderTypeLocal)
|
||||||
DeployProviderTypeQiniuCDN = DeployProviderType("qiniu-cdn")
|
DeployProviderTypeQiniuCDN = DeployProviderType(AccessProviderTypeQiniu + "-cdn")
|
||||||
DeployProviderTypeQiniuKodo = DeployProviderType("qiniu-kodo")
|
DeployProviderTypeQiniuKodo = DeployProviderType(AccessProviderTypeQiniu + "-kodo")
|
||||||
DeployProviderTypeQiniuPili = DeployProviderType("qiniu-pili")
|
DeployProviderTypeQiniuPili = DeployProviderType(AccessProviderTypeQiniu + "-pili")
|
||||||
DeployProviderTypeRainYunRCDN = DeployProviderType("rainyun-rcdn")
|
DeployProviderTypeRainYunRCDN = DeployProviderType(AccessProviderTypeRainYun + "-rcdn")
|
||||||
DeployProviderTypeSafeLine = DeployProviderType("safeline")
|
DeployProviderTypeSafeLine = DeployProviderType(AccessProviderTypeSafeLine)
|
||||||
DeployProviderTypeSSH = DeployProviderType("ssh")
|
DeployProviderTypeSSH = DeployProviderType(AccessProviderTypeSSH)
|
||||||
DeployProviderTypeTencentCloudCDN = DeployProviderType("tencentcloud-cdn")
|
DeployProviderTypeTencentCloudCDN = DeployProviderType(AccessProviderTypeTencentCloud + "-cdn")
|
||||||
DeployProviderTypeTencentCloudCLB = DeployProviderType("tencentcloud-clb")
|
DeployProviderTypeTencentCloudCLB = DeployProviderType(AccessProviderTypeTencentCloud + "-clb")
|
||||||
DeployProviderTypeTencentCloudCOS = DeployProviderType("tencentcloud-cos")
|
DeployProviderTypeTencentCloudCOS = DeployProviderType(AccessProviderTypeTencentCloud + "-cos")
|
||||||
DeployProviderTypeTencentCloudCSS = DeployProviderType("tencentcloud-css")
|
DeployProviderTypeTencentCloudCSS = DeployProviderType(AccessProviderTypeTencentCloud + "-css")
|
||||||
DeployProviderTypeTencentCloudECDN = DeployProviderType("tencentcloud-ecdn")
|
DeployProviderTypeTencentCloudECDN = DeployProviderType(AccessProviderTypeTencentCloud + "-ecdn")
|
||||||
DeployProviderTypeTencentCloudEO = DeployProviderType("tencentcloud-eo")
|
DeployProviderTypeTencentCloudEO = DeployProviderType(AccessProviderTypeTencentCloud + "-eo")
|
||||||
DeployProviderTypeTencentCloudSCF = DeployProviderType("tencentcloud-scf")
|
DeployProviderTypeTencentCloudSCF = DeployProviderType(AccessProviderTypeTencentCloud + "-scf")
|
||||||
DeployProviderTypeTencentCloudSSL = DeployProviderType("tencentcloud-ssl")
|
DeployProviderTypeTencentCloudSSL = DeployProviderType(AccessProviderTypeTencentCloud + "-ssl")
|
||||||
DeployProviderTypeTencentCloudSSLDeploy = DeployProviderType("tencentcloud-ssldeploy")
|
DeployProviderTypeTencentCloudSSLDeploy = DeployProviderType(AccessProviderTypeTencentCloud + "-ssldeploy")
|
||||||
DeployProviderTypeTencentCloudVOD = DeployProviderType("tencentcloud-vod")
|
DeployProviderTypeTencentCloudVOD = DeployProviderType(AccessProviderTypeTencentCloud + "-vod")
|
||||||
DeployProviderTypeTencentCloudWAF = DeployProviderType("tencentcloud-waf")
|
DeployProviderTypeTencentCloudWAF = DeployProviderType(AccessProviderTypeTencentCloud + "-waf")
|
||||||
DeployProviderTypeUCloudUCDN = DeployProviderType("ucloud-ucdn")
|
DeployProviderTypeUCloudUCDN = DeployProviderType(AccessProviderTypeUCloud + "-ucdn")
|
||||||
DeployProviderTypeUCloudUS3 = DeployProviderType("ucloud-us3")
|
DeployProviderTypeUCloudUS3 = DeployProviderType(AccessProviderTypeUCloud + "-us3")
|
||||||
DeployProviderTypeUpyunCDN = DeployProviderType("upyun-cdn")
|
DeployProviderTypeUpyunCDN = DeployProviderType(AccessProviderTypeUpyun + "-cdn")
|
||||||
DeployProviderTypeUpyunFile = DeployProviderType("upyun-file")
|
DeployProviderTypeUpyunFile = DeployProviderType(AccessProviderTypeUpyun + "-file")
|
||||||
DeployProviderTypeVolcEngineALB = DeployProviderType("volcengine-alb")
|
DeployProviderTypeVolcEngineALB = DeployProviderType(AccessProviderTypeVolcEngine + "-alb")
|
||||||
DeployProviderTypeVolcEngineCDN = DeployProviderType("volcengine-cdn")
|
DeployProviderTypeVolcEngineCDN = DeployProviderType(AccessProviderTypeVolcEngine + "-cdn")
|
||||||
DeployProviderTypeVolcEngineCertCenter = DeployProviderType("volcengine-certcenter")
|
DeployProviderTypeVolcEngineCertCenter = DeployProviderType(AccessProviderTypeVolcEngine + "-certcenter")
|
||||||
DeployProviderTypeVolcEngineCLB = DeployProviderType("volcengine-clb")
|
DeployProviderTypeVolcEngineCLB = DeployProviderType(AccessProviderTypeVolcEngine + "-clb")
|
||||||
DeployProviderTypeVolcEngineDCDN = DeployProviderType("volcengine-dcdn")
|
DeployProviderTypeVolcEngineDCDN = DeployProviderType(AccessProviderTypeVolcEngine + "-dcdn")
|
||||||
DeployProviderTypeVolcEngineImageX = DeployProviderType("volcengine-imagex")
|
DeployProviderTypeVolcEngineImageX = DeployProviderType(AccessProviderTypeVolcEngine + "-imagex")
|
||||||
DeployProviderTypeVolcEngineLive = DeployProviderType("volcengine-live")
|
DeployProviderTypeVolcEngineLive = DeployProviderType(AccessProviderTypeVolcEngine + "-live")
|
||||||
DeployProviderTypeVolcEngineTOS = DeployProviderType("volcengine-tos")
|
DeployProviderTypeVolcEngineTOS = DeployProviderType(AccessProviderTypeVolcEngine + "-tos")
|
||||||
DeployProviderTypeWangsuCDNPro = DeployProviderType("wangsu-cdnpro")
|
DeployProviderTypeWangsuCDNPro = DeployProviderType(AccessProviderTypeWangsu + "-cdnpro")
|
||||||
DeployProviderTypeWebhook = DeployProviderType("webhook")
|
DeployProviderTypeWebhook = DeployProviderType(AccessProviderTypeWebhook)
|
||||||
|
)
|
||||||
|
|
||||||
|
type NotifyProviderType string
|
||||||
|
|
||||||
|
/*
|
||||||
|
消息通知提供商常量值。
|
||||||
|
短横线前的部分始终等于授权提供商类型。
|
||||||
|
|
||||||
|
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
||||||
|
NOTICE: If you add new constant, please keep ASCII order.
|
||||||
|
*/
|
||||||
|
const (
|
||||||
|
NotifyProviderTypeWebhook = NotifyProviderType(AccessProviderTypeWebhook)
|
||||||
)
|
)
|
||||||
|
@ -13,6 +13,7 @@ type Settings struct {
|
|||||||
Content string `json:"content" db:"content"`
|
Content string `json:"content" db:"content"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated: v0.4.x 将废弃
|
||||||
type NotifyTemplatesSettingsContent struct {
|
type NotifyTemplatesSettingsContent struct {
|
||||||
NotifyTemplates []struct {
|
NotifyTemplates []struct {
|
||||||
Subject string `json:"subject"`
|
Subject string `json:"subject"`
|
||||||
@ -20,8 +21,10 @@ type NotifyTemplatesSettingsContent struct {
|
|||||||
} `json:"notifyTemplates"`
|
} `json:"notifyTemplates"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated: v0.4.x 将废弃
|
||||||
type NotifyChannelsSettingsContent map[string]map[string]any
|
type NotifyChannelsSettingsContent map[string]map[string]any
|
||||||
|
|
||||||
|
// Deprecated: v0.4.x 将废弃
|
||||||
func (s *Settings) GetNotifyChannelConfig(channel string) (map[string]any, error) {
|
func (s *Settings) GetNotifyChannelConfig(channel string) (map[string]any, error) {
|
||||||
conf := &NotifyChannelsSettingsContent{}
|
conf := &NotifyChannelsSettingsContent{}
|
||||||
if err := json.Unmarshal([]byte(s.Content), conf); err != nil {
|
if err := json.Unmarshal([]byte(s.Content), conf); err != nil {
|
||||||
|
@ -71,7 +71,7 @@ type WorkflowNodeConfigForApply struct {
|
|||||||
CAProvider string `json:"caProvider,omitempty"` // CA 提供商(零值将使用全局配置)
|
CAProvider string `json:"caProvider,omitempty"` // CA 提供商(零值将使用全局配置)
|
||||||
CAProviderAccessId string `json:"caProviderAccessId,omitempty"` // CA 提供商授权记录 ID
|
CAProviderAccessId string `json:"caProviderAccessId,omitempty"` // CA 提供商授权记录 ID
|
||||||
CAProviderConfig map[string]any `json:"caProviderConfig,omitempty"` // CA 提供商额外配置
|
CAProviderConfig map[string]any `json:"caProviderConfig,omitempty"` // CA 提供商额外配置
|
||||||
KeyAlgorithm string `json:"keyAlgorithm"` // 密钥算法
|
KeyAlgorithm string `json:"keyAlgorithm"` // 证书算法
|
||||||
Nameservers string `json:"nameservers,omitempty"` // DNS 服务器列表,以半角分号分隔
|
Nameservers string `json:"nameservers,omitempty"` // DNS 服务器列表,以半角分号分隔
|
||||||
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` // DNS 传播超时时间(零值取决于提供商的默认值)
|
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` // DNS 传播超时时间(零值取决于提供商的默认值)
|
||||||
DnsTTL int32 `json:"dnsTTL,omitempty"` // DNS TTL(零值取决于提供商的默认值)
|
DnsTTL int32 `json:"dnsTTL,omitempty"` // DNS TTL(零值取决于提供商的默认值)
|
||||||
@ -95,7 +95,10 @@ type WorkflowNodeConfigForDeploy struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type WorkflowNodeConfigForNotify struct {
|
type WorkflowNodeConfigForNotify struct {
|
||||||
Channel string `json:"channel"` // 通知渠道
|
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"` // 通知主题
|
Subject string `json:"subject"` // 通知主题
|
||||||
Message string `json:"message"` // 通知内容
|
Message string `json:"message"` // 通知内容
|
||||||
}
|
}
|
||||||
@ -111,10 +114,10 @@ func (n *WorkflowNode) GetConfigForApply() WorkflowNodeConfigForApply {
|
|||||||
ContactEmail: maputil.GetString(n.Config, "contactEmail"),
|
ContactEmail: maputil.GetString(n.Config, "contactEmail"),
|
||||||
Provider: maputil.GetString(n.Config, "provider"),
|
Provider: maputil.GetString(n.Config, "provider"),
|
||||||
ProviderAccessId: maputil.GetString(n.Config, "providerAccessId"),
|
ProviderAccessId: maputil.GetString(n.Config, "providerAccessId"),
|
||||||
ProviderConfig: maputil.GetAnyMap(n.Config, "providerConfig"),
|
ProviderConfig: maputil.GetMap(n.Config, "providerConfig"),
|
||||||
CAProvider: maputil.GetString(n.Config, "caProvider"),
|
CAProvider: maputil.GetString(n.Config, "caProvider"),
|
||||||
CAProviderAccessId: maputil.GetString(n.Config, "caProviderAccessId"),
|
CAProviderAccessId: maputil.GetString(n.Config, "caProviderAccessId"),
|
||||||
CAProviderConfig: maputil.GetAnyMap(n.Config, "caProviderConfig"),
|
CAProviderConfig: maputil.GetMap(n.Config, "caProviderConfig"),
|
||||||
KeyAlgorithm: maputil.GetString(n.Config, "keyAlgorithm"),
|
KeyAlgorithm: maputil.GetString(n.Config, "keyAlgorithm"),
|
||||||
Nameservers: maputil.GetString(n.Config, "nameservers"),
|
Nameservers: maputil.GetString(n.Config, "nameservers"),
|
||||||
DnsPropagationTimeout: maputil.GetInt32(n.Config, "dnsPropagationTimeout"),
|
DnsPropagationTimeout: maputil.GetInt32(n.Config, "dnsPropagationTimeout"),
|
||||||
@ -138,7 +141,7 @@ func (n *WorkflowNode) GetConfigForDeploy() WorkflowNodeConfigForDeploy {
|
|||||||
Certificate: maputil.GetString(n.Config, "certificate"),
|
Certificate: maputil.GetString(n.Config, "certificate"),
|
||||||
Provider: maputil.GetString(n.Config, "provider"),
|
Provider: maputil.GetString(n.Config, "provider"),
|
||||||
ProviderAccessId: maputil.GetString(n.Config, "providerAccessId"),
|
ProviderAccessId: maputil.GetString(n.Config, "providerAccessId"),
|
||||||
ProviderConfig: maputil.GetAnyMap(n.Config, "providerConfig"),
|
ProviderConfig: maputil.GetMap(n.Config, "providerConfig"),
|
||||||
SkipOnLastSucceeded: maputil.GetBool(n.Config, "skipOnLastSucceeded"),
|
SkipOnLastSucceeded: maputil.GetBool(n.Config, "skipOnLastSucceeded"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,6 +149,9 @@ func (n *WorkflowNode) GetConfigForDeploy() WorkflowNodeConfigForDeploy {
|
|||||||
func (n *WorkflowNode) GetConfigForNotify() WorkflowNodeConfigForNotify {
|
func (n *WorkflowNode) GetConfigForNotify() WorkflowNodeConfigForNotify {
|
||||||
return WorkflowNodeConfigForNotify{
|
return WorkflowNodeConfigForNotify{
|
||||||
Channel: maputil.GetString(n.Config, "channel"),
|
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"),
|
Subject: maputil.GetString(n.Config, "subject"),
|
||||||
Message: maputil.GetString(n.Config, "message"),
|
Message: maputil.GetString(n.Config, "message"),
|
||||||
}
|
}
|
||||||
|
72
internal/notify/notifier.go
Normal file
72
internal/notify/notifier.go
Normal file
@ -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
|
||||||
|
}
|
@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/usual2970/certimate/internal/repository"
|
"github.com/usual2970/certimate/internal/repository"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Deprecated: v0.4.x 将废弃
|
||||||
func SendToAllChannels(subject, message string) error {
|
func SendToAllChannels(subject, message string) error {
|
||||||
notifiers, err := getEnabledNotifiers()
|
notifiers, err := getEnabledNotifiers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -38,8 +39,9 @@ func SendToAllChannels(subject, message string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated: v0.4.x 将废弃
|
||||||
func SendToChannel(subject, message string, channel string, channelConfig map[string]any) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -48,6 +50,7 @@ func SendToChannel(subject, message string, channel string, channelConfig map[st
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated: v0.4.x 将废弃
|
||||||
func getEnabledNotifiers() ([]notifier.Notifier, error) {
|
func getEnabledNotifiers() ([]notifier.Notifier, error) {
|
||||||
settingsRepo := repository.NewSettingsRepository()
|
settingsRepo := repository.NewSettingsRepository()
|
||||||
settings, err := settingsRepo.GetByName(context.Background(), "notifyChannels")
|
settings, err := settingsRepo.GetByName(context.Background(), "notifyChannels")
|
||||||
@ -66,7 +69,7 @@ func getEnabledNotifiers() ([]notifier.Notifier, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
notifier, err := createNotifier(domain.NotifyChannelType(k), v)
|
notifier, err := createNotifierProviderUseGlobalSettings(domain.NotifyChannelType(k), v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -5,102 +5,28 @@ import (
|
|||||||
|
|
||||||
"github.com/usual2970/certimate/internal/domain"
|
"github.com/usual2970/certimate/internal/domain"
|
||||||
"github.com/usual2970/certimate/internal/pkg/core/notifier"
|
"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"
|
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"
|
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 排序。
|
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
||||||
NOTICE: If you add new constant, please keep ASCII order.
|
NOTICE: If you add new constant, please keep ASCII order.
|
||||||
*/
|
*/
|
||||||
switch channel {
|
switch options.Provider {
|
||||||
case domain.NotifyChannelTypeBark:
|
case domain.NotifyProviderTypeWebhook:
|
||||||
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{
|
return pWebhook.NewNotifier(&pWebhook.NotifierConfig{
|
||||||
Url: maputil.GetString(channelConfig, "url"),
|
Url: maputil.GetString(options.ProviderAccessConfig, "url"),
|
||||||
AllowInsecureConnections: maputil.GetBool(channelConfig, "allowInsecureConnections"),
|
AllowInsecureConnections: maputil.GetBool(options.ProviderAccessConfig, "allowInsecureConnections"),
|
||||||
})
|
|
||||||
|
|
||||||
case domain.NotifyChannelTypeWeCom:
|
|
||||||
return pWeCom.NewNotifier(&pWeCom.NotifierConfig{
|
|
||||||
WebhookUrl: maputil.GetString(channelConfig, "webhookUrl"),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("unsupported notifier channel '%s'", channelConfig)
|
return nil, fmt.Errorf("unsupported notifier provider '%s'", options.Provider)
|
||||||
}
|
}
|
||||||
|
108
internal/notify/providers_deprecated.go
Normal file
108
internal/notify/providers_deprecated.go
Normal file
@ -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)
|
||||||
|
}
|
@ -8,25 +8,30 @@ import (
|
|||||||
"github.com/usual2970/certimate/internal/domain/dtos"
|
"github.com/usual2970/certimate/internal/domain/dtos"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Deprecated: v0.4.x 将废弃
|
||||||
const (
|
const (
|
||||||
notifyTestTitle = "测试通知"
|
notifyTestTitle = "测试通知"
|
||||||
notifyTestBody = "欢迎使用 Certimate ,这是一条测试通知。"
|
notifyTestBody = "欢迎使用 Certimate ,这是一条测试通知。"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Deprecated: v0.4.x 将废弃
|
||||||
type settingsRepository interface {
|
type settingsRepository interface {
|
||||||
GetByName(ctx context.Context, name string) (*domain.Settings, error)
|
GetByName(ctx context.Context, name string) (*domain.Settings, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated: v0.4.x 将废弃
|
||||||
type NotifyService struct {
|
type NotifyService struct {
|
||||||
settingsRepo settingsRepository
|
settingsRepo settingsRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated: v0.4.x 将废弃
|
||||||
func NewNotifyService(settingsRepo settingsRepository) *NotifyService {
|
func NewNotifyService(settingsRepo settingsRepository) *NotifyService {
|
||||||
return &NotifyService{
|
return &NotifyService{
|
||||||
settingsRepo: settingsRepo,
|
settingsRepo: settingsRepo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated: v0.4.x 将废弃
|
||||||
func (n *NotifyService) Test(ctx context.Context, req *dtos.NotifyTestPushReq) error {
|
func (n *NotifyService) Test(ctx context.Context, req *dtos.NotifyTestPushReq) error {
|
||||||
settings, err := n.settingsRepo.GetByName(ctx, "notifyChannels")
|
settings, err := n.settingsRepo.GetByName(ctx, "notifyChannels")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -207,7 +207,7 @@ func GetOrDefaultBool(dict map[string]any, key string, defaultValue bool) bool {
|
|||||||
//
|
//
|
||||||
// 出参:
|
// 出参:
|
||||||
// - 字典中键对应的 `map[string]any` 对象。
|
// - 字典中键对应的 `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 {
|
if dict == nil {
|
||||||
return make(map[string]any)
|
return make(map[string]any)
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
if err != nil {
|
||||||
n.logger.Warn("failed to create applicant provider")
|
n.logger.Warn("failed to create applicant provider")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 申请证书
|
// 申请证书
|
||||||
applyResult, err := applicant.Apply()
|
applyResult, err := applicant.Apply(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
n.logger.Warn("failed to apply")
|
n.logger.Warn("failed to apply")
|
||||||
return err
|
return err
|
||||||
|
@ -63,17 +63,18 @@ func (n *deployNode) Process(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 初始化部署器
|
// 初始化部署器
|
||||||
deployer, err := deployer.NewWithDeployNode(n.node, struct {
|
deployer, err := deployer.NewWithWorkflowNode(deployer.DeployerWithWorkflowNodeConfig{
|
||||||
Certificate string
|
Node: n.node,
|
||||||
PrivateKey string
|
Logger: n.logger,
|
||||||
}{Certificate: certificate.Certificate, PrivateKey: certificate.PrivateKey})
|
CertificatePEM: certificate.Certificate,
|
||||||
|
PrivateKeyPEM: certificate.PrivateKey,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
n.logger.Warn("failed to create deployer provider")
|
n.logger.Warn("failed to create deployer provider")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 部署证书
|
// 部署证书
|
||||||
deployer.SetLogger(n.logger)
|
|
||||||
if err := deployer.Deploy(ctx); err != nil {
|
if err := deployer.Deploy(ctx); err != nil {
|
||||||
n.logger.Warn("failed to deploy")
|
n.logger.Warn("failed to deploy")
|
||||||
return err
|
return err
|
||||||
|
@ -30,6 +30,11 @@ func (n *notifyNode) Process(ctx context.Context) error {
|
|||||||
|
|
||||||
nodeConfig := n.node.GetConfigForNotify()
|
nodeConfig := n.node.GetConfigForNotify()
|
||||||
|
|
||||||
|
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")
|
settings, err := n.settingsRepo.GetByName(ctx, "notifyChannels")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -49,6 +54,26 @@ func (n *notifyNode) Process(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
n.logger.Info("notify completed")
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 推送通知
|
||||||
|
if err := deployer.Notify(ctx); err != nil {
|
||||||
|
n.logger.Warn("failed to notify")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
67
ui/src/components/provider/NotifyProviderSelect.tsx
Normal file
67
ui/src/components/provider/NotifyProviderSelect.tsx
Normal file
@ -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<Array<{ key: string; value: string; label: string; data: NotifyProvider }>>([]);
|
||||||
|
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 (
|
||||||
|
<Space className="max-w-full grow overflow-hidden truncate" size={4}>
|
||||||
|
<Avatar src={provider?.icon} size="small" />
|
||||||
|
<Typography.Text className="leading-loose" ellipsis>
|
||||||
|
{t(provider?.name ?? "")}
|
||||||
|
</Typography.Text>
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
{...props}
|
||||||
|
filterOption={(inputValue, option) => {
|
||||||
|
if (!option) return false;
|
||||||
|
|
||||||
|
const value = inputValue.toLowerCase();
|
||||||
|
return option.value.toLowerCase().includes(value) || option.label.toLowerCase().includes(value);
|
||||||
|
}}
|
||||||
|
labelRender={({ label, value }) => {
|
||||||
|
if (!label) {
|
||||||
|
return <Typography.Text type="secondary">{props.placeholder}</Typography.Text>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return renderOption(value as string);
|
||||||
|
}}
|
||||||
|
options={options}
|
||||||
|
optionFilterProp={undefined}
|
||||||
|
optionLabelProp={undefined}
|
||||||
|
optionRender={(option) => renderOption(option.data.value)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(NotifyProviderSelect);
|
@ -193,6 +193,7 @@ const WorkflowRunLogs = ({ runId, runStatus }: { runId: string; runStatus: strin
|
|||||||
const NEWLINE = "\n";
|
const NEWLINE = "\n";
|
||||||
const logstr = listData
|
const logstr = listData
|
||||||
.map((group) => {
|
.map((group) => {
|
||||||
|
const escape = (str: string) => str.replaceAll("\r", "\\r").replaceAll("\n", "\\n");
|
||||||
return (
|
return (
|
||||||
group.name +
|
group.name +
|
||||||
NEWLINE +
|
NEWLINE +
|
||||||
@ -200,8 +201,9 @@ const WorkflowRunLogs = ({ runId, runStatus }: { runId: string; runStatus: strin
|
|||||||
.map((record) => {
|
.map((record) => {
|
||||||
const datetime = dayjs(record.timestamp).format("YYYY-MM-DDTHH:mm:ss.SSSZ");
|
const datetime = dayjs(record.timestamp).format("YYYY-MM-DDTHH:mm:ss.SSSZ");
|
||||||
const level = record.level;
|
const level = record.level;
|
||||||
const message = record.message.trim().replaceAll("\r", "\\r").replaceAll("\n", "\\n");
|
const message = record.message;
|
||||||
return `[${datetime}] [${level}] ${message}`;
|
const data = record.data && Object.keys(record.data).length > 0 ? JSON.stringify(record.data) : "";
|
||||||
|
return `[${datetime}] [${level}] ${escape(message)} ${escape(data)}`.trim();
|
||||||
})
|
})
|
||||||
.join(NEWLINE)
|
.join(NEWLINE)
|
||||||
);
|
);
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { memo, useMemo, useRef, useState } from "react";
|
import { memo, useMemo, useRef, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Flex, Typography } from "antd";
|
import { Avatar, Flex, Typography } from "antd";
|
||||||
import { produce } from "immer";
|
import { produce } from "immer";
|
||||||
|
|
||||||
|
import { notifyProvidersMap } from "@/domain/provider";
|
||||||
import { notifyChannelsMap } from "@/domain/settings";
|
import { notifyChannelsMap } from "@/domain/settings";
|
||||||
import { type WorkflowNodeConfigForNotify, WorkflowNodeType } from "@/domain/workflow";
|
import { type WorkflowNodeConfigForNotify, WorkflowNodeType } from "@/domain/workflow";
|
||||||
import { useZustandShallowSelector } from "@/hooks";
|
import { useZustandShallowSelector } from "@/hooks";
|
||||||
@ -39,9 +40,11 @@ const NotifyNode = ({ node, disabled }: NotifyNodeProps) => {
|
|||||||
|
|
||||||
const config = (node.config as WorkflowNodeConfigForNotify) ?? {};
|
const config = (node.config as WorkflowNodeConfigForNotify) ?? {};
|
||||||
const channel = notifyChannelsMap.get(config.channel as string);
|
const channel = notifyChannelsMap.get(config.channel as string);
|
||||||
|
const provider = notifyProvidersMap.get(config.provider);
|
||||||
return (
|
return (
|
||||||
<Flex className="size-full overflow-hidden" align="center" gap={8}>
|
<Flex className="size-full overflow-hidden" align="center" gap={8}>
|
||||||
<Typography.Text className="flex-1 truncate">{t(channel?.name ?? " ")}</Typography.Text>
|
<Avatar src={provider?.icon} size="small" />
|
||||||
|
<Typography.Text className="flex-1 truncate">{t(channel?.name ?? provider?.name ?? " ")}</Typography.Text>
|
||||||
<Typography.Text className="truncate" type="secondary">
|
<Typography.Text className="truncate" type="secondary">
|
||||||
{config.subject ?? ""}
|
{config.subject ?? ""}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
import { forwardRef, memo, useEffect, useImperativeHandle } from "react";
|
import { forwardRef, memo, useEffect, useImperativeHandle, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Link } from "react-router";
|
import { Link } from "react-router";
|
||||||
import { RightOutlined as RightOutlinedIcon } from "@ant-design/icons";
|
import { PlusOutlined as PlusOutlinedIcon, RightOutlined as RightOutlinedIcon } from "@ant-design/icons";
|
||||||
import { Button, Form, type FormInstance, Input, Select } from "antd";
|
import { Alert, Button, Form, type FormInstance, Input, Select } from "antd";
|
||||||
import { createSchemaFieldRule } from "antd-zod";
|
import { createSchemaFieldRule } from "antd-zod";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import AccessEditModal from "@/components/access/AccessEditModal";
|
||||||
|
import AccessSelect from "@/components/access/AccessSelect";
|
||||||
|
import NotifyProviderSelect from "@/components/provider/NotifyProviderSelect";
|
||||||
|
import { ACCESS_USAGES, accessProvidersMap, notifyProvidersMap } from "@/domain/provider";
|
||||||
import { notifyChannelsMap } from "@/domain/settings";
|
import { notifyChannelsMap } from "@/domain/settings";
|
||||||
import { type WorkflowNodeConfigForNotify } from "@/domain/workflow";
|
import { type WorkflowNodeConfigForNotify } from "@/domain/workflow";
|
||||||
import { useAntdForm, useZustandShallowSelector } from "@/hooks";
|
import { useAntdForm, useZustandShallowSelector } from "@/hooks";
|
||||||
|
import { useAccessesStore } from "@/stores/access";
|
||||||
import { useNotifyChannelsStore } from "@/stores/notify";
|
import { useNotifyChannelsStore } from "@/stores/notify";
|
||||||
|
|
||||||
type NotifyNodeConfigFormFieldValues = Partial<WorkflowNodeConfigForNotify>;
|
type NotifyNodeConfigFormFieldValues = Partial<WorkflowNodeConfigForNotify>;
|
||||||
@ -35,6 +40,8 @@ const NotifyNodeConfigForm = forwardRef<NotifyNodeConfigFormInstance, NotifyNode
|
|||||||
({ className, style, disabled, initialValues, onValuesChange }, ref) => {
|
({ className, style, disabled, initialValues, onValuesChange }, ref) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const { accesses } = useAccessesStore(useZustandShallowSelector("accesses"));
|
||||||
|
|
||||||
const {
|
const {
|
||||||
channels,
|
channels,
|
||||||
loadedAtOnce: channelsLoadedAtOnce,
|
loadedAtOnce: channelsLoadedAtOnce,
|
||||||
@ -53,7 +60,11 @@ const NotifyNodeConfigForm = forwardRef<NotifyNodeConfigFormInstance, NotifyNode
|
|||||||
.string({ message: t("workflow_node.notify.form.message.placeholder") })
|
.string({ message: t("workflow_node.notify.form.message.placeholder") })
|
||||||
.min(1, t("workflow_node.notify.form.message.placeholder"))
|
.min(1, t("workflow_node.notify.form.message.placeholder"))
|
||||||
.max(1000, t("common.errmsg.string_max", { max: 1000 })),
|
.max(1000, t("common.errmsg.string_max", { max: 1000 })),
|
||||||
channel: z.string({ message: t("workflow_node.notify.form.channel.placeholder") }).min(1, t("workflow_node.notify.form.channel.placeholder")),
|
channel: z.string().nullish(),
|
||||||
|
provider: z.string({ message: t("workflow_node.notify.form.provider.placeholder") }).nonempty(t("workflow_node.notify.form.provider.placeholder")),
|
||||||
|
providerAccessId: z
|
||||||
|
.string({ message: t("workflow_node.notify.form.provider_access.placeholder") })
|
||||||
|
.nonempty(t("workflow_node.notify.form.provider_access.placeholder")),
|
||||||
});
|
});
|
||||||
const formRule = createSchemaFieldRule(formSchema);
|
const formRule = createSchemaFieldRule(formSchema);
|
||||||
const { form: formInst, formProps } = useAntdForm({
|
const { form: formInst, formProps } = useAntdForm({
|
||||||
@ -61,6 +72,49 @@ const NotifyNodeConfigForm = forwardRef<NotifyNodeConfigFormInstance, NotifyNode
|
|||||||
initialValues: initialValues ?? initFormModel(),
|
initialValues: initialValues ?? initFormModel(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const fieldProvider = Form.useWatch<string>("provider", { form: formInst, preserve: true });
|
||||||
|
const fieldProviderAccessId = Form.useWatch<string>("providerAccessId", formInst);
|
||||||
|
|
||||||
|
const [showProvider, setShowProvider] = useState(false);
|
||||||
|
useEffect(() => {
|
||||||
|
// 通常情况下每个授权信息只对应一个消息通知提供商,此时无需显示消息通知提供商字段;
|
||||||
|
// 如果对应多个,则显示。
|
||||||
|
if (fieldProviderAccessId) {
|
||||||
|
const access = accesses.find((e) => e.id === fieldProviderAccessId);
|
||||||
|
const providers = Array.from(notifyProvidersMap.values()).filter((e) => e.provider === access?.provider);
|
||||||
|
setShowProvider(providers.length > 1);
|
||||||
|
} else {
|
||||||
|
setShowProvider(false);
|
||||||
|
}
|
||||||
|
}, [accesses, fieldProviderAccessId]);
|
||||||
|
|
||||||
|
const handleProviderSelect = (value: string) => {
|
||||||
|
if (fieldProvider === value) return;
|
||||||
|
|
||||||
|
// 切换消息通知提供商时联动授权信息
|
||||||
|
if (initialValues?.provider === value) {
|
||||||
|
formInst.setFieldValue("providerAccessId", initialValues?.providerAccessId);
|
||||||
|
onValuesChange?.(formInst.getFieldsValue(true));
|
||||||
|
} else {
|
||||||
|
if (notifyProvidersMap.get(fieldProvider)?.provider !== notifyProvidersMap.get(value)?.provider) {
|
||||||
|
formInst.setFieldValue("providerAccessId", undefined);
|
||||||
|
onValuesChange?.(formInst.getFieldsValue(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleProviderAccessSelect = (value: string) => {
|
||||||
|
if (fieldProviderAccessId === value) return;
|
||||||
|
|
||||||
|
// 切换授权信息时联动消息通知提供商
|
||||||
|
const access = accesses.find((access) => access.id === value);
|
||||||
|
const provider = Array.from(notifyProvidersMap.values()).find((provider) => provider.provider === access?.provider);
|
||||||
|
if (fieldProvider !== provider?.type) {
|
||||||
|
formInst.setFieldValue("provider", provider?.type);
|
||||||
|
onValuesChange?.(formInst.getFieldsValue(true));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
|
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
|
||||||
onValuesChange?.(values as NotifyNodeConfigFormFieldValues);
|
onValuesChange?.(values as NotifyNodeConfigFormFieldValues);
|
||||||
};
|
};
|
||||||
@ -92,7 +146,7 @@ const NotifyNodeConfigForm = forwardRef<NotifyNodeConfigFormInstance, NotifyNode
|
|||||||
<Form.Item className="mb-0">
|
<Form.Item className="mb-0">
|
||||||
<label className="mb-1 block">
|
<label className="mb-1 block">
|
||||||
<div className="flex w-full items-center justify-between gap-4">
|
<div className="flex w-full items-center justify-between gap-4">
|
||||||
<div className="max-w-full grow truncate">{t("workflow_node.notify.form.channel.label")}</div>
|
<div className="max-w-full grow truncate line-through">{t("workflow_node.notify.form.channel.label")}</div>
|
||||||
<div className="text-right">
|
<div className="text-right">
|
||||||
<Link className="ant-typography" to="/settings/notification" target="_blank">
|
<Link className="ant-typography" to="/settings/notification" target="_blank">
|
||||||
<Button size="small" type="link">
|
<Button size="small" type="link">
|
||||||
@ -116,6 +170,60 @@ const NotifyNodeConfigForm = forwardRef<NotifyNodeConfigFormInstance, NotifyNode
|
|||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item name="provider" label={t("workflow_node.notify.form.provider.label")} hidden={!showProvider} rules={[formRule]}>
|
||||||
|
<NotifyProviderSelect
|
||||||
|
disabled={!showProvider}
|
||||||
|
filter={(record) => {
|
||||||
|
if (fieldProviderAccessId) {
|
||||||
|
return accesses.find((e) => e.id === fieldProviderAccessId)?.provider === record.provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}}
|
||||||
|
placeholder={t("workflow_node.notify.form.provider.placeholder")}
|
||||||
|
showSearch
|
||||||
|
onSelect={handleProviderSelect}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item className="mb-0">
|
||||||
|
<label className="mb-1 block">
|
||||||
|
<div className="flex w-full items-center justify-between gap-4">
|
||||||
|
<div className="max-w-full grow truncate">
|
||||||
|
<span>{t("workflow_node.notify.form.provider_access.label")}</span>
|
||||||
|
</div>
|
||||||
|
<div className="text-right">
|
||||||
|
<AccessEditModal
|
||||||
|
range="notify-only"
|
||||||
|
scene="add"
|
||||||
|
trigger={
|
||||||
|
<Button size="small" type="link">
|
||||||
|
{t("workflow_node.notify.form.provider_access.button")}
|
||||||
|
<PlusOutlinedIcon className="text-xs" />
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
afterSubmit={(record) => {
|
||||||
|
const provider = accessProvidersMap.get(record.provider);
|
||||||
|
if (provider?.usages?.includes(ACCESS_USAGES.NOTIFICATION)) {
|
||||||
|
formInst.setFieldValue("providerAccessId", record.id);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
<Form.Item name="providerAccessId" rules={[formRule]}>
|
||||||
|
<AccessSelect
|
||||||
|
filter={(record) => {
|
||||||
|
const provider = accessProvidersMap.get(record.provider);
|
||||||
|
return !!provider?.usages?.includes(ACCESS_USAGES.NOTIFICATION);
|
||||||
|
}}
|
||||||
|
placeholder={t("workflow_node.notify.form.provider_access.placeholder")}
|
||||||
|
onChange={handleProviderAccessSelect}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -500,3 +500,38 @@ export const deployProvidersMap: Map<DeployProvider["type"] | string, DeployProv
|
|||||||
])
|
])
|
||||||
);
|
);
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
|
// #region NotifyProvider
|
||||||
|
/*
|
||||||
|
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
||||||
|
NOTICE: If you add new constant, please keep ASCII order.
|
||||||
|
*/
|
||||||
|
export const NOTIFY_PROVIDERS = Object.freeze({
|
||||||
|
WEBHOOK: `${ACCESS_PROVIDERS.WEBHOOK}`,
|
||||||
|
} as const);
|
||||||
|
|
||||||
|
export type NotifyProviderType = (typeof APPLY_CA_PROVIDERS)[keyof typeof APPLY_CA_PROVIDERS];
|
||||||
|
|
||||||
|
export type NotifyProvider = {
|
||||||
|
type: NotifyProviderType;
|
||||||
|
name: string;
|
||||||
|
icon: string;
|
||||||
|
provider: AccessProviderType;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const notifyProvidersMap: Map<NotifyProvider["type"] | string, NotifyProvider> = new Map(
|
||||||
|
/*
|
||||||
|
注意:此处的顺序决定显示在前端的顺序。
|
||||||
|
NOTICE: The following order determines the order displayed at the frontend.
|
||||||
|
*/
|
||||||
|
[[NOTIFY_PROVIDERS.WEBHOOK]].map(([type]) => [
|
||||||
|
type,
|
||||||
|
{
|
||||||
|
type: type as ApplyCAProviderType,
|
||||||
|
name: accessProvidersMap.get(type.split("-")[0])!.name,
|
||||||
|
icon: accessProvidersMap.get(type.split("-")[0])!.icon,
|
||||||
|
provider: type.split("-")[0] as AccessProviderType,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
);
|
||||||
|
// #endregion
|
||||||
|
@ -3,6 +3,9 @@ import { type ApplyCAProviderType } from "./provider";
|
|||||||
export const SETTINGS_NAMES = Object.freeze({
|
export const SETTINGS_NAMES = Object.freeze({
|
||||||
EMAILS: "emails",
|
EMAILS: "emails",
|
||||||
NOTIFY_TEMPLATES: "notifyTemplates",
|
NOTIFY_TEMPLATES: "notifyTemplates",
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
NOTIFY_CHANNELS: "notifyChannels",
|
NOTIFY_CHANNELS: "notifyChannels",
|
||||||
SSL_PROVIDER: "sslProvider",
|
SSL_PROVIDER: "sslProvider",
|
||||||
PERSISTENCE: "persistence",
|
PERSISTENCE: "persistence",
|
||||||
@ -38,6 +41,9 @@ export const defaultNotifyTemplate: NotifyTemplate = {
|
|||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
// #region Settings: NotifyChannels
|
// #region Settings: NotifyChannels
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
export const NOTIFY_CHANNELS = Object.freeze({
|
export const NOTIFY_CHANNELS = Object.freeze({
|
||||||
BARK: "bark",
|
BARK: "bark",
|
||||||
DINGTALK: "dingtalk",
|
DINGTALK: "dingtalk",
|
||||||
@ -53,8 +59,14 @@ export const NOTIFY_CHANNELS = Object.freeze({
|
|||||||
WECOM: "wecom",
|
WECOM: "wecom",
|
||||||
} as const);
|
} as const);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
export type NotifyChannels = (typeof NOTIFY_CHANNELS)[keyof typeof NOTIFY_CHANNELS];
|
export type NotifyChannels = (typeof NOTIFY_CHANNELS)[keyof typeof NOTIFY_CHANNELS];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
export type NotifyChannelsSettingsContent = {
|
export type NotifyChannelsSettingsContent = {
|
||||||
/*
|
/*
|
||||||
注意:如果追加新的类型,请保持以 ASCII 排序。
|
注意:如果追加新的类型,请保持以 ASCII 排序。
|
||||||
@ -116,7 +128,7 @@ export type MattermostNotifyChannelConfig = {
|
|||||||
username: string;
|
username: string;
|
||||||
password: string;
|
password: string;
|
||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type PushoverNotifyChannelConfig = {
|
export type PushoverNotifyChannelConfig = {
|
||||||
token: string;
|
token: string;
|
||||||
@ -155,6 +167,9 @@ export type NotifyChannel = {
|
|||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
export const notifyChannelsMap: Map<NotifyChannel["type"], NotifyChannel> = new Map(
|
export const notifyChannelsMap: Map<NotifyChannel["type"], NotifyChannel> = new Map(
|
||||||
[
|
[
|
||||||
[NOTIFY_CHANNELS.EMAIL, "common.notifier.email"],
|
[NOTIFY_CHANNELS.EMAIL, "common.notifier.email"],
|
||||||
|
@ -154,9 +154,15 @@ export type WorkflowNodeConfigForDeploy = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type WorkflowNodeConfigForNotify = {
|
export type WorkflowNodeConfigForNotify = {
|
||||||
channel: string;
|
|
||||||
subject: string;
|
subject: string;
|
||||||
message: string;
|
message: string;
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
channel?: string;
|
||||||
|
provider: string;
|
||||||
|
providerAccessId: string;
|
||||||
|
providerConfig?: Record<string, unknown>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type WorkflowNodeConfigForBranch = never;
|
export type WorkflowNodeConfigForBranch = never;
|
||||||
|
@ -712,9 +712,14 @@
|
|||||||
"workflow_node.notify.form.subject.placeholder": "Please enter subject",
|
"workflow_node.notify.form.subject.placeholder": "Please enter subject",
|
||||||
"workflow_node.notify.form.message.label": "Message",
|
"workflow_node.notify.form.message.label": "Message",
|
||||||
"workflow_node.notify.form.message.placeholder": "Please enter message",
|
"workflow_node.notify.form.message.placeholder": "Please enter message",
|
||||||
"workflow_node.notify.form.channel.label": "Channel",
|
"workflow_node.notify.form.channel.label": "Channel (Deprecated)",
|
||||||
"workflow_node.notify.form.channel.placeholder": "Please select channel",
|
"workflow_node.notify.form.channel.placeholder": "Please select channel",
|
||||||
"workflow_node.notify.form.channel.button": "Configure",
|
"workflow_node.notify.form.channel.button": "Configure",
|
||||||
|
"workflow_node.notify.form.provider.label": "Notification channel",
|
||||||
|
"workflow_node.notify.form.provider.placeholder": "Please select notification channel",
|
||||||
|
"workflow_node.notify.form.provider_access.label": "Notification provider authorization",
|
||||||
|
"workflow_node.notify.form.provider_access.placeholder": "Please select an authorization of notification provider",
|
||||||
|
"workflow_node.notify.form.provider_access.button": "Create",
|
||||||
|
|
||||||
"workflow_node.end.label": "End",
|
"workflow_node.end.label": "End",
|
||||||
|
|
||||||
|
@ -711,9 +711,14 @@
|
|||||||
"workflow_node.notify.form.subject.placeholder": "请输入通知主题",
|
"workflow_node.notify.form.subject.placeholder": "请输入通知主题",
|
||||||
"workflow_node.notify.form.message.label": "通知内容",
|
"workflow_node.notify.form.message.label": "通知内容",
|
||||||
"workflow_node.notify.form.message.placeholder": "请输入通知内容",
|
"workflow_node.notify.form.message.placeholder": "请输入通知内容",
|
||||||
"workflow_node.notify.form.channel.label": "通知渠道",
|
"workflow_node.notify.form.channel.label": "通知渠道(已废弃,请使用「通知渠道授权」字段)",
|
||||||
"workflow_node.notify.form.channel.placeholder": "请选择通知渠道",
|
"workflow_node.notify.form.channel.placeholder": "请选择通知渠道",
|
||||||
"workflow_node.notify.form.channel.button": "去配置",
|
"workflow_node.notify.form.channel.button": "设置",
|
||||||
|
"workflow_node.notify.form.provider.label": "通知渠道",
|
||||||
|
"workflow_node.notify.form.provider.placeholder": "请选择通知渠道",
|
||||||
|
"workflow_node.notify.form.provider_access.label": "通知渠道授权",
|
||||||
|
"workflow_node.notify.form.provider_access.placeholder": "请选择通知渠道授权",
|
||||||
|
"workflow_node.notify.form.provider_access.button": "新建",
|
||||||
|
|
||||||
"workflow_node.end.label": "结束",
|
"workflow_node.end.label": "结束",
|
||||||
|
|
||||||
|
@ -185,10 +185,12 @@ const AccessList = () => {
|
|||||||
|
|
||||||
const handleTabChange = (key: string) => {
|
const handleTabChange = (key: string) => {
|
||||||
setFilters((prev) => ({ ...prev, range: key }));
|
setFilters((prev) => ({ ...prev, range: key }));
|
||||||
|
setPage(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSearch = (value: string) => {
|
const handleSearch = (value: string) => {
|
||||||
setFilters((prev) => ({ ...prev, keyword: value }));
|
setFilters((prev) => ({ ...prev, keyword: value }));
|
||||||
|
setPage(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleReloadClick = () => {
|
const handleReloadClick = () => {
|
||||||
@ -251,10 +253,10 @@ const AccessList = () => {
|
|||||||
key: "ca-only",
|
key: "ca-only",
|
||||||
label: t("access.props.range.ca_only"),
|
label: t("access.props.range.ca_only"),
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// key: "notify-only",
|
key: "notify-only",
|
||||||
// label: t("access.props.range.notify_only"),
|
label: t("access.props.range.notify_only"),
|
||||||
// },
|
},
|
||||||
]}
|
]}
|
||||||
activeTabKey={filters["range"] as string}
|
activeTabKey={filters["range"] as string}
|
||||||
onTabChange={(key) => handleTabChange(key)}
|
onTabChange={(key) => handleTabChange(key)}
|
||||||
|
@ -251,6 +251,7 @@ const CertificateList = () => {
|
|||||||
|
|
||||||
const handleSearch = (value: string) => {
|
const handleSearch = (value: string) => {
|
||||||
setFilters((prev) => ({ ...prev, keyword: value.trim() }));
|
setFilters((prev) => ({ ...prev, keyword: value.trim() }));
|
||||||
|
setPage(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleReloadClick = () => {
|
const handleReloadClick = () => {
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Card, Divider } from "antd";
|
import { Alert, Card, Divider } from "antd";
|
||||||
|
|
||||||
import NotifyChannels from "@/components/notification/NotifyChannels";
|
import NotifyChannels from "@/components/notification/NotifyChannels";
|
||||||
import NotifyTemplate from "@/components/notification/NotifyTemplate";
|
import NotifyTemplate from "@/components/notification/NotifyTemplate";
|
||||||
import { useZustandShallowSelector } from "@/hooks";
|
import { useZustandShallowSelector } from "@/hooks";
|
||||||
import { useNotifyChannelsStore } from "@/stores/notify";
|
import { useNotifyChannelsStore } from "@/stores/notify";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
const SettingsNotification = () => {
|
const SettingsNotification = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@ -22,6 +25,7 @@ const SettingsNotification = () => {
|
|||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
<Card className="shadow" styles={{ body: loadedAtOnce ? { padding: 0 } : {} }} title={t("settings.notification.channels.card.title")}>
|
<Card className="shadow" styles={{ body: loadedAtOnce ? { padding: 0 } : {} }} title={t("settings.notification.channels.card.title")}>
|
||||||
|
<Alert type="warning" banner message="本页面相关功能即将在后续版本中废弃,请使用「授权管理」页面来管理通知渠道。" />
|
||||||
<NotifyChannels classNames={{ form: "md:max-w-[40rem]" }} />
|
<NotifyChannels classNames={{ form: "md:max-w-[40rem]" }} />
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
@ -281,6 +281,7 @@ const WorkflowList = () => {
|
|||||||
|
|
||||||
const handleSearch = (value: string) => {
|
const handleSearch = (value: string) => {
|
||||||
setFilters((prev) => ({ ...prev, keyword: value.trim() }));
|
setFilters((prev) => ({ ...prev, keyword: value.trim() }));
|
||||||
|
setPage(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCreateClick = () => {
|
const handleCreateClick = () => {
|
||||||
|
@ -4,6 +4,9 @@ import { create } from "zustand";
|
|||||||
import { type NotifyChannelsSettingsContent, SETTINGS_NAMES, type SettingsModel } from "@/domain/settings";
|
import { type NotifyChannelsSettingsContent, SETTINGS_NAMES, type SettingsModel } from "@/domain/settings";
|
||||||
import { get as getSettings, save as saveSettings } from "@/repository/settings";
|
import { get as getSettings, save as saveSettings } from "@/repository/settings";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
export interface NotifyChannelsState {
|
export interface NotifyChannelsState {
|
||||||
channels: NotifyChannelsSettingsContent;
|
channels: NotifyChannelsSettingsContent;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
@ -14,6 +17,9 @@ export interface NotifyChannelsState {
|
|||||||
setChannels: (channels: NotifyChannelsSettingsContent) => Promise<void>;
|
setChannels: (channels: NotifyChannelsSettingsContent) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
export const useNotifyChannelsStore = create<NotifyChannelsState>((set, get) => {
|
export const useNotifyChannelsStore = create<NotifyChannelsState>((set, get) => {
|
||||||
let fetcher: Promise<SettingsModel<NotifyChannelsSettingsContent>> | null = null; // 防止多次重复请求
|
let fetcher: Promise<SettingsModel<NotifyChannelsSettingsContent>> | null = null; // 防止多次重复请求
|
||||||
let settings: SettingsModel<NotifyChannelsSettingsContent>; // 记录当前设置的其他字段,保存回数据库时用
|
let settings: SettingsModel<NotifyChannelsSettingsContent>; // 记录当前设置的其他字段,保存回数据库时用
|
||||||
|
Loading…
x
Reference in New Issue
Block a user