refactor: clean code

This commit is contained in:
Fu Diwei 2025-01-05 00:08:12 +08:00
parent 3b9a7fe805
commit 61843a4997
69 changed files with 972 additions and 839 deletions

View File

@ -1,43 +0,0 @@
package applicant
import (
"encoding/json"
"net/url"
"time"
"github.com/go-acme/lego/v4/providers/dns/httpreq"
"github.com/usual2970/certimate/internal/domain"
)
type acmeHttpReqApplicant struct {
option *ApplyOption
}
func NewACMEHttpReqApplicant(option *ApplyOption) Applicant {
return &acmeHttpReqApplicant{
option: option,
}
}
func (a *acmeHttpReqApplicant) Apply() (*Certificate, error) {
access := &domain.ACMEHttpReqAccessConfig{}
json.Unmarshal([]byte(a.option.AccessConfig), access)
config := httpreq.NewDefaultConfig()
endpoint, _ := url.Parse(access.Endpoint)
config.Endpoint = endpoint
config.Mode = access.Mode
config.Username = access.Username
config.Password = access.Password
if a.option.PropagationTimeout != 0 {
config.PropagationTimeout = time.Duration(a.option.PropagationTimeout) * time.Second
}
provider, err := httpreq.NewDNSProviderConfig(config)
if err != nil {
return nil, err
}
return apply(a.option, provider)
}

View File

@ -1,39 +0,0 @@
package applicant
import (
"encoding/json"
"time"
"github.com/go-acme/lego/v4/providers/dns/alidns"
"github.com/usual2970/certimate/internal/domain"
)
type aliyunApplicant struct {
option *ApplyOption
}
func NewAliyunApplicant(option *ApplyOption) Applicant {
return &aliyunApplicant{
option: option,
}
}
func (a *aliyunApplicant) Apply() (*Certificate, error) {
access := &domain.AliyunAccessConfig{}
json.Unmarshal([]byte(a.option.AccessConfig), access)
config := alidns.NewDefaultConfig()
config.APIKey = access.AccessKeyId
config.SecretKey = access.AccessKeySecret
if a.option.PropagationTimeout != 0 {
config.PropagationTimeout = time.Duration(a.option.PropagationTimeout) * time.Second
}
provider, err := alidns.NewDNSProviderConfig(config)
if err != nil {
return nil, err
}
return apply(a.option, provider)
}

View File

@ -50,10 +50,10 @@ type Certificate struct {
PrivateKey string `json:"privateKey"`
Certificate string `json:"certificate"`
IssuerCertificate string `json:"issuerCertificate"`
Csr string `json:"csr"`
CSR string `json:"csr"`
}
type ApplyOption struct {
type applyConfig struct {
Domains string `json:"domains"`
ContactEmail string `json:"contactEmail"`
AccessConfig string `json:"accessConfig"`
@ -63,65 +63,79 @@ type ApplyOption struct {
DisableFollowCNAME bool `json:"disableFollowCNAME"`
}
type ApplyUser struct {
Ca string
type applyUser struct {
CA string
Email string
Registration *registration.Resource
key string
privkey string
}
func newApplyUser(ca, email string) (*ApplyUser, error) {
func newApplyUser(ca, email string) (*applyUser, error) {
repo := getAcmeAccountRepository()
rs := &ApplyUser{
Ca: ca,
applyUser := &applyUser{
CA: ca,
Email: email,
}
resp, err := repo.GetByCAAndEmail(ca, email)
if err != nil {
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, err
}
keyStr, err := x509.ConvertECPrivateKeyToPEM(privateKey)
if err != nil {
return nil, err
}
rs.key = keyStr
return rs, nil
acmeAccount, err := repo.GetByCAAndEmail(ca, email)
if err != nil {
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, err
}
keyStr, err := x509.ConvertECPrivateKeyToPEM(key)
if err != nil {
return nil, err
}
applyUser.privkey = keyStr
return applyUser, nil
}
rs.Registration = resp.Resource
rs.key = resp.Key
applyUser.Registration = acmeAccount.Resource
applyUser.privkey = acmeAccount.Key
return rs, nil
return applyUser, nil
}
func (u *ApplyUser) GetEmail() string {
func (u *applyUser) GetEmail() string {
return u.Email
}
func (u ApplyUser) GetRegistration() *registration.Resource {
func (u applyUser) GetRegistration() *registration.Resource {
return u.Registration
}
func (u *ApplyUser) GetPrivateKey() crypto.PrivateKey {
rs, _ := x509.ParseECPrivateKeyFromPEM(u.key)
func (u *applyUser) GetPrivateKey() crypto.PrivateKey {
rs, _ := x509.ParseECPrivateKeyFromPEM(u.privkey)
return rs
}
func (u *ApplyUser) hasRegistration() bool {
func (u *applyUser) hasRegistration() bool {
return u.Registration != nil
}
func (u *ApplyUser) getPrivateKeyString() string {
return u.key
func (u *applyUser) getPrivateKeyString() string {
return u.privkey
}
type Applicant interface {
Apply() (*Certificate, error)
}
// TODO: 暂时使用代理模式以兼容之前版本代码,后续重新实现此处逻辑
type proxyApplicant struct {
applyConfig *applyConfig
applicant challenge.Provider
}
func (d *proxyApplicant) Apply() (*Certificate, error) {
return apply(d.applyConfig, d.applicant)
}
func GetWithApplyNode(node *domain.WorkflowNode) (Applicant, error) {
// 获取授权配置
accessRepo := repository.NewAccessRepository()
@ -131,7 +145,7 @@ func GetWithApplyNode(node *domain.WorkflowNode) (Applicant, error) {
return nil, fmt.Errorf("access record not found: %w", err)
}
applyConfig := &ApplyOption{
applyConfig := &applyConfig{
Domains: node.GetConfigString("domains"),
ContactEmail: node.GetConfigString("contactEmail"),
AccessConfig: access.Config,
@ -141,40 +155,15 @@ func GetWithApplyNode(node *domain.WorkflowNode) (Applicant, error) {
DisableFollowCNAME: node.GetConfigBool("disableFollowCNAME"),
}
return GetWithTypeOption(domain.AccessProviderType(access.Provider), applyConfig)
}
func GetWithTypeOption(provider domain.AccessProviderType, option *ApplyOption) (Applicant, error) {
/*
注意如果追加新的常量值请保持以 ASCII 排序
NOTICE: If you add new constant, please keep ASCII order.
*/
switch provider {
case domain.ACCESS_PROVIDER_ACMEHTTPREQ:
return NewACMEHttpReqApplicant(option), nil
case domain.ACCESS_PROVIDER_ALIYUN:
return NewAliyunApplicant(option), nil
case domain.ACCESS_PROVIDER_AWS:
return NewAWSApplicant(option), nil
case domain.ACCESS_PROVIDER_CLOUDFLARE:
return NewCloudflareApplicant(option), nil
case domain.ACCESS_PROVIDER_GODADDY:
return NewGoDaddyApplicant(option), nil
case domain.ACCESS_PROVIDER_HUAWEICLOUD:
return NewHuaweiCloudApplicant(option), nil
case domain.ACCESS_PROVIDER_NAMEDOTCOM:
return NewNameDotComApplicant(option), nil
case domain.ACCESS_PROVIDER_NAMESILO:
return NewNamesiloApplicant(option), nil
case domain.ACCESS_PROVIDER_POWERDNS:
return NewPowerDNSApplicant(option), nil
case domain.ACCESS_PROVIDER_TENCENTCLOUD:
return NewTencentCloudApplicant(option), nil
case domain.ACCESS_PROVIDER_VOLCENGINE:
return NewVolcEngineApplicant(option), nil
default:
return nil, fmt.Errorf("unsupported applicant provider type: %s", provider)
challengeProvider, err := createChallengeProvider(domain.AccessProviderType(access.Provider), access.Config, applyConfig)
if err != nil {
return nil, err
}
return &proxyApplicant{
applyConfig: applyConfig,
applicant: challengeProvider,
}, nil
}
type SSLProviderConfig struct {
@ -192,7 +181,7 @@ type SSLProviderEab struct {
EabKid string `json:"eabKid"`
}
func apply(option *ApplyOption, provider challenge.Provider) (*Certificate, error) {
func apply(option *applyConfig, provider challenge.Provider) (*Certificate, error) {
record, _ := app.GetApp().Dao().FindFirstRecordByFilter("settings", "name='sslProvider'")
sslProvider := &SSLProviderConfig{
@ -259,7 +248,7 @@ func apply(option *ApplyOption, provider challenge.Provider) (*Certificate, erro
PrivateKey: string(certificates.PrivateKey),
Certificate: string(certificates.Certificate),
IssuerCertificate: string(certificates.IssuerCertificate),
Csr: string(certificates.CSR),
CSR: string(certificates.CSR),
}, nil
}
@ -272,7 +261,9 @@ func getAcmeAccountRepository() AcmeAccountRepository {
return repository.NewAcmeAccountRepository()
}
func getReg(client *lego.Client, sslProvider *SSLProviderConfig, user *ApplyUser) (*registration.Resource, error) {
func getReg(client *lego.Client, sslProvider *SSLProviderConfig, user *applyUser) (*registration.Resource, error) {
// TODO: fix 潜在的并发问题
var reg *registration.Resource
var err error
switch sslProvider.Provider {
@ -304,7 +295,7 @@ func getReg(client *lego.Client, sslProvider *SSLProviderConfig, user *ApplyUser
resp, err := repo.GetByCAAndEmail(sslProvider.Provider, user.GetEmail())
if err == nil {
user.key = resp.Key
user.privkey = resp.Key
return resp.Resource, nil
}

View File

@ -1,41 +0,0 @@
package applicant
import (
"encoding/json"
"time"
"github.com/go-acme/lego/v4/providers/dns/route53"
"github.com/usual2970/certimate/internal/domain"
)
type awsApplicant struct {
option *ApplyOption
}
func NewAWSApplicant(option *ApplyOption) Applicant {
return &awsApplicant{
option: option,
}
}
func (a *awsApplicant) Apply() (*Certificate, error) {
access := &domain.AWSAccessConfig{}
json.Unmarshal([]byte(a.option.AccessConfig), access)
config := route53.NewDefaultConfig()
config.AccessKeyID = access.AccessKeyId
config.SecretAccessKey = access.SecretAccessKey
config.Region = access.Region
config.HostedZoneID = access.HostedZoneId
if a.option.PropagationTimeout != 0 {
config.PropagationTimeout = time.Duration(a.option.PropagationTimeout) * time.Second
}
provider, err := route53.NewDNSProviderConfig(config)
if err != nil {
return nil, err
}
return apply(a.option, provider)
}

View File

@ -1,38 +0,0 @@
package applicant
import (
"encoding/json"
"time"
"github.com/go-acme/lego/v4/providers/dns/cloudflare"
"github.com/usual2970/certimate/internal/domain"
)
type cloudflareApplicant struct {
option *ApplyOption
}
func NewCloudflareApplicant(option *ApplyOption) Applicant {
return &cloudflareApplicant{
option: option,
}
}
func (a *cloudflareApplicant) Apply() (*Certificate, error) {
access := &domain.CloudflareAccessConfig{}
json.Unmarshal([]byte(a.option.AccessConfig), access)
config := cloudflare.NewDefaultConfig()
config.AuthToken = access.DnsApiToken
if a.option.PropagationTimeout != 0 {
config.PropagationTimeout = time.Duration(a.option.PropagationTimeout) * time.Second
}
provider, err := cloudflare.NewDNSProviderConfig(config)
if err != nil {
return nil, err
}
return apply(a.option, provider)
}

View File

@ -1,39 +0,0 @@
package applicant
import (
"encoding/json"
"time"
"github.com/go-acme/lego/v4/providers/dns/godaddy"
"github.com/usual2970/certimate/internal/domain"
)
type godaddyApplicant struct {
option *ApplyOption
}
func NewGoDaddyApplicant(option *ApplyOption) Applicant {
return &godaddyApplicant{
option: option,
}
}
func (a *godaddyApplicant) Apply() (*Certificate, error) {
access := &domain.GoDaddyAccessConfig{}
json.Unmarshal([]byte(a.option.AccessConfig), access)
config := godaddy.NewDefaultConfig()
config.APIKey = access.ApiKey
config.APISecret = access.ApiSecret
if a.option.PropagationTimeout != 0 {
config.PropagationTimeout = time.Duration(a.option.PropagationTimeout) * time.Second
}
provider, err := godaddy.NewDNSProviderConfig(config)
if err != nil {
return nil, err
}
return apply(a.option, provider)
}

View File

@ -1,46 +0,0 @@
package applicant
import (
"encoding/json"
"time"
huaweicloud "github.com/go-acme/lego/v4/providers/dns/huaweicloud"
"github.com/usual2970/certimate/internal/domain"
)
type huaweicloudApplicant struct {
option *ApplyOption
}
func NewHuaweiCloudApplicant(option *ApplyOption) Applicant {
return &huaweicloudApplicant{
option: option,
}
}
func (a *huaweicloudApplicant) Apply() (*Certificate, error) {
access := &domain.HuaweiCloudAccessConfig{}
json.Unmarshal([]byte(a.option.AccessConfig), access)
region := access.Region
if region == "" {
// 华为云的 SDK 要求必须传一个区域,实际上 DNS-01 流程里用不到,但不传会报错
region = "cn-north-1"
}
config := huaweicloud.NewDefaultConfig()
config.AccessKeyID = access.AccessKeyId
config.SecretAccessKey = access.SecretAccessKey
config.Region = region
if a.option.PropagationTimeout != 0 {
config.PropagationTimeout = time.Duration(a.option.PropagationTimeout) * time.Second
}
provider, err := huaweicloud.NewDNSProviderConfig(config)
if err != nil {
return nil, err
}
return apply(a.option, provider)
}

View File

@ -1,38 +0,0 @@
package applicant
import (
"encoding/json"
"time"
"github.com/go-acme/lego/v4/providers/dns/namedotcom"
"github.com/usual2970/certimate/internal/domain"
)
type nameDotComApplicant struct {
option *ApplyOption
}
func NewNameDotComApplicant(option *ApplyOption) Applicant {
return &nameDotComApplicant{
option: option,
}
}
func (a *nameDotComApplicant) Apply() (*Certificate, error) {
access := &domain.NameDotComAccessConfig{}
json.Unmarshal([]byte(a.option.AccessConfig), access)
config := namedotcom.NewDefaultConfig()
config.Username = access.Username
config.APIToken = access.ApiToken
if a.option.PropagationTimeout != 0 {
config.PropagationTimeout = time.Duration(a.option.PropagationTimeout) * time.Second
}
provider, err := namedotcom.NewDNSProviderConfig(config)
if err != nil {
return nil, err
}
return apply(a.option, provider)
}

View File

@ -1,38 +0,0 @@
package applicant
import (
"encoding/json"
"time"
namesilo "github.com/go-acme/lego/v4/providers/dns/namesilo"
"github.com/usual2970/certimate/internal/domain"
)
type namesiloApplicant struct {
option *ApplyOption
}
func NewNamesiloApplicant(option *ApplyOption) Applicant {
return &namesiloApplicant{
option: option,
}
}
func (a *namesiloApplicant) Apply() (*Certificate, error) {
access := &domain.NameSiloAccessConfig{}
json.Unmarshal([]byte(a.option.AccessConfig), access)
config := namesilo.NewDefaultConfig()
config.APIKey = access.ApiKey
if a.option.PropagationTimeout != 0 {
config.PropagationTimeout = time.Duration(a.option.PropagationTimeout) * time.Second
}
provider, err := namesilo.NewDNSProviderConfig(config)
if err != nil {
return nil, err
}
return apply(a.option, provider)
}

View File

@ -1,41 +0,0 @@
package applicant
import (
"encoding/json"
"net/url"
"time"
"github.com/go-acme/lego/v4/providers/dns/pdns"
"github.com/usual2970/certimate/internal/domain"
)
type powerdnsApplicant struct {
option *ApplyOption
}
func NewPowerDNSApplicant(option *ApplyOption) Applicant {
return &powerdnsApplicant{
option: option,
}
}
func (a *powerdnsApplicant) Apply() (*Certificate, error) {
access := &domain.PowerDNSAccessConfig{}
json.Unmarshal([]byte(a.option.AccessConfig), access)
config := pdns.NewDefaultConfig()
host, _ := url.Parse(access.ApiUrl)
config.Host = host
config.APIKey = access.ApiKey
if a.option.PropagationTimeout != 0 {
config.PropagationTimeout = time.Duration(a.option.PropagationTimeout) * time.Second
}
provider, err := pdns.NewDNSProviderConfig(config)
if err != nil {
return nil, err
}
return apply(a.option, provider)
}

View File

@ -0,0 +1,199 @@
package applicant
import (
"encoding/json"
"fmt"
"github.com/go-acme/lego/v4/challenge"
"github.com/usual2970/certimate/internal/domain"
providerACMEHttpReq "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/acmehttpreq"
providerAliyun "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun"
providerAWS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aws"
providerCloudflare "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare"
providerGoDaddy "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy"
providerHuaweiCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud"
providerNameDotCom "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namedotcom"
providerNameSilo "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namesilo"
providerPowerDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns"
providerTencentCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud"
providerVolcEngine "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/volcengine"
)
func createChallengeProvider(provider domain.AccessProviderType, accessConfig string, applyConfig *applyConfig) (challenge.Provider, error) {
/*
注意如果追加新的常量值请保持以 ASCII 排序
NOTICE: If you add new constant, please keep ASCII order.
*/
switch provider {
case domain.AccessProviderTypeACMEHttpReq:
{
access := &domain.AccessConfigForACMEHttpReq{}
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
return nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
applicant, err := providerACMEHttpReq.NewChallengeProvider(&providerACMEHttpReq.ACMEHttpReqApplicantConfig{
Endpoint: access.Endpoint,
Mode: access.Mode,
Username: access.Username,
Password: access.Password,
PropagationTimeout: applyConfig.PropagationTimeout,
})
return applicant, err
}
case domain.AccessProviderTypeAliyun:
{
access := &domain.AccessConfigForAliyun{}
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
return nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
applicant, err := providerAliyun.NewChallengeProvider(&providerAliyun.AliyunApplicantConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.AccessKeySecret,
PropagationTimeout: applyConfig.PropagationTimeout,
})
return applicant, err
}
case domain.AccessProviderTypeAWS:
{
access := &domain.AccessConfigForAWS{}
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
return nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
applicant, err := providerAWS.NewChallengeProvider(&providerAWS.AWSApplicantConfig{
AccessKeyId: access.AccessKeyId,
SecretAccessKey: access.SecretAccessKey,
Region: access.Region,
HostedZoneId: access.HostedZoneId,
PropagationTimeout: applyConfig.PropagationTimeout,
})
return applicant, err
}
case domain.AccessProviderTypeCloudflare:
{
access := &domain.AccessConfigForCloudflare{}
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
return nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
applicant, err := providerCloudflare.NewChallengeProvider(&providerCloudflare.CloudflareApplicantConfig{
DnsApiToken: access.DnsApiToken,
PropagationTimeout: applyConfig.PropagationTimeout,
})
return applicant, err
}
case domain.AccessProviderTypeGoDaddy:
{
access := &domain.AccessConfigForGoDaddy{}
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
return nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
applicant, err := providerGoDaddy.NewChallengeProvider(&providerGoDaddy.GoDaddyApplicantConfig{
ApiKey: access.ApiKey,
ApiSecret: access.ApiSecret,
PropagationTimeout: applyConfig.PropagationTimeout,
})
return applicant, err
}
case domain.AccessProviderTypeHuaweiCloud:
{
access := &domain.AccessConfigForHuaweiCloud{}
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
return nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
applicant, err := providerHuaweiCloud.NewChallengeProvider(&providerHuaweiCloud.HuaweiCloudApplicantConfig{
AccessKeyId: access.AccessKeyId,
SecretAccessKey: access.SecretAccessKey,
Region: access.Region,
PropagationTimeout: applyConfig.PropagationTimeout,
})
return applicant, err
}
case domain.AccessProviderTypeNameDotCom:
{
access := &domain.AccessConfigForNameDotCom{}
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
return nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
applicant, err := providerNameDotCom.NewChallengeProvider(&providerNameDotCom.NameDotComApplicantConfig{
Username: access.Username,
ApiToken: access.ApiToken,
PropagationTimeout: applyConfig.PropagationTimeout,
})
return applicant, err
}
case domain.AccessProviderTypeNameSilo:
{
access := &domain.AccessConfigForNameSilo{}
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
return nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
applicant, err := providerNameSilo.NewChallengeProvider(&providerNameSilo.NameSiloApplicantConfig{
ApiKey: access.ApiKey,
PropagationTimeout: applyConfig.PropagationTimeout,
})
return applicant, err
}
case domain.AccessProviderTypePowerDNS:
{
access := &domain.AccessConfigForPowerDNS{}
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
return nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
applicant, err := providerPowerDNS.NewChallengeProvider(&providerPowerDNS.PowerDNSApplicantConfig{
ApiUrl: access.ApiUrl,
ApiKey: access.ApiKey,
PropagationTimeout: applyConfig.PropagationTimeout,
})
return applicant, err
}
case domain.AccessProviderTypeTencentCloud:
{
access := &domain.AccessConfigForTencentCloud{}
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
return nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
applicant, err := providerTencentCloud.NewChallengeProvider(&providerTencentCloud.TencentCloudApplicantConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
PropagationTimeout: applyConfig.PropagationTimeout,
})
return applicant, err
}
case domain.AccessProviderTypeVolcEngine:
{
access := &domain.AccessConfigForVolcEngine{}
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
return nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
applicant, err := providerVolcEngine.NewChallengeProvider(&providerVolcEngine.VolcEngineApplicantConfig{
AccessKeyId: access.AccessKeyId,
SecretAccessKey: access.SecretAccessKey,
PropagationTimeout: applyConfig.PropagationTimeout,
})
return applicant, err
}
}
return nil, fmt.Errorf("unsupported applicant provider: %s", provider)
}

View File

@ -1,39 +0,0 @@
package applicant
import (
"encoding/json"
"time"
"github.com/go-acme/lego/v4/providers/dns/tencentcloud"
"github.com/usual2970/certimate/internal/domain"
)
type tencentcloudApplicant struct {
option *ApplyOption
}
func NewTencentCloudApplicant(option *ApplyOption) Applicant {
return &tencentcloudApplicant{
option: option,
}
}
func (a *tencentcloudApplicant) Apply() (*Certificate, error) {
access := &domain.TencentCloudAccessConfig{}
json.Unmarshal([]byte(a.option.AccessConfig), access)
config := tencentcloud.NewDefaultConfig()
config.SecretID = access.SecretId
config.SecretKey = access.SecretKey
if a.option.PropagationTimeout != 0 {
config.PropagationTimeout = time.Duration(a.option.PropagationTimeout) * time.Second
}
provider, err := tencentcloud.NewDNSProviderConfig(config)
if err != nil {
return nil, err
}
return apply(a.option, provider)
}

View File

@ -1,38 +0,0 @@
package applicant
import (
"encoding/json"
"time"
"github.com/go-acme/lego/v4/providers/dns/volcengine"
"github.com/usual2970/certimate/internal/domain"
)
type volcengineApplicant struct {
option *ApplyOption
}
func NewVolcEngineApplicant(option *ApplyOption) Applicant {
return &volcengineApplicant{
option: option,
}
}
func (a *volcengineApplicant) Apply() (*Certificate, error) {
access := &domain.VolcEngineAccessConfig{}
json.Unmarshal([]byte(a.option.AccessConfig), access)
config := volcengine.NewDefaultConfig()
config.AccessKey = access.AccessKeyId
config.SecretKey = access.SecretAccessKey
if a.option.PropagationTimeout != 0 {
config.PropagationTimeout = time.Duration(a.option.PropagationTimeout) * time.Second
}
provider, err := volcengine.NewDNSProviderConfig(config)
if err != nil {
return nil, err
}
return apply(a.option, provider)
}

View File

@ -2,7 +2,6 @@ package deployer
import (
"context"
"fmt"
"github.com/usual2970/certimate/internal/applicant"
"github.com/usual2970/certimate/internal/domain"
@ -10,39 +9,6 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/logger"
)
/*
提供商部署目标常量值
短横线前的部分始终等于提供商类型
注意如果追加新的常量值请保持以 ASCII 排序
NOTICE: If you add new constant, please keep ASCII order.
*/
const (
targetAliyunALB = "aliyun-alb"
targetAliyunCDN = "aliyun-cdn"
targetAliyunCLB = "aliyun-clb"
targetAliyunDCDN = "aliyun-dcdn"
targetAliyunNLB = "aliyun-nlb"
targetAliyunOSS = "aliyun-oss"
targetBaiduCloudCDN = "baiducloud-cdn"
targetBytePlusCDN = "byteplus-cdn"
targetDogeCloudCDN = "dogecloud-cdn"
targetHuaweiCloudCDN = "huaweicloud-cdn"
targetHuaweiCloudELB = "huaweicloud-elb"
targetK8sSecret = "k8s-secret"
targetLocal = "local"
targetQiniuCDN = "qiniu-cdn"
targetSSH = "ssh"
targetTencentCloudCDN = "tencentcloud-cdn"
targetTencentCloudCLB = "tencentcloud-clb"
targetTencentCloudCOS = "tencentcloud-cos"
targetTencentCloudECDN = "tencentcloud-ecdn"
targetTencentCloudEO = "tencentcloud-eo"
targetVolcEngineCDN = "volcengine-cdn"
targetVolcEngineLive = "volcengine-live"
targetWebhook = "webhook"
)
type DeployerOption struct {
NodeId string `json:"nodeId"`
Domains string `json:"domains"`
@ -50,17 +16,14 @@ type DeployerOption struct {
AccessRecord *domain.Access `json:"-"`
DeployConfig domain.DeployConfig `json:"deployConfig"`
Certificate applicant.Certificate `json:"certificate"`
Variables map[string]string `json:"variables"`
}
type Deployer interface {
Deploy(ctx context.Context) error
GetInfos() []string
GetID() string
}
func GetWithTypeAndOption(deployType string, option *DeployerOption) (Deployer, error) {
deployer, logger, err := createDeployer(deployType, option.AccessRecord.Config, option.DeployConfig.NodeConfig)
func GetWithProviderAndOption(provider string, option *DeployerOption) (Deployer, error) {
deployer, logger, err := createDeployer(domain.DeployProviderType(provider), option.AccessRecord.Config, option.DeployConfig.NodeConfig)
if err != nil {
return nil, err
}
@ -79,14 +42,6 @@ type proxyDeployer struct {
deployer deployer.Deployer
}
func (d *proxyDeployer) GetID() string {
return fmt.Sprintf("%s-%s", d.option.AccessRecord.Name, d.option.AccessRecord.Id)
}
func (d *proxyDeployer) GetInfos() []string {
return d.logger.GetRecords()
}
func (d *proxyDeployer) Deploy(ctx context.Context) error {
_, err := d.deployer.Deploy(ctx, d.option.Certificate.Certificate, d.option.Certificate.PrivateKey)
return err

View File

@ -34,23 +34,23 @@ import (
"github.com/usual2970/certimate/internal/pkg/utils/maps"
)
func createDeployer(target string, accessConfig string, deployConfig map[string]any) (deployer.Deployer, logger.Logger, error) {
func createDeployer(provider domain.DeployProviderType, accessConfig string, deployConfig map[string]any) (deployer.Deployer, logger.Logger, error) {
logger := logger.NewDefaultLogger()
/*
注意如果追加新的常量值请保持以 ASCII 排序
NOTICE: If you add new constant, please keep ASCII order.
*/
switch target {
case targetAliyunALB, targetAliyunCDN, targetAliyunCLB, targetAliyunDCDN, targetAliyunNLB, targetAliyunOSS:
switch provider {
case domain.DeployProviderTypeAliyunALB, domain.DeployProviderTypeAliyunCDN, domain.DeployProviderTypeAliyunCLB, domain.DeployProviderTypeAliyunDCDN, domain.DeployProviderTypeAliyunNLB, domain.DeployProviderTypeAliyunOSS:
{
access := &domain.AliyunAccessConfig{}
access := &domain.AccessConfigForAliyun{}
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
return nil, nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
switch target {
case targetAliyunALB:
switch provider {
case domain.DeployProviderTypeAliyunALB:
deployer, err := providerAliyunALB.NewWithLogger(&providerAliyunALB.AliyunALBDeployerConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.AccessKeySecret,
@ -61,7 +61,7 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
}, logger)
return deployer, logger, err
case targetAliyunCDN:
case domain.DeployProviderTypeAliyunCDN:
deployer, err := providerAliyunCDN.NewWithLogger(&providerAliyunCDN.AliyunCDNDeployerConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.AccessKeySecret,
@ -69,7 +69,7 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
}, logger)
return deployer, logger, err
case targetAliyunCLB:
case domain.DeployProviderTypeAliyunCLB:
deployer, err := providerAliyunCLB.NewWithLogger(&providerAliyunCLB.AliyunCLBDeployerConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.AccessKeySecret,
@ -80,7 +80,7 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
}, logger)
return deployer, logger, err
case targetAliyunDCDN:
case domain.DeployProviderTypeAliyunDCDN:
deployer, err := providerAliyunDCDN.NewWithLogger(&providerAliyunDCDN.AliyunDCDNDeployerConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.AccessKeySecret,
@ -88,7 +88,7 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
}, logger)
return deployer, logger, err
case targetAliyunNLB:
case domain.DeployProviderTypeAliyunNLB:
deployer, err := providerAliyunNLB.NewWithLogger(&providerAliyunNLB.AliyunNLBDeployerConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.AccessKeySecret,
@ -99,7 +99,7 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
}, logger)
return deployer, logger, err
case targetAliyunOSS:
case domain.DeployProviderTypeAliyunOSS:
deployer, err := providerAliyunOSS.NewWithLogger(&providerAliyunOSS.AliyunOSSDeployerConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.AccessKeySecret,
@ -114,9 +114,9 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
}
}
case targetBaiduCloudCDN:
case domain.DeployProviderTypeBaiduCloudCDN:
{
access := &domain.BaiduCloudAccessConfig{}
access := &domain.AccessConfigForBaiduCloud{}
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
return nil, nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
@ -129,9 +129,9 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
return deployer, logger, err
}
case targetBytePlusCDN:
case domain.DeployProviderTypeBytePlusCDN:
{
access := &domain.BytePlusAccessConfig{}
access := &domain.AccessConfigForBytePlus{}
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
return nil, nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
@ -144,9 +144,9 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
return deployer, logger, err
}
case targetDogeCloudCDN:
case domain.DeployProviderTypeDogeCloudCDN:
{
access := &domain.DogeCloudAccessConfig{}
access := &domain.AccessConfigForDogeCloud{}
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
return nil, nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
@ -159,15 +159,15 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
return deployer, logger, err
}
case targetHuaweiCloudCDN, targetHuaweiCloudELB:
case domain.DeployProviderTypeHuaweiCloudCDN, domain.DeployProviderTypeHuaweiCloudELB:
{
access := &domain.HuaweiCloudAccessConfig{}
access := &domain.AccessConfigForHuaweiCloud{}
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
return nil, nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
switch target {
case targetHuaweiCloudCDN:
switch provider {
case domain.DeployProviderTypeHuaweiCloudCDN:
deployer, err := providerHuaweiCloudCDN.NewWithLogger(&providerHuaweiCloudCDN.HuaweiCloudCDNDeployerConfig{
AccessKeyId: access.AccessKeyId,
SecretAccessKey: access.SecretAccessKey,
@ -176,7 +176,7 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
}, logger)
return deployer, logger, err
case targetHuaweiCloudELB:
case domain.DeployProviderTypeHuaweiCloudELB:
deployer, err := providerHuaweiCloudELB.NewWithLogger(&providerHuaweiCloudELB.HuaweiCloudELBDeployerConfig{
AccessKeyId: access.AccessKeyId,
SecretAccessKey: access.SecretAccessKey,
@ -193,7 +193,7 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
}
}
case targetLocal:
case domain.DeployProviderTypeLocal:
{
deployer, err := providerLocal.NewWithLogger(&providerLocal.LocalDeployerConfig{
ShellEnv: providerLocal.ShellEnvType(maps.GetValueAsString(deployConfig, "shellEnv")),
@ -210,9 +210,9 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
return deployer, logger, err
}
case targetK8sSecret:
case domain.DeployProviderTypeK8sSecret:
{
access := &domain.KubernetesAccessConfig{}
access := &domain.AccessConfigForKubernetes{}
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
return nil, nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
@ -228,9 +228,9 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
return deployer, logger, err
}
case targetQiniuCDN:
case domain.DeployProviderTypeQiniuCDN:
{
access := &domain.QiniuAccessConfig{}
access := &domain.AccessConfigForQiniu{}
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
return nil, nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
@ -243,9 +243,9 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
return deployer, logger, err
}
case targetSSH:
case domain.DeployProviderTypeSSH:
{
access := &domain.SSHAccessConfig{}
access := &domain.AccessConfigForSSH{}
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
return nil, nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
@ -271,15 +271,15 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
return deployer, logger, err
}
case targetTencentCloudCDN, targetTencentCloudCLB, targetTencentCloudCOS, targetTencentCloudECDN, targetTencentCloudEO:
case domain.DeployProviderTypeTencentCloudCDN, domain.DeployProviderTypeTencentCloudCLB, domain.DeployProviderTypeTencentCloudCOS, domain.DeployProviderTypeTencentCloudECDN, domain.DeployProviderTypeTencentCloudEO:
{
access := &domain.TencentCloudAccessConfig{}
access := &domain.AccessConfigForTencentCloud{}
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
return nil, nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
switch target {
case targetTencentCloudCDN:
switch provider {
case domain.DeployProviderTypeTencentCloudCDN:
deployer, err := providerTencentCloudCDN.NewWithLogger(&providerTencentCloudCDN.TencentCloudCDNDeployerConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
@ -287,7 +287,7 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
}, logger)
return deployer, logger, err
case targetTencentCloudCLB:
case domain.DeployProviderTypeTencentCloudCLB:
deployer, err := providerTencentCloudCLB.NewWithLogger(&providerTencentCloudCLB.TencentCloudCLBDeployerConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
@ -299,7 +299,7 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
}, logger)
return deployer, logger, err
case targetTencentCloudCOS:
case domain.DeployProviderTypeTencentCloudCOS:
deployer, err := providerTencentCloudCOD.NewWithLogger(&providerTencentCloudCOD.TencentCloudCOSDeployerConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
@ -309,7 +309,7 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
}, logger)
return deployer, logger, err
case targetTencentCloudECDN:
case domain.DeployProviderTypeTencentCloudECDN:
deployer, err := providerTencentCloudECDN.NewWithLogger(&providerTencentCloudECDN.TencentCloudECDNDeployerConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
@ -317,7 +317,7 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
}, logger)
return deployer, logger, err
case targetTencentCloudEO:
case domain.DeployProviderTypeTencentCloudEO:
deployer, err := providerTencentCloudEO.NewWithLogger(&providerTencentCloudEO.TencentCloudEODeployerConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
@ -331,15 +331,15 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
}
}
case targetVolcEngineCDN, targetVolcEngineLive:
case domain.DeployProviderTypeVolcEngineCDN, domain.DeployProviderTypeVolcEngineLive:
{
access := &domain.VolcEngineAccessConfig{}
access := &domain.AccessConfigForVolcEngine{}
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
return nil, nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
switch target {
case targetVolcEngineCDN:
switch provider {
case domain.DeployProviderTypeVolcEngineCDN:
deployer, err := providerVolcEngineCDN.NewWithLogger(&providerVolcEngineCDN.VolcEngineCDNDeployerConfig{
AccessKey: access.AccessKeyId,
SecretKey: access.SecretAccessKey,
@ -347,7 +347,7 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
}, logger)
return deployer, logger, err
case targetVolcEngineLive:
case domain.DeployProviderTypeVolcEngineLive:
deployer, err := providerVolcEngineLive.NewWithLogger(&providerVolcEngineLive.VolcEngineLiveDeployerConfig{
AccessKey: access.AccessKeyId,
SecretKey: access.SecretAccessKey,
@ -360,9 +360,9 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
}
}
case targetWebhook:
case domain.DeployProviderTypeWebhook:
{
access := &domain.WebhookAccessConfig{}
access := &domain.AccessConfigForWebhook{}
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
return nil, nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
@ -375,5 +375,5 @@ func createDeployer(target string, accessConfig string, deployConfig map[string]
}
}
return nil, nil, fmt.Errorf("unsupported deployer target: %s", target)
return nil, nil, fmt.Errorf("unsupported deployer provider: %s", provider)
}

View File

@ -11,111 +11,81 @@ type Access struct {
DeletedAt time.Time `json:"deleted" db:"deleted"`
}
type AccessProviderType string
/*
提供商类型常量值
注意如果追加新的常量值请保持以 ASCII 排序
NOTICE: If you add new constant, please keep ASCII order.
*/
const (
ACCESS_PROVIDER_ACMEHTTPREQ = AccessProviderType("acmehttpreq")
ACCESS_PROVIDER_ALIYUN = AccessProviderType("aliyun")
ACCESS_PROVIDER_AWS = AccessProviderType("aws")
ACCESS_PROVIDER_BAIDUCLOUD = AccessProviderType("baiducloud")
ACCESS_PROVIDER_BYTEPLUS = AccessProviderType("byteplus")
ACCESS_PROVIDER_CLOUDFLARE = AccessProviderType("cloudflare")
ACCESS_PROVIDER_DOGECLOUD = AccessProviderType("dogecloud")
ACCESS_PROVIDER_GODADDY = AccessProviderType("godaddy")
ACCESS_PROVIDER_HUAWEICLOUD = AccessProviderType("huaweicloud")
ACCESS_PROVIDER_KUBERNETES = AccessProviderType("k8s")
ACCESS_PROVIDER_LOCAL = AccessProviderType("local")
ACCESS_PROVIDER_NAMEDOTCOM = AccessProviderType("namedotcom")
ACCESS_PROVIDER_NAMESILO = AccessProviderType("namesilo")
ACCESS_PROVIDER_POWERDNS = AccessProviderType("powerdns")
ACCESS_PROVIDER_QINIU = AccessProviderType("qiniu")
ACCESS_PROVIDER_SSH = AccessProviderType("ssh")
ACCESS_PROVIDER_TENCENTCLOUD = AccessProviderType("tencentcloud")
ACCESS_PROVIDER_VOLCENGINE = AccessProviderType("volcengine")
ACCESS_PROVIDER_WEBHOOK = AccessProviderType("webhook")
)
type ACMEHttpReqAccessConfig struct {
type AccessConfigForACMEHttpReq struct {
Endpoint string `json:"endpoint"`
Mode string `json:"mode"`
Username string `json:"username"`
Password string `json:"password"`
}
type AliyunAccessConfig struct {
type AccessConfigForAliyun struct {
AccessKeyId string `json:"accessKeyId"`
AccessKeySecret string `json:"accessKeySecret"`
}
type AWSAccessConfig struct {
type AccessConfigForAWS struct {
AccessKeyId string `json:"accessKeyId"`
SecretAccessKey string `json:"secretAccessKey"`
Region string `json:"region"`
HostedZoneId string `json:"hostedZoneId"`
}
type BaiduCloudAccessConfig struct {
type AccessConfigForBaiduCloud struct {
AccessKeyId string `json:"accessKeyId"`
SecretAccessKey string `json:"secretAccessKey"`
}
type BytePlusAccessConfig struct {
type AccessConfigForBytePlus struct {
AccessKey string `json:"accessKey"`
SecretKey string `json:"secretKey"`
}
type CloudflareAccessConfig struct {
type AccessConfigForCloudflare struct {
DnsApiToken string `json:"dnsApiToken"`
}
type DogeCloudAccessConfig struct {
type AccessConfigForDogeCloud struct {
AccessKey string `json:"accessKey"`
SecretKey string `json:"secretKey"`
}
type GoDaddyAccessConfig struct {
type AccessConfigForGoDaddy struct {
ApiKey string `json:"apiKey"`
ApiSecret string `json:"apiSecret"`
}
type HuaweiCloudAccessConfig struct {
type AccessConfigForHuaweiCloud struct {
AccessKeyId string `json:"accessKeyId"`
SecretAccessKey string `json:"secretAccessKey"`
Region string `json:"region"`
}
type LocalAccessConfig struct{}
type AccessConfigForLocal struct{}
type KubernetesAccessConfig struct {
type AccessConfigForKubernetes struct {
KubeConfig string `json:"kubeConfig"`
}
type NameDotComAccessConfig struct {
type AccessConfigForNameDotCom struct {
Username string `json:"username"`
ApiToken string `json:"apiToken"`
}
type NameSiloAccessConfig struct {
type AccessConfigForNameSilo struct {
ApiKey string `json:"apiKey"`
}
type PowerDNSAccessConfig struct {
type AccessConfigForPowerDNS struct {
ApiUrl string `json:"apiUrl"`
ApiKey string `json:"apiKey"`
}
type QiniuAccessConfig struct {
type AccessConfigForQiniu struct {
AccessKey string `json:"accessKey"`
SecretKey string `json:"secretKey"`
}
type SSHAccessConfig struct {
type AccessConfigForSSH struct {
Host string `json:"host"`
Port string `json:"port"`
Username string `json:"username"`
@ -124,16 +94,16 @@ type SSHAccessConfig struct {
KeyPassphrase string `json:"keyPassphrase"`
}
type TencentCloudAccessConfig struct {
type AccessConfigForTencentCloud struct {
SecretId string `json:"secretId"`
SecretKey string `json:"secretKey"`
}
type VolcEngineAccessConfig struct {
type AccessConfigForVolcEngine struct {
AccessKeyId string `json:"accessKeyId"`
SecretAccessKey string `json:"secretAccessKey"`
}
type WebhookAccessConfig struct {
type AccessConfigForWebhook struct {
Url string `json:"url"`
}

View File

@ -18,8 +18,8 @@ type Certificate struct {
IssuerCertificate string `json:"issuerCertificate" db:"issuerCertificate"`
EffectAt time.Time `json:"effectAt" db:"effectAt"`
ExpireAt time.Time `json:"expireAt" db:"expireAt"`
AcmeCertUrl string `json:"acmeCertUrl" db:"acmeCertUrl"`
AcmeCertStableUrl string `json:"acmeCertStableUrl" db:"acmeCertStableUrl"`
ACMECertUrl string `json:"acmeCertUrl" db:"acmeCertUrl"`
ACMECertStableUrl string `json:"acmeCertStableUrl" db:"acmeCertStableUrl"`
WorkflowId string `json:"workflowId" db:"workflowId"`
WorkflowNodeId string `json:"workflowNodeId" db:"workflowNodeId"`
WorkflowOutputId string `json:"workflowOutputId" db:"workflowOutputId"`

View File

@ -9,14 +9,14 @@ type NotifyChannelType string
NOTICE: If you add new constant, please keep ASCII order.
*/
const (
NOTIFY_CHANNEL_BARK = NotifyChannelType("bark")
NOTIFY_CHANNEL_DINGTALK = NotifyChannelType("dingtalk")
NOTIFY_CHANNEL_EMAIL = NotifyChannelType("email")
NOTIFY_CHANNEL_LARK = NotifyChannelType("lark")
NOTIFY_CHANNEL_SERVERCHAN = NotifyChannelType("serverchan")
NOTIFY_CHANNEL_TELEGRAM = NotifyChannelType("telegram")
NOTIFY_CHANNEL_WEBHOOK = NotifyChannelType("webhook")
NOTIFY_CHANNEL_WECOM = NotifyChannelType("wecom")
NotifyChannelTypeBark = NotifyChannelType("bark")
NotifyChannelTypeDingTalk = NotifyChannelType("dingtalk")
NotifyChannelTypeEmail = NotifyChannelType("email")
NotifyChannelTypeLark = NotifyChannelType("lark")
NotifyChannelTypeServerChan = NotifyChannelType("serverchan")
NotifyChannelTypeTelegram = NotifyChannelType("telegram")
NotifyChannelTypeWebhook = NotifyChannelType("webhook")
NotifyChannelTypeWeCom = NotifyChannelType("wecom")
)
type NotifyTestPushReq struct {

View File

@ -0,0 +1,66 @@
package domain
type AccessProviderType string
/*
提供商类型常量值
注意如果追加新的常量值请保持以 ASCII 排序
NOTICE: If you add new constant, please keep ASCII order.
*/
const (
AccessProviderTypeACMEHttpReq = AccessProviderType("acmehttpreq")
AccessProviderTypeAliyun = AccessProviderType("aliyun")
AccessProviderTypeAWS = AccessProviderType("aws")
AccessProviderTypeBaiduCloud = AccessProviderType("baiducloud")
AccessProviderTypeBytePlus = AccessProviderType("byteplus")
AccessProviderTypeCloudflare = AccessProviderType("cloudflare")
AccessProviderTypeDogeCloud = AccessProviderType("dogecloud")
AccessProviderTypeGoDaddy = AccessProviderType("godaddy")
AccessProviderTypeHuaweiCloud = AccessProviderType("huaweicloud")
AccessProviderTypeKubernetes = AccessProviderType("k8s")
AccessProviderTypeLocal = AccessProviderType("local")
AccessProviderTypeNameDotCom = AccessProviderType("namedotcom")
AccessProviderTypeNameSilo = AccessProviderType("namesilo")
AccessProviderTypePowerDNS = AccessProviderType("powerdns")
AccessProviderTypeQiniu = AccessProviderType("qiniu")
AccessProviderTypeSSH = AccessProviderType("ssh")
AccessProviderTypeTencentCloud = AccessProviderType("tencentcloud")
AccessProviderTypeVolcEngine = AccessProviderType("volcengine")
AccessProviderTypeWebhook = AccessProviderType("webhook")
)
type DeployProviderType string
/*
提供商部署目标常量值
短横线前的部分始终等于提供商类型
注意如果追加新的常量值请保持以 ASCII 排序
NOTICE: If you add new constant, please keep ASCII order.
*/
const (
DeployProviderTypeAliyunALB = DeployProviderType("aliyun-alb")
DeployProviderTypeAliyunCDN = DeployProviderType("aliyun-cdn")
DeployProviderTypeAliyunCLB = DeployProviderType("aliyun-clb")
DeployProviderTypeAliyunDCDN = DeployProviderType("aliyun-dcdn")
DeployProviderTypeAliyunNLB = DeployProviderType("aliyun-nlb")
DeployProviderTypeAliyunOSS = DeployProviderType("aliyun-oss")
DeployProviderTypeBaiduCloudCDN = DeployProviderType("baiducloud-cdn")
DeployProviderTypeBytePlusCDN = DeployProviderType("byteplus-cdn")
DeployProviderTypeDogeCloudCDN = DeployProviderType("dogecloud-cdn")
DeployProviderTypeHuaweiCloudCDN = DeployProviderType("huaweicloud-cdn")
DeployProviderTypeHuaweiCloudELB = DeployProviderType("huaweicloud-elb")
DeployProviderTypeK8sSecret = DeployProviderType("k8s-secret")
DeployProviderTypeLocal = DeployProviderType("local")
DeployProviderTypeQiniuCDN = DeployProviderType("qiniu-cdn")
DeployProviderTypeSSH = DeployProviderType("ssh")
DeployProviderTypeTencentCloudCDN = DeployProviderType("tencentcloud-cdn")
DeployProviderTypeTencentCloudCLB = DeployProviderType("tencentcloud-clb")
DeployProviderTypeTencentCloudCOS = DeployProviderType("tencentcloud-cos")
DeployProviderTypeTencentCloudECDN = DeployProviderType("tencentcloud-ecdn")
DeployProviderTypeTencentCloudEO = DeployProviderType("tencentcloud-eo")
DeployProviderTypeVolcEngineCDN = DeployProviderType("volcengine-cdn")
DeployProviderTypeVolcEngineLive = DeployProviderType("volcengine-live")
DeployProviderTypeWebhook = DeployProviderType("webhook")
)

View File

@ -1,7 +1,5 @@
package domain
const WorkflowOutputCertificate = "certificate"
type WorkflowOutput struct {
Meta
WorkflowId string `json:"workflowId" db:"workflow"`
@ -10,3 +8,5 @@ type WorkflowOutput struct {
Outputs []WorkflowNodeIO `json:"outputs" db:"outputs"`
Succeeded bool `json:"succeeded" db:"succeeded"`
}
const WORKFLOW_OUTPUT_CERTIFICATE = "certificate"

View File

@ -22,19 +22,19 @@ func createNotifier(channel domain.NotifyChannelType, channelConfig map[string]a
NOTICE: If you add new constant, please keep ASCII order.
*/
switch channel {
case domain.NOTIFY_CHANNEL_BARK:
case domain.NotifyChannelTypeBark:
return providerBark.New(&providerBark.BarkNotifierConfig{
DeviceKey: maps.GetValueAsString(channelConfig, "deviceKey"),
ServerUrl: maps.GetValueAsString(channelConfig, "serverUrl"),
})
case domain.NOTIFY_CHANNEL_DINGTALK:
case domain.NotifyChannelTypeDingTalk:
return providerDingTalk.New(&providerDingTalk.DingTalkNotifierConfig{
AccessToken: maps.GetValueAsString(channelConfig, "accessToken"),
Secret: maps.GetValueAsString(channelConfig, "secret"),
})
case domain.NOTIFY_CHANNEL_EMAIL:
case domain.NotifyChannelTypeEmail:
return providerEmail.New(&providerEmail.EmailNotifierConfig{
SmtpHost: maps.GetValueAsString(channelConfig, "smtpHost"),
SmtpPort: maps.GetValueAsInt32(channelConfig, "smtpPort"),
@ -45,28 +45,28 @@ func createNotifier(channel domain.NotifyChannelType, channelConfig map[string]a
ReceiverAddress: maps.GetValueAsString(channelConfig, "receiverAddress"),
})
case domain.NOTIFY_CHANNEL_LARK:
case domain.NotifyChannelTypeLark:
return providerLark.New(&providerLark.LarkNotifierConfig{
WebhookUrl: maps.GetValueAsString(channelConfig, "webhookUrl"),
})
case domain.NOTIFY_CHANNEL_SERVERCHAN:
case domain.NotifyChannelTypeServerChan:
return providerServerChan.New(&providerServerChan.ServerChanNotifierConfig{
Url: maps.GetValueAsString(channelConfig, "url"),
})
case domain.NOTIFY_CHANNEL_TELEGRAM:
case domain.NotifyChannelTypeTelegram:
return providerTelegram.New(&providerTelegram.TelegramNotifierConfig{
ApiToken: maps.GetValueAsString(channelConfig, "apiToken"),
ChatId: maps.GetValueAsInt64(channelConfig, "chatId"),
})
case domain.NOTIFY_CHANNEL_WEBHOOK:
case domain.NotifyChannelTypeWebhook:
return providerWebhook.New(&providerWebhook.WebhookNotifierConfig{
Url: maps.GetValueAsString(channelConfig, "url"),
})
case domain.NOTIFY_CHANNEL_WECOM:
case domain.NotifyChannelTypeWeCom:
return providerWeCom.New(&providerWeCom.WeComNotifierConfig{
WebhookUrl: maps.GetValueAsString(channelConfig, "webhookUrl"),
})

View File

@ -0,0 +1,41 @@
package acmehttpreq
import (
"errors"
"net/url"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/httpreq"
)
type ACMEHttpReqApplicantConfig struct {
Endpoint string `json:"endpoint"`
Mode string `json:"mode"`
Username string `json:"username"`
Password string `json:"password"`
PropagationTimeout int32 `json:"propagationTimeout,omitempty"`
}
func NewChallengeProvider(config *ACMEHttpReqApplicantConfig) (challenge.Provider, error) {
if config == nil {
return nil, errors.New("config is nil")
}
endpoint, _ := url.Parse(config.Endpoint)
providerConfig := httpreq.NewDefaultConfig()
providerConfig.Endpoint = endpoint
providerConfig.Mode = config.Mode
providerConfig.Username = config.Username
providerConfig.Password = config.Password
if config.PropagationTimeout != 0 {
providerConfig.PropagationTimeout = time.Duration(config.PropagationTimeout) * time.Second
}
provider, err := httpreq.NewDNSProviderConfig(providerConfig)
if err != nil {
return nil, err
}
return provider, nil
}

View File

@ -0,0 +1,35 @@
package aliyun
import (
"errors"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/alidns"
)
type AliyunApplicantConfig struct {
AccessKeyId string `json:"accessKeyId"`
AccessKeySecret string `json:"accessKeySecret"`
PropagationTimeout int32 `json:"propagationTimeout,omitempty"`
}
func NewChallengeProvider(config *AliyunApplicantConfig) (challenge.Provider, error) {
if config == nil {
return nil, errors.New("config is nil")
}
providerConfig := alidns.NewDefaultConfig()
providerConfig.APIKey = config.AccessKeyId
providerConfig.SecretKey = config.AccessKeySecret
if config.PropagationTimeout != 0 {
providerConfig.PropagationTimeout = time.Duration(config.PropagationTimeout) * time.Second
}
provider, err := alidns.NewDNSProviderConfig(providerConfig)
if err != nil {
return nil, err
}
return provider, nil
}

View File

@ -0,0 +1,39 @@
package aws
import (
"errors"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/route53"
)
type AWSApplicantConfig struct {
AccessKeyId string `json:"accessKeyId"`
SecretAccessKey string `json:"secretAccessKey"`
Region string `json:"region"`
HostedZoneId string `json:"hostedZoneId"`
PropagationTimeout int32 `json:"propagationTimeout,omitempty"`
}
func NewChallengeProvider(config *AWSApplicantConfig) (challenge.Provider, error) {
if config == nil {
return nil, errors.New("config is nil")
}
providerConfig := route53.NewDefaultConfig()
providerConfig.AccessKeyID = config.AccessKeyId
providerConfig.SecretAccessKey = config.SecretAccessKey
providerConfig.Region = config.Region
providerConfig.HostedZoneID = config.HostedZoneId
if config.PropagationTimeout != 0 {
providerConfig.PropagationTimeout = time.Duration(config.PropagationTimeout) * time.Second
}
provider, err := route53.NewDNSProviderConfig(providerConfig)
if err != nil {
return nil, err
}
return provider, nil
}

View File

@ -0,0 +1,33 @@
package cloudflare
import (
"errors"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/cloudflare"
)
type CloudflareApplicantConfig struct {
DnsApiToken string `json:"dnsApiToken"`
PropagationTimeout int32 `json:"propagationTimeout,omitempty"`
}
func NewChallengeProvider(config *CloudflareApplicantConfig) (challenge.Provider, error) {
if config == nil {
return nil, errors.New("config is nil")
}
providerConfig := cloudflare.NewDefaultConfig()
providerConfig.AuthToken = config.DnsApiToken
if config.PropagationTimeout != 0 {
providerConfig.PropagationTimeout = time.Duration(config.PropagationTimeout) * time.Second
}
provider, err := cloudflare.NewDNSProviderConfig(providerConfig)
if err != nil {
return nil, err
}
return provider, nil
}

View File

@ -0,0 +1,35 @@
package godaddy
import (
"errors"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/godaddy"
)
type GoDaddyApplicantConfig struct {
ApiKey string `json:"apiKey"`
ApiSecret string `json:"apiSecret"`
PropagationTimeout int32 `json:"propagationTimeout,omitempty"`
}
func NewChallengeProvider(config *GoDaddyApplicantConfig) (challenge.Provider, error) {
if config == nil {
return nil, errors.New("config is nil")
}
providerConfig := godaddy.NewDefaultConfig()
providerConfig.APIKey = config.ApiKey
providerConfig.APISecret = config.ApiSecret
if config.PropagationTimeout != 0 {
providerConfig.PropagationTimeout = time.Duration(config.PropagationTimeout) * time.Second
}
provider, err := godaddy.NewDNSProviderConfig(providerConfig)
if err != nil {
return nil, err
}
return provider, nil
}

View File

@ -0,0 +1,43 @@
package huaweicloud
import (
"errors"
"time"
"github.com/go-acme/lego/v4/challenge"
hwc "github.com/go-acme/lego/v4/providers/dns/huaweicloud"
)
type HuaweiCloudApplicantConfig struct {
AccessKeyId string `json:"accessKeyId"`
SecretAccessKey string `json:"secretAccessKey"`
Region string `json:"region"`
PropagationTimeout int32 `json:"propagationTimeout,omitempty"`
}
func NewChallengeProvider(config *HuaweiCloudApplicantConfig) (challenge.Provider, error) {
if config == nil {
return nil, errors.New("config is nil")
}
region := config.Region
if region == "" {
// 华为云的 SDK 要求必须传一个区域,实际上 DNS-01 流程里用不到,但不传会报错
region = "cn-north-1"
}
providerConfig := hwc.NewDefaultConfig()
providerConfig.AccessKeyID = config.AccessKeyId
providerConfig.SecretAccessKey = config.SecretAccessKey
providerConfig.Region = region
if config.PropagationTimeout != 0 {
providerConfig.PropagationTimeout = time.Duration(config.PropagationTimeout) * time.Second
}
provider, err := hwc.NewDNSProviderConfig(providerConfig)
if err != nil {
return nil, err
}
return provider, nil
}

View File

@ -0,0 +1,35 @@
package namedotcom
import (
"errors"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/namedotcom"
)
type NameDotComApplicantConfig struct {
Username string `json:"username"`
ApiToken string `json:"apiToken"`
PropagationTimeout int32 `json:"propagationTimeout,omitempty"`
}
func NewChallengeProvider(config *NameDotComApplicantConfig) (challenge.Provider, error) {
if config == nil {
return nil, errors.New("config is nil")
}
providerConfig := namedotcom.NewDefaultConfig()
providerConfig.Username = config.Username
providerConfig.APIToken = config.ApiToken
if config.PropagationTimeout != 0 {
providerConfig.PropagationTimeout = time.Duration(config.PropagationTimeout) * time.Second
}
provider, err := namedotcom.NewDNSProviderConfig(providerConfig)
if err != nil {
return nil, err
}
return provider, nil
}

View File

@ -0,0 +1,33 @@
package namesilo
import (
"errors"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/namesilo"
)
type NameSiloApplicantConfig struct {
ApiKey string `json:"apiKey"`
PropagationTimeout int32 `json:"propagationTimeout,omitempty"`
}
func NewChallengeProvider(config *NameSiloApplicantConfig) (challenge.Provider, error) {
if config == nil {
return nil, errors.New("config is nil")
}
providerConfig := namesilo.NewDefaultConfig()
providerConfig.APIKey = config.ApiKey
if config.PropagationTimeout != 0 {
providerConfig.PropagationTimeout = time.Duration(config.PropagationTimeout) * time.Second
}
provider, err := namesilo.NewDNSProviderConfig(providerConfig)
if err != nil {
return nil, err
}
return provider, nil
}

View File

@ -0,0 +1,37 @@
package namesilo
import (
"errors"
"net/url"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/pdns"
)
type PowerDNSApplicantConfig struct {
ApiUrl string `json:"apiUrl"`
ApiKey string `json:"apiKey"`
PropagationTimeout int32 `json:"propagationTimeout,omitempty"`
}
func NewChallengeProvider(config *PowerDNSApplicantConfig) (challenge.Provider, error) {
if config == nil {
return nil, errors.New("config is nil")
}
host, _ := url.Parse(config.ApiUrl)
providerConfig := pdns.NewDefaultConfig()
providerConfig.Host = host
providerConfig.APIKey = config.ApiKey
if config.PropagationTimeout != 0 {
providerConfig.PropagationTimeout = time.Duration(config.PropagationTimeout) * time.Second
}
provider, err := pdns.NewDNSProviderConfig(providerConfig)
if err != nil {
return nil, err
}
return provider, nil
}

View File

@ -0,0 +1,35 @@
package tencentcloud
import (
"errors"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/tencentcloud"
)
type TencentCloudApplicantConfig struct {
SecretId string `json:"secretId"`
SecretKey string `json:"secretKey"`
PropagationTimeout int32 `json:"propagationTimeout,omitempty"`
}
func NewChallengeProvider(config *TencentCloudApplicantConfig) (challenge.Provider, error) {
if config == nil {
return nil, errors.New("config is nil")
}
providerConfig := tencentcloud.NewDefaultConfig()
providerConfig.SecretID = config.SecretId
providerConfig.SecretKey = config.SecretKey
if config.PropagationTimeout != 0 {
providerConfig.PropagationTimeout = time.Duration(config.PropagationTimeout) * time.Second
}
provider, err := tencentcloud.NewDNSProviderConfig(providerConfig)
if err != nil {
return nil, err
}
return provider, nil
}

View File

@ -0,0 +1,35 @@
package volcengine
import (
"errors"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/volcengine"
)
type VolcEngineApplicantConfig struct {
AccessKeyId string `json:"accessKeyId"`
SecretAccessKey string `json:"secretAccessKey"`
PropagationTimeout int32 `json:"propagationTimeout,omitempty"`
}
func NewChallengeProvider(config *VolcEngineApplicantConfig) (challenge.Provider, error) {
if config == nil {
return nil, errors.New("config is nil")
}
providerConfig := volcengine.NewDefaultConfig()
providerConfig.AccessKey = config.AccessKeyId
providerConfig.SecretKey = config.SecretAccessKey
if config.PropagationTimeout != 0 {
providerConfig.PropagationTimeout = time.Duration(config.PropagationTimeout) * time.Second
}
provider, err := volcengine.NewDNSProviderConfig(providerConfig)
if err != nil {
return nil, err
}
return provider, nil
}

View File

@ -14,11 +14,13 @@ func NewCertificateRepository() *CertificateRepository {
}
func (c *CertificateRepository) ListExpireSoon(ctx context.Context) ([]domain.Certificate, error) {
rs := []domain.Certificate{}
if err := app.GetApp().Dao().DB().
certificates := []domain.Certificate{}
err := app.GetApp().Dao().DB().
NewQuery("SELECT * FROM certificate WHERE expireAt > DATETIME('now') AND expireAt < DATETIME('now', '+20 days')").
All(&rs); err != nil {
All(&certificates)
if err != nil {
return nil, err
}
return rs, nil
return certificates, nil
}

View File

@ -20,7 +20,7 @@ func (s *SettingsRepository) GetByName(ctx context.Context, name string) (*domai
return nil, err
}
rs := &domain.Settings{
settings := &domain.Settings{
Meta: domain.Meta{
Id: record.GetId(),
CreatedAt: record.GetCreated().Time(),
@ -29,6 +29,5 @@ func (s *SettingsRepository) GetByName(ctx context.Context, name string) (*domai
Name: record.GetString("name"),
Content: record.GetString("content"),
}
return rs, nil
return settings, nil
}

View File

@ -15,6 +15,7 @@ func NewStatisticsRepository() *StatisticsRepository {
func (r *StatisticsRepository) Get(ctx context.Context) (*domain.Statistics, error) {
rs := &domain.Statistics{}
// 所有证书
certTotal := struct {
Total int `db:"total"`

View File

@ -82,7 +82,7 @@ func (w *WorkflowRepository) SaveRun(ctx context.Context, run *domain.WorkflowRu
return nil
}
func (w *WorkflowRepository) Get(ctx context.Context, id string) (*domain.Workflow, error) {
func (w *WorkflowRepository) GetById(ctx context.Context, id string) (*domain.Workflow, error) {
record, err := app.GetApp().Dao().FindRecordById("workflow", id)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {

View File

@ -17,7 +17,7 @@ func NewWorkflowOutputRepository() *WorkflowOutputRepository {
return &WorkflowOutputRepository{}
}
func (w *WorkflowOutputRepository) Get(ctx context.Context, nodeId string) (*domain.WorkflowOutput, error) {
func (w *WorkflowOutputRepository) GetByNodeId(ctx context.Context, nodeId string) (*domain.WorkflowOutput, error) {
records, err := app.GetApp().Dao().FindRecordsByFilter("workflow_output", "nodeId={:nodeId}", "-created", 1, 0, dbx.Params{"nodeId": nodeId})
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
@ -56,7 +56,7 @@ func (w *WorkflowOutputRepository) Get(ctx context.Context, nodeId string) (*dom
return rs, nil
}
func (w *WorkflowOutputRepository) GetCertificate(ctx context.Context, nodeId string) (*domain.Certificate, error) {
func (w *WorkflowOutputRepository) GetCertificateByNodeId(ctx context.Context, nodeId string) (*domain.Certificate, error) {
records, err := app.GetApp().Dao().FindRecordsByFilter("certificate", "workflowNodeId={:workflowNodeId}", "-created", 1, 0, dbx.Params{"workflowNodeId": nodeId})
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
@ -83,8 +83,8 @@ func (w *WorkflowOutputRepository) GetCertificate(ctx context.Context, nodeId st
IssuerCertificate: record.GetString("issuerCertificate"),
EffectAt: record.GetTime("effectAt"),
ExpireAt: record.GetTime("expireAt"),
AcmeCertUrl: record.GetString("acmeCertUrl"),
AcmeCertStableUrl: record.GetString("acmeCertStableUrl"),
ACMECertUrl: record.GetString("acmeCertUrl"),
ACMECertStableUrl: record.GetString("acmeCertStableUrl"),
WorkflowId: record.GetString("workflowId"),
WorkflowNodeId: record.GetString("workflowNodeId"),
WorkflowOutputId: record.GetString("workflowOutputId"),
@ -137,8 +137,8 @@ func (w *WorkflowOutputRepository) Save(ctx context.Context, output *domain.Work
certRecord.Set("issuerCertificate", certificate.IssuerCertificate)
certRecord.Set("effectAt", certificate.EffectAt)
certRecord.Set("expireAt", certificate.ExpireAt)
certRecord.Set("acmeCertUrl", certificate.AcmeCertUrl)
certRecord.Set("acmeCertStableUrl", certificate.AcmeCertStableUrl)
certRecord.Set("acmeCertUrl", certificate.ACMECertUrl)
certRecord.Set("acmeCertStableUrl", certificate.ACMECertStableUrl)
certRecord.Set("workflowId", certificate.WorkflowId)
certRecord.Set("workflowNodeId", certificate.WorkflowNodeId)
certRecord.Set("workflowOutputId", certificate.WorkflowOutputId)
@ -149,7 +149,7 @@ func (w *WorkflowOutputRepository) Save(ctx context.Context, output *domain.Work
// 更新 certificate
for i, item := range output.Outputs {
if item.Name == "certificate" {
if item.Name == domain.WORKFLOW_OUTPUT_CERTIFICATE {
output.Outputs[i].Value = certRecord.GetId()
break
}

View File

@ -14,7 +14,7 @@ import (
const tableName = "workflow"
func AddEvent() error {
func RegisterEvents() error {
app := app.GetApp()
app.OnRecordAfterCreateRequest(tableName).Add(func(e *core.RecordCreateEvent) error {
@ -32,30 +32,23 @@ func AddEvent() error {
return nil
}
func delete(_ context.Context, record *models.Record) error {
id := record.Id
scheduler := app.GetScheduler()
scheduler.Remove(id)
scheduler.Start()
return nil
}
func update(ctx context.Context, record *models.Record) error {
// 是不是自动
// 是不是 enabled
scheduler := app.GetScheduler()
workflowId := record.Id
// 向数据库插入/更新时,同时更新定时任务
workflowId := record.GetId()
enabled := record.GetBool("enabled")
trigger := record.GetString("trigger")
scheduler := app.GetScheduler()
// 如果是手动触发或未启用,移除定时任务
if !enabled || trigger == string(domain.WorkflowTriggerTypeManual) {
scheduler.Remove(workflowId)
scheduler.Remove(fmt.Sprintf("workflow#%s", workflowId))
scheduler.Start()
return nil
}
err := scheduler.Add(workflowId, record.GetString("triggerCron"), func() {
// 反之,重新添加定时任务
err := scheduler.Add(fmt.Sprintf("workflow#%s", workflowId), record.GetString("triggerCron"), func() {
NewWorkflowService(repository.NewWorkflowRepository()).Run(ctx, &domain.WorkflowRunReq{
WorkflowId: workflowId,
Trigger: domain.WorkflowTriggerTypeAuto,
@ -65,8 +58,19 @@ func update(ctx context.Context, record *models.Record) error {
app.GetLogger().Error("add cron job failed", "err", err)
return fmt.Errorf("add cron job failed: %w", err)
}
app.GetLogger().Error("add cron job failed", "subjectAltNames", record.GetString("subjectAltNames"))
scheduler.Start()
return nil
}
func delete(_ context.Context, record *models.Record) error {
scheduler := app.GetScheduler()
// 从数据库删除时,同时移除定时任务
workflowId := record.GetId()
scheduler.Remove(fmt.Sprintf("workflow#%s", workflowId))
scheduler.Start()
return nil
}

View File

@ -29,10 +29,10 @@ func NewApplyNode(node *domain.WorkflowNode) *applyNode {
type WorkflowOutputRepository interface {
// 查询节点输出
Get(ctx context.Context, nodeId string) (*domain.WorkflowOutput, error)
GetByNodeId(ctx context.Context, nodeId string) (*domain.WorkflowOutput, error)
// 查询申请节点的证书
GetCertificate(ctx context.Context, nodeId string) (*domain.Certificate, error)
GetCertificateByNodeId(ctx context.Context, nodeId string) (*domain.Certificate, error)
// 保存节点输出
Save(ctx context.Context, output *domain.WorkflowOutput, certificate *domain.Certificate, cb func(id string) error) error
@ -42,14 +42,14 @@ type WorkflowOutputRepository interface {
func (a *applyNode) Run(ctx context.Context) error {
a.AddOutput(ctx, a.node.Name, "开始执行")
// 查询是否申请过,已申请过则直接返回(先保持和 v0.2 一致)
output, err := a.outputRepo.Get(ctx, a.node.Id)
output, err := a.outputRepo.GetByNodeId(ctx, a.node.Id)
if err != nil && !domain.IsRecordNotFound(err) {
a.AddOutput(ctx, a.node.Name, "查询申请记录失败", err.Error())
return err
}
if output != nil && output.Succeeded {
cert, err := a.outputRepo.GetCertificate(ctx, a.node.Id)
cert, err := a.outputRepo.GetCertificateByNodeId(ctx, a.node.Id)
if err != nil {
a.AddOutput(ctx, a.node.Name, "获取证书失败", err.Error())
return err
@ -62,14 +62,14 @@ func (a *applyNode) Run(ctx context.Context) error {
}
// 获取Applicant
apply, err := applicant.GetWithApplyNode(a.node)
applicant, err := applicant.GetWithApplyNode(a.node)
if err != nil {
a.AddOutput(ctx, a.node.Name, "获取申请对象失败", err.Error())
return err
}
// 申请
certificate, err := apply.Apply()
certificate, err := applicant.Apply()
if err != nil {
a.AddOutput(ctx, a.node.Name, "申请失败", err.Error())
return err
@ -103,8 +103,8 @@ func (a *applyNode) Run(ctx context.Context) error {
Certificate: certificate.Certificate,
PrivateKey: certificate.PrivateKey,
IssuerCertificate: certificate.IssuerCertificate,
AcmeCertUrl: certificate.CertUrl,
AcmeCertStableUrl: certificate.CertStableUrl,
ACMECertUrl: certificate.CertUrl,
ACMECertStableUrl: certificate.CertStableUrl,
EffectAt: certX509.NotBefore,
ExpireAt: certX509.NotAfter,
WorkflowId: GetWorkflowId(ctx),

View File

@ -28,7 +28,7 @@ func NewDeployNode(node *domain.WorkflowNode) *deployNode {
func (d *deployNode) Run(ctx context.Context) error {
d.AddOutput(ctx, d.node.Name, "开始执行")
// 检查是否部署过(部署过则直接返回,和 v0.2 暂时保持一致)
output, err := d.outputRepo.Get(ctx, d.node.Id)
output, err := d.outputRepo.GetByNodeId(ctx, d.node.Id)
if err != nil && !domain.IsRecordNotFound(err) {
d.AddOutput(ctx, d.node.Name, "查询部署记录失败", err.Error())
return err
@ -43,7 +43,7 @@ func (d *deployNode) Run(ctx context.Context) error {
return fmt.Errorf("证书来源配置错误: %s", certSource)
}
cert, err := d.outputRepo.GetCertificate(ctx, certSourceSlice[0])
cert, err := d.outputRepo.GetCertificateByNodeId(ctx, certSourceSlice[0])
if err != nil {
d.AddOutput(ctx, d.node.Name, "获取证书失败", err.Error())
return err
@ -71,8 +71,8 @@ func (d *deployNode) Run(ctx context.Context) error {
AccessConfig: access.Config,
AccessRecord: access,
Certificate: applicant.Certificate{
CertUrl: cert.AcmeCertUrl,
CertStableUrl: cert.AcmeCertStableUrl,
CertUrl: cert.ACMECertUrl,
CertStableUrl: cert.ACMECertStableUrl,
PrivateKey: cert.PrivateKey,
Certificate: cert.Certificate,
IssuerCertificate: cert.IssuerCertificate,
@ -85,7 +85,7 @@ func (d *deployNode) Run(ctx context.Context) error {
},
}
deploy, err := deployer.GetWithTypeAndOption(d.node.GetConfigString("provider"), option)
deploy, err := deployer.GetWithProviderAndOption(d.node.GetConfigString("provider"), option)
if err != nil {
d.AddOutput(ctx, d.node.Name, "获取部署对象失败", err.Error())
return err

View File

@ -11,7 +11,7 @@ import (
)
type WorkflowRepository interface {
Get(ctx context.Context, id string) (*domain.Workflow, error)
GetById(ctx context.Context, id string) (*domain.Workflow, error)
SaveRun(ctx context.Context, run *domain.WorkflowRun) error
ListEnabledAuto(ctx context.Context) ([]domain.Workflow, error)
}
@ -27,7 +27,6 @@ func NewWorkflowService(repo WorkflowRepository) *WorkflowService {
}
func (s *WorkflowService) InitSchedule(ctx context.Context) error {
// 查询所有的 enabled auto workflow
workflows, err := s.repo.ListEnabledAuto(ctx)
if err != nil {
return err
@ -35,7 +34,7 @@ func (s *WorkflowService) InitSchedule(ctx context.Context) error {
scheduler := app.GetScheduler()
for _, workflow := range workflows {
err := scheduler.Add(workflow.Id, workflow.TriggerCron, func() {
err := scheduler.Add(fmt.Sprintf("workflow#%s", workflow.Id), workflow.TriggerCron, func() {
s.Run(ctx, &domain.WorkflowRunReq{
WorkflowId: workflow.Id,
Trigger: domain.WorkflowTriggerTypeAuto,
@ -55,21 +54,12 @@ func (s *WorkflowService) InitSchedule(ctx context.Context) error {
func (s *WorkflowService) Run(ctx context.Context, options *domain.WorkflowRunReq) error {
// 查询
if options.WorkflowId == "" {
return domain.ErrInvalidParams
}
workflow, err := s.repo.Get(ctx, options.WorkflowId)
workflow, err := s.repo.GetById(ctx, options.WorkflowId)
if err != nil {
app.GetLogger().Error("failed to get workflow", "id", options.WorkflowId, "err", err)
return err
}
if !workflow.Enabled {
app.GetLogger().Error("workflow is disabled", "id", options.WorkflowId)
return fmt.Errorf("workflow is disabled")
}
// 执行
run := &domain.WorkflowRun{
WorkflowId: workflow.Id,
@ -78,7 +68,6 @@ func (s *WorkflowService) Run(ctx context.Context, options *domain.WorkflowRunRe
StartedAt: time.Now(),
EndedAt: time.Now(),
}
processor := nodeprocessor.NewWorkflowProcessor(workflow)
if err := processor.Run(ctx); err != nil {
run.Status = domain.WorkflowRunStatusTypeFailed
@ -93,7 +82,7 @@ func (s *WorkflowService) Run(ctx context.Context, options *domain.WorkflowRunRe
return fmt.Errorf("failed to run workflow: %w", err)
}
// 保存执行日志
// 保存日志
logs := processor.Log(ctx)
runStatus := domain.WorkflowRunStatusTypeSucceeded
runError := domain.WorkflowRunLogs(logs).FirstError()

View File

@ -39,7 +39,7 @@ func main() {
Automigrate: isGoRun,
})
workflow.AddEvent()
workflow.RegisterEvents()
app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
routes.Register(e.Router)

View File

@ -3,10 +3,10 @@ import { Form, type FormInstance, Input, Select } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type ACMEHttpReqAccessConfig } from "@/domain/access";
import { type AccessConfigForACMEHttpReq } from "@/domain/access";
import { useAntdForm } from "@/hooks";
type AccessEditFormACMEHttpReqConfigFieldValues = Partial<ACMEHttpReqAccessConfig>;
type AccessEditFormACMEHttpReqConfigFieldValues = Partial<AccessConfigForACMEHttpReq>;
export type AccessEditFormACMEHttpReqConfigProps = {
form: FormInstance;

View File

@ -3,10 +3,10 @@ import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type AWSAccessConfig } from "@/domain/access";
import { type AccessConfigForAWS } from "@/domain/access";
import { useAntdForm } from "@/hooks";
type AccessEditFormAWSConfigFieldValues = Partial<AWSAccessConfig>;
type AccessEditFormAWSConfigFieldValues = Partial<AccessConfigForAWS>;
export type AccessEditFormAWSConfigProps = {
form: FormInstance;

View File

@ -3,10 +3,10 @@ import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type AliyunAccessConfig } from "@/domain/access";
import { type AccessConfigForAliyun } from "@/domain/access";
import { useAntdForm } from "@/hooks";
type AccessEditFormAliyunConfigFieldValues = Partial<AliyunAccessConfig>;
type AccessEditFormAliyunConfigFieldValues = Partial<AccessConfigForAliyun>;
export type AccessEditFormAliyunConfigProps = {
form: FormInstance;

View File

@ -3,10 +3,10 @@ import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type BaiduCloudAccessConfig } from "@/domain/access";
import { type AccessConfigForBaiduCloud } from "@/domain/access";
import { useAntdForm } from "@/hooks";
type AccessEditFormBaiduCloudConfigFieldValues = Partial<BaiduCloudAccessConfig>;
type AccessEditFormBaiduCloudConfigFieldValues = Partial<AccessConfigForBaiduCloud>;
export type AccessEditFormBaiduCloudConfigProps = {
form: FormInstance;

View File

@ -3,10 +3,10 @@ import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type BytePlusAccessConfig } from "@/domain/access";
import { type AccessConfigForBytePlus } from "@/domain/access";
import { useAntdForm } from "@/hooks";
type AccessEditFormBytePlusConfigFieldValues = Partial<BytePlusAccessConfig>;
type AccessEditFormBytePlusConfigFieldValues = Partial<AccessConfigForBytePlus>;
export type AccessEditFormBytePlusConfigProps = {
form: FormInstance;

View File

@ -3,10 +3,10 @@ import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type CloudflareAccessConfig } from "@/domain/access";
import { type AccessConfigForCloudflare } from "@/domain/access";
import { useAntdForm } from "@/hooks";
type AccessEditFormCloudflareConfigFieldValues = Partial<CloudflareAccessConfig>;
type AccessEditFormCloudflareConfigFieldValues = Partial<AccessConfigForCloudflare>;
export type AccessEditFormCloudflareConfigProps = {
form: FormInstance;

View File

@ -3,10 +3,10 @@ import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type DogeCloudAccessConfig } from "@/domain/access";
import { type AccessConfigForDogeCloud } from "@/domain/access";
import { useAntdForm } from "@/hooks";
type AccessEditFormDogeCloudConfigFieldValues = Partial<DogeCloudAccessConfig>;
type AccessEditFormDogeCloudConfigFieldValues = Partial<AccessConfigForDogeCloud>;
export type AccessEditFormDogeCloudConfigProps = {
form: FormInstance;

View File

@ -3,10 +3,10 @@ import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type GoDaddyAccessConfig } from "@/domain/access";
import { type AccessConfigForGoDaddy } from "@/domain/access";
import { useAntdForm } from "@/hooks";
type AccessEditFormGoDaddyConfigFieldValues = Partial<GoDaddyAccessConfig>;
type AccessEditFormGoDaddyConfigFieldValues = Partial<AccessConfigForGoDaddy>;
export type AccessEditFormGoDaddyConfigProps = {
form: FormInstance;

View File

@ -3,10 +3,10 @@ import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type HuaweiCloudAccessConfig } from "@/domain/access";
import { type AccessConfigForHuaweiCloud } from "@/domain/access";
import { useAntdForm } from "@/hooks";
type AccessEditFormHuaweiCloudConfigFieldValues = Partial<HuaweiCloudAccessConfig>;
type AccessEditFormHuaweiCloudConfigFieldValues = Partial<AccessConfigForHuaweiCloud>;
export type AccessEditFormHuaweiCloudConfigProps = {
form: FormInstance;

View File

@ -7,11 +7,11 @@ import { Button, Form, type FormInstance, Input, Upload, type UploadFile, type U
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type KubernetesAccessConfig } from "@/domain/access";
import { type AccessConfigForKubernetes } from "@/domain/access";
import { useAntdForm } from "@/hooks";
import { readFileContent } from "@/utils/file";
type AccessEditFormKubernetesConfigFieldValues = Partial<KubernetesAccessConfig>;
type AccessEditFormKubernetesConfigFieldValues = Partial<AccessConfigForKubernetes>;
export type AccessEditFormKubernetesConfigProps = {
form: FormInstance;

View File

@ -1,9 +1,9 @@
import { Form, type FormInstance } from "antd";
import { type LocalAccessConfig } from "@/domain/access";
import { type AccessConfigForLocal } from "@/domain/access";
import { useAntdForm } from "@/hooks";
type AccessEditFormLocalConfigFieldValues = Partial<LocalAccessConfig>;
type AccessEditFormLocalConfigFieldValues = Partial<AccessConfigForLocal>;
export type AccessEditFormLocalConfigProps = {
form: FormInstance;

View File

@ -3,10 +3,10 @@ import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type NameDotComAccessConfig } from "@/domain/access";
import { type AccessConfigForNameDotCom } from "@/domain/access";
import { useAntdForm } from "@/hooks";
type AccessEditFormNameDotComConfigFieldValues = Partial<NameDotComAccessConfig>;
type AccessEditFormNameDotComConfigFieldValues = Partial<AccessConfigForNameDotCom>;
export type AccessEditFormNameDotComConfigProps = {
form: FormInstance;

View File

@ -3,10 +3,10 @@ import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type NameSiloAccessConfig } from "@/domain/access";
import { type AccessConfigForNameSilo } from "@/domain/access";
import { useAntdForm } from "@/hooks";
type AccessEditFormNameSiloConfigFieldValues = Partial<NameSiloAccessConfig>;
type AccessEditFormNameSiloConfigFieldValues = Partial<AccessConfigForNameSilo>;
export type AccessEditFormNameSiloConfigProps = {
form: FormInstance;

View File

@ -3,10 +3,10 @@ import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type PowerDNSAccessConfig } from "@/domain/access";
import { type AccessConfigForPowerDNS } from "@/domain/access";
import { useAntdForm } from "@/hooks";
type AccessEditFormPowerDNSConfigFieldValues = Partial<PowerDNSAccessConfig>;
type AccessEditFormPowerDNSConfigFieldValues = Partial<AccessConfigForPowerDNS>;
export type AccessEditFormPowerDNSConfigProps = {
form: FormInstance;

View File

@ -3,10 +3,10 @@ import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type QiniuAccessConfig } from "@/domain/access";
import { type AccessConfigForQiniu } from "@/domain/access";
import { useAntdForm } from "@/hooks";
type AccessEditFormQiniuConfigFieldValues = Partial<QiniuAccessConfig>;
type AccessEditFormQiniuConfigFieldValues = Partial<AccessConfigForQiniu>;
export type AccessEditFormQiniuConfigProps = {
form: FormInstance;

View File

@ -7,12 +7,12 @@ import { Button, Form, type FormInstance, Input, InputNumber, Upload, type Uploa
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type SSHAccessConfig } from "@/domain/access";
import { type AccessConfigForSSH } from "@/domain/access";
import { useAntdForm } from "@/hooks";
import { readFileContent } from "@/utils/file";
import { validDomainName, validIPv4Address, validIPv6Address } from "@/utils/validators";
type AccessEditFormSSHConfigFieldValues = Partial<SSHAccessConfig>;
type AccessEditFormSSHConfigFieldValues = Partial<AccessConfigForSSH>;
export type AccessEditFormSSHConfigProps = {
form: FormInstance;

View File

@ -3,10 +3,10 @@ import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type TencentCloudAccessConfig } from "@/domain/access";
import { type AccessConfigForTencentCloud } from "@/domain/access";
import { useAntdForm } from "@/hooks";
type AccessEditFormTencentCloudConfigFieldValues = Partial<TencentCloudAccessConfig>;
type AccessEditFormTencentCloudConfigFieldValues = Partial<AccessConfigForTencentCloud>;
export type AccessEditFormTencentCloudConfigProps = {
form: FormInstance;

View File

@ -3,10 +3,10 @@ import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type VolcEngineAccessConfig } from "@/domain/access";
import { type AccessConfigForVolcEngine } from "@/domain/access";
import { useAntdForm } from "@/hooks";
type AccessEditFormVolcEngineConfigFieldValues = Partial<VolcEngineAccessConfig>;
type AccessEditFormVolcEngineConfigFieldValues = Partial<AccessConfigForVolcEngine>;
export type AccessEditFormVolcEngineConfigProps = {
form: FormInstance;

View File

@ -3,10 +3,10 @@ import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type WebhookAccessConfig } from "@/domain/access";
import { type AccessConfigForWebhook } from "@/domain/access";
import { useAntdForm } from "@/hooks";
type AccessEditFormWebhookConfigFieldValues = Partial<WebhookAccessConfig>;
type AccessEditFormWebhookConfigFieldValues = Partial<AccessConfigForWebhook>;
export type AccessEditFormWebhookConfigProps = {
form: FormInstance;

View File

@ -96,16 +96,14 @@ const CertificateDetail = ({ data, ...props }: CertificateDetailProps) => {
key: "PFX",
label: "PFX",
onClick: () => {
// TODO: 下载 PFX 格式证书
alert("TODO");
alert("TODO: 暂时不支持下载 PFX 证书");
},
},
{
key: "JKS",
label: "JKS",
onClick: () => {
// TODO: 下载 JKS 格式证书
alert("TODO");
alert("TODO: 暂时不支持下载 JKS 证书");
},
},
],

View File

@ -9,10 +9,10 @@ import { notifyChannelsMap } from "@/domain/settings";
import {
WORKFLOW_TRIGGERS,
type WorkflowNode,
type WorkflowNodeConfigAsApply,
type WorkflowNodeConfigAsDeploy,
type WorkflowNodeConfigAsNotify,
type WorkflowNodeConfigAsStart,
type WorkflowNodeConfigForApply,
type WorkflowNodeConfigForDeploy,
type WorkflowNodeConfigForNotify,
type WorkflowNodeConfigForStart,
WorkflowNodeType,
} from "@/domain/workflow";
import { useZustandShallowSelector } from "@/hooks";
@ -40,7 +40,7 @@ const WorkflowElement = ({ node, disabled }: NodeProps) => {
switch (node.type) {
case WorkflowNodeType.Start: {
const config = (node.config as WorkflowNodeConfigAsStart) ?? {};
const config = (node.config as WorkflowNodeConfigForStart) ?? {};
return (
<div className="flex items-center justify-between space-x-2">
<Typography.Text className="truncate">
@ -58,12 +58,12 @@ const WorkflowElement = ({ node, disabled }: NodeProps) => {
}
case WorkflowNodeType.Apply: {
const config = (node.config as WorkflowNodeConfigAsApply) ?? {};
const config = (node.config as WorkflowNodeConfigForApply) ?? {};
return <Typography.Text className="truncate">{config.domains || " "}</Typography.Text>;
}
case WorkflowNodeType.Deploy: {
const config = (node.config as WorkflowNodeConfigAsDeploy) ?? {};
const config = (node.config as WorkflowNodeConfigForDeploy) ?? {};
const provider = deployProvidersMap.get(config.provider);
return (
<Space>
@ -74,7 +74,7 @@ const WorkflowElement = ({ node, disabled }: NodeProps) => {
}
case WorkflowNodeType.Notify: {
const config = (node.config as WorkflowNodeConfigAsNotify) ?? {};
const config = (node.config as WorkflowNodeConfigForNotify) ?? {};
const channel = notifyChannelsMap.get(config.channel as string);
return (
<div className="flex items-center justify-between space-x-2">

View File

@ -12,7 +12,7 @@ import MultipleInput from "@/components/MultipleInput";
import AccessEditModal from "@/components/access/AccessEditModal";
import AccessSelect from "@/components/access/AccessSelect";
import { ACCESS_USAGES, accessProvidersMap } from "@/domain/provider";
import { type WorkflowNode, type WorkflowNodeConfigAsApply } from "@/domain/workflow";
import { type WorkflowNode, type WorkflowNodeConfigForApply } from "@/domain/workflow";
import { useAntdForm, useZustandShallowSelector } from "@/hooks";
import { useAccessesStore } from "@/stores/access";
import { useContactEmailsStore } from "@/stores/contact";
@ -26,7 +26,7 @@ export type ApplyNodeFormProps = {
const MULTIPLE_INPUT_DELIMITER = ";";
const initFormModel = (): Partial<WorkflowNodeConfigAsApply> => {
const initFormModel = (): Partial<WorkflowNodeConfigForApply> => {
return {
keyAlgorithm: "RSA2048",
propagationTimeout: 60,
@ -76,7 +76,7 @@ const ApplyNodeForm = ({ node }: ApplyNodeFormProps) => {
formPending,
formProps,
} = useAntdForm<z.infer<typeof formSchema>>({
initialValues: (node?.config as WorkflowNodeConfigAsApply) ?? initFormModel(),
initialValues: (node?.config as WorkflowNodeConfigForApply) ?? initFormModel(),
onSubmit: async (values) => {
await formInst.validateFields();
await addEmail(values.contactEmail);
@ -85,7 +85,7 @@ const ApplyNodeForm = ({ node }: ApplyNodeFormProps) => {
draft.config = {
provider: accesses.find((e) => e.id === values.providerAccessId)?.provider,
...values,
} as WorkflowNodeConfigAsApply;
} as WorkflowNodeConfigForApply;
draft.validated = true;
})
);

View File

@ -12,7 +12,7 @@ import AccessSelect from "@/components/access/AccessSelect";
import DeployProviderPicker from "@/components/provider/DeployProviderPicker";
import DeployProviderSelect from "@/components/provider/DeployProviderSelect";
import { ACCESS_USAGES, DEPLOY_PROVIDERS, accessProvidersMap, deployProvidersMap } from "@/domain/provider";
import { type WorkflowNode, type WorkflowNodeConfigAsDeploy } from "@/domain/workflow";
import { type WorkflowNode, type WorkflowNodeConfigForDeploy } from "@/domain/workflow";
import { useAntdForm, useZustandShallowSelector } from "@/hooks";
import { useWorkflowStore } from "@/stores/workflow";
import { usePanel } from "../PanelProvider";
@ -44,7 +44,7 @@ export type DeployFormProps = {
node: WorkflowNode;
};
const initFormModel = (): Partial<WorkflowNodeConfigAsDeploy> => {
const initFormModel = (): Partial<WorkflowNodeConfigForDeploy> => {
return {};
};
@ -67,7 +67,7 @@ const DeployNodeForm = ({ node }: DeployFormProps) => {
formPending,
formProps,
} = useAntdForm<z.infer<typeof formSchema>>({
initialValues: (node?.config as WorkflowNodeConfigAsDeploy) ?? initFormModel(),
initialValues: (node?.config as WorkflowNodeConfigForDeploy) ?? initFormModel(),
onSubmit: async (values) => {
await formInst.validateFields();
await updateNode(

View File

@ -8,7 +8,7 @@ import { produce } from "immer";
import { z } from "zod";
import { notifyChannelsMap } from "@/domain/settings";
import { type WorkflowNode, type WorkflowNodeConfigAsNotify } from "@/domain/workflow";
import { type WorkflowNode, type WorkflowNodeConfigForNotify } from "@/domain/workflow";
import { useAntdForm, useZustandShallowSelector } from "@/hooks";
import { useNotifyChannelsStore } from "@/stores/notify";
import { useWorkflowStore } from "@/stores/workflow";
@ -18,7 +18,7 @@ export type NotifyNodeFormProps = {
node: WorkflowNode;
};
const initFormModel = (): Partial<WorkflowNodeConfigAsNotify> => {
const initFormModel = (): Partial<WorkflowNodeConfigForNotify> => {
return {
subject: "Completed!",
message: "Your workflow has been completed on Certimate.",
@ -57,7 +57,7 @@ const NotifyNodeForm = ({ node }: NotifyNodeFormProps) => {
formPending,
formProps,
} = useAntdForm<z.infer<typeof formSchema>>({
initialValues: (node?.config as WorkflowNodeConfigAsNotify) ?? initFormModel(),
initialValues: (node?.config as WorkflowNodeConfigForNotify) ?? initFormModel(),
onSubmit: async (values) => {
await formInst.validateFields();
await updateNode(

View File

@ -7,7 +7,7 @@ import { produce } from "immer";
import { z } from "zod";
import Show from "@/components/Show";
import { WORKFLOW_TRIGGERS, type WorkflowNode, type WorkflowNodeConfigAsStart } from "@/domain/workflow";
import { WORKFLOW_TRIGGERS, type WorkflowNode, type WorkflowNodeConfigForStart } from "@/domain/workflow";
import { useAntdForm, useZustandShallowSelector } from "@/hooks";
import { useWorkflowStore } from "@/stores/workflow";
import { getNextCronExecutions, validCronExpression } from "@/utils/cron";
@ -17,7 +17,7 @@ export type StartNodeFormProps = {
node: WorkflowNode;
};
const initFormModel = (): WorkflowNodeConfigAsStart => {
const initFormModel = (): WorkflowNodeConfigForStart => {
return {
trigger: WORKFLOW_TRIGGERS.AUTO,
triggerCron: "0 0 * * *",
@ -54,7 +54,7 @@ const StartNodeForm = ({ node }: StartNodeFormProps) => {
formPending,
formProps,
} = useAntdForm<z.infer<typeof formSchema>>({
initialValues: (node?.config as WorkflowNodeConfigAsStart) ?? initFormModel(),
initialValues: (node?.config as WorkflowNodeConfigForStart) ?? initFormModel(),
onSubmit: async (values) => {
await formInst.validateFields();
await updateNode(

View File

@ -1,6 +1,5 @@
import { type AccessUsageType } from "./provider";
// #region AccessModel
export interface AccessModel extends BaseModel {
name: string;
provider: string;
@ -9,106 +8,105 @@ export interface AccessModel extends BaseModel {
NOTICE: If you add new type, please keep ASCII order.
*/ Record<string, unknown> &
(
| ACMEHttpReqAccessConfig
| AliyunAccessConfig
| AWSAccessConfig
| BaiduCloudAccessConfig
| BytePlusAccessConfig
| CloudflareAccessConfig
| DogeCloudAccessConfig
| GoDaddyAccessConfig
| HuaweiCloudAccessConfig
| KubernetesAccessConfig
| LocalAccessConfig
| NameDotComAccessConfig
| NameSiloAccessConfig
| PowerDNSAccessConfig
| QiniuAccessConfig
| SSHAccessConfig
| TencentCloudAccessConfig
| VolcEngineAccessConfig
| WebhookAccessConfig
| AccessConfigForACMEHttpReq
| AccessConfigForAliyun
| AccessConfigForAWS
| AccessConfigForBaiduCloud
| AccessConfigForBytePlus
| AccessConfigForCloudflare
| AccessConfigForDogeCloud
| AccessConfigForGoDaddy
| AccessConfigForHuaweiCloud
| AccessConfigForKubernetes
| AccessConfigForLocal
| AccessConfigForNameDotCom
| AccessConfigForNameSilo
| AccessConfigForPowerDNS
| AccessConfigForQiniu
| AccessConfigForSSH
| AccessConfigForTencentCloud
| AccessConfigForVolcEngine
| AccessConfigForWebhook
);
usage: AccessUsageType;
}
// #endregion
// #region AccessConfig
export type ACMEHttpReqAccessConfig = {
export type AccessConfigForACMEHttpReq = {
endpoint: string;
mode?: string;
username?: string;
password?: string;
};
export type AliyunAccessConfig = {
export type AccessConfigForAliyun = {
accessKeyId: string;
accessKeySecret: string;
};
export type AWSAccessConfig = {
export type AccessConfigForAWS = {
accessKeyId: string;
secretAccessKey: string;
region?: string;
hostedZoneId?: string;
};
export type BaiduCloudAccessConfig = {
export type AccessConfigForBaiduCloud = {
accessKeyId: string;
secretAccessKey: string;
};
export type BytePlusAccessConfig = {
export type AccessConfigForBytePlus = {
accessKey: string;
secretKey: string;
};
export type CloudflareAccessConfig = {
export type AccessConfigForCloudflare = {
dnsApiToken: string;
};
export type DogeCloudAccessConfig = {
export type AccessConfigForDogeCloud = {
accessKey: string;
secretKey: string;
};
export type GoDaddyAccessConfig = {
export type AccessConfigForGoDaddy = {
apiKey: string;
apiSecret: string;
};
export type HuaweiCloudAccessConfig = {
export type AccessConfigForHuaweiCloud = {
accessKeyId: string;
secretAccessKey: string;
region?: string;
};
export type KubernetesAccessConfig = {
export type AccessConfigForKubernetes = {
kubeConfig?: string;
};
export type LocalAccessConfig = NonNullable<unknown>;
export type AccessConfigForLocal = NonNullable<unknown>;
export type NameDotComAccessConfig = {
export type AccessConfigForNameDotCom = {
username: string;
apiToken: string;
};
export type NameSiloAccessConfig = {
export type AccessConfigForNameSilo = {
apiKey: string;
};
export type PowerDNSAccessConfig = {
export type AccessConfigForPowerDNS = {
apiUrl: string;
apiKey: string;
};
export type QiniuAccessConfig = {
export type AccessConfigForQiniu = {
accessKey: string;
secretKey: string;
};
export type SSHAccessConfig = {
export type AccessConfigForSSH = {
host: string;
port: number;
username: string;
@ -117,17 +115,17 @@ export type SSHAccessConfig = {
keyPassphrase?: string;
};
export type TencentCloudAccessConfig = {
export type AccessConfigForTencentCloud = {
secretId: string;
secretKey: string;
};
export type VolcEngineAccessConfig = {
export type AccessConfigForVolcEngine = {
accessKeyId: string;
secretAccessKey: string;
};
export type WebhookAccessConfig = {
export type AccessConfigForWebhook = {
url: string;
};
// #endregion

View File

@ -95,12 +95,12 @@ export type WorkflowNode = {
validated?: boolean;
};
export type WorkflowNodeConfigAsStart = {
export type WorkflowNodeConfigForStart = {
trigger: string;
triggerCron?: string;
};
export type WorkflowNodeConfigAsApply = {
export type WorkflowNodeConfigForApply = {
domains: string;
contactEmail: string;
provider: string;
@ -111,22 +111,22 @@ export type WorkflowNodeConfigAsApply = {
disableFollowCNAME?: boolean;
};
export type WorkflowNodeConfigAsDeploy = {
export type WorkflowNodeConfigForDeploy = {
provider: string;
providerAccessId: string;
certificate: string;
[key: string]: unknown;
};
export type WorkflowNodeConfigAsNotify = {
export type WorkflowNodeConfigForNotify = {
channel: string;
subject: string;
message: string;
};
export type WorkflowNodeConfigAsBranch = never;
export type WorkflowNodeConfigForBranch = never;
export type WorkflowNodeConfigAsEnd = never;
export type WorkflowNodeConfigForEnd = never;
export type WorkflowNodeIO = {
name: string;
@ -403,7 +403,7 @@ export const isAllNodesValidated = (node: WorkflowNode): boolean => {
*/
export const getExecuteMethod = (node: WorkflowNode): { trigger: string; triggerCron: string } => {
if (node.type === WorkflowNodeType.Start) {
const config = node.config as WorkflowNodeConfigAsStart;
const config = node.config as WorkflowNodeConfigForStart;
return {
trigger: config.trigger ?? "",
triggerCron: config.triggerCron ?? "",