Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b91cbd67e | ||
|
|
9b5e1052a1 | ||
|
|
0d47d7cfd0 | ||
|
|
ef87975c80 | ||
|
|
9db757fbbb | ||
|
|
f6ef305441 | ||
|
|
004c6a8506 |
@@ -78,6 +78,7 @@ go run main.go serve
|
|||||||
| 腾讯云 | √ | √ | 可签发在腾讯云注册的域名;可部署到腾讯云 CDN |
|
| 腾讯云 | √ | √ | 可签发在腾讯云注册的域名;可部署到腾讯云 CDN |
|
||||||
| 华为云 | √ | | 可签发在华为云注册的域名 |
|
| 华为云 | √ | | 可签发在华为云注册的域名 |
|
||||||
| 七牛云 | | √ | 可部署到七牛云 CDN |
|
| 七牛云 | | √ | 可部署到七牛云 CDN |
|
||||||
|
| AWS | √ | | 可签发在 AWS Route53 托管的域名 |
|
||||||
| CloudFlare | √ | | 可签发在 CloudFlare 注册的域名;CloudFlare 服务自带 SSL 证书 |
|
| CloudFlare | √ | | 可签发在 CloudFlare 注册的域名;CloudFlare 服务自带 SSL 证书 |
|
||||||
| GoDaddy | √ | | 可签发在 GoDaddy 注册的域名 |
|
| GoDaddy | √ | | 可签发在 GoDaddy 注册的域名 |
|
||||||
| Namesilo | √ | | 可签发在 Namesilo 注册的域名 |
|
| Namesilo | √ | | 可签发在 Namesilo 注册的域名 |
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ password:1234567890
|
|||||||
| Tencent Cloud | √ | √ | Supports domains registered on Tencent Cloud; supports deployment to Tencent Cloud CDN |
|
| Tencent Cloud | √ | √ | Supports domains registered on Tencent Cloud; supports deployment to Tencent Cloud CDN |
|
||||||
| Huawei Cloud | √ | | Supports domains registered on Huawei Cloud |
|
| Huawei Cloud | √ | | Supports domains registered on Huawei Cloud |
|
||||||
| Qiniu Cloud | | √ | Supports deployment to Qiniu Cloud CDN |
|
| Qiniu Cloud | | √ | Supports deployment to Qiniu Cloud CDN |
|
||||||
|
| AWS | √ | | Supports domains managed on AWS Route53 |
|
||||||
| CloudFlare | √ | | Supports domains registered on CloudFlare; CloudFlare services come with SSL certificates |
|
| CloudFlare | √ | | Supports domains registered on CloudFlare; CloudFlare services come with SSL certificates |
|
||||||
| GoDaddy | √ | | Supports domains registered on GoDaddy |
|
| GoDaddy | √ | | Supports domains registered on GoDaddy |
|
||||||
| Namesilo | √ | | Supports domains registered on Namesilo |
|
| Namesilo | √ | | Supports domains registered on Namesilo |
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -29,7 +29,9 @@ require (
|
|||||||
github.com/alibabacloud-go/tea-fileform v1.1.1 // indirect
|
github.com/alibabacloud-go/tea-fileform v1.1.1 // indirect
|
||||||
github.com/alibabacloud-go/tea-oss-sdk v1.1.3 // indirect
|
github.com/alibabacloud-go/tea-oss-sdk v1.1.3 // indirect
|
||||||
github.com/alibabacloud-go/tea-oss-utils v1.1.0 // indirect
|
github.com/alibabacloud-go/tea-oss-utils v1.1.0 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/route53 v1.43.2 // indirect
|
||||||
github.com/blinkbean/dingtalk v1.1.3 // indirect
|
github.com/blinkbean/dingtalk v1.1.3 // indirect
|
||||||
|
github.com/go-lark/lark v1.14.1 // indirect
|
||||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect
|
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect
|
||||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.114 // indirect
|
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.114 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
|
|||||||
6
go.sum
6
go.sum
@@ -117,6 +117,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.19 h1:rfprUlsd
|
|||||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.19/go.mod h1:SCWkEdRq8/7EK60NcvvQ6NXKuTcchAD4ROAsC37VEZE=
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.19/go.mod h1:SCWkEdRq8/7EK60NcvvQ6NXKuTcchAD4ROAsC37VEZE=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.17 h1:u+EfGmksnJc/x5tq3A+OD7LrMbSSR/5TrKLvkdy/fhY=
|
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.17 h1:u+EfGmksnJc/x5tq3A+OD7LrMbSSR/5TrKLvkdy/fhY=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.17/go.mod h1:VaMx6302JHax2vHJWgRo+5n9zvbacs3bLU/23DNQrTY=
|
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.17/go.mod h1:VaMx6302JHax2vHJWgRo+5n9zvbacs3bLU/23DNQrTY=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/route53 v1.43.2 h1:957e1/SwXIfPi/0OUJkH9YnPZRe9G6Kisd/xUhF7AUE=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/route53 v1.43.2/go.mod h1:343vcjcyOTuHTBBgUrOxPM36/jE96qLZnGL447ldrB0=
|
||||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.61.2 h1:Kp6PWAlXwP1UvIflkIP6MFZYBNDCa4mFCGtxrpICVOg=
|
github.com/aws/aws-sdk-go-v2/service/s3 v1.61.2 h1:Kp6PWAlXwP1UvIflkIP6MFZYBNDCa4mFCGtxrpICVOg=
|
||||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.61.2/go.mod h1:5FmD/Dqq57gP+XwaUnd5WFPipAuzrf0HmupX27Gvjvc=
|
github.com/aws/aws-sdk-go-v2/service/s3 v1.61.2/go.mod h1:5FmD/Dqq57gP+XwaUnd5WFPipAuzrf0HmupX27Gvjvc=
|
||||||
github.com/aws/aws-sdk-go-v2/service/sso v1.22.7 h1:pIaGg+08llrP7Q5aiz9ICWbY8cqhTkyy+0SHvfzQpTc=
|
github.com/aws/aws-sdk-go-v2/service/sso v1.22.7 h1:pIaGg+08llrP7Q5aiz9ICWbY8cqhTkyy+0SHvfzQpTc=
|
||||||
@@ -178,6 +180,8 @@ github.com/go-acme/lego/v4 v4.19.2/go.mod h1:wtDe3dDkmV4/oI2nydpNXSJpvV10J9RCyZ6
|
|||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E=
|
github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E=
|
||||||
github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc=
|
github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc=
|
||||||
|
github.com/go-lark/lark v1.14.1 h1:qWYQTk6wLwf/08u8WbdNAHNmfqavdOvmsENlQ+Cb8aY=
|
||||||
|
github.com/go-lark/lark v1.14.1/go.mod h1:6ltbSztPZRT6IaO9ZIQyVaY5pVp/KeMizDYtfZkU+vM=
|
||||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
@@ -271,6 +275,8 @@ github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHW
|
|||||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||||
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak=
|
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak=
|
||||||
|
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
||||||
|
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||||
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible h1:jdpOPRN1zP63Td1hDQbZW73xKmzDvZHzVdNYxhnTMDA=
|
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible h1:jdpOPRN1zP63Td1hDQbZW73xKmzDvZHzVdNYxhnTMDA=
|
||||||
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A=
|
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A=
|
||||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package applicant
|
package applicant
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"certimate/internal/domain"
|
||||||
|
"certimate/internal/utils/app"
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
@@ -16,15 +18,13 @@ import (
|
|||||||
"github.com/go-acme/lego/v4/lego"
|
"github.com/go-acme/lego/v4/lego"
|
||||||
"github.com/go-acme/lego/v4/registration"
|
"github.com/go-acme/lego/v4/registration"
|
||||||
"github.com/pocketbase/pocketbase/models"
|
"github.com/pocketbase/pocketbase/models"
|
||||||
|
|
||||||
"certimate/internal/domain"
|
|
||||||
"certimate/internal/utils/app"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
configTypeAliyun = "aliyun"
|
configTypeAliyun = "aliyun"
|
||||||
configTypeTencent = "tencent"
|
configTypeTencent = "tencent"
|
||||||
configTypeHuaweicloud = "huaweicloud"
|
configTypeHuaweicloud = "huaweicloud"
|
||||||
|
configTypeAws = "aws"
|
||||||
configTypeCloudflare = "cloudflare"
|
configTypeCloudflare = "cloudflare"
|
||||||
configTypeNamesilo = "namesilo"
|
configTypeNamesilo = "namesilo"
|
||||||
configTypeGodaddy = "godaddy"
|
configTypeGodaddy = "godaddy"
|
||||||
@@ -127,6 +127,8 @@ func Get(record *models.Record) (Applicant, error) {
|
|||||||
return NewTencent(option), nil
|
return NewTencent(option), nil
|
||||||
case configTypeHuaweicloud:
|
case configTypeHuaweicloud:
|
||||||
return NewHuaweiCloud(option), nil
|
return NewHuaweiCloud(option), nil
|
||||||
|
case configTypeAws:
|
||||||
|
return NewAws(option), nil
|
||||||
case configTypeCloudflare:
|
case configTypeCloudflare:
|
||||||
return NewCloudflare(option), nil
|
return NewCloudflare(option), nil
|
||||||
case configTypeNamesilo:
|
case configTypeNamesilo:
|
||||||
|
|||||||
38
internal/applicant/aws.go
Normal file
38
internal/applicant/aws.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package applicant
|
||||||
|
|
||||||
|
import (
|
||||||
|
"certimate/internal/domain"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/route53"
|
||||||
|
)
|
||||||
|
|
||||||
|
type aws struct {
|
||||||
|
option *ApplyOption
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAws(option *ApplyOption) Applicant {
|
||||||
|
return &aws{
|
||||||
|
option: option,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *aws) Apply() (*Certificate, error) {
|
||||||
|
access := &domain.AwsAccess{}
|
||||||
|
json.Unmarshal([]byte(t.option.Access), access)
|
||||||
|
|
||||||
|
os.Setenv("AWS_REGION", access.Region)
|
||||||
|
os.Setenv("AWS_ACCESS_KEY_ID", access.AccessKeyId)
|
||||||
|
os.Setenv("AWS_SECRET_ACCESS_KEY", access.SecretAccessKey)
|
||||||
|
os.Setenv("AWS_HOSTED_ZONE_ID", access.HostedZoneId)
|
||||||
|
os.Setenv("AWS_PROPAGATION_TIMEOUT", fmt.Sprintf("%d", t.option.Timeout))
|
||||||
|
|
||||||
|
dnsProvider, err := route53.NewDNSProvider()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return apply(t.option, dnsProvider)
|
||||||
|
}
|
||||||
@@ -16,6 +16,13 @@ type HuaweiCloudAccess struct {
|
|||||||
SecretAccessKey string `json:"secretAccessKey"`
|
SecretAccessKey string `json:"secretAccessKey"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AwsAccess struct {
|
||||||
|
Region string `json:"region"`
|
||||||
|
AccessKeyId string `json:"accessKeyId"`
|
||||||
|
SecretAccessKey string `json:"secretAccessKey"`
|
||||||
|
HostedZoneId string `json:"hostedZoneId"`
|
||||||
|
}
|
||||||
|
|
||||||
type CloudflareAccess struct {
|
type CloudflareAccess struct {
|
||||||
DnsApiToken string `json:"dnsApiToken"`
|
DnsApiToken string `json:"dnsApiToken"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package notify
|
package notify
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"certimate/internal/utils/app"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -8,15 +9,15 @@ import (
|
|||||||
notifyPackage "github.com/nikoksr/notify"
|
notifyPackage "github.com/nikoksr/notify"
|
||||||
"github.com/nikoksr/notify/service/dingding"
|
"github.com/nikoksr/notify/service/dingding"
|
||||||
"github.com/nikoksr/notify/service/http"
|
"github.com/nikoksr/notify/service/http"
|
||||||
|
"github.com/nikoksr/notify/service/lark"
|
||||||
"github.com/nikoksr/notify/service/telegram"
|
"github.com/nikoksr/notify/service/telegram"
|
||||||
|
|
||||||
"certimate/internal/utils/app"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
notifyChannelDingtalk = "dingtalk"
|
notifyChannelDingtalk = "dingtalk"
|
||||||
notifyChannelWebhook = "webhook"
|
notifyChannelWebhook = "webhook"
|
||||||
notifyChannelTelegram = "telegram"
|
notifyChannelTelegram = "telegram"
|
||||||
|
notifyChannelLark = "lark"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Send(title, content string) error {
|
func Send(title, content string) error {
|
||||||
@@ -67,6 +68,8 @@ func getNotifiers() ([]notifyPackage.Notifier, error) {
|
|||||||
notifiers = append(notifiers, temp)
|
notifiers = append(notifiers, temp)
|
||||||
case notifyChannelDingtalk:
|
case notifyChannelDingtalk:
|
||||||
notifiers = append(notifiers, getDingTalkNotifier(v))
|
notifiers = append(notifiers, getDingTalkNotifier(v))
|
||||||
|
case notifyChannelLark:
|
||||||
|
notifiers = append(notifiers, getLarkNotifier(v))
|
||||||
case notifyChannelWebhook:
|
case notifyChannelWebhook:
|
||||||
notifiers = append(notifiers, getWebhookNotifier(v))
|
notifiers = append(notifiers, getWebhookNotifier(v))
|
||||||
}
|
}
|
||||||
@@ -108,6 +111,10 @@ func getDingTalkNotifier(conf map[string]any) notifyPackage.Notifier {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getLarkNotifier(conf map[string]any) notifyPackage.Notifier {
|
||||||
|
return lark.NewWebhookService(getString(conf, "webhookUrl"))
|
||||||
|
}
|
||||||
|
|
||||||
func getString(conf map[string]any, key string) string {
|
func getString(conf map[string]any, key string) string {
|
||||||
if _, ok := conf[key]; !ok {
|
if _, ok := conf[key]; !ok {
|
||||||
return ""
|
return ""
|
||||||
|
|||||||
93
migrations/1729160433_updated_access.go
Normal file
93
migrations/1729160433_updated_access.go
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
package migrations
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/pocketbase/dbx"
|
||||||
|
"github.com/pocketbase/pocketbase/daos"
|
||||||
|
m "github.com/pocketbase/pocketbase/migrations"
|
||||||
|
"github.com/pocketbase/pocketbase/models/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
m.Register(func(db dbx.Builder) error {
|
||||||
|
dao := daos.New(db);
|
||||||
|
|
||||||
|
collection, err := dao.FindCollectionByNameOrId("4yzbv8urny5ja1e")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// update
|
||||||
|
edit_configType := &schema.SchemaField{}
|
||||||
|
if err := json.Unmarshal([]byte(`{
|
||||||
|
"system": false,
|
||||||
|
"id": "hwy7m03o",
|
||||||
|
"name": "configType",
|
||||||
|
"type": "select",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"maxSelect": 1,
|
||||||
|
"values": [
|
||||||
|
"aliyun",
|
||||||
|
"tencent",
|
||||||
|
"huaweicloud",
|
||||||
|
"qiniu",
|
||||||
|
"aws",
|
||||||
|
"cloudflare",
|
||||||
|
"namesilo",
|
||||||
|
"godaddy",
|
||||||
|
"local",
|
||||||
|
"ssh",
|
||||||
|
"webhook"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}`), edit_configType); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
collection.Schema.AddField(edit_configType)
|
||||||
|
|
||||||
|
return dao.SaveCollection(collection)
|
||||||
|
}, func(db dbx.Builder) error {
|
||||||
|
dao := daos.New(db);
|
||||||
|
|
||||||
|
collection, err := dao.FindCollectionByNameOrId("4yzbv8urny5ja1e")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// update
|
||||||
|
edit_configType := &schema.SchemaField{}
|
||||||
|
if err := json.Unmarshal([]byte(`{
|
||||||
|
"system": false,
|
||||||
|
"id": "hwy7m03o",
|
||||||
|
"name": "configType",
|
||||||
|
"type": "select",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"maxSelect": 1,
|
||||||
|
"values": [
|
||||||
|
"aliyun",
|
||||||
|
"tencent",
|
||||||
|
"huaweicloud",
|
||||||
|
"qiniu",
|
||||||
|
"cloudflare",
|
||||||
|
"namesilo",
|
||||||
|
"godaddy",
|
||||||
|
"local",
|
||||||
|
"ssh",
|
||||||
|
"webhook"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}`), edit_configType); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
collection.Schema.AddField(edit_configType)
|
||||||
|
|
||||||
|
return dao.SaveCollection(collection)
|
||||||
|
})
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
2
ui/dist/imgs/providers/aliyun.svg
vendored
2
ui/dist/imgs/providers/aliyun.svg
vendored
@@ -1 +1 @@
|
|||||||
<svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9731" width="64" height="64" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M1020.586667 361.813333c0-92.16-75.093333-167.253333-167.253334-167.253333h-266.24l23.893334 95.573333 228.693333 51.2c20.48 3.413333 37.546667 23.893333 37.546667 44.373334v245.76c0 20.48-17.066667 40.96-37.546667 44.373333l-228.693333 51.2-27.306667 92.16h266.24c92.16 0 167.253333-75.093333 167.253333-167.253333 3.413333 0 3.413333-290.133333 3.413334-290.133334zM187.733333 672.426667c-20.48-3.413333-37.546667-23.893333-37.546666-44.373334v-245.76c0-20.48 17.066667-40.96 37.546666-44.373333l228.693334-51.2 23.893333-95.573333H174.08C81.92 191.146667 6.826667 266.24 6.826667 358.4V648.533333c0 92.16 75.093333 167.253333 167.253333 167.253334h266.24l-23.893333-95.573334c0 3.413333-228.693333-47.786667-228.693334-47.786666z m215.04-211.626667h218.453334v88.746667h-218.453334v-88.746667z" fill="#ff6b01" p-id="9732"></path></svg>
|
<svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5262" width="200" height="200"><path d="M512 64a448 448 0 1 1 0 896A448 448 0 0 1 512 64z" fill="#FF6A00" p-id="5263"></path><path d="M324.8 602.624a26.752 26.752 0 0 1-21.312-25.92v-142.72a27.712 27.712 0 0 1 21.376-25.984l132.416-28.672 13.952-56.896H317.312a97.6 97.6 0 0 0-98.24 96.96v169.344c0.384 54.08 44.16 97.856 98.24 98.176h153.92l-13.888-56.512-132.544-27.776zM710.4 322.432c54.016 0.128 97.92 43.584 98.56 97.6v170.176a98.368 98.368 0 0 1-98.56 98.048H555.328l14.08-56.832 132.608-28.736a27.84 27.84 0 0 0 21.376-25.92v-142.72a26.88 26.88 0 0 0-21.376-25.984l-132.544-28.8-14.08-56.832zM570.368 497.92v13.952H457.28v-13.952h113.088z" fill="#FFFFFF" p-id="5264"></path></svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1017 B After Width: | Height: | Size: 785 B |
1
ui/dist/imgs/providers/aws.svg
vendored
Normal file
1
ui/dist/imgs/providers/aws.svg
vendored
Normal file
File diff suppressed because one or more lines are too long
2
ui/dist/index.html
vendored
2
ui/dist/index.html
vendored
@@ -5,7 +5,7 @@
|
|||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Certimate - Your Trusted SSL Automation Partner</title>
|
<title>Certimate - Your Trusted SSL Automation Partner</title>
|
||||||
<script type="module" crossorigin src="/assets/index-BTjl7ZFn.js"></script>
|
<script type="module" crossorigin src="/assets/index-j5PIjQ7r.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-YqBWA4KK.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-YqBWA4KK.css">
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-background">
|
<body class="bg-background">
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9731" width="64" height="64" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M1020.586667 361.813333c0-92.16-75.093333-167.253333-167.253334-167.253333h-266.24l23.893334 95.573333 228.693333 51.2c20.48 3.413333 37.546667 23.893333 37.546667 44.373334v245.76c0 20.48-17.066667 40.96-37.546667 44.373333l-228.693333 51.2-27.306667 92.16h266.24c92.16 0 167.253333-75.093333 167.253333-167.253333 3.413333 0 3.413333-290.133333 3.413334-290.133334zM187.733333 672.426667c-20.48-3.413333-37.546667-23.893333-37.546666-44.373334v-245.76c0-20.48 17.066667-40.96 37.546666-44.373333l228.693334-51.2 23.893333-95.573333H174.08C81.92 191.146667 6.826667 266.24 6.826667 358.4V648.533333c0 92.16 75.093333 167.253333 167.253333 167.253334h266.24l-23.893333-95.573334c0 3.413333-228.693333-47.786667-228.693334-47.786666z m215.04-211.626667h218.453334v88.746667h-218.453334v-88.746667z" fill="#ff6b01" p-id="9732"></path></svg>
|
<svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5262" width="200" height="200"><path d="M512 64a448 448 0 1 1 0 896A448 448 0 0 1 512 64z" fill="#FF6A00" p-id="5263"></path><path d="M324.8 602.624a26.752 26.752 0 0 1-21.312-25.92v-142.72a27.712 27.712 0 0 1 21.376-25.984l132.416-28.672 13.952-56.896H317.312a97.6 97.6 0 0 0-98.24 96.96v169.344c0.384 54.08 44.16 97.856 98.24 98.176h153.92l-13.888-56.512-132.544-27.776zM710.4 322.432c54.016 0.128 97.92 43.584 98.56 97.6v170.176a98.368 98.368 0 0 1-98.56 98.048H555.328l14.08-56.832 132.608-28.736a27.84 27.84 0 0 0 21.376-25.92v-142.72a26.88 26.88 0 0 0-21.376-25.984l-132.544-28.8-14.08-56.832zM570.368 497.92v13.952H457.28v-13.952h113.088z" fill="#FFFFFF" p-id="5264"></path></svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1017 B After Width: | Height: | Size: 785 B |
1
ui/public/imgs/providers/aws.svg
Normal file
1
ui/public/imgs/providers/aws.svg
Normal file
File diff suppressed because one or more lines are too long
240
ui/src/components/certimate/AccessAwsForm.tsx
Normal file
240
ui/src/components/certimate/AccessAwsForm.tsx
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import z from "zod";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import { ClientResponseError } from "pocketbase";
|
||||||
|
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { PbErrorData } from "@/domain/base";
|
||||||
|
import { Access, accessFormType, AwsConfig, getUsageByConfigType } from "@/domain/access";
|
||||||
|
import { save } from "@/repository/access";
|
||||||
|
import { useConfig } from "@/providers/config";
|
||||||
|
|
||||||
|
type AccessAwsFormProps = {
|
||||||
|
op: "add" | "edit" | "copy";
|
||||||
|
data?: Access;
|
||||||
|
onAfterReq: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const AccessAwsForm = ({ data, op, onAfterReq }: AccessAwsFormProps) => {
|
||||||
|
const { addAccess, updateAccess } = useConfig();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const formSchema = z.object({
|
||||||
|
id: z.string().optional(),
|
||||||
|
name: z
|
||||||
|
.string()
|
||||||
|
.min(1, "access.authorization.form.name.placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
|
configType: accessFormType,
|
||||||
|
region: z
|
||||||
|
.string()
|
||||||
|
.min(1, "access.authorization.form.region.placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
|
accessKeyId: z
|
||||||
|
.string()
|
||||||
|
.min(1, "access.authorization.form.access_key_id.placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
|
secretAccessKey: z
|
||||||
|
.string()
|
||||||
|
.min(1, "access.authorization.form.secret_access_key.placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
|
hostedZoneId: z
|
||||||
|
.string()
|
||||||
|
.min(0, "access.authorization.form.aws_hosted_zone_id.placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
|
});
|
||||||
|
|
||||||
|
let config: AwsConfig = {
|
||||||
|
region: "cn-north-1",
|
||||||
|
accessKeyId: "",
|
||||||
|
secretAccessKey: "",
|
||||||
|
hostedZoneId: "",
|
||||||
|
};
|
||||||
|
if (data) config = data.config as AwsConfig;
|
||||||
|
|
||||||
|
const form = useForm<z.infer<typeof formSchema>>({
|
||||||
|
resolver: zodResolver(formSchema),
|
||||||
|
defaultValues: {
|
||||||
|
id: data?.id,
|
||||||
|
name: data?.name || "",
|
||||||
|
configType: "aws",
|
||||||
|
region: config.region,
|
||||||
|
accessKeyId: config.accessKeyId,
|
||||||
|
secretAccessKey: config.secretAccessKey,
|
||||||
|
hostedZoneId: config.hostedZoneId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = async (data: z.infer<typeof formSchema>) => {
|
||||||
|
const req: Access = {
|
||||||
|
id: data.id as string,
|
||||||
|
name: data.name,
|
||||||
|
configType: data.configType,
|
||||||
|
usage: getUsageByConfigType(data.configType),
|
||||||
|
config: {
|
||||||
|
region: data.region,
|
||||||
|
accessKeyId: data.accessKeyId,
|
||||||
|
secretAccessKey: data.secretAccessKey,
|
||||||
|
hostedZoneId: data.hostedZoneId,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
req.id = op == "copy" ? "" : req.id;
|
||||||
|
const rs = await save(req);
|
||||||
|
|
||||||
|
onAfterReq();
|
||||||
|
|
||||||
|
req.id = rs.id;
|
||||||
|
req.created = rs.created;
|
||||||
|
req.updated = rs.updated;
|
||||||
|
if (data.id && op == "edit") {
|
||||||
|
updateAccess(req);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addAccess(req);
|
||||||
|
} catch (e) {
|
||||||
|
const err = e as ClientResponseError;
|
||||||
|
|
||||||
|
Object.entries(err.response.data as PbErrorData).forEach(([key, value]) => {
|
||||||
|
form.setError(key as keyof z.infer<typeof formSchema>, {
|
||||||
|
type: "manual",
|
||||||
|
message: value.message,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="max-w-[35em] mx-auto mt-10">
|
||||||
|
<Form {...form}>
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
form.handleSubmit(onSubmit)(e);
|
||||||
|
}}
|
||||||
|
className="space-y-8"
|
||||||
|
>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="name"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("access.authorization.form.name.label")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input placeholder={t("access.authorization.form.name.placeholder")} {...field} />
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="id"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem className="hidden">
|
||||||
|
<FormLabel>{t("access.authorization.form.config.label")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input {...field} />
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="configType"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem className="hidden">
|
||||||
|
<FormLabel>{t("access.authorization.form.config.label")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input {...field} />
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="region"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("access.authorization.form.region.label")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input placeholder={t("access.authorization.form.region.placeholder")} {...field} />
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="accessKeyId"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("access.authorization.form.access_key_id.label")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input placeholder={t("access.authorization.form.access_key_id.placeholder")} {...field} />
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="secretAccessKey"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("access.authorization.form.secret_access_key.label")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input placeholder={t("access.authorization.form.secret_access_key.placeholder")} {...field} />
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="hostedZoneId"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("access.authorization.form.aws_hosted_zone_id.label")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input placeholder={t("access.authorization.form.aws_hosted_zone_id.placeholder")} {...field} />
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
|
||||||
|
<div className="flex justify-end">
|
||||||
|
<Button type="submit">{t("common.save")}</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AccessAwsForm;
|
||||||
@@ -10,6 +10,7 @@ import AccessAliyunForm from "./AccessAliyunForm";
|
|||||||
import AccessTencentForm from "./AccessTencentForm";
|
import AccessTencentForm from "./AccessTencentForm";
|
||||||
import AccessHuaweicloudForm from "./AccessHuaweicloudForm";
|
import AccessHuaweicloudForm from "./AccessHuaweicloudForm";
|
||||||
import AccessQiniuForm from "./AccessQiniuForm";
|
import AccessQiniuForm from "./AccessQiniuForm";
|
||||||
|
import AccessAwsForm from "./AccessAwsForm";
|
||||||
import AccessCloudflareForm from "./AccessCloudflareForm";
|
import AccessCloudflareForm from "./AccessCloudflareForm";
|
||||||
import AccessNamesiloForm from "./AccessNamesiloForm";
|
import AccessNamesiloForm from "./AccessNamesiloForm";
|
||||||
import AccessGodaddyForm from "./AccessGodaddyForm";
|
import AccessGodaddyForm from "./AccessGodaddyForm";
|
||||||
@@ -79,6 +80,17 @@ const AccessEdit = ({ trigger, op, data, className }: AccessEditProps) => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case "aws":
|
||||||
|
form = (
|
||||||
|
<AccessAwsForm
|
||||||
|
data={data}
|
||||||
|
op={op}
|
||||||
|
onAfterReq={() => {
|
||||||
|
setOpen(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
break;
|
||||||
case "cloudflare":
|
case "cloudflare":
|
||||||
form = (
|
form = (
|
||||||
<AccessCloudflareForm
|
<AccessCloudflareForm
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ const AccessHuaweicloudForm = ({ data, op, onAfterReq }: AccessHuaweicloudFormPr
|
|||||||
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
secretAccessKey: z
|
secretAccessKey: z
|
||||||
.string()
|
.string()
|
||||||
.min(1, "access.authorization.form.access_key_secret.placeholder")
|
.min(1, "access.authorization.form.secret_access_key.placeholder")
|
||||||
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -193,9 +193,9 @@ const AccessHuaweicloudForm = ({ data, op, onAfterReq }: AccessHuaweicloudFormPr
|
|||||||
name="secretAccessKey"
|
name="secretAccessKey"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t("access.authorization.form.access_key_secret.label")}</FormLabel>
|
<FormLabel>{t("access.authorization.form.secret_access_key.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t("access.authorization.form.access_key_secret.placeholder")} {...field} />
|
<Input placeholder={t("access.authorization.form.secret_access_key.placeholder")} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
|||||||
136
ui/src/components/notify/Lark.tsx
Normal file
136
ui/src/components/notify/Lark.tsx
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
import { Input } from "../ui/input";
|
||||||
|
import { Button } from "../ui/button";
|
||||||
|
import { Switch } from "../ui/switch";
|
||||||
|
import { Label } from "../ui/label";
|
||||||
|
import { useNotify } from "@/providers/notify";
|
||||||
|
import { NotifyChannelLark, NotifyChannels } from "@/domain/settings";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { update } from "@/repository/settings";
|
||||||
|
import { getErrMessage } from "@/lib/error";
|
||||||
|
import { useToast } from "../ui/use-toast";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
type LarkSetting = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
data: NotifyChannelLark;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Lark = () => {
|
||||||
|
const { config, setChannels } = useNotify();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const [lark, setLark] = useState<LarkSetting>({
|
||||||
|
id: config.id ?? "",
|
||||||
|
name: "notifyChannels",
|
||||||
|
data: {
|
||||||
|
webhookUrl: "",
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const getDetailLark = () => {
|
||||||
|
const df: NotifyChannelLark = {
|
||||||
|
webhookUrl: "",
|
||||||
|
enabled: false,
|
||||||
|
};
|
||||||
|
if (!config.content) {
|
||||||
|
return df;
|
||||||
|
}
|
||||||
|
const chanels = config.content as NotifyChannels;
|
||||||
|
if (!chanels.lark) {
|
||||||
|
return df;
|
||||||
|
}
|
||||||
|
|
||||||
|
return chanels.lark as NotifyChannelLark;
|
||||||
|
};
|
||||||
|
const data = getDetailLark();
|
||||||
|
setLark({
|
||||||
|
id: config.id ?? "",
|
||||||
|
name: "lark",
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
}, [config]);
|
||||||
|
|
||||||
|
const { toast } = useToast();
|
||||||
|
|
||||||
|
const handleSaveClick = async () => {
|
||||||
|
try {
|
||||||
|
const resp = await update({
|
||||||
|
...config,
|
||||||
|
name: "notifyChannels",
|
||||||
|
content: {
|
||||||
|
...config.content,
|
||||||
|
lark: {
|
||||||
|
...lark.data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
setChannels(resp);
|
||||||
|
toast({
|
||||||
|
title: t("common.save.succeeded.message"),
|
||||||
|
description: t("settings.notification.config.saved.message"),
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
const msg = getErrMessage(e);
|
||||||
|
|
||||||
|
toast({
|
||||||
|
title: t("common.save.failed.message"),
|
||||||
|
description: `${t(
|
||||||
|
"settings.notification.config.failed.message"
|
||||||
|
)}: ${msg}`,
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Input
|
||||||
|
placeholder="Webhook Url"
|
||||||
|
value={lark.data.webhookUrl}
|
||||||
|
onChange={(e) => {
|
||||||
|
setLark({
|
||||||
|
...lark,
|
||||||
|
data: {
|
||||||
|
...lark.data,
|
||||||
|
webhookUrl: e.target.value,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="flex items-center space-x-1 mt-2">
|
||||||
|
<Switch
|
||||||
|
id="airplane-mode"
|
||||||
|
checked={lark.data.enabled}
|
||||||
|
onCheckedChange={() => {
|
||||||
|
setLark({
|
||||||
|
...lark,
|
||||||
|
data: {
|
||||||
|
...lark.data,
|
||||||
|
enabled: !lark.data.enabled,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Label htmlFor="airplane-mode">
|
||||||
|
{t("settings.notification.config.enable")}
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex justify-end mt-2">
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
handleSaveClick();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("common.save")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Lark;
|
||||||
@@ -5,6 +5,7 @@ export const accessTypeMap: Map<string, [string, string]> = new Map([
|
|||||||
["tencent", ["common.provider.tencent", "/imgs/providers/tencent.svg"]],
|
["tencent", ["common.provider.tencent", "/imgs/providers/tencent.svg"]],
|
||||||
["huaweicloud", ["common.provider.huaweicloud", "/imgs/providers/huaweicloud.svg"]],
|
["huaweicloud", ["common.provider.huaweicloud", "/imgs/providers/huaweicloud.svg"]],
|
||||||
["qiniu", ["common.provider.qiniu", "/imgs/providers/qiniu.svg"]],
|
["qiniu", ["common.provider.qiniu", "/imgs/providers/qiniu.svg"]],
|
||||||
|
["aws", ["common.provider.aws", "/imgs/providers/aws.svg"]],
|
||||||
["cloudflare", ["common.provider.cloudflare", "/imgs/providers/cloudflare.svg"]],
|
["cloudflare", ["common.provider.cloudflare", "/imgs/providers/cloudflare.svg"]],
|
||||||
["namesilo", ["common.provider.namesilo", "/imgs/providers/namesilo.svg"]],
|
["namesilo", ["common.provider.namesilo", "/imgs/providers/namesilo.svg"]],
|
||||||
["godaddy", ["common.provider.godaddy", "/imgs/providers/godaddy.svg"]],
|
["godaddy", ["common.provider.godaddy", "/imgs/providers/godaddy.svg"]],
|
||||||
@@ -23,6 +24,7 @@ export const accessFormType = z.union(
|
|||||||
z.literal("tencent"),
|
z.literal("tencent"),
|
||||||
z.literal("huaweicloud"),
|
z.literal("huaweicloud"),
|
||||||
z.literal("qiniu"),
|
z.literal("qiniu"),
|
||||||
|
z.literal("aws"),
|
||||||
z.literal("cloudflare"),
|
z.literal("cloudflare"),
|
||||||
z.literal("namesilo"),
|
z.literal("namesilo"),
|
||||||
z.literal("godaddy"),
|
z.literal("godaddy"),
|
||||||
@@ -46,6 +48,7 @@ export type Access = {
|
|||||||
| TencentConfig
|
| TencentConfig
|
||||||
| HuaweicloudConfig
|
| HuaweicloudConfig
|
||||||
| QiniuConfig
|
| QiniuConfig
|
||||||
|
| AwsConfig
|
||||||
| CloudflareConfig
|
| CloudflareConfig
|
||||||
| NamesiloConfig
|
| NamesiloConfig
|
||||||
| GodaddyConfig
|
| GodaddyConfig
|
||||||
@@ -78,6 +81,13 @@ export type QiniuConfig = {
|
|||||||
secretKey: string;
|
secretKey: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type AwsConfig = {
|
||||||
|
region: string;
|
||||||
|
accessKeyId: string;
|
||||||
|
secretAccessKey: string;
|
||||||
|
hostedZoneId?: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type CloudflareConfig = {
|
export type CloudflareConfig = {
|
||||||
dnsApiToken: string;
|
dnsApiToken: string;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,11 +19,12 @@ export type NotifyTemplate = {
|
|||||||
|
|
||||||
export type NotifyChannels = {
|
export type NotifyChannels = {
|
||||||
dingtalk?: NotifyChannel;
|
dingtalk?: NotifyChannel;
|
||||||
|
lark?: NotifyChannel;
|
||||||
telegram?: NotifyChannel;
|
telegram?: NotifyChannel;
|
||||||
webhook?: NotifyChannel;
|
webhook?: NotifyChannel;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type NotifyChannel = NotifyChannelDingTalk | NotifyChannelTelegram | NotifyChannelWebhook;
|
export type NotifyChannel = NotifyChannelDingTalk | NotifyChannelLark | NotifyChannelTelegram | NotifyChannelWebhook;
|
||||||
|
|
||||||
export type NotifyChannelDingTalk = {
|
export type NotifyChannelDingTalk = {
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
@@ -31,6 +32,11 @@ export type NotifyChannelDingTalk = {
|
|||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type NotifyChannelLark = {
|
||||||
|
webhookUrl: string;
|
||||||
|
enabled: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export type NotifyChannelTelegram = {
|
export type NotifyChannelTelegram = {
|
||||||
apiToken: string;
|
apiToken: string;
|
||||||
chatId: string;
|
chatId: string;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export const version = "Certimate v0.2.2";
|
export const version = "Certimate v0.2.3";
|
||||||
|
|||||||
@@ -28,6 +28,10 @@
|
|||||||
"access.authorization.form.secret_id.placeholder": "Please enter SecretId",
|
"access.authorization.form.secret_id.placeholder": "Please enter SecretId",
|
||||||
"access.authorization.form.secret_key.label": "SecretKey",
|
"access.authorization.form.secret_key.label": "SecretKey",
|
||||||
"access.authorization.form.secret_key.placeholder": "Please enter SecretKey",
|
"access.authorization.form.secret_key.placeholder": "Please enter SecretKey",
|
||||||
|
"access.authorization.form.secret_access_key.label": "SecretAccessKey",
|
||||||
|
"access.authorization.form.secret_access_key.placeholder": "Please enter SecretAccessKey",
|
||||||
|
"access.authorization.form.aws_hosted_zone_id.label": "AWS Hosted Zone ID",
|
||||||
|
"access.authorization.form.aws_hosted_zone_id.placeholder": "Please enter AWS Hosted Zone ID",
|
||||||
"access.authorization.form.cloud_dns_api_token.label": "CLOUD_DNS_API_TOKEN",
|
"access.authorization.form.cloud_dns_api_token.label": "CLOUD_DNS_API_TOKEN",
|
||||||
"access.authorization.form.cloud_dns_api_token.placeholder": "Please enter CLOUD_DNS_API_TOKEN",
|
"access.authorization.form.cloud_dns_api_token.placeholder": "Please enter CLOUD_DNS_API_TOKEN",
|
||||||
"access.authorization.form.godaddy_api_key.label": "GO_DADDY_API_KEY",
|
"access.authorization.form.godaddy_api_key.label": "GO_DADDY_API_KEY",
|
||||||
|
|||||||
@@ -61,6 +61,7 @@
|
|||||||
"common.provider.huaweicloud": "Huawei Cloud",
|
"common.provider.huaweicloud": "Huawei Cloud",
|
||||||
"common.provider.qiniu": "Qiniu",
|
"common.provider.qiniu": "Qiniu",
|
||||||
"common.provider.qiniu.cdn": "Qiniu - CDN",
|
"common.provider.qiniu.cdn": "Qiniu - CDN",
|
||||||
|
"common.provider.aws": "AWS",
|
||||||
"common.provider.cloudflare": "Cloudflare",
|
"common.provider.cloudflare": "Cloudflare",
|
||||||
"common.provider.namesilo": "Namesilo",
|
"common.provider.namesilo": "Namesilo",
|
||||||
"common.provider.godaddy": "GoDaddy",
|
"common.provider.godaddy": "GoDaddy",
|
||||||
@@ -68,5 +69,6 @@
|
|||||||
"common.provider.ssh": "SSH Deployment",
|
"common.provider.ssh": "SSH Deployment",
|
||||||
"common.provider.webhook": "Webhook",
|
"common.provider.webhook": "Webhook",
|
||||||
"common.provider.dingtalk": "DingTalk",
|
"common.provider.dingtalk": "DingTalk",
|
||||||
"common.provider.telegram": "Telegram"
|
"common.provider.telegram": "Telegram",
|
||||||
|
"common.provider.lark": "Lark"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,10 @@
|
|||||||
"access.authorization.form.secret_id.placeholder": "请输入 SecretId",
|
"access.authorization.form.secret_id.placeholder": "请输入 SecretId",
|
||||||
"access.authorization.form.secret_key.label": "SecretKey",
|
"access.authorization.form.secret_key.label": "SecretKey",
|
||||||
"access.authorization.form.secret_key.placeholder": "请输入 SecretKey",
|
"access.authorization.form.secret_key.placeholder": "请输入 SecretKey",
|
||||||
|
"access.authorization.form.secret_access_key.label": "SecretAccessKey",
|
||||||
|
"access.authorization.form.secret_access_key.placeholder": "请输入 SecretAccessKey",
|
||||||
|
"access.authorization.form.aws_hosted_zone_id.label": "AWS 托管区域 ID",
|
||||||
|
"access.authorization.form.aws_hosted_zone_id.placeholder": "请输入 AWS Hosted Zone ID",
|
||||||
"access.authorization.form.cloud_dns_api_token.label": "CLOUD_DNS_API_TOKEN",
|
"access.authorization.form.cloud_dns_api_token.label": "CLOUD_DNS_API_TOKEN",
|
||||||
"access.authorization.form.cloud_dns_api_token.placeholder": "请输入 CLOUD_DNS_API_TOKEN",
|
"access.authorization.form.cloud_dns_api_token.placeholder": "请输入 CLOUD_DNS_API_TOKEN",
|
||||||
"access.authorization.form.godaddy_api_key.label": "GO_DADDY_API_KEY",
|
"access.authorization.form.godaddy_api_key.label": "GO_DADDY_API_KEY",
|
||||||
|
|||||||
@@ -61,6 +61,7 @@
|
|||||||
"common.provider.huaweicloud": "华为云",
|
"common.provider.huaweicloud": "华为云",
|
||||||
"common.provider.qiniu": "七牛云",
|
"common.provider.qiniu": "七牛云",
|
||||||
"common.provider.qiniu.cdn": "七牛云 - CDN",
|
"common.provider.qiniu.cdn": "七牛云 - CDN",
|
||||||
|
"common.provider.aws": "AWS",
|
||||||
"common.provider.cloudflare": "Cloudflare",
|
"common.provider.cloudflare": "Cloudflare",
|
||||||
"common.provider.namesilo": "Namesilo",
|
"common.provider.namesilo": "Namesilo",
|
||||||
"common.provider.godaddy": "GoDaddy",
|
"common.provider.godaddy": "GoDaddy",
|
||||||
@@ -68,5 +69,6 @@
|
|||||||
"common.provider.ssh": "SSH 部署",
|
"common.provider.ssh": "SSH 部署",
|
||||||
"common.provider.webhook": "Webhook",
|
"common.provider.webhook": "Webhook",
|
||||||
"common.provider.dingtalk": "钉钉",
|
"common.provider.dingtalk": "钉钉",
|
||||||
"common.provider.telegram": "Telegram"
|
"common.provider.telegram": "Telegram",
|
||||||
|
"common.provider.lark": "飞书"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
|
|
||||||
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion";
|
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion";
|
||||||
import DingTalk from "@/components/notify/DingTalk";
|
import DingTalk from "@/components/notify/DingTalk";
|
||||||
|
import Lark from "@/components/notify/Lark";
|
||||||
import NotifyTemplate from "@/components/notify/NotifyTemplate";
|
import NotifyTemplate from "@/components/notify/NotifyTemplate";
|
||||||
import Telegram from "@/components/notify/Telegram";
|
import Telegram from "@/components/notify/Telegram";
|
||||||
import Webhook from "@/components/notify/Webhook";
|
import Webhook from "@/components/notify/Webhook";
|
||||||
@@ -32,6 +33,13 @@ const Notify = () => {
|
|||||||
</AccordionContent>
|
</AccordionContent>
|
||||||
</AccordionItem>
|
</AccordionItem>
|
||||||
|
|
||||||
|
<AccordionItem value="item-3" className="dark:border-stone-200">
|
||||||
|
<AccordionTrigger>{t("common.provider.lark")}</AccordionTrigger>
|
||||||
|
<AccordionContent>
|
||||||
|
<Lark />
|
||||||
|
</AccordionContent>
|
||||||
|
</AccordionItem>
|
||||||
|
|
||||||
<AccordionItem value="item-4" className="dark:border-stone-200">
|
<AccordionItem value="item-4" className="dark:border-stone-200">
|
||||||
<AccordionTrigger>{t("common.provider.telegram")}</AccordionTrigger>
|
<AccordionTrigger>{t("common.provider.telegram")}</AccordionTrigger>
|
||||||
<AccordionContent>
|
<AccordionContent>
|
||||||
|
|||||||
Reference in New Issue
Block a user