Merge branch 'main' of https://github.com/usual2970/certimate into usual2970-main

This commit is contained in:
wood chen 2025-05-28 18:51:06 +08:00
commit b829080c0f
152 changed files with 3508 additions and 1652 deletions

View File

@ -31,7 +31,7 @@ builds:
goarch: arm goarch: arm
upx: upx:
enable: true - enabled: true
release: release:
draft: true draft: true

View File

@ -49,7 +49,7 @@ Certimate 旨在为用户提供一个安全、简便的 SSL 证书管理解决
- 支持单域名、多域名、泛域名证书,可选 RSA、ECC 签名算法; - 支持单域名、多域名、泛域名证书,可选 RSA、ECC 签名算法;
- 支持 PEM、PFX、JKS 等多种格式输出证书; - 支持 PEM、PFX、JKS 等多种格式输出证书;
- 支持 30+ 域名托管商如阿里云、腾讯云、Cloudflare 等,[点此查看完整清单](https://docs.certimate.me/docs/reference/providers#supported-dns-providers) - 支持 30+ 域名托管商如阿里云、腾讯云、Cloudflare 等,[点此查看完整清单](https://docs.certimate.me/docs/reference/providers#supported-dns-providers)
- 支持 80+ 部署目标(如 Kubernetes、CDN、WAF、负载均衡等[点此查看完整清单](https://docs.certimate.me/docs/reference/providers#supported-hosting-providers) - 支持 90+ 部署目标(如 Kubernetes、CDN、WAF、负载均衡等[点此查看完整清单](https://docs.certimate.me/docs/reference/providers#supported-hosting-providers)
- 支持邮件、钉钉、飞书、企业微信、Webhook 等多种通知渠道; - 支持邮件、钉钉、飞书、企业微信、Webhook 等多种通知渠道;
- 支持 Let's Encrypt、Buypass、Google Trust Services、SSL.com、ZeroSSL 等多种 ACME 证书颁发机构; - 支持 Let's Encrypt、Buypass、Google Trust Services、SSL.com、ZeroSSL 等多种 ACME 证书颁发机构;
- 更多特性等待探索。 - 更多特性等待探索。

View File

@ -39,7 +39,7 @@ Certimate aims to provide users with a secure and user-friendly SSL certificate
- Supports single-domain, multi-domain, wildcard certificates, with options for RSA or ECC. - Supports single-domain, multi-domain, wildcard certificates, with options for RSA or ECC.
- Supports various certificate formats such as PEM, PFX, JKS. - Supports various certificate formats such as PEM, PFX, JKS.
- Supports more than 30+ domain registrars (e.g., Alibaba Cloud, Tencent Cloud, Cloudflare, etc. [Check out this link](https://docs.certimate.me/en/docs/reference/providers#supported-dns-providers)); - Supports more than 30+ domain registrars (e.g., Alibaba Cloud, Tencent Cloud, Cloudflare, etc. [Check out this link](https://docs.certimate.me/en/docs/reference/providers#supported-dns-providers));
- Supports more than 80+ deployment targets (e.g., Kubernetes, CDN, WAF, load balancers, etc. [Check out this link](https://docs.certimate.me/en/docs/reference/providers#supported-hosting-providers)); - Supports more than 90+ deployment targets (e.g., Kubernetes, CDN, WAF, load balancers, etc. [Check out this link](https://docs.certimate.me/en/docs/reference/providers#supported-hosting-providers));
- Supports multiple notification channels including email, DingTalk, Feishu, WeCom, Webhook, and more; - Supports multiple notification channels including email, DingTalk, Feishu, WeCom, Webhook, and more;
- Supports multiple ACME CAs including Let's Encrypt, Buypass, Google Trust ServicesSSL.com, ZeroSSL, and more; - Supports multiple ACME CAs including Let's Encrypt, Buypass, Google Trust ServicesSSL.com, ZeroSSL, and more;
- More features waiting to be discovered. - More features waiting to be discovered.

46
go.mod
View File

@ -6,7 +6,7 @@ toolchain go1.24.3
require ( require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates v1.3.1 github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates v1.3.1
github.com/Edgio/edgio-api v0.0.0-workspace github.com/Edgio/edgio-api v0.0.0-workspace
github.com/G-Core/gcorelabscdn-go v1.0.31 github.com/G-Core/gcorelabscdn-go v1.0.31
@ -14,10 +14,10 @@ require (
github.com/alibabacloud-go/apig-20240327/v3 v3.2.2 github.com/alibabacloud-go/apig-20240327/v3 v3.2.2
github.com/alibabacloud-go/cas-20200407/v3 v3.0.4 github.com/alibabacloud-go/cas-20200407/v3 v3.0.4
github.com/alibabacloud-go/cdn-20180510/v5 v5.2.2 github.com/alibabacloud-go/cdn-20180510/v5 v5.2.2
github.com/alibabacloud-go/cloudapi-20160714/v5 v5.7.3 github.com/alibabacloud-go/cloudapi-20160714/v5 v5.7.4
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.7 github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.7
github.com/alibabacloud-go/ddoscoo-20200101/v4 v4.0.0 github.com/alibabacloud-go/ddoscoo-20200101/v4 v4.0.0
github.com/alibabacloud-go/esa-20240910/v2 v2.32.0 github.com/alibabacloud-go/esa-20240910/v2 v2.33.0
github.com/alibabacloud-go/fc-20230330/v4 v4.3.5 github.com/alibabacloud-go/fc-20230330/v4 v4.3.5
github.com/alibabacloud-go/fc-open-20210406/v2 v2.0.12 github.com/alibabacloud-go/fc-open-20210406/v2 v2.0.12
github.com/alibabacloud-go/ga-20191120/v3 v3.1.8 github.com/alibabacloud-go/ga-20191120/v3 v3.1.8
@ -26,18 +26,18 @@ require (
github.com/alibabacloud-go/slb-20140515/v4 v4.0.10 github.com/alibabacloud-go/slb-20140515/v4 v4.0.10
github.com/alibabacloud-go/tea v1.3.9 github.com/alibabacloud-go/tea v1.3.9
github.com/alibabacloud-go/vod-20170321/v4 v4.8.4 github.com/alibabacloud-go/vod-20170321/v4 v4.8.4
github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.2 github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.3
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
github.com/aws/aws-sdk-go-v2/service/acm v1.32.0 github.com/aws/aws-sdk-go-v2/service/acm v1.32.0
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.46.1 github.com/aws/aws-sdk-go-v2/service/cloudfront v1.46.1
github.com/baidubce/bce-sdk-go v0.9.226 github.com/baidubce/bce-sdk-go v0.9.228
github.com/blinkbean/dingtalk v1.1.3 github.com/blinkbean/dingtalk v1.1.3
github.com/byteplus-sdk/byteplus-sdk-golang v1.0.46 github.com/byteplus-sdk/byteplus-sdk-golang v1.0.46
github.com/go-acme/lego/v4 v4.23.1 github.com/go-acme/lego/v4 v4.23.1
github.com/go-lark/lark v1.16.0 github.com/go-lark/lark v1.16.0
github.com/go-resty/resty/v2 v2.16.5 github.com/go-resty/resty/v2 v2.16.5
github.com/go-viper/mapstructure/v2 v2.2.1 github.com/go-viper/mapstructure/v2 v2.2.1
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.148 github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.150
github.com/jdcloud-api/jdcloud-sdk-go v1.64.0 github.com/jdcloud-api/jdcloud-sdk-go v1.64.0
github.com/libdns/dynv6 v1.0.0 github.com/libdns/dynv6 v1.0.0
github.com/libdns/libdns v0.2.3 github.com/libdns/libdns v0.2.3
@ -45,29 +45,29 @@ require (
github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0 github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0
github.com/pkg/sftp v1.13.9 github.com/pkg/sftp v1.13.9
github.com/pocketbase/dbx v1.11.0 github.com/pocketbase/dbx v1.11.0
github.com/pocketbase/pocketbase v0.28.0 github.com/pocketbase/pocketbase v0.28.2
github.com/povsister/scp v0.0.0-20250504051308-e467f71ea63c github.com/povsister/scp v0.0.0-20250504051308-e467f71ea63c
github.com/qiniu/go-sdk/v7 v7.25.3 github.com/qiniu/go-sdk/v7 v7.25.3
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1155 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1155
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1161 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1166
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1162 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1173
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1150 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1150
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1120 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1172
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1124 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1169
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1162 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1166
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1160 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1164
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1162 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1170
github.com/ucloud/ucloud-sdk-go v0.22.35 github.com/ucloud/ucloud-sdk-go v0.22.41
github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.12 github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.12
github.com/volcengine/volc-sdk-golang v1.0.207 github.com/volcengine/volc-sdk-golang v1.0.208
github.com/volcengine/volcengine-go-sdk v1.1.7 github.com/volcengine/volcengine-go-sdk v1.1.8
gitlab.ecloud.com/ecloud/ecloudsdkclouddns v1.0.1 gitlab.ecloud.com/ecloud/ecloudsdkclouddns v1.0.1
gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0 gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0
golang.org/x/crypto v0.38.0 golang.org/x/crypto v0.38.0
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6
k8s.io/api v0.33.0 k8s.io/api v0.33.1
k8s.io/apimachinery v0.33.0 k8s.io/apimachinery v0.33.1
k8s.io/client-go v0.33.0 k8s.io/client-go v0.33.1
software.sslmate.com/src/go-pkcs12 v0.5.0 software.sslmate.com/src/go-pkcs12 v0.5.0
) )
@ -211,10 +211,10 @@ require (
google.golang.org/protobuf v1.36.5 // indirect google.golang.org/protobuf v1.36.5 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
modernc.org/libc v1.62.1 // indirect modernc.org/libc v1.65.7 // indirect
modernc.org/mathutil v1.7.1 // indirect modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.9.1 // indirect modernc.org/memory v1.11.0 // indirect
modernc.org/sqlite v1.37.0 // indirect modernc.org/sqlite v1.37.1 // indirect
) )
replace github.com/Edgio/edgio-api v0.0.0-workspace => ./internal/pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace replace github.com/Edgio/edgio-api v0.0.0-workspace => ./internal/pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace

117
go.sum
View File

@ -36,8 +36,8 @@ filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 h1:OVoM452qUFBrX+URdH3VpR299ma4kfom0yB0URYky9g= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 h1:j8BorDEigD8UFOSZQiSqAMOOleyQOOQPnUAwV+Ls1gA=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0/go.mod h1:kUjrAo8bgEwLeZ/CmHqNl3Z/kPm7y6FKfxxK0izYUg4= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4=
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY=
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4=
@ -101,8 +101,8 @@ github.com/alibabacloud-go/cas-20200407/v3 v3.0.4 h1:ngRlctbt135zoujwX0lXSv9m4h1
github.com/alibabacloud-go/cas-20200407/v3 v3.0.4/go.mod h1:6n9MZ9SH3HlSzfe2oKwjOqhJx3dxvW2gMDO+lq8t9U4= github.com/alibabacloud-go/cas-20200407/v3 v3.0.4/go.mod h1:6n9MZ9SH3HlSzfe2oKwjOqhJx3dxvW2gMDO+lq8t9U4=
github.com/alibabacloud-go/cdn-20180510/v5 v5.2.2 h1:+KJOPukTM+xMyiLOW5qBwYKG2df3Ar7coRsqc1juKO8= github.com/alibabacloud-go/cdn-20180510/v5 v5.2.2 h1:+KJOPukTM+xMyiLOW5qBwYKG2df3Ar7coRsqc1juKO8=
github.com/alibabacloud-go/cdn-20180510/v5 v5.2.2/go.mod h1:GnPiPL3HlzCi8SGiLiVgKrAFkP1vTtcF4yGtjsl4wfo= github.com/alibabacloud-go/cdn-20180510/v5 v5.2.2/go.mod h1:GnPiPL3HlzCi8SGiLiVgKrAFkP1vTtcF4yGtjsl4wfo=
github.com/alibabacloud-go/cloudapi-20160714/v5 v5.7.3 h1:OTLn0ShbE0jJj+5Z+P76zeHsZYxZjO7YVThQoeaBM9M= github.com/alibabacloud-go/cloudapi-20160714/v5 v5.7.4 h1:SsyAoXM1R4J3I4xQdPW/rRW8cTo2KN440/4h/pGiwRQ=
github.com/alibabacloud-go/cloudapi-20160714/v5 v5.7.3/go.mod h1:eUmD1G4BjEBOAHIeJrHJL7pyLGgXSRTPLjBmYY7uPEg= github.com/alibabacloud-go/cloudapi-20160714/v5 v5.7.4/go.mod h1:eUmD1G4BjEBOAHIeJrHJL7pyLGgXSRTPLjBmYY7uPEg=
github.com/alibabacloud-go/darabonba-array v0.1.0 h1:vR8s7b1fWAQIjEjWnuF0JiKsCvclSRTfDzZHTYqfufY= github.com/alibabacloud-go/darabonba-array v0.1.0 h1:vR8s7b1fWAQIjEjWnuF0JiKsCvclSRTfDzZHTYqfufY=
github.com/alibabacloud-go/darabonba-array v0.1.0/go.mod h1:BLKxr0brnggqOJPqT09DFJ8g3fsDshapUD3C3aOEFaI= github.com/alibabacloud-go/darabonba-array v0.1.0/go.mod h1:BLKxr0brnggqOJPqT09DFJ8g3fsDshapUD3C3aOEFaI=
github.com/alibabacloud-go/darabonba-encode-util v0.0.2 h1:1uJGrbsGEVqWcWxrS9MyC2NG0Ax+GpOM5gtupki31XE= github.com/alibabacloud-go/darabonba-encode-util v0.0.2 h1:1uJGrbsGEVqWcWxrS9MyC2NG0Ax+GpOM5gtupki31XE=
@ -132,8 +132,8 @@ github.com/alibabacloud-go/debug v1.0.1/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/ql
github.com/alibabacloud-go/endpoint-util v1.1.0/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE= github.com/alibabacloud-go/endpoint-util v1.1.0/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE=
github.com/alibabacloud-go/endpoint-util v1.1.1 h1:ZkBv2/jnghxtU0p+upSU0GGzW1VL9GQdZO3mcSUTUy8= github.com/alibabacloud-go/endpoint-util v1.1.1 h1:ZkBv2/jnghxtU0p+upSU0GGzW1VL9GQdZO3mcSUTUy8=
github.com/alibabacloud-go/endpoint-util v1.1.1/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE= github.com/alibabacloud-go/endpoint-util v1.1.1/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE=
github.com/alibabacloud-go/esa-20240910/v2 v2.32.0 h1:eudSgNIkCg6huIu3HuF16BJG6+CA6bIuIddxpuPydpg= github.com/alibabacloud-go/esa-20240910/v2 v2.33.0 h1:10IWxrMcF1W6/7BUJIJifrofduSG0wRFqDbRfIsR3Zw=
github.com/alibabacloud-go/esa-20240910/v2 v2.32.0/go.mod h1:HZS5PmYJvcmH4vrJYuCvK3AnYzD9hLlO8CT0hgRyDXo= github.com/alibabacloud-go/esa-20240910/v2 v2.33.0/go.mod h1:HZS5PmYJvcmH4vrJYuCvK3AnYzD9hLlO8CT0hgRyDXo=
github.com/alibabacloud-go/fc-20230330/v4 v4.3.5 h1:nDNjVzGwkQPbQnAuxAmxvS9x8QGLph8j0ptEdZDPGBA= github.com/alibabacloud-go/fc-20230330/v4 v4.3.5 h1:nDNjVzGwkQPbQnAuxAmxvS9x8QGLph8j0ptEdZDPGBA=
github.com/alibabacloud-go/fc-20230330/v4 v4.3.5/go.mod h1:vEJimQ6E/e+m2z0/oXdeQWlFw/Pi/Ar6NKcMrSvcILE= github.com/alibabacloud-go/fc-20230330/v4 v4.3.5/go.mod h1:vEJimQ6E/e+m2z0/oXdeQWlFw/Pi/Ar6NKcMrSvcILE=
github.com/alibabacloud-go/fc-open-20210406/v2 v2.0.12 h1:A3D8Mp6qf8DfR6Dt5MpS8aDVaWfS4N85T5CvGUvgrjM= github.com/alibabacloud-go/fc-open-20210406/v2 v2.0.12 h1:A3D8Mp6qf8DfR6Dt5MpS8aDVaWfS4N85T5CvGUvgrjM=
@ -190,8 +190,8 @@ github.com/alibabacloud-go/tea-xml v1.1.3 h1:7LYnm+JbOq2B+T/B0fHC4Ies4/FofC4zHzY
github.com/alibabacloud-go/tea-xml v1.1.3/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8= github.com/alibabacloud-go/tea-xml v1.1.3/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8=
github.com/alibabacloud-go/vod-20170321/v4 v4.8.4 h1:MYP2xfrcud8vlWljQ4lhemNgAgi9/AUAa450n8TUXZo= github.com/alibabacloud-go/vod-20170321/v4 v4.8.4 h1:MYP2xfrcud8vlWljQ4lhemNgAgi9/AUAa450n8TUXZo=
github.com/alibabacloud-go/vod-20170321/v4 v4.8.4/go.mod h1:5ocQ6hIc9tpGixD2iy099aOGwIgpzjT2le4Krd4aLn8= github.com/alibabacloud-go/vod-20170321/v4 v4.8.4/go.mod h1:5ocQ6hIc9tpGixD2iy099aOGwIgpzjT2le4Krd4aLn8=
github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.2 h1:CmhJzCZ5RiSiWU6BV2XJUtIMD2LDo9FFfqlYGtx1aAw= github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.3 h1:25tmcJxIitrk55crBGssPlqRzmFcpGVW5TEFxdUvfg0=
github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.2/go.mod h1:9itYSTzipL3NlvhvNYfTjFaapoZzG68nlu/KUdh9SpA= github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.3/go.mod h1:9itYSTzipL3NlvhvNYfTjFaapoZzG68nlu/KUdh9SpA=
github.com/aliyun/alibaba-cloud-sdk-go v1.63.100 h1:yUkCbrSM1cWtgBfRVKMQtdt22KhDvKY7g4V+92eG9wA= github.com/aliyun/alibaba-cloud-sdk-go v1.63.100 h1:yUkCbrSM1cWtgBfRVKMQtdt22KhDvKY7g4V+92eG9wA=
github.com/aliyun/alibaba-cloud-sdk-go v1.63.100/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ= github.com/aliyun/alibaba-cloud-sdk-go v1.63.100/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ=
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible h1:8psS8a+wKfiLt1iVDX79F7Y6wUM49Lcha2FMXt4UM8g= github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible h1:8psS8a+wKfiLt1iVDX79F7Y6wUM49Lcha2FMXt4UM8g=
@ -250,8 +250,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.33.17/go.mod h1:cQnB8CUnxbMU82JvlqjK
github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ= github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ=
github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
github.com/baidubce/bce-sdk-go v0.9.226 h1:VKEKcJC9P33yIfYJZr12Q/4Bvj18RFbgO8w8XOfU8AI= github.com/baidubce/bce-sdk-go v0.9.228 h1:XEY3/oAxXcsi7+3atib9fMI6YNE9sL5qo+WMZ+iqmNE=
github.com/baidubce/bce-sdk-go v0.9.226/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg= github.com/baidubce/bce-sdk-go v0.9.228/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
@ -545,8 +545,8 @@ github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg
github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.148 h1:PdWSbniKnPhKe1B19KUHW/9ahYbFH2EY6Iq6sxOnomo= github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.150 h1:Ih+z79Ko1ClH4dlv7O1lyHRiVCjkb2NZYYk+1cSZbU8=
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.148/go.mod h1:Y/+YLCFCJtS29i2MbYPTUlNNfwXvkzEsZKR0imY/2aY= github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.150/go.mod h1:Y/+YLCFCJtS29i2MbYPTUlNNfwXvkzEsZKR0imY/2aY=
github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo= github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo=
github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
@ -737,8 +737,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pocketbase/dbx v1.11.0 h1:LpZezioMfT3K4tLrqA55wWFw1EtH1pM4tzSVa7kgszU= github.com/pocketbase/dbx v1.11.0 h1:LpZezioMfT3K4tLrqA55wWFw1EtH1pM4tzSVa7kgszU=
github.com/pocketbase/dbx v1.11.0/go.mod h1:xXRCIAKTHMgUCyCKZm55pUOdvFziJjQfXaWKhu2vhMs= github.com/pocketbase/dbx v1.11.0/go.mod h1:xXRCIAKTHMgUCyCKZm55pUOdvFziJjQfXaWKhu2vhMs=
github.com/pocketbase/pocketbase v0.28.0 h1:dnMHSO0wuYpKs6oP3X5buw1lY9ptd8zy1fTjN+Ae+mA= github.com/pocketbase/pocketbase v0.28.2 h1:b6cfUfr5d4whvUFGFhI8oHRzx/eB76GCUQGftqgv9lM=
github.com/pocketbase/pocketbase v0.28.0/go.mod h1:WE6xMM4+pxKIVNl4B1mcOEZXlDvPGl7cZ64TW2iXHdI= github.com/pocketbase/pocketbase v0.28.2/go.mod h1:ElwIYS1b5xS9w0U7AK7tsm6FuC0lzw57H8p/118Cu7g=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/povsister/scp v0.0.0-20250504051308-e467f71ea63c h1:1+j5JHz9mUzYSp0scuF6hzvJP28EDBFe5eBJb0xnGk4= github.com/povsister/scp v0.0.0-20250504051308-e467f71ea63c h1:1+j5JHz9mUzYSp0scuF6hzvJP28EDBFe5eBJb0xnGk4=
@ -771,8 +771,8 @@ github.com/qiniu/x v1.10.5 h1:7V/CYWEmo9axJULvrJN6sMYh2FdY+esN5h8jwDkA4b0=
github.com/qiniu/x v1.10.5/go.mod h1:03Ni9tj+N2h2aKnAz+6N0Xfl8FwMEDRC2PAlxekASDs= github.com/qiniu/x v1.10.5/go.mod h1:03Ni9tj+N2h2aKnAz+6N0Xfl8FwMEDRC2PAlxekASDs=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM= github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI=
github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA= github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
@ -829,31 +829,32 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1155 h1:ildxJtjnqiKZxWDVKHT/ncIknGDijtg60MuFELON8bY= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1155 h1:ildxJtjnqiKZxWDVKHT/ncIknGDijtg60MuFELON8bY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1155/go.mod h1:iLASpooTdyXtx642E5Ws7cfWENsp4/uZ/78TFoln7OI= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1155/go.mod h1:iLASpooTdyXtx642E5Ws7cfWENsp4/uZ/78TFoln7OI=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1161 h1:yGFg9/6j3NP10r9PfSWHfekuq4SwPyqblWnfISfKANo= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1166 h1:cEoDsBt7vGh7YtfVHVmgXKQURZANBE8UKK/So84QUdU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1161/go.mod h1:9MzQSEULYm5wHAKz8R3oQ8ovg4vWeLFzn0DmRWTc6zg= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1166/go.mod h1:0o5Cfgdh+bAx7kpQ5a5wce/ZUiDvy4Md8NcbrLtk6i8=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1120/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1124/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1128/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1128/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1150/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1150/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1155/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1155/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1160/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1164/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1161/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1166/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1162 h1:bscCBygP9JRl6iNabF+vmBOhY+xayFFGYV5Wa0NzH0A= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1169/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1162/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1170/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1172/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1173 h1:W5bzEWiJwiwRZR0/P1l78OYWUXYsXLjhBaQ64c+9+fk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1173/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1128 h1:mrJ5Fbkd7sZIJ5F6oRfh5zebPQaudPH9Y0+GUmFytYU= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1128 h1:mrJ5Fbkd7sZIJ5F6oRfh5zebPQaudPH9Y0+GUmFytYU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1128/go.mod h1:zbsYIBT+VTX4z4ocjTAdLBIWyNYj3z0BRqd0iPdnjsk= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1128/go.mod h1:zbsYIBT+VTX4z4ocjTAdLBIWyNYj3z0BRqd0iPdnjsk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1150 h1:RQQYfZOFYlkxKR2+xp8el3+8xs9DhxBy+ajlHtapqtQ= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1150 h1:RQQYfZOFYlkxKR2+xp8el3+8xs9DhxBy+ajlHtapqtQ=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1150/go.mod h1:zpfr6EBWy7ClASTGUgIy01Gn4R79UXf+2QGQeyR124A= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1150/go.mod h1:zpfr6EBWy7ClASTGUgIy01Gn4R79UXf+2QGQeyR124A=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1120 h1:z0t0lb5h1mZirXftO8MRg25COYZHx0ubQjSPhZT/LY0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1172 h1:6SUO0hTie3zxnUEMxmhnS1iRIXpAukSZV27Nrx4NwIk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1120/go.mod h1:IFZL44Keyl+MHrhpFwUaQmJvMDwGr+t+cUfFAC+74lU= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1172/go.mod h1:tmN4zfu70SD0iee3qfpc09NRLel30zGoAuzIs4X0Kfs=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1124 h1:LQKAlxFb0sYiE8ojK5h9+seuFzogoJtYnXmiRF+4F4Q= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1169 h1:oBymtJEmKDnS2NIR0PDLd+xCGQ+7uMoEt7zEB5Q3x8U=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1124/go.mod h1:tYbK0FbHVG+78od7eZpzczE8qk0JWKO/osTQWuiJ3Fo= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1169/go.mod h1:K27PNEgRJ602ESXUNnlRnCkf1+XYHI6RVP/ylIe/Aro=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1162 h1:z/JF+JGi6bGf8vnK9ZeVXz+1Q3ih8nF6KjThxhtIrNc= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1166 h1:+kIsoG2If/0y15PpZsXfT0QqTuwec9nMgo1JP8KQMkw=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1162/go.mod h1:rsO8JCP+WQeLQ32wAB4oRRjsEz0O+kvCGDqc7Ze1jc4= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1166/go.mod h1:lGmBMXqe3vBg6Bi9h4mVpWLKd7jQIMRbndr8KNHBqSw=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1160 h1:aNVEDS1yQ7sLfXOOQ/bF3eljFjyvHoJ/J8qSC9mC9gw= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1164 h1:caaIGWOs/JtWOK5ptVMEiiGgzU7Jf6UpMv+9IbIa4vs=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1160/go.mod h1:kf6NQmKK6sh1ACwh8iliBy7I/burd+AWusNz6zbDvLM= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1164/go.mod h1:SJI2mc77gDC7Tw1QoF/4d5SwLvz8HQFUecWtIXb+r/Q=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1162 h1:gnmuUaoFAShc9FKj3Omswu3n08bHM/sGsl8xjFAkFNs= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1170 h1:kcQCWuI9zOkZgL5CK66HNAJmSWCSJxRrDxXT+j02CeE=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1162/go.mod h1:bu3KAFeoJ1xDGQp72h9Le3FqbOcCcdomOUig3OqgcE4= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1170/go.mod h1:vTukVfThbBIc4lOf4eq/q51eEk78oZUJd2lAoJBOJwI=
github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho= github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
@ -862,18 +863,18 @@ github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaO
github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg=
github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
github.com/ucloud/ucloud-sdk-go v0.22.35 h1:Q4CY3Ae5813jmNUrGdCjc8tlyleL5Lyl0APnpK5L4sk= github.com/ucloud/ucloud-sdk-go v0.22.41 h1:JndTJhCx7A1wggZfVb4KMm7D0Wfvd/HkmQVfSNjClQA=
github.com/ucloud/ucloud-sdk-go v0.22.35/go.mod h1:dyLmFHmUfgb4RZKYQP9IArlvQ2pxzFthfhwxRzOEPIw= github.com/ucloud/ucloud-sdk-go v0.22.41/go.mod h1:dyLmFHmUfgb4RZKYQP9IArlvQ2pxzFthfhwxRzOEPIw=
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.12 h1:u9+32DXQIOFPG8oQ3xrjSAUSyAcaq5bqO4cEBom/6lA= github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.12 h1:u9+32DXQIOFPG8oQ3xrjSAUSyAcaq5bqO4cEBom/6lA=
github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.12/go.mod h1:IrjK84IJJTuOZOTMv/P18Ydjy/x+ow7fF7q11jAxXLM= github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.12/go.mod h1:IrjK84IJJTuOZOTMv/P18Ydjy/x+ow7fF7q11jAxXLM=
github.com/volcengine/volc-sdk-golang v1.0.23/go.mod h1:AfG/PZRUkHJ9inETvbjNifTDgut25Wbkm2QoYBTbvyU= github.com/volcengine/volc-sdk-golang v1.0.23/go.mod h1:AfG/PZRUkHJ9inETvbjNifTDgut25Wbkm2QoYBTbvyU=
github.com/volcengine/volc-sdk-golang v1.0.207 h1:1OJ/nC92dF1URRoyO1AHSghCob12NT1PAA/GoK8uU18= github.com/volcengine/volc-sdk-golang v1.0.208 h1:DyGUPjEKhWS08BkptfqenXTuUq+LKb7+gX/RBAtNl8w=
github.com/volcengine/volc-sdk-golang v1.0.207/go.mod h1:stZX+EPgv1vF4nZwOlEe8iGcriUPRBKX8zA19gXycOQ= github.com/volcengine/volc-sdk-golang v1.0.208/go.mod h1:stZX+EPgv1vF4nZwOlEe8iGcriUPRBKX8zA19gXycOQ=
github.com/volcengine/volcengine-go-sdk v1.1.7 h1:5ElF1inqX1QUKX8/XGk+HGpG+F01W+m73cLQH+0x50s= github.com/volcengine/volcengine-go-sdk v1.1.8 h1:/T2p7qeeLWWhGrhtB00b8VNlE32S266LcO+jqFUYwzY=
github.com/volcengine/volcengine-go-sdk v1.1.7/go.mod h1:EyKoi6t6eZxoPNGr2GdFCZti2Skd7MO3eUzx7TtSvNo= github.com/volcengine/volcengine-go-sdk v1.1.8/go.mod h1:EyKoi6t6eZxoPNGr2GdFCZti2Skd7MO3eUzx7TtSvNo=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
@ -1394,39 +1395,39 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.33.0 h1:yTgZVn1XEe6opVpP1FylmNrIFWuDqe2H0V8CT5gxfIU= k8s.io/api v0.33.1 h1:tA6Cf3bHnLIrUK4IqEgb2v++/GYUtqiu9sRVk3iBXyw=
k8s.io/api v0.33.0/go.mod h1:CTO61ECK/KU7haa3qq8sarQ0biLq2ju405IZAd9zsiM= k8s.io/api v0.33.1/go.mod h1:87esjTn9DRSRTD4fWMXamiXxJhpOIREjWOSjsW1kEHw=
k8s.io/apimachinery v0.33.0 h1:1a6kHrJxb2hs4t8EE5wuR/WxKDwGN1FKH3JvDtA0CIQ= k8s.io/apimachinery v0.33.1 h1:mzqXWV8tW9Rw4VeW9rEkqvnxj59k1ezDUl20tFK/oM4=
k8s.io/apimachinery v0.33.0/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= k8s.io/apimachinery v0.33.1/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
k8s.io/client-go v0.33.0 h1:UASR0sAYVUzs2kYuKn/ZakZlcs2bEHaizrrHUZg0G98= k8s.io/client-go v0.33.1 h1:ZZV/Ks2g92cyxWkRRnfUDsnhNn28eFpt26aGc8KbXF4=
k8s.io/client-go v0.33.0/go.mod h1:kGkd+l/gNGg8GYWAPr0xF1rRKvVWvzh9vmZAMXtaKOg= k8s.io/client-go v0.33.1/go.mod h1:JAsUrl1ArO7uRVFWfcj6kOomSlCv+JpvIsp6usAGefA=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4= k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8=
k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0= k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0=
k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
modernc.org/cc/v4 v4.25.2 h1:T2oH7sZdGvTaie0BRNFbIYsabzCxUQg8nLqCdQ2i0ic= modernc.org/cc/v4 v4.26.1 h1:+X5NtzVBn0KgsBCBe+xkDC7twLb/jNVj9FPgiwSQO3s=
modernc.org/cc/v4 v4.25.2/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= modernc.org/cc/v4 v4.26.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
modernc.org/ccgo/v4 v4.25.1 h1:TFSzPrAGmDsdnhT9X2UrcPMI3N/mJ9/X9ykKXwLhDsU= modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU=
modernc.org/ccgo/v4 v4.25.1/go.mod h1:njjuAYiPflywOOrm3B7kCB444ONP5pAVr8PIEoE0uDw= modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE=
modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8= modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8=
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= modernc.org/fileutil v1.3.1 h1:8vq5fe7jdtEvoCf3Zf9Nm0Q05sH6kGx0Op2CPx1wTC8=
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= modernc.org/fileutil v1.3.1/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/libc v1.62.1 h1:s0+fv5E3FymN8eJVmnk0llBe6rOxCu/DEU+XygRbS8s= modernc.org/libc v1.65.7 h1:Ia9Z4yzZtWNtUIuiPuQ7Qf7kxYrxP1/jeHZzG8bFu00=
modernc.org/libc v1.62.1/go.mod h1:iXhATfJQLjG3NWy56a6WVU73lWOcdYVxsvwCgoPljuo= modernc.org/libc v1.65.7/go.mod h1:011EQibzzio/VX3ygj1qGFt5kMjP0lHb0qCW5/D/pQU=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.9.1 h1:V/Z1solwAVmMW1yttq3nDdZPJqV1rM05Ccq6KMSZ34g= modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
modernc.org/memory v1.9.1/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8= modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.37.0 h1:s1TMe7T3Q3ovQiK2Ouz4Jwh7dw4ZDqbebSDTlSJdfjI= modernc.org/sqlite v1.37.1 h1:EgHJK/FPoqC+q2YBXg7fUmES37pCHFc97sI7zSayBEs=
modernc.org/sqlite v1.37.0/go.mod h1:5YiWv+YviqGMuGw4V+PNplcyaJ5v+vQd7TQOgkACoJM= modernc.org/sqlite v1.37.1/go.mod h1:XwdRtsE1MpiBcL54+MbKcaDvcuej+IYSMfLN6gSKV8g=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=

View File

@ -26,13 +26,14 @@ import (
) )
type ApplyResult struct { type ApplyResult struct {
CSR string
FullChainCertificate string FullChainCertificate string
IssuerCertificate string IssuerCertificate string
PrivateKey string PrivateKey string
ACMEAccountUrl string ACMEAccountUrl string
ACMECertUrl string ACMECertUrl string
ACMECertStableUrl string ACMECertStableUrl string
CSR string ARIReplaced bool
} }
type Applicant interface { type Applicant interface {
@ -109,7 +110,7 @@ func NewWithWorkflowNode(config ApplicantWithWorkflowNodeConfig) (Applicant, err
certRepo := repository.NewCertificateRepository() certRepo := repository.NewCertificateRepository()
lastCertificate, _ := certRepo.GetByWorkflowNodeId(context.Background(), config.Node.Id) lastCertificate, _ := certRepo.GetByWorkflowNodeId(context.Background(), config.Node.Id)
if lastCertificate != nil { if lastCertificate != nil && !lastCertificate.ACMERenewed {
newCertSan := slices.Clone(options.Domains) newCertSan := slices.Clone(options.Domains)
oldCertSan := strings.Split(lastCertificate.SubjectAltNames, ";") oldCertSan := strings.Split(lastCertificate.SubjectAltNames, ";")
slices.Sort(newCertSan) slices.Sort(newCertSan)
@ -119,8 +120,8 @@ func NewWithWorkflowNode(config ApplicantWithWorkflowNodeConfig) (Applicant, err
lastCertX509, _ := certcrypto.ParsePEMCertificate([]byte(lastCertificate.Certificate)) lastCertX509, _ := certcrypto.ParsePEMCertificate([]byte(lastCertificate.Certificate))
if lastCertX509 != nil { if lastCertX509 != nil {
replacedARICertId, _ := certificate.MakeARICertID(lastCertX509) replacedARICertId, _ := certificate.MakeARICertID(lastCertX509)
options.ReplacedARIAcct = lastCertificate.ACMEAccountUrl options.ARIReplaceAcct = lastCertificate.ACMEAccountUrl
options.ReplacedARICert = replacedARICertId options.ARIReplaceCert = replacedARICertId
} }
} }
} }
@ -235,22 +236,24 @@ func applyUseLego(legoProvider challenge.Provider, options *applicantProviderOpt
Domains: options.Domains, Domains: options.Domains,
Bundle: true, Bundle: true,
} }
if options.ReplacedARIAcct == user.Registration.URI { if options.ARIReplaceAcct == user.Registration.URI {
certRequest.ReplacesCertID = options.ReplacedARICert certRequest.ReplacesCertID = options.ARIReplaceCert
} }
certResource, err := client.Certificate.Obtain(certRequest) certResource, err := client.Certificate.Obtain(certRequest)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &ApplyResult{ return &ApplyResult{
CSR: strings.TrimSpace(string(certResource.CSR)),
FullChainCertificate: strings.TrimSpace(string(certResource.Certificate)), FullChainCertificate: strings.TrimSpace(string(certResource.Certificate)),
IssuerCertificate: strings.TrimSpace(string(certResource.IssuerCertificate)), IssuerCertificate: strings.TrimSpace(string(certResource.IssuerCertificate)),
PrivateKey: strings.TrimSpace(string(certResource.PrivateKey)), PrivateKey: strings.TrimSpace(string(certResource.PrivateKey)),
ACMEAccountUrl: user.Registration.URI, ACMEAccountUrl: user.Registration.URI,
ACMECertUrl: certResource.CertURL, ACMECertUrl: certResource.CertURL,
ACMECertStableUrl: certResource.CertStableURL, ACMECertStableUrl: certResource.CertStableURL,
CSR: strings.TrimSpace(string(certResource.CSR)), ARIReplaced: certRequest.ReplacesCertID != "",
}, nil }, nil
} }

View File

@ -17,11 +17,14 @@ import (
pClouDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns" pClouDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns"
pCMCCCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud" pCMCCCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud"
pDeSEC "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/desec" pDeSEC "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/desec"
pDigitalOcean "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/digitalocean"
pDNSLA "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla" pDNSLA "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla"
pDuckDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/duckdns"
pDynv6 "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/dynv6" pDynv6 "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/dynv6"
pGcore "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore" pGcore "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore"
pGname "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname" pGname "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname"
pGoDaddy "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy" pGoDaddy "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy"
pHetzner "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/hetzner"
pHuaweiCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud" pHuaweiCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud"
pJDCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud" pJDCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud"
pNamecheap "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namecheap" pNamecheap "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namecheap"
@ -57,8 +60,8 @@ type applicantProviderOptions struct {
DnsPropagationTimeout int32 DnsPropagationTimeout int32
DnsTTL int32 DnsTTL int32
DisableFollowCNAME bool DisableFollowCNAME bool
ReplacedARIAcct string ARIReplaceAcct string
ReplacedARICert string ARIReplaceCert string
} }
func createApplicantProvider(options *applicantProviderOptions) (challenge.Provider, error) { func createApplicantProvider(options *applicantProviderOptions) (challenge.Provider, error) {
@ -246,6 +249,21 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
return applicant, err return applicant, err
} }
case domain.ACMEDns01ProviderTypeDigitalOcean:
{
access := domain.AccessConfigForDigitalOcean{}
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
applicant, err := pDigitalOcean.NewChallengeProvider(&pDigitalOcean.ChallengeProviderConfig{
AccessToken: access.AccessToken,
DnsPropagationTimeout: options.DnsPropagationTimeout,
DnsTTL: options.DnsTTL,
})
return applicant, err
}
case domain.ACMEDns01ProviderTypeDNSLA: case domain.ACMEDns01ProviderTypeDNSLA:
{ {
access := domain.AccessConfigForDNSLA{} access := domain.AccessConfigForDNSLA{}
@ -262,6 +280,20 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
return applicant, err return applicant, err
} }
case domain.ACMEDns01ProviderTypeDuckDNS:
{
access := domain.AccessConfigForDuckDNS{}
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
applicant, err := pDuckDNS.NewChallengeProvider(&pDuckDNS.ChallengeProviderConfig{
Token: access.Token,
DnsPropagationTimeout: options.DnsPropagationTimeout,
})
return applicant, err
}
case domain.ACMEDns01ProviderTypeDynv6: case domain.ACMEDns01ProviderTypeDynv6:
{ {
access := domain.AccessConfigForDynv6{} access := domain.AccessConfigForDynv6{}
@ -324,6 +356,21 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
return applicant, err return applicant, err
} }
case domain.ACMEDns01ProviderTypeHetzner:
{
access := domain.AccessConfigForHetzner{}
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
applicant, err := pHetzner.NewChallengeProvider(&pHetzner.ChallengeProviderConfig{
ApiToken: access.ApiToken,
DnsPropagationTimeout: options.DnsPropagationTimeout,
DnsTTL: options.DnsTTL,
})
return applicant, err
}
case domain.ACMEDns01ProviderTypeHuaweiCloud, domain.ACMEDns01ProviderTypeHuaweiCloudDNS: case domain.ACMEDns01ProviderTypeHuaweiCloud, domain.ACMEDns01ProviderTypeHuaweiCloudDNS:
{ {
access := domain.AccessConfigForHuaweiCloud{} access := domain.AccessConfigForHuaweiCloud{}
@ -476,7 +523,7 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
} }
applicant, err := pPowerDNS.NewChallengeProvider(&pPowerDNS.ChallengeProviderConfig{ applicant, err := pPowerDNS.NewChallengeProvider(&pPowerDNS.ChallengeProviderConfig{
ApiUrl: access.ApiUrl, ServerUrl: access.ServerUrl,
ApiKey: access.ApiKey, ApiKey: access.ApiKey,
AllowInsecureConnections: access.AllowInsecureConnections, AllowInsecureConnections: access.AllowInsecureConnections,
DnsPropagationTimeout: options.DnsPropagationTimeout, DnsPropagationTimeout: options.DnsPropagationTimeout,

View File

@ -79,6 +79,7 @@ import (
pTencentCloudWAF "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-waf" pTencentCloudWAF "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-waf"
pUCloudUCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ucloud-ucdn" pUCloudUCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ucloud-ucdn"
pUCloudUS3 "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ucloud-us3" pUCloudUS3 "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ucloud-us3"
pUniCloudWebHost "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/unicloud-webhost"
pUpyunCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/upyun-cdn" pUpyunCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/upyun-cdn"
pVolcEngineALB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-alb" pVolcEngineALB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-alb"
pVolcEngineCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-cdn" pVolcEngineCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-cdn"
@ -119,7 +120,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
switch options.Provider { switch options.Provider {
case domain.DeploymentProviderType1PanelConsole: case domain.DeploymentProviderType1PanelConsole:
deployer, err := p1PanelConsole.NewDeployer(&p1PanelConsole.DeployerConfig{ deployer, err := p1PanelConsole.NewDeployer(&p1PanelConsole.DeployerConfig{
ApiUrl: access.ApiUrl, ServerUrl: access.ServerUrl,
ApiVersion: access.ApiVersion, ApiVersion: access.ApiVersion,
ApiKey: access.ApiKey, ApiKey: access.ApiKey,
AllowInsecureConnections: access.AllowInsecureConnections, AllowInsecureConnections: access.AllowInsecureConnections,
@ -129,7 +130,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
case domain.DeploymentProviderType1PanelSite: case domain.DeploymentProviderType1PanelSite:
deployer, err := p1PanelSite.NewDeployer(&p1PanelSite.DeployerConfig{ deployer, err := p1PanelSite.NewDeployer(&p1PanelSite.DeployerConfig{
ApiUrl: access.ApiUrl, ServerUrl: access.ServerUrl,
ApiVersion: access.ApiVersion, ApiVersion: access.ApiVersion,
ApiKey: access.ApiKey, ApiKey: access.ApiKey,
AllowInsecureConnections: access.AllowInsecureConnections, AllowInsecureConnections: access.AllowInsecureConnections,
@ -454,7 +455,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
switch options.Provider { switch options.Provider {
case domain.DeploymentProviderTypeBaotaPanelConsole: case domain.DeploymentProviderTypeBaotaPanelConsole:
deployer, err := pBaotaPanelConsole.NewDeployer(&pBaotaPanelConsole.DeployerConfig{ deployer, err := pBaotaPanelConsole.NewDeployer(&pBaotaPanelConsole.DeployerConfig{
ApiUrl: access.ApiUrl, ServerUrl: access.ServerUrl,
ApiKey: access.ApiKey, ApiKey: access.ApiKey,
AllowInsecureConnections: access.AllowInsecureConnections, AllowInsecureConnections: access.AllowInsecureConnections,
AutoRestart: maputil.GetBool(options.ProviderServiceConfig, "autoRestart"), AutoRestart: maputil.GetBool(options.ProviderServiceConfig, "autoRestart"),
@ -463,7 +464,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
case domain.DeploymentProviderTypeBaotaPanelSite: case domain.DeploymentProviderTypeBaotaPanelSite:
deployer, err := pBaotaPanelSite.NewDeployer(&pBaotaPanelSite.DeployerConfig{ deployer, err := pBaotaPanelSite.NewDeployer(&pBaotaPanelSite.DeployerConfig{
ApiUrl: access.ApiUrl, ServerUrl: access.ServerUrl,
ApiKey: access.ApiKey, ApiKey: access.ApiKey,
AllowInsecureConnections: access.AllowInsecureConnections, AllowInsecureConnections: access.AllowInsecureConnections,
SiteType: maputil.GetOrDefaultString(options.ProviderServiceConfig, "siteType", "other"), SiteType: maputil.GetOrDefaultString(options.ProviderServiceConfig, "siteType", "other"),
@ -487,7 +488,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
switch options.Provider { switch options.Provider {
case domain.DeploymentProviderTypeBaotaWAFConsole: case domain.DeploymentProviderTypeBaotaWAFConsole:
deployer, err := pBaotaWAFConsole.NewDeployer(&pBaotaWAFConsole.DeployerConfig{ deployer, err := pBaotaWAFConsole.NewDeployer(&pBaotaWAFConsole.DeployerConfig{
ApiUrl: access.ApiUrl, ServerUrl: access.ServerUrl,
ApiKey: access.ApiKey, ApiKey: access.ApiKey,
AllowInsecureConnections: access.AllowInsecureConnections, AllowInsecureConnections: access.AllowInsecureConnections,
}) })
@ -495,7 +496,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
case domain.DeploymentProviderTypeBaotaWAFSite: case domain.DeploymentProviderTypeBaotaWAFSite:
deployer, err := pBaotaWAFSite.NewDeployer(&pBaotaWAFSite.DeployerConfig{ deployer, err := pBaotaWAFSite.NewDeployer(&pBaotaWAFSite.DeployerConfig{
ApiUrl: access.ApiUrl, ServerUrl: access.ServerUrl,
ApiKey: access.ApiKey, ApiKey: access.ApiKey,
AllowInsecureConnections: access.AllowInsecureConnections, AllowInsecureConnections: access.AllowInsecureConnections,
SiteName: maputil.GetString(options.ProviderServiceConfig, "siteName"), SiteName: maputil.GetString(options.ProviderServiceConfig, "siteName"),
@ -565,7 +566,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
} }
deployer, err := pCdnfly.NewDeployer(&pCdnfly.DeployerConfig{ deployer, err := pCdnfly.NewDeployer(&pCdnfly.DeployerConfig{
ApiUrl: access.ApiUrl, ServerUrl: access.ServerUrl,
ApiKey: access.ApiKey, ApiKey: access.ApiKey,
ApiSecret: access.ApiSecret, ApiSecret: access.ApiSecret,
AllowInsecureConnections: access.AllowInsecureConnections, AllowInsecureConnections: access.AllowInsecureConnections,
@ -614,7 +615,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
} }
deployer, err := pFlexCDN.NewDeployer(&pFlexCDN.DeployerConfig{ deployer, err := pFlexCDN.NewDeployer(&pFlexCDN.DeployerConfig{
ApiUrl: access.ApiUrl, ServerUrl: access.ServerUrl,
ApiRole: access.ApiRole, ApiRole: access.ApiRole,
AccessKeyId: access.AccessKeyId, AccessKeyId: access.AccessKeyId,
AccessKey: access.AccessKey, AccessKey: access.AccessKey,
@ -654,7 +655,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
} }
deployer, err := pGoEdge.NewDeployer(&pGoEdge.DeployerConfig{ deployer, err := pGoEdge.NewDeployer(&pGoEdge.DeployerConfig{
ApiUrl: access.ApiUrl, ServerUrl: access.ServerUrl,
ApiRole: access.ApiRole, ApiRole: access.ApiRole,
AccessKeyId: access.AccessKeyId, AccessKeyId: access.AccessKeyId,
AccessKey: access.AccessKey, AccessKey: access.AccessKey,
@ -773,7 +774,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
} }
deployer, err := pLeCDN.NewDeployer(&pLeCDN.DeployerConfig{ deployer, err := pLeCDN.NewDeployer(&pLeCDN.DeployerConfig{
ApiUrl: access.ApiUrl, ServerUrl: access.ServerUrl,
ApiVersion: access.ApiVersion, ApiVersion: access.ApiVersion,
ApiRole: access.ApiRole, ApiRole: access.ApiRole,
Username: access.Username, Username: access.Username,
@ -845,7 +846,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
} }
deployer, err := pProxmoxVE.NewDeployer(&pProxmoxVE.DeployerConfig{ deployer, err := pProxmoxVE.NewDeployer(&pProxmoxVE.DeployerConfig{
ApiUrl: access.ApiUrl, ServerUrl: access.ServerUrl,
ApiToken: access.ApiToken, ApiToken: access.ApiToken,
ApiTokenSecret: access.ApiTokenSecret, ApiTokenSecret: access.ApiTokenSecret,
AllowInsecureConnections: access.AllowInsecureConnections, AllowInsecureConnections: access.AllowInsecureConnections,
@ -916,7 +917,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
switch options.Provider { switch options.Provider {
case domain.DeploymentProviderTypeRatPanelConsole: case domain.DeploymentProviderTypeRatPanelConsole:
deployer, err := pRatPanelConsole.NewDeployer(&pRatPanelConsole.DeployerConfig{ deployer, err := pRatPanelConsole.NewDeployer(&pRatPanelConsole.DeployerConfig{
ApiUrl: access.ApiUrl, ServerUrl: access.ServerUrl,
AccessTokenId: access.AccessTokenId, AccessTokenId: access.AccessTokenId,
AccessToken: access.AccessToken, AccessToken: access.AccessToken,
AllowInsecureConnections: access.AllowInsecureConnections, AllowInsecureConnections: access.AllowInsecureConnections,
@ -925,7 +926,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
case domain.DeploymentProviderTypeRatPanelSite: case domain.DeploymentProviderTypeRatPanelSite:
deployer, err := pRatPanelSite.NewDeployer(&pRatPanelSite.DeployerConfig{ deployer, err := pRatPanelSite.NewDeployer(&pRatPanelSite.DeployerConfig{
ApiUrl: access.ApiUrl, ServerUrl: access.ServerUrl,
AccessTokenId: access.AccessTokenId, AccessTokenId: access.AccessTokenId,
AccessToken: access.AccessToken, AccessToken: access.AccessToken,
AllowInsecureConnections: access.AllowInsecureConnections, AllowInsecureConnections: access.AllowInsecureConnections,
@ -946,7 +947,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
} }
deployer, err := pSafeLine.NewDeployer(&pSafeLine.DeployerConfig{ deployer, err := pSafeLine.NewDeployer(&pSafeLine.DeployerConfig{
ApiUrl: access.ApiUrl, ServerUrl: access.ServerUrl,
ApiToken: access.ApiToken, ApiToken: access.ApiToken,
AllowInsecureConnections: access.AllowInsecureConnections, AllowInsecureConnections: access.AllowInsecureConnections,
ResourceType: pSafeLine.ResourceType(maputil.GetString(options.ProviderServiceConfig, "resourceType")), ResourceType: pSafeLine.ResourceType(maputil.GetString(options.ProviderServiceConfig, "resourceType")),
@ -1144,6 +1145,23 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
} }
} }
case domain.DeploymentProviderTypeUniCloudWebHost:
{
access := domain.AccessConfigForUniCloud{}
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
deployer, err := pUniCloudWebHost.NewDeployer(&pUniCloudWebHost.DeployerConfig{
Username: access.Username,
Password: access.Password,
SpaceProvider: maputil.GetString(options.ProviderServiceConfig, "spaceProvider"),
SpaceId: maputil.GetString(options.ProviderServiceConfig, "spaceId"),
Domain: maputil.GetString(options.ProviderServiceConfig, "domain"),
})
return deployer, err
}
case domain.DeploymentProviderTypeUpyunCDN, domain.DeploymentProviderTypeUpyunFile: case domain.DeploymentProviderTypeUpyunCDN, domain.DeploymentProviderTypeUpyunFile:
{ {
access := domain.AccessConfigForUpyun{} access := domain.AccessConfigForUpyun{}

View File

@ -16,7 +16,7 @@ type Access struct {
} }
type AccessConfigFor1Panel struct { type AccessConfigFor1Panel struct {
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
ApiVersion string `json:"apiVersion"` ApiVersion string `json:"apiVersion"`
ApiKey string `json:"apiKey"` ApiKey string `json:"apiKey"`
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
@ -62,13 +62,13 @@ type AccessConfigForBaishan struct {
} }
type AccessConfigForBaotaPanel struct { type AccessConfigForBaotaPanel struct {
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
ApiKey string `json:"apiKey"` ApiKey string `json:"apiKey"`
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
} }
type AccessConfigForBaotaWAF struct { type AccessConfigForBaotaWAF struct {
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
ApiKey string `json:"apiKey"` ApiKey string `json:"apiKey"`
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
} }
@ -87,7 +87,7 @@ type AccessConfigForCacheFly struct {
} }
type AccessConfigForCdnfly struct { type AccessConfigForCdnfly struct {
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
ApiKey string `json:"apiKey"` ApiKey string `json:"apiKey"`
ApiSecret string `json:"apiSecret"` ApiSecret string `json:"apiSecret"`
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
@ -112,11 +112,20 @@ type AccessConfigForDeSEC struct {
Token string `json:"token"` Token string `json:"token"`
} }
type AccessConfigForDigitalOcean struct {
AccessToken string `json:"accessToken"`
}
type AccessConfigForDingTalkBot struct { type AccessConfigForDingTalkBot struct {
WebhookUrl string `json:"webhookUrl"` WebhookUrl string `json:"webhookUrl"`
Secret string `json:"secret"` Secret string `json:"secret"`
} }
type AccessConfigForDiscordBot struct {
BotToken string `json:"botToken"`
DefaultChannelId string `json:"defaultChannelId,omitempty"`
}
type AccessConfigForDNSLA struct { type AccessConfigForDNSLA struct {
ApiId string `json:"apiId"` ApiId string `json:"apiId"`
ApiSecret string `json:"apiSecret"` ApiSecret string `json:"apiSecret"`
@ -127,6 +136,10 @@ type AccessConfigForDogeCloud struct {
SecretKey string `json:"secretKey"` SecretKey string `json:"secretKey"`
} }
type AccessConfigForDuckDNS struct {
Token string `json:"token"`
}
type AccessConfigForDynv6 struct { type AccessConfigForDynv6 struct {
HttpToken string `json:"httpToken"` HttpToken string `json:"httpToken"`
} }
@ -147,7 +160,7 @@ type AccessConfigForEmail struct {
} }
type AccessConfigForFlexCDN struct { type AccessConfigForFlexCDN struct {
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
ApiRole string `json:"apiRole"` ApiRole string `json:"apiRole"`
AccessKeyId string `json:"accessKeyId"` AccessKeyId string `json:"accessKeyId"`
AccessKey string `json:"accessKey"` AccessKey string `json:"accessKey"`
@ -169,7 +182,7 @@ type AccessConfigForGoDaddy struct {
} }
type AccessConfigForGoEdge struct { type AccessConfigForGoEdge struct {
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
ApiRole string `json:"apiRole"` ApiRole string `json:"apiRole"`
AccessKeyId string `json:"accessKeyId"` AccessKeyId string `json:"accessKeyId"`
AccessKey string `json:"accessKey"` AccessKey string `json:"accessKey"`
@ -181,6 +194,10 @@ type AccessConfigForGoogleTrustServices struct {
EabHmacKey string `json:"eabHmacKey"` EabHmacKey string `json:"eabHmacKey"`
} }
type AccessConfigForHetzner struct {
ApiToken string `json:"apiToken"`
}
type AccessConfigForHuaweiCloud struct { type AccessConfigForHuaweiCloud struct {
AccessKeyId string `json:"accessKeyId"` AccessKeyId string `json:"accessKeyId"`
SecretAccessKey string `json:"secretAccessKey"` SecretAccessKey string `json:"secretAccessKey"`
@ -200,7 +217,7 @@ type AccessConfigForLarkBot struct {
} }
type AccessConfigForLeCDN struct { type AccessConfigForLeCDN struct {
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
ApiVersion string `json:"apiVersion"` ApiVersion string `json:"apiVersion"`
ApiRole string `json:"apiRole"` ApiRole string `json:"apiRole"`
Username string `json:"username"` Username string `json:"username"`
@ -249,13 +266,13 @@ type AccessConfigForPorkbun struct {
} }
type AccessConfigForPowerDNS struct { type AccessConfigForPowerDNS struct {
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
ApiKey string `json:"apiKey"` ApiKey string `json:"apiKey"`
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
} }
type AccessConfigForProxmoxVE struct { type AccessConfigForProxmoxVE struct {
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
ApiToken string `json:"apiToken"` ApiToken string `json:"apiToken"`
ApiTokenSecret string `json:"apiTokenSecret,omitempty"` ApiTokenSecret string `json:"apiTokenSecret,omitempty"`
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
@ -271,18 +288,23 @@ type AccessConfigForRainYun struct {
} }
type AccessConfigForRatPanel struct { type AccessConfigForRatPanel struct {
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
AccessTokenId int32 `json:"accessTokenId"` AccessTokenId int32 `json:"accessTokenId"`
AccessToken string `json:"accessToken"` AccessToken string `json:"accessToken"`
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
} }
type AccessConfigForSafeLine struct { type AccessConfigForSafeLine struct {
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
ApiToken string `json:"apiToken"` ApiToken string `json:"apiToken"`
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
} }
type AccessConfigForSlackBot struct {
BotToken string `json:"botToken"`
DefaultChannelId string `json:"defaultChannelId,omitempty"`
}
type AccessConfigForSSH struct { type AccessConfigForSSH struct {
Host string `json:"host"` Host string `json:"host"`
Port int32 `json:"port"` Port int32 `json:"port"`
@ -321,6 +343,11 @@ type AccessConfigForUCloud struct {
ProjectId string `json:"projectId,omitempty"` ProjectId string `json:"projectId,omitempty"`
} }
type AccessConfigForUniCloud struct {
Username string `json:"username"`
Password string `json:"password"`
}
type AccessConfigForUpyun struct { type AccessConfigForUpyun struct {
Username string `json:"username"` Username string `json:"username"`
Password string `json:"password"` Password string `json:"password"`

View File

@ -28,6 +28,7 @@ type Certificate struct {
ACMEAccountUrl string `json:"acmeAccountUrl" db:"acmeAccountUrl"` ACMEAccountUrl string `json:"acmeAccountUrl" db:"acmeAccountUrl"`
ACMECertUrl string `json:"acmeCertUrl" db:"acmeCertUrl"` ACMECertUrl string `json:"acmeCertUrl" db:"acmeCertUrl"`
ACMECertStableUrl string `json:"acmeCertStableUrl" db:"acmeCertStableUrl"` ACMECertStableUrl string `json:"acmeCertStableUrl" db:"acmeCertStableUrl"`
ACMERenewed bool `json:"acmeRenewed" db:"acmeRenewed"`
WorkflowId string `json:"workflowId" db:"workflowId"` WorkflowId string `json:"workflowId" db:"workflowId"`
WorkflowNodeId string `json:"workflowNodeId" db:"workflowNodeId"` WorkflowNodeId string `json:"workflowNodeId" db:"workflowNodeId"`
WorkflowRunId string `json:"workflowRunId" db:"workflowRunId"` WorkflowRunId string `json:"workflowRunId" db:"workflowRunId"`

View File

@ -31,9 +31,12 @@ const (
AccessProviderTypeCTCCCloud = AccessProviderType("ctcccloud") // 天翼云(预留) AccessProviderTypeCTCCCloud = AccessProviderType("ctcccloud") // 天翼云(预留)
AccessProviderTypeCUCCCloud = AccessProviderType("cucccloud") // 联通云(预留) AccessProviderTypeCUCCCloud = AccessProviderType("cucccloud") // 联通云(预留)
AccessProviderTypeDeSEC = AccessProviderType("desec") AccessProviderTypeDeSEC = AccessProviderType("desec")
AccessProviderTypeDigitalOcean = AccessProviderType("digitalocean")
AccessProviderTypeDingTalkBot = AccessProviderType("dingtalkbot") AccessProviderTypeDingTalkBot = AccessProviderType("dingtalkbot")
AccessProviderTypeDiscordBot = AccessProviderType("discordbot")
AccessProviderTypeDNSLA = AccessProviderType("dnsla") AccessProviderTypeDNSLA = AccessProviderType("dnsla")
AccessProviderTypeDogeCloud = AccessProviderType("dogecloud") AccessProviderTypeDogeCloud = AccessProviderType("dogecloud")
AccessProviderTypeDuckDNS = AccessProviderType("duckdns")
AccessProviderTypeDynv6 = AccessProviderType("dynv6") AccessProviderTypeDynv6 = AccessProviderType("dynv6")
AccessProviderTypeEdgio = AccessProviderType("edgio") AccessProviderTypeEdgio = AccessProviderType("edgio")
AccessProviderTypeEmail = AccessProviderType("email") AccessProviderTypeEmail = AccessProviderType("email")
@ -44,6 +47,7 @@ const (
AccessProviderTypeGoDaddy = AccessProviderType("godaddy") AccessProviderTypeGoDaddy = AccessProviderType("godaddy")
AccessProviderTypeGoEdge = AccessProviderType("goedge") AccessProviderTypeGoEdge = AccessProviderType("goedge")
AccessProviderTypeGoogleTrustServices = AccessProviderType("googletrustservices") AccessProviderTypeGoogleTrustServices = AccessProviderType("googletrustservices")
AccessProviderTypeHetzner = AccessProviderType("hetzner")
AccessProviderTypeHuaweiCloud = AccessProviderType("huaweicloud") AccessProviderTypeHuaweiCloud = AccessProviderType("huaweicloud")
AccessProviderTypeJDCloud = AccessProviderType("jdcloud") AccessProviderTypeJDCloud = AccessProviderType("jdcloud")
AccessProviderTypeKubernetes = AccessProviderType("k8s") AccessProviderTypeKubernetes = AccessProviderType("k8s")
@ -67,11 +71,13 @@ const (
AccessProviderTypeRainYun = AccessProviderType("rainyun") AccessProviderTypeRainYun = AccessProviderType("rainyun")
AccessProviderTypeRatPanel = AccessProviderType("ratpanel") AccessProviderTypeRatPanel = AccessProviderType("ratpanel")
AccessProviderTypeSafeLine = AccessProviderType("safeline") AccessProviderTypeSafeLine = AccessProviderType("safeline")
AccessProviderTypeSlackBot = AccessProviderType("slackbot")
AccessProviderTypeSSH = AccessProviderType("ssh") AccessProviderTypeSSH = AccessProviderType("ssh")
AccessProviderTypeSSLCOM = AccessProviderType("sslcom") AccessProviderTypeSSLCOM = AccessProviderType("sslcom")
AccessProviderTypeTelegramBot = AccessProviderType("telegrambot") AccessProviderTypeTelegramBot = AccessProviderType("telegrambot")
AccessProviderTypeTencentCloud = AccessProviderType("tencentcloud") AccessProviderTypeTencentCloud = AccessProviderType("tencentcloud")
AccessProviderTypeUCloud = AccessProviderType("ucloud") AccessProviderTypeUCloud = AccessProviderType("ucloud")
AccessProviderTypeUniCloud = AccessProviderType("unicloud")
AccessProviderTypeUpyun = AccessProviderType("upyun") AccessProviderTypeUpyun = AccessProviderType("upyun")
AccessProviderTypeVercel = AccessProviderType("vercel") AccessProviderTypeVercel = AccessProviderType("vercel")
AccessProviderTypeVolcEngine = AccessProviderType("volcengine") AccessProviderTypeVolcEngine = AccessProviderType("volcengine")
@ -126,11 +132,14 @@ const (
ACMEDns01ProviderTypeClouDNS = ACMEDns01ProviderType(AccessProviderTypeClouDNS) ACMEDns01ProviderTypeClouDNS = ACMEDns01ProviderType(AccessProviderTypeClouDNS)
ACMEDns01ProviderTypeCMCCCloud = ACMEDns01ProviderType(AccessProviderTypeCMCCCloud) ACMEDns01ProviderTypeCMCCCloud = ACMEDns01ProviderType(AccessProviderTypeCMCCCloud)
ACMEDns01ProviderTypeDeSEC = ACMEDns01ProviderType(AccessProviderTypeDeSEC) ACMEDns01ProviderTypeDeSEC = ACMEDns01ProviderType(AccessProviderTypeDeSEC)
ACMEDns01ProviderTypeDigitalOcean = ACMEDns01ProviderType(AccessProviderTypeDigitalOcean)
ACMEDns01ProviderTypeDNSLA = ACMEDns01ProviderType(AccessProviderTypeDNSLA) ACMEDns01ProviderTypeDNSLA = ACMEDns01ProviderType(AccessProviderTypeDNSLA)
ACMEDns01ProviderTypeDuckDNS = ACMEDns01ProviderType(AccessProviderTypeDuckDNS)
ACMEDns01ProviderTypeDynv6 = ACMEDns01ProviderType(AccessProviderTypeDynv6) ACMEDns01ProviderTypeDynv6 = ACMEDns01ProviderType(AccessProviderTypeDynv6)
ACMEDns01ProviderTypeGcore = ACMEDns01ProviderType(AccessProviderTypeGcore) ACMEDns01ProviderTypeGcore = ACMEDns01ProviderType(AccessProviderTypeGcore)
ACMEDns01ProviderTypeGname = ACMEDns01ProviderType(AccessProviderTypeGname) ACMEDns01ProviderTypeGname = ACMEDns01ProviderType(AccessProviderTypeGname)
ACMEDns01ProviderTypeGoDaddy = ACMEDns01ProviderType(AccessProviderTypeGoDaddy) ACMEDns01ProviderTypeGoDaddy = ACMEDns01ProviderType(AccessProviderTypeGoDaddy)
ACMEDns01ProviderTypeHetzner = ACMEDns01ProviderType(AccessProviderTypeHetzner)
ACMEDns01ProviderTypeHuaweiCloud = ACMEDns01ProviderType(AccessProviderTypeHuaweiCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeHuaweiCloudDNS] ACMEDns01ProviderTypeHuaweiCloud = ACMEDns01ProviderType(AccessProviderTypeHuaweiCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeHuaweiCloudDNS]
ACMEDns01ProviderTypeHuaweiCloudDNS = ACMEDns01ProviderType(AccessProviderTypeHuaweiCloud + "-dns") ACMEDns01ProviderTypeHuaweiCloudDNS = ACMEDns01ProviderType(AccessProviderTypeHuaweiCloud + "-dns")
ACMEDns01ProviderTypeJDCloud = ACMEDns01ProviderType(AccessProviderTypeJDCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeJDCloudDNS] ACMEDns01ProviderTypeJDCloud = ACMEDns01ProviderType(AccessProviderTypeJDCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeJDCloudDNS]
@ -236,6 +245,7 @@ const (
DeploymentProviderTypeTencentCloudWAF = DeploymentProviderType(AccessProviderTypeTencentCloud + "-waf") DeploymentProviderTypeTencentCloudWAF = DeploymentProviderType(AccessProviderTypeTencentCloud + "-waf")
DeploymentProviderTypeUCloudUCDN = DeploymentProviderType(AccessProviderTypeUCloud + "-ucdn") DeploymentProviderTypeUCloudUCDN = DeploymentProviderType(AccessProviderTypeUCloud + "-ucdn")
DeploymentProviderTypeUCloudUS3 = DeploymentProviderType(AccessProviderTypeUCloud + "-us3") DeploymentProviderTypeUCloudUS3 = DeploymentProviderType(AccessProviderTypeUCloud + "-us3")
DeploymentProviderTypeUniCloudWebHost = DeploymentProviderType(AccessProviderTypeUniCloud + "-webhost")
DeploymentProviderTypeUpyunCDN = DeploymentProviderType(AccessProviderTypeUpyun + "-cdn") DeploymentProviderTypeUpyunCDN = DeploymentProviderType(AccessProviderTypeUpyun + "-cdn")
DeploymentProviderTypeUpyunFile = DeploymentProviderType(AccessProviderTypeUpyun + "-file") DeploymentProviderTypeUpyunFile = DeploymentProviderType(AccessProviderTypeUpyun + "-file")
DeploymentProviderTypeVolcEngineALB = DeploymentProviderType(AccessProviderTypeVolcEngine + "-alb") DeploymentProviderTypeVolcEngineALB = DeploymentProviderType(AccessProviderTypeVolcEngine + "-alb")
@ -263,9 +273,11 @@ type NotificationProviderType string
*/ */
const ( const (
NotificationProviderTypeDingTalkBot = NotificationProviderType(AccessProviderTypeDingTalkBot) NotificationProviderTypeDingTalkBot = NotificationProviderType(AccessProviderTypeDingTalkBot)
NotificationProviderTypeDiscordBot = NotificationProviderType(AccessProviderTypeDiscordBot)
NotificationProviderTypeEmail = NotificationProviderType(AccessProviderTypeEmail) NotificationProviderTypeEmail = NotificationProviderType(AccessProviderTypeEmail)
NotificationProviderTypeLarkBot = NotificationProviderType(AccessProviderTypeLarkBot) NotificationProviderTypeLarkBot = NotificationProviderType(AccessProviderTypeLarkBot)
NotificationProviderTypeMattermost = NotificationProviderType(AccessProviderTypeMattermost) NotificationProviderTypeMattermost = NotificationProviderType(AccessProviderTypeMattermost)
NotificationProviderTypeSlackBot = NotificationProviderType(AccessProviderTypeSlackBot)
NotificationProviderTypeTelegramBot = NotificationProviderType(AccessProviderTypeTelegramBot) NotificationProviderTypeTelegramBot = NotificationProviderType(AccessProviderTypeTelegramBot)
NotificationProviderTypeWebhook = NotificationProviderType(AccessProviderTypeWebhook) NotificationProviderTypeWebhook = NotificationProviderType(AccessProviderTypeWebhook)
NotificationProviderTypeWeComBot = NotificationProviderType(AccessProviderTypeWeComBot) NotificationProviderTypeWeComBot = NotificationProviderType(AccessProviderTypeWeComBot)

View File

@ -7,9 +7,11 @@ import (
"github.com/usual2970/certimate/internal/domain" "github.com/usual2970/certimate/internal/domain"
"github.com/usual2970/certimate/internal/pkg/core/notifier" "github.com/usual2970/certimate/internal/pkg/core/notifier"
pDingTalkBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/dingtalkbot" pDingTalkBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/dingtalkbot"
pDiscordBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/discordbot"
pEmail "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email" pEmail "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email"
pLarkBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/larkbot" pLarkBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/larkbot"
pMattermost "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/mattermost" pMattermost "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/mattermost"
pSlackBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/slackbot"
pTelegramBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/telegrambot" pTelegramBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/telegrambot"
pWebhook "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/webhook" pWebhook "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/webhook"
pWeComBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/wecombot" pWeComBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/wecombot"
@ -42,6 +44,19 @@ func createNotifierProvider(options *notifierProviderOptions) (notifier.Notifier
}) })
} }
case domain.NotificationProviderTypeDiscordBot:
{
access := domain.AccessConfigForDiscordBot{}
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
return pDiscordBot.NewNotifier(&pDiscordBot.NotifierConfig{
BotToken: access.BotToken,
ChannelId: maputil.GetOrDefaultString(options.ProviderServiceConfig, "channelId", access.DefaultChannelId),
})
}
case domain.NotificationProviderTypeEmail: case domain.NotificationProviderTypeEmail:
{ {
access := domain.AccessConfigForEmail{} access := domain.AccessConfigForEmail{}
@ -87,6 +102,19 @@ func createNotifierProvider(options *notifierProviderOptions) (notifier.Notifier
}) })
} }
case domain.NotificationProviderTypeSlackBot:
{
access := domain.AccessConfigForSlackBot{}
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
return pSlackBot.NewNotifier(&pSlackBot.NotifierConfig{
BotToken: access.BotToken,
ChannelId: maputil.GetOrDefaultString(options.ProviderServiceConfig, "channelId", access.DefaultChannelId),
})
}
case domain.NotificationProviderTypeTelegramBot: case domain.NotificationProviderTypeTelegramBot:
{ {
access := domain.AccessConfigForTelegramBot{} access := domain.AccessConfigForTelegramBot{}

View File

@ -102,9 +102,10 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
return fmt.Errorf("alicloud-esa: could not find zone for domain %q: %w", domain, err) return fmt.Errorf("alicloud-esa: could not find zone for domain %q: %w", domain, err)
} }
siteId, err := d.getSiteId(strings.TrimRight(authZone, ".")) siteName := strings.TrimRight(authZone, ".")
siteId, err := d.getSiteId(siteName)
if err != nil { if err != nil {
return fmt.Errorf("alicloud-esa: could not find site for zone %q: %w", authZone, err) return fmt.Errorf("alicloud-esa: could not find site for zone %q: %w", siteName, err)
} }
if err := d.addOrUpdateDNSRecord(siteId, strings.TrimRight(info.EffectiveFQDN, "."), info.Value); err != nil { if err := d.addOrUpdateDNSRecord(siteId, strings.TrimRight(info.EffectiveFQDN, "."), info.Value); err != nil {
@ -122,9 +123,10 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
return fmt.Errorf("alicloud-esa: could not find zone for domain %q: %w", domain, err) return fmt.Errorf("alicloud-esa: could not find zone for domain %q: %w", domain, err)
} }
siteId, err := d.getSiteId(strings.TrimRight(authZone, ".")) siteName := strings.TrimRight(authZone, ".")
siteId, err := d.getSiteId(siteName)
if err != nil { if err != nil {
return fmt.Errorf("alicloud-esa: could not find site for zone %q: %w", authZone, err) return fmt.Errorf("alicloud-esa: could not find site for zone %q: %w", siteName, err)
} }
if err := d.removeDNSRecord(siteId, strings.TrimRight(info.EffectiveFQDN, ".")); err != nil { if err := d.removeDNSRecord(siteId, strings.TrimRight(info.EffectiveFQDN, ".")); err != nil {

View File

@ -0,0 +1,36 @@
package namedotcom
import (
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/digitalocean"
)
type ChallengeProviderConfig struct {
AccessToken string `json:"accessToken"`
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
DnsTTL int32 `json:"dnsTTL,omitempty"`
}
func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
if config == nil {
panic("config is nil")
}
providerConfig := digitalocean.NewDefaultConfig()
providerConfig.AuthToken = config.AccessToken
if config.DnsPropagationTimeout != 0 {
providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second
}
if config.DnsTTL != 0 {
providerConfig.TTL = int(config.DnsTTL)
}
provider, err := digitalocean.NewDNSProviderConfig(providerConfig)
if err != nil {
return nil, err
}
return provider, nil
}

View File

@ -0,0 +1,32 @@
package namedotcom
import (
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/duckdns"
)
type ChallengeProviderConfig struct {
Token string `json:"token"`
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
}
func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
if config == nil {
panic("config is nil")
}
providerConfig := duckdns.NewDefaultConfig()
providerConfig.Token = config.Token
if config.DnsPropagationTimeout != 0 {
providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second
}
provider, err := duckdns.NewDNSProviderConfig(providerConfig)
if err != nil {
return nil, err
}
return provider, nil
}

View File

@ -0,0 +1,36 @@
package namedotcom
import (
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/hetzner"
)
type ChallengeProviderConfig struct {
ApiToken string `json:"apiToken"`
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
DnsTTL int32 `json:"dnsTTL,omitempty"`
}
func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
if config == nil {
panic("config is nil")
}
providerConfig := hetzner.NewDefaultConfig()
providerConfig.APIKey = config.ApiToken
if config.DnsPropagationTimeout != 0 {
providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second
}
if config.DnsTTL != 0 {
providerConfig.TTL = int(config.DnsTTL)
}
provider, err := hetzner.NewDNSProviderConfig(providerConfig)
if err != nil {
return nil, err
}
return provider, nil
}

View File

@ -11,7 +11,7 @@ import (
) )
type ChallengeProviderConfig struct { type ChallengeProviderConfig struct {
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
ApiKey string `json:"apiKey"` ApiKey string `json:"apiKey"`
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
@ -23,9 +23,9 @@ func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider,
panic("config is nil") panic("config is nil")
} }
host, _ := url.Parse(config.ApiUrl) serverUrl, _ := url.Parse(config.ServerUrl)
providerConfig := pdns.NewDefaultConfig() providerConfig := pdns.NewDefaultConfig()
providerConfig.Host = host providerConfig.Host = serverUrl
providerConfig.APIKey = config.ApiKey providerConfig.APIKey = config.ApiKey
if config.AllowInsecureConnections { if config.AllowInsecureConnections {
providerConfig.HTTPClient.Transport = &http.Transport{ providerConfig.HTTPClient.Transport = &http.Transport{

View File

@ -13,8 +13,8 @@ import (
) )
type DeployerConfig struct { type DeployerConfig struct {
// 1Panel 地址。 // 1Panel 服务地址。
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
// 1Panel 版本。 // 1Panel 版本。
// 可取值 "v1"、"v2"。 // 可取值 "v1"、"v2"。
ApiVersion string `json:"apiVersion"` ApiVersion string `json:"apiVersion"`
@ -39,7 +39,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
panic("config is nil") panic("config is nil")
} }
client, err := createSdkClient(config.ApiUrl, config.ApiVersion, config.ApiKey, config.AllowInsecureConnections) client, err := createSdkClient(config.ServerUrl, config.ApiVersion, config.ApiKey, config.AllowInsecureConnections)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create sdk client: %w", err) return nil, fmt.Errorf("failed to create sdk client: %w", err)
} }
@ -82,9 +82,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
return &deployer.DeployResult{}, nil return &deployer.DeployResult{}, nil
} }
func createSdkClient(apiUrl, apiVersion, apiKey string, skipTlsVerify bool) (*onepanelsdk.Client, error) { func createSdkClient(serverUrl, apiVersion, apiKey string, skipTlsVerify bool) (*onepanelsdk.Client, error) {
if _, err := url.Parse(apiUrl); err != nil { if _, err := url.Parse(serverUrl); err != nil {
return nil, errors.New("invalid 1panel api url") return nil, errors.New("invalid 1panel server url")
} }
if apiVersion == "" { if apiVersion == "" {
@ -95,7 +95,7 @@ func createSdkClient(apiUrl, apiVersion, apiKey string, skipTlsVerify bool) (*on
return nil, errors.New("invalid 1panel api key") return nil, errors.New("invalid 1panel api key")
} }
client := onepanelsdk.NewClient(apiUrl, apiVersion, apiKey) client := onepanelsdk.NewClient(serverUrl, apiVersion, apiKey)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }

View File

@ -14,7 +14,7 @@ import (
var ( var (
fInputCertPath string fInputCertPath string
fInputKeyPath string fInputKeyPath string
fApiUrl string fServerUrl string
fApiVersion string fApiVersion string
fApiKey string fApiKey string
) )
@ -24,7 +24,7 @@ func init() {
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "")
flag.StringVar(&fApiVersion, argsPrefix+"APIVERSION", "v1", "") flag.StringVar(&fApiVersion, argsPrefix+"APIVERSION", "v1", "")
flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "") flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "")
} }
@ -35,7 +35,7 @@ Shell command to run this test:
go test -v ./1panel_console_test.go -args \ go test -v ./1panel_console_test.go -args \
--CERTIMATE_DEPLOYER_1PANELCONSOLE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_1PANELCONSOLE_INPUTCERTPATH="/path/to/your-input-cert.pem" \
--CERTIMATE_DEPLOYER_1PANELCONSOLE_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_1PANELCONSOLE_INPUTKEYPATH="/path/to/your-input-key.pem" \
--CERTIMATE_DEPLOYER_1PANELCONSOLE_APIURL="http://127.0.0.1:20410" \ --CERTIMATE_DEPLOYER_1PANELCONSOLE_SERVERURL="http://127.0.0.1:20410" \
--CERTIMATE_DEPLOYER_1PANELCONSOLE_APIVERSION="v1" \ --CERTIMATE_DEPLOYER_1PANELCONSOLE_APIVERSION="v1" \
--CERTIMATE_DEPLOYER_1PANELCONSOLE_APIKEY="your-api-key" --CERTIMATE_DEPLOYER_1PANELCONSOLE_APIKEY="your-api-key"
*/ */
@ -47,13 +47,13 @@ func TestDeploy(t *testing.T) {
"args:", "args:",
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
fmt.Sprintf("APIURL: %v", fApiUrl), fmt.Sprintf("SERVERURL: %v", fServerUrl),
fmt.Sprintf("APIVERSION: %v", fApiVersion), fmt.Sprintf("APIVERSION: %v", fApiVersion),
fmt.Sprintf("APIKEY: %v", fApiKey), fmt.Sprintf("APIKEY: %v", fApiKey),
}, "\n")) }, "\n"))
deployer, err := provider.NewDeployer(&provider.DeployerConfig{ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
ApiUrl: fApiUrl, ServerUrl: fServerUrl,
ApiVersion: fApiVersion, ApiVersion: fApiVersion,
ApiKey: fApiKey, ApiKey: fApiKey,
AllowInsecureConnections: true, AllowInsecureConnections: true,

View File

@ -16,8 +16,8 @@ import (
) )
type DeployerConfig struct { type DeployerConfig struct {
// 1Panel 地址。 // 1Panel 服务地址。
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
// 1Panel 版本。 // 1Panel 版本。
// 可取值 "v1"、"v2"。 // 可取值 "v1"、"v2"。
ApiVersion string `json:"apiVersion"` ApiVersion string `json:"apiVersion"`
@ -49,15 +49,16 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
panic("config is nil") panic("config is nil")
} }
client, err := createSdkClient(config.ApiUrl, config.ApiVersion, config.ApiKey, config.AllowInsecureConnections) client, err := createSdkClient(config.ServerUrl, config.ApiVersion, config.ApiKey, config.AllowInsecureConnections)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create sdk client: %w", err) return nil, fmt.Errorf("failed to create sdk client: %w", err)
} }
uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
ApiUrl: config.ApiUrl, ServerUrl: config.ServerUrl,
ApiVersion: config.ApiVersion, ApiVersion: config.ApiVersion,
ApiKey: config.ApiKey, ApiKey: config.ApiKey,
AllowInsecureConnections: config.AllowInsecureConnections,
}) })
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create ssl uploader: %w", err) return nil, fmt.Errorf("failed to create ssl uploader: %w", err)
@ -177,9 +178,9 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri
return nil return nil
} }
func createSdkClient(apiUrl, apiVersion, apiKey string, skipTlsVerify bool) (*onepanelsdk.Client, error) { func createSdkClient(serverUrl, apiVersion, apiKey string, skipTlsVerify bool) (*onepanelsdk.Client, error) {
if _, err := url.Parse(apiUrl); err != nil { if _, err := url.Parse(serverUrl); err != nil {
return nil, errors.New("invalid 1panel api url") return nil, errors.New("invalid 1panel server url")
} }
if apiVersion == "" { if apiVersion == "" {
@ -190,7 +191,7 @@ func createSdkClient(apiUrl, apiVersion, apiKey string, skipTlsVerify bool) (*on
return nil, errors.New("invalid 1panel api key") return nil, errors.New("invalid 1panel api key")
} }
client := onepanelsdk.NewClient(apiUrl, apiVersion, apiKey) client := onepanelsdk.NewClient(serverUrl, apiVersion, apiKey)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }

View File

@ -14,7 +14,7 @@ import (
var ( var (
fInputCertPath string fInputCertPath string
fInputKeyPath string fInputKeyPath string
fApiUrl string fServerUrl string
fApiVersion string fApiVersion string
fApiKey string fApiKey string
fWebsiteId int64 fWebsiteId int64
@ -25,7 +25,7 @@ func init() {
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "")
flag.StringVar(&fApiVersion, argsPrefix+"APIVERSION", "v1", "") flag.StringVar(&fApiVersion, argsPrefix+"APIVERSION", "v1", "")
flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "") flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "")
flag.Int64Var(&fWebsiteId, argsPrefix+"WEBSITEID", 0, "") flag.Int64Var(&fWebsiteId, argsPrefix+"WEBSITEID", 0, "")
@ -37,7 +37,7 @@ Shell command to run this test:
go test -v ./1panel_site_test.go -args \ go test -v ./1panel_site_test.go -args \
--CERTIMATE_DEPLOYER_1PANELSITE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_1PANELSITE_INPUTCERTPATH="/path/to/your-input-cert.pem" \
--CERTIMATE_DEPLOYER_1PANELSITE_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_1PANELSITE_INPUTKEYPATH="/path/to/your-input-key.pem" \
--CERTIMATE_DEPLOYER_1PANELSITE_APIURL="http://127.0.0.1:20410" \ --CERTIMATE_DEPLOYER_1PANELSITE_SERVERURL="http://127.0.0.1:20410" \
--CERTIMATE_DEPLOYER_1PANELSITE_APIVERSION="v1" \ --CERTIMATE_DEPLOYER_1PANELSITE_APIVERSION="v1" \
--CERTIMATE_DEPLOYER_1PANELSITE_APIKEY="your-api-key" \ --CERTIMATE_DEPLOYER_1PANELSITE_APIKEY="your-api-key" \
--CERTIMATE_DEPLOYER_1PANELSITE_WEBSITEID="your-website-id" --CERTIMATE_DEPLOYER_1PANELSITE_WEBSITEID="your-website-id"
@ -50,14 +50,14 @@ func TestDeploy(t *testing.T) {
"args:", "args:",
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
fmt.Sprintf("APIURL: %v", fApiUrl), fmt.Sprintf("SERVERURL: %v", fServerUrl),
fmt.Sprintf("APIVERSION: %v", fApiVersion), fmt.Sprintf("APIVERSION: %v", fApiVersion),
fmt.Sprintf("APIKEY: %v", fApiKey), fmt.Sprintf("APIKEY: %v", fApiKey),
fmt.Sprintf("WEBSITEID: %v", fWebsiteId), fmt.Sprintf("WEBSITEID: %v", fWebsiteId),
}, "\n")) }, "\n"))
deployer, err := provider.NewDeployer(&provider.DeployerConfig{ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
ApiUrl: fApiUrl, ServerUrl: fServerUrl,
ApiVersion: fApiVersion, ApiVersion: fApiVersion,
ApiKey: fApiKey, ApiKey: fApiKey,
AllowInsecureConnections: true, AllowInsecureConnections: true,

View File

@ -13,8 +13,8 @@ import (
) )
type DeployerConfig struct { type DeployerConfig struct {
// 宝塔面板地址。 // 宝塔面板服务地址。
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
// 宝塔面板接口密钥。 // 宝塔面板接口密钥。
ApiKey string `json:"apiKey"` ApiKey string `json:"apiKey"`
// 是否允许不安全的连接。 // 是否允许不安全的连接。
@ -36,7 +36,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
panic("config is nil") panic("config is nil")
} }
client, err := createSdkClient(config.ApiUrl, config.ApiKey, config.AllowInsecureConnections) client, err := createSdkClient(config.ServerUrl, config.ApiKey, config.AllowInsecureConnections)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create sdk client: %w", err) return nil, fmt.Errorf("failed to create sdk client: %w", err)
} }
@ -82,16 +82,16 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
return &deployer.DeployResult{}, nil return &deployer.DeployResult{}, nil
} }
func createSdkClient(apiUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) { func createSdkClient(serverUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) {
if _, err := url.Parse(apiUrl); err != nil { if _, err := url.Parse(serverUrl); err != nil {
return nil, errors.New("invalid baota api url") return nil, errors.New("invalid baota server url")
} }
if apiKey == "" { if apiKey == "" {
return nil, errors.New("invalid baota api key") return nil, errors.New("invalid baota api key")
} }
client := btsdk.NewClient(apiUrl, apiKey) client := btsdk.NewClient(serverUrl, apiKey)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }

View File

@ -14,7 +14,7 @@ import (
var ( var (
fInputCertPath string fInputCertPath string
fInputKeyPath string fInputKeyPath string
fApiUrl string fServerUrl string
fApiKey string fApiKey string
) )
@ -23,7 +23,7 @@ func init() {
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "")
flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "") flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "")
} }
@ -33,7 +33,7 @@ Shell command to run this test:
go test -v ./baotapanel_console_test.go -args \ go test -v ./baotapanel_console_test.go -args \
--CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_INPUTCERTPATH="/path/to/your-input-cert.pem" \
--CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_INPUTKEYPATH="/path/to/your-input-key.pem" \
--CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_APIURL="http://127.0.0.1:8888" \ --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_SERVERURL="http://127.0.0.1:8888" \
--CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_APIKEY="your-api-key" --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_APIKEY="your-api-key"
*/ */
func TestDeploy(t *testing.T) { func TestDeploy(t *testing.T) {
@ -44,12 +44,12 @@ func TestDeploy(t *testing.T) {
"args:", "args:",
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
fmt.Sprintf("APIURL: %v", fApiUrl), fmt.Sprintf("SERVERURL: %v", fServerUrl),
fmt.Sprintf("APIKEY: %v", fApiKey), fmt.Sprintf("APIKEY: %v", fApiKey),
}, "\n")) }, "\n"))
deployer, err := provider.NewDeployer(&provider.DeployerConfig{ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
ApiUrl: fApiUrl, ServerUrl: fServerUrl,
ApiKey: fApiKey, ApiKey: fApiKey,
AllowInsecureConnections: true, AllowInsecureConnections: true,
AutoRestart: true, AutoRestart: true,

View File

@ -14,8 +14,8 @@ import (
) )
type DeployerConfig struct { type DeployerConfig struct {
// 宝塔面板地址。 // 宝塔面板服务地址。
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
// 宝塔面板接口密钥。 // 宝塔面板接口密钥。
ApiKey string `json:"apiKey"` ApiKey string `json:"apiKey"`
// 是否允许不安全的连接。 // 是否允许不安全的连接。
@ -41,7 +41,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
panic("config is nil") panic("config is nil")
} }
client, err := createSdkClient(config.ApiUrl, config.ApiKey, config.AllowInsecureConnections) client, err := createSdkClient(config.ServerUrl, config.ApiKey, config.AllowInsecureConnections)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create sdk client: %w", err) return nil, fmt.Errorf("failed to create sdk client: %w", err)
} }
@ -124,16 +124,16 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
return &deployer.DeployResult{}, nil return &deployer.DeployResult{}, nil
} }
func createSdkClient(apiUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) { func createSdkClient(serverUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) {
if _, err := url.Parse(apiUrl); err != nil { if _, err := url.Parse(serverUrl); err != nil {
return nil, errors.New("invalid baota api url") return nil, errors.New("invalid baota server url")
} }
if apiKey == "" { if apiKey == "" {
return nil, errors.New("invalid baota api key") return nil, errors.New("invalid baota api key")
} }
client := btsdk.NewClient(apiUrl, apiKey) client := btsdk.NewClient(serverUrl, apiKey)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }

View File

@ -14,7 +14,7 @@ import (
var ( var (
fInputCertPath string fInputCertPath string
fInputKeyPath string fInputKeyPath string
fApiUrl string fServerUrl string
fApiKey string fApiKey string
fSiteType string fSiteType string
fSiteName string fSiteName string
@ -25,7 +25,7 @@ func init() {
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "")
flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "") flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "")
flag.StringVar(&fSiteType, argsPrefix+"SITETYPE", "", "") flag.StringVar(&fSiteType, argsPrefix+"SITETYPE", "", "")
flag.StringVar(&fSiteName, argsPrefix+"SITENAME", "", "") flag.StringVar(&fSiteName, argsPrefix+"SITENAME", "", "")
@ -37,7 +37,7 @@ Shell command to run this test:
go test -v ./baotapanel_site_test.go -args \ go test -v ./baotapanel_site_test.go -args \
--CERTIMATE_DEPLOYER_BAOTAPANELSITE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_INPUTCERTPATH="/path/to/your-input-cert.pem" \
--CERTIMATE_DEPLOYER_BAOTAPANELSITE_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_INPUTKEYPATH="/path/to/your-input-key.pem" \
--CERTIMATE_DEPLOYER_BAOTAPANELSITE_APIURL="http://127.0.0.1:8888" \ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_SERVERURL="http://127.0.0.1:8888" \
--CERTIMATE_DEPLOYER_BAOTAPANELSITE_APIKEY="your-api-key" \ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_APIKEY="your-api-key" \
--CERTIMATE_DEPLOYER_BAOTAPANELSITE_SITETYPE="php" \ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_SITETYPE="php" \
--CERTIMATE_DEPLOYER_BAOTAPANELSITE_SITENAME="your-site-name" --CERTIMATE_DEPLOYER_BAOTAPANELSITE_SITENAME="your-site-name"
@ -50,14 +50,14 @@ func TestDeploy(t *testing.T) {
"args:", "args:",
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
fmt.Sprintf("APIURL: %v", fApiUrl), fmt.Sprintf("SERVERURL: %v", fServerUrl),
fmt.Sprintf("APIKEY: %v", fApiKey), fmt.Sprintf("APIKEY: %v", fApiKey),
fmt.Sprintf("SITETYPE: %v", fSiteType), fmt.Sprintf("SITETYPE: %v", fSiteType),
fmt.Sprintf("SITENAME: %v", fSiteName), fmt.Sprintf("SITENAME: %v", fSiteName),
}, "\n")) }, "\n"))
deployer, err := provider.NewDeployer(&provider.DeployerConfig{ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
ApiUrl: fApiUrl, ServerUrl: fServerUrl,
ApiKey: fApiKey, ApiKey: fApiKey,
AllowInsecureConnections: true, AllowInsecureConnections: true,
SiteType: fSiteType, SiteType: fSiteType,

View File

@ -13,8 +13,8 @@ import (
) )
type DeployerConfig struct { type DeployerConfig struct {
// 堡塔云 WAF 地址。 // 堡塔云 WAF 服务地址。
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
// 堡塔云 WAF 接口密钥。 // 堡塔云 WAF 接口密钥。
ApiKey string `json:"apiKey"` ApiKey string `json:"apiKey"`
// 是否允许不安全的连接。 // 是否允许不安全的连接。
@ -34,7 +34,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
panic("config is nil") panic("config is nil")
} }
client, err := createSdkClient(config.ApiUrl, config.ApiKey, config.AllowInsecureConnections) client, err := createSdkClient(config.ServerUrl, config.ApiKey, config.AllowInsecureConnections)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create sdk client: %w", err) return nil, fmt.Errorf("failed to create sdk client: %w", err)
} }
@ -70,16 +70,16 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
return &deployer.DeployResult{}, nil return &deployer.DeployResult{}, nil
} }
func createSdkClient(apiUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) { func createSdkClient(serverUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) {
if _, err := url.Parse(apiUrl); err != nil { if _, err := url.Parse(serverUrl); err != nil {
return nil, errors.New("invalid baota api url") return nil, errors.New("invalid baota server url")
} }
if apiKey == "" { if apiKey == "" {
return nil, errors.New("invalid baota api key") return nil, errors.New("invalid baota api key")
} }
client := btsdk.NewClient(apiUrl, apiKey) client := btsdk.NewClient(serverUrl, apiKey)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }

View File

@ -14,7 +14,7 @@ import (
var ( var (
fInputCertPath string fInputCertPath string
fInputKeyPath string fInputKeyPath string
fApiUrl string fServerUrl string
fApiKey string fApiKey string
fSiteName string fSiteName string
fSitePort int64 fSitePort int64
@ -25,7 +25,7 @@ func init() {
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "")
flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "") flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "")
} }
@ -35,7 +35,7 @@ Shell command to run this test:
go test -v ./baotawaf_console_test.go -args \ go test -v ./baotawaf_console_test.go -args \
--CERTIMATE_DEPLOYER_BAOTAWAFCONSOLE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_BAOTAWAFCONSOLE_INPUTCERTPATH="/path/to/your-input-cert.pem" \
--CERTIMATE_DEPLOYER_BAOTAWAFCONSOLE_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_BAOTAWAFCONSOLE_INPUTKEYPATH="/path/to/your-input-key.pem" \
--CERTIMATE_DEPLOYER_BAOTAWAFCONSOLE_APIURL="http://127.0.0.1:8888" \ --CERTIMATE_DEPLOYER_BAOTAWAFCONSOLE_SERVERURL="http://127.0.0.1:8888" \
--CERTIMATE_DEPLOYER_BAOTAWAFCONSOLE_APIKEY="your-api-key" --CERTIMATE_DEPLOYER_BAOTAWAFCONSOLE_APIKEY="your-api-key"
*/ */
func TestDeploy(t *testing.T) { func TestDeploy(t *testing.T) {
@ -46,12 +46,12 @@ func TestDeploy(t *testing.T) {
"args:", "args:",
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
fmt.Sprintf("APIURL: %v", fApiUrl), fmt.Sprintf("SERVERURL: %v", fServerUrl),
fmt.Sprintf("APIKEY: %v", fApiKey), fmt.Sprintf("APIKEY: %v", fApiKey),
}, "\n")) }, "\n"))
deployer, err := provider.NewDeployer(&provider.DeployerConfig{ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
ApiUrl: fApiUrl, ServerUrl: fServerUrl,
ApiKey: fApiKey, ApiKey: fApiKey,
AllowInsecureConnections: true, AllowInsecureConnections: true,
}) })

View File

@ -14,8 +14,8 @@ import (
) )
type DeployerConfig struct { type DeployerConfig struct {
// 堡塔云 WAF 地址。 // 堡塔云 WAF 服务地址。
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
// 堡塔云 WAF 接口密钥。 // 堡塔云 WAF 接口密钥。
ApiKey string `json:"apiKey"` ApiKey string `json:"apiKey"`
// 是否允许不安全的连接。 // 是否允许不安全的连接。
@ -40,7 +40,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
panic("config is nil") panic("config is nil")
} }
client, err := createSdkClient(config.ApiUrl, config.ApiKey, config.AllowInsecureConnections) client, err := createSdkClient(config.ServerUrl, config.ApiKey, config.AllowInsecureConnections)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create sdk client: %w", err) return nil, fmt.Errorf("failed to create sdk client: %w", err)
} }
@ -133,16 +133,16 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
return &deployer.DeployResult{}, nil return &deployer.DeployResult{}, nil
} }
func createSdkClient(apiUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) { func createSdkClient(serverUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) {
if _, err := url.Parse(apiUrl); err != nil { if _, err := url.Parse(serverUrl); err != nil {
return nil, errors.New("invalid baota api url") return nil, errors.New("invalid baota server url")
} }
if apiKey == "" { if apiKey == "" {
return nil, errors.New("invalid baota api key") return nil, errors.New("invalid baota api key")
} }
client := btsdk.NewClient(apiUrl, apiKey) client := btsdk.NewClient(serverUrl, apiKey)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }

View File

@ -14,7 +14,7 @@ import (
var ( var (
fInputCertPath string fInputCertPath string
fInputKeyPath string fInputKeyPath string
fApiUrl string fServerUrl string
fApiKey string fApiKey string
fSiteName string fSiteName string
fSitePort int64 fSitePort int64
@ -25,7 +25,7 @@ func init() {
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "")
flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "") flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "")
flag.StringVar(&fSiteName, argsPrefix+"SITENAME", "", "") flag.StringVar(&fSiteName, argsPrefix+"SITENAME", "", "")
flag.Int64Var(&fSitePort, argsPrefix+"SITEPORT", 0, "") flag.Int64Var(&fSitePort, argsPrefix+"SITEPORT", 0, "")
@ -37,7 +37,7 @@ Shell command to run this test:
go test -v ./baotawaf_site_test.go -args \ go test -v ./baotawaf_site_test.go -args \
--CERTIMATE_DEPLOYER_BAOTAWAFSITE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_BAOTAWAFSITE_INPUTCERTPATH="/path/to/your-input-cert.pem" \
--CERTIMATE_DEPLOYER_BAOTAWAFSITE_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_BAOTAWAFSITE_INPUTKEYPATH="/path/to/your-input-key.pem" \
--CERTIMATE_DEPLOYER_BAOTAWAFSITE_APIURL="http://127.0.0.1:8888" \ --CERTIMATE_DEPLOYER_BAOTAWAFSITE_SERVERURL="http://127.0.0.1:8888" \
--CERTIMATE_DEPLOYER_BAOTAWAFSITE_APIKEY="your-api-key" \ --CERTIMATE_DEPLOYER_BAOTAWAFSITE_APIKEY="your-api-key" \
--CERTIMATE_DEPLOYER_BAOTAWAFSITE_SITENAME="your-site-name"\ --CERTIMATE_DEPLOYER_BAOTAWAFSITE_SITENAME="your-site-name"\
--CERTIMATE_DEPLOYER_BAOTAWAFSITE_SITEPORT=443 --CERTIMATE_DEPLOYER_BAOTAWAFSITE_SITEPORT=443
@ -50,14 +50,14 @@ func TestDeploy(t *testing.T) {
"args:", "args:",
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
fmt.Sprintf("APIURL: %v", fApiUrl), fmt.Sprintf("SERVERURL: %v", fServerUrl),
fmt.Sprintf("APIKEY: %v", fApiKey), fmt.Sprintf("APIKEY: %v", fApiKey),
fmt.Sprintf("SITENAME: %v", fSiteName), fmt.Sprintf("SITENAME: %v", fSiteName),
fmt.Sprintf("SITEPORT: %v", fSitePort), fmt.Sprintf("SITEPORT: %v", fSitePort),
}, "\n")) }, "\n"))
deployer, err := provider.NewDeployer(&provider.DeployerConfig{ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
ApiUrl: fApiUrl, ServerUrl: fServerUrl,
ApiKey: fApiKey, ApiKey: fApiKey,
AllowInsecureConnections: true, AllowInsecureConnections: true,
SiteName: fSiteName, SiteName: fSiteName,

View File

@ -15,8 +15,8 @@ import (
) )
type DeployerConfig struct { type DeployerConfig struct {
// Cdnfly 地址。 // Cdnfly 服务地址。
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
// Cdnfly 用户端 API Key。 // Cdnfly 用户端 API Key。
ApiKey string `json:"apiKey"` ApiKey string `json:"apiKey"`
// Cdnfly 用户端 API Secret。 // Cdnfly 用户端 API Secret。
@ -46,7 +46,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
panic("config is nil") panic("config is nil")
} }
client, err := createSdkClient(config.ApiUrl, config.ApiKey, config.ApiSecret, config.AllowInsecureConnections) client, err := createSdkClient(config.ServerUrl, config.ApiKey, config.ApiSecret, config.AllowInsecureConnections)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create sdk client: %w", err) return nil, fmt.Errorf("failed to create sdk client: %w", err)
} }
@ -160,9 +160,9 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri
return nil return nil
} }
func createSdkClient(apiUrl, apiKey, apiSecret string, skipTlsVerify bool) (*cfsdk.Client, error) { func createSdkClient(serverUrl, apiKey, apiSecret string, skipTlsVerify bool) (*cfsdk.Client, error) {
if _, err := url.Parse(apiUrl); err != nil { if _, err := url.Parse(serverUrl); err != nil {
return nil, errors.New("invalid cachefly api url") return nil, errors.New("invalid cachefly server url")
} }
if apiKey == "" { if apiKey == "" {
@ -173,7 +173,7 @@ func createSdkClient(apiUrl, apiKey, apiSecret string, skipTlsVerify bool) (*cfs
return nil, errors.New("invalid cachefly api secret") return nil, errors.New("invalid cachefly api secret")
} }
client := cfsdk.NewClient(apiUrl, apiKey, apiSecret) client := cfsdk.NewClient(serverUrl, apiKey, apiSecret)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }

View File

@ -14,7 +14,7 @@ import (
var ( var (
fInputCertPath string fInputCertPath string
fInputKeyPath string fInputKeyPath string
fApiUrl string fServerUrl string
fApiKey string fApiKey string
fApiSecret string fApiSecret string
fCertificateId string fCertificateId string
@ -25,7 +25,7 @@ func init() {
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "")
flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "") flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "")
flag.StringVar(&fApiSecret, argsPrefix+"APISECRET", "", "") flag.StringVar(&fApiSecret, argsPrefix+"APISECRET", "", "")
flag.StringVar(&fCertificateId, argsPrefix+"CERTIFICATEID", "", "") flag.StringVar(&fCertificateId, argsPrefix+"CERTIFICATEID", "", "")
@ -37,7 +37,7 @@ Shell command to run this test:
go test -v ./cdnfly_test.go -args \ go test -v ./cdnfly_test.go -args \
--CERTIMATE_DEPLOYER_CDNFLY_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_CDNFLY_INPUTCERTPATH="/path/to/your-input-cert.pem" \
--CERTIMATE_DEPLOYER_CDNFLY_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_CDNFLY_INPUTKEYPATH="/path/to/your-input-key.pem" \
--CERTIMATE_DEPLOYER_CDNFLY_APIURL="http://127.0.0.1:88" \ --CERTIMATE_DEPLOYER_CDNFLY_SERVERURL="http://127.0.0.1:88" \
--CERTIMATE_DEPLOYER_CDNFLY_APIKEY="your-api-key" \ --CERTIMATE_DEPLOYER_CDNFLY_APIKEY="your-api-key" \
--CERTIMATE_DEPLOYER_CDNFLY_APISECRET="your-api-secret" \ --CERTIMATE_DEPLOYER_CDNFLY_APISECRET="your-api-secret" \
--CERTIMATE_DEPLOYER_CDNFLY_CERTIFICATEID="your-cert-id" --CERTIMATE_DEPLOYER_CDNFLY_CERTIFICATEID="your-cert-id"
@ -50,14 +50,14 @@ func TestDeploy(t *testing.T) {
"args:", "args:",
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
fmt.Sprintf("APIURL: %v", fApiUrl), fmt.Sprintf("SERVERURL: %v", fServerUrl),
fmt.Sprintf("APIKEY: %v", fApiKey), fmt.Sprintf("APIKEY: %v", fApiKey),
fmt.Sprintf("APISECRET: %v", fApiSecret), fmt.Sprintf("APISECRET: %v", fApiSecret),
fmt.Sprintf("CERTIFICATEID: %v", fCertificateId), fmt.Sprintf("CERTIFICATEID: %v", fCertificateId),
}, "\n")) }, "\n"))
deployer, err := provider.NewDeployer(&provider.DeployerConfig{ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
ApiUrl: fApiUrl, ServerUrl: fServerUrl,
ApiKey: fApiKey, ApiKey: fApiKey,
ApiSecret: fApiSecret, ApiSecret: fApiSecret,
AllowInsecureConnections: true, AllowInsecureConnections: true,

View File

@ -16,8 +16,8 @@ import (
) )
type DeployerConfig struct { type DeployerConfig struct {
// FlexCDN URL // FlexCDN 服务地址
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
// FlexCDN 用户角色。 // FlexCDN 用户角色。
// 可取值 "user"、"admin"。 // 可取值 "user"、"admin"。
ApiRole string `json:"apiRole"` ApiRole string `json:"apiRole"`
@ -47,7 +47,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
panic("config is nil") panic("config is nil")
} }
client, err := createSdkClient(config.ApiUrl, config.ApiRole, config.AccessKeyId, config.AccessKey, config.AllowInsecureConnections) client, err := createSdkClient(config.ServerUrl, config.ApiRole, config.AccessKeyId, config.AccessKey, config.AllowInsecureConnections)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create sdk client: %w", err) return nil, fmt.Errorf("failed to create sdk client: %w", err)
} }
@ -119,9 +119,9 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri
return nil return nil
} }
func createSdkClient(apiUrl, apiRole, accessKeyId, accessKey string, skipTlsVerify bool) (*flexcdnsdk.Client, error) { func createSdkClient(serverUrl, apiRole, accessKeyId, accessKey string, skipTlsVerify bool) (*flexcdnsdk.Client, error) {
if _, err := url.Parse(apiUrl); err != nil { if _, err := url.Parse(serverUrl); err != nil {
return nil, errors.New("invalid flexcdn api url") return nil, errors.New("invalid flexcdn server url")
} }
if apiRole != "user" && apiRole != "admin" { if apiRole != "user" && apiRole != "admin" {
@ -136,7 +136,7 @@ func createSdkClient(apiUrl, apiRole, accessKeyId, accessKey string, skipTlsVeri
return nil, errors.New("invalid flexcdn access key") return nil, errors.New("invalid flexcdn access key")
} }
client := flexcdnsdk.NewClient(apiUrl, apiRole, accessKeyId, accessKey) client := flexcdnsdk.NewClient(serverUrl, apiRole, accessKeyId, accessKey)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }

View File

@ -14,7 +14,7 @@ import (
var ( var (
fInputCertPath string fInputCertPath string
fInputKeyPath string fInputKeyPath string
fApiUrl string fServerUrl string
fAccessKeyId string fAccessKeyId string
fAccessKey string fAccessKey string
fCertificateId int64 fCertificateId int64
@ -25,7 +25,7 @@ func init() {
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "")
flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "") flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "")
flag.StringVar(&fAccessKey, argsPrefix+"ACCESSKEY", "", "") flag.StringVar(&fAccessKey, argsPrefix+"ACCESSKEY", "", "")
flag.Int64Var(&fCertificateId, argsPrefix+"CERTIFICATEID", 0, "") flag.Int64Var(&fCertificateId, argsPrefix+"CERTIFICATEID", 0, "")
@ -37,7 +37,7 @@ Shell command to run this test:
go test -v ./flexcdn_test.go -args \ go test -v ./flexcdn_test.go -args \
--CERTIMATE_DEPLOYER_FLEXCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_FLEXCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \
--CERTIMATE_DEPLOYER_FLEXCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_FLEXCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \
--CERTIMATE_DEPLOYER_FLEXCDN_APIURL="http://127.0.0.1:7788" \ --CERTIMATE_DEPLOYER_FLEXCDN_SERVERURL="http://127.0.0.1:7788" \
--CERTIMATE_DEPLOYER_FLEXCDN_ACCESSKEYID="your-access-key-id" \ --CERTIMATE_DEPLOYER_FLEXCDN_ACCESSKEYID="your-access-key-id" \
--CERTIMATE_DEPLOYER_FLEXCDN_ACCESSKEY="your-access-key" \ --CERTIMATE_DEPLOYER_FLEXCDN_ACCESSKEY="your-access-key" \
--CERTIMATE_DEPLOYER_FLEXCDN_CERTIFICATEID="your-cerficiate-id" --CERTIMATE_DEPLOYER_FLEXCDN_CERTIFICATEID="your-cerficiate-id"
@ -50,14 +50,14 @@ func TestDeploy(t *testing.T) {
"args:", "args:",
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
fmt.Sprintf("APIURL: %v", fApiUrl), fmt.Sprintf("SERVERURL: %v", fServerUrl),
fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId), fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId),
fmt.Sprintf("ACCESSKEY: %v", fAccessKey), fmt.Sprintf("ACCESSKEY: %v", fAccessKey),
fmt.Sprintf("CERTIFICATEID: %v", fCertificateId), fmt.Sprintf("CERTIFICATEID: %v", fCertificateId),
}, "\n")) }, "\n"))
deployer, err := provider.NewDeployer(&provider.DeployerConfig{ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
ApiUrl: fApiUrl, ServerUrl: fServerUrl,
ApiRole: "user", ApiRole: "user",
AccessKeyId: fAccessKeyId, AccessKeyId: fAccessKeyId,
AccessKey: fAccessKey, AccessKey: fAccessKey,

View File

@ -16,8 +16,8 @@ import (
) )
type DeployerConfig struct { type DeployerConfig struct {
// GoEdge URL // GoEdge 服务地址
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
// GoEdge 用户角色。 // GoEdge 用户角色。
// 可取值 "user"、"admin"。 // 可取值 "user"、"admin"。
ApiRole string `json:"apiRole"` ApiRole string `json:"apiRole"`
@ -47,7 +47,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
panic("config is nil") panic("config is nil")
} }
client, err := createSdkClient(config.ApiUrl, config.ApiRole, config.AccessKeyId, config.AccessKey, config.AllowInsecureConnections) client, err := createSdkClient(config.ServerUrl, config.ApiRole, config.AccessKeyId, config.AccessKey, config.AllowInsecureConnections)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create sdk client: %w", err) return nil, fmt.Errorf("failed to create sdk client: %w", err)
} }
@ -119,9 +119,9 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri
return nil return nil
} }
func createSdkClient(apiUrl, apiRole, accessKeyId, accessKey string, skipTlsVerify bool) (*goedgesdk.Client, error) { func createSdkClient(serverUrl, apiRole, accessKeyId, accessKey string, skipTlsVerify bool) (*goedgesdk.Client, error) {
if _, err := url.Parse(apiUrl); err != nil { if _, err := url.Parse(serverUrl); err != nil {
return nil, errors.New("invalid goedge api url") return nil, errors.New("invalid goedge server url")
} }
if apiRole != "user" && apiRole != "admin" { if apiRole != "user" && apiRole != "admin" {
@ -136,7 +136,7 @@ func createSdkClient(apiUrl, apiRole, accessKeyId, accessKey string, skipTlsVeri
return nil, errors.New("invalid goedge access key") return nil, errors.New("invalid goedge access key")
} }
client := goedgesdk.NewClient(apiUrl, apiRole, accessKeyId, accessKey) client := goedgesdk.NewClient(serverUrl, apiRole, accessKeyId, accessKey)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }

View File

@ -14,7 +14,7 @@ import (
var ( var (
fInputCertPath string fInputCertPath string
fInputKeyPath string fInputKeyPath string
fApiUrl string fServerUrl string
fAccessKeyId string fAccessKeyId string
fAccessKey string fAccessKey string
fCertificateId int64 fCertificateId int64
@ -25,7 +25,7 @@ func init() {
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "")
flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "") flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "")
flag.StringVar(&fAccessKey, argsPrefix+"ACCESSKEY", "", "") flag.StringVar(&fAccessKey, argsPrefix+"ACCESSKEY", "", "")
flag.Int64Var(&fCertificateId, argsPrefix+"CERTIFICATEID", 0, "") flag.Int64Var(&fCertificateId, argsPrefix+"CERTIFICATEID", 0, "")
@ -37,7 +37,7 @@ Shell command to run this test:
go test -v ./goedge_test.go -args \ go test -v ./goedge_test.go -args \
--CERTIMATE_DEPLOYER_GOEDGE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_GOEDGE_INPUTCERTPATH="/path/to/your-input-cert.pem" \
--CERTIMATE_DEPLOYER_GOEDGE_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_GOEDGE_INPUTKEYPATH="/path/to/your-input-key.pem" \
--CERTIMATE_DEPLOYER_GOEDGE_APIURL="http://127.0.0.1:7788" \ --CERTIMATE_DEPLOYER_GOEDGE_SERVERURL="http://127.0.0.1:7788" \
--CERTIMATE_DEPLOYER_GOEDGE_ACCESSKEYID="your-access-key-id" \ --CERTIMATE_DEPLOYER_GOEDGE_ACCESSKEYID="your-access-key-id" \
--CERTIMATE_DEPLOYER_GOEDGE_ACCESSKEY="your-access-key" \ --CERTIMATE_DEPLOYER_GOEDGE_ACCESSKEY="your-access-key" \
--CERTIMATE_DEPLOYER_GOEDGE_CERTIFICATEID="your-cerficiate-id" --CERTIMATE_DEPLOYER_GOEDGE_CERTIFICATEID="your-cerficiate-id"
@ -50,14 +50,14 @@ func TestDeploy(t *testing.T) {
"args:", "args:",
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
fmt.Sprintf("APIURL: %v", fApiUrl), fmt.Sprintf("SERVERURL: %v", fServerUrl),
fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId), fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId),
fmt.Sprintf("ACCESSKEY: %v", fAccessKey), fmt.Sprintf("ACCESSKEY: %v", fAccessKey),
fmt.Sprintf("CERTIFICATEID: %v", fCertificateId), fmt.Sprintf("CERTIFICATEID: %v", fCertificateId),
}, "\n")) }, "\n"))
deployer, err := provider.NewDeployer(&provider.DeployerConfig{ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
ApiUrl: fApiUrl, ServerUrl: fServerUrl,
ApiRole: "user", ApiRole: "user",
AccessKeyId: fAccessKeyId, AccessKeyId: fAccessKeyId,
AccessKey: fAccessKey, AccessKey: fAccessKey,

View File

@ -15,8 +15,8 @@ import (
) )
type DeployerConfig struct { type DeployerConfig struct {
// LeCDN URL // LeCDN 服务地址
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
// LeCDN 版本。 // LeCDN 版本。
// 可取值 "v3"。 // 可取值 "v3"。
ApiVersion string `json:"apiVersion"` ApiVersion string `json:"apiVersion"`
@ -59,7 +59,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
panic("config is nil") panic("config is nil")
} }
client, err := createSdkClient(config.ApiUrl, config.ApiVersion, config.ApiRole, config.Username, config.Password, config.AllowInsecureConnections) client, err := createSdkClient(config.ServerUrl, config.ApiVersion, config.ApiRole, config.Username, config.Password, config.AllowInsecureConnections)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create sdk client: %w", err) return nil, fmt.Errorf("failed to create sdk client: %w", err)
} }
@ -141,9 +141,9 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri
return nil return nil
} }
func createSdkClient(apiUrl, apiVersion, apiRole, username, password string, skipTlsVerify bool) (interface{}, error) { func createSdkClient(serverUrl, apiVersion, apiRole, username, password string, skipTlsVerify bool) (interface{}, error) {
if _, err := url.Parse(apiUrl); err != nil { if _, err := url.Parse(serverUrl); err != nil {
return nil, errors.New("invalid lecdn api url") return nil, errors.New("invalid lecdn server url")
} }
if username == "" { if username == "" {
@ -156,7 +156,7 @@ func createSdkClient(apiUrl, apiVersion, apiRole, username, password string, ski
if apiVersion == apiVersionV3 && apiRole == apiRoleClient { if apiVersion == apiVersionV3 && apiRole == apiRoleClient {
// v3 版客户端 // v3 版客户端
client := leclientsdkv3.NewClient(apiUrl, username, password) client := leclientsdkv3.NewClient(serverUrl, username, password)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }
@ -164,7 +164,7 @@ func createSdkClient(apiUrl, apiVersion, apiRole, username, password string, ski
return client, nil return client, nil
} else if apiVersion == apiVersionV3 && apiRole == apiRoleMaster { } else if apiVersion == apiVersionV3 && apiRole == apiRoleMaster {
// v3 版主控端 // v3 版主控端
client := lemastersdkv3.NewClient(apiUrl, username, password) client := lemastersdkv3.NewClient(serverUrl, username, password)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }

View File

@ -14,7 +14,7 @@ import (
var ( var (
fInputCertPath string fInputCertPath string
fInputKeyPath string fInputKeyPath string
fApiUrl string fServerUrl string
fApiVersion string fApiVersion string
fUsername string fUsername string
fPassword string fPassword string
@ -26,7 +26,7 @@ func init() {
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "")
flag.StringVar(&fApiVersion, argsPrefix+"APIVERSION", "v3", "") flag.StringVar(&fApiVersion, argsPrefix+"APIVERSION", "v3", "")
flag.StringVar(&fUsername, argsPrefix+"USERNAME", "", "") flag.StringVar(&fUsername, argsPrefix+"USERNAME", "", "")
flag.StringVar(&fPassword, argsPrefix+"PASSWORD", "", "") flag.StringVar(&fPassword, argsPrefix+"PASSWORD", "", "")
@ -39,7 +39,7 @@ Shell command to run this test:
go test -v ./lecdn_test.go -args \ go test -v ./lecdn_test.go -args \
--CERTIMATE_DEPLOYER_LECDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_LECDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \
--CERTIMATE_DEPLOYER_LECDN_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_LECDN_INPUTKEYPATH="/path/to/your-input-key.pem" \
--CERTIMATE_DEPLOYER_LECDN_APIURL="http://127.0.0.1:5090" \ --CERTIMATE_DEPLOYER_LECDN_SERVERURL="http://127.0.0.1:5090" \
--CERTIMATE_DEPLOYER_LECDN_USERNAME="your-username" \ --CERTIMATE_DEPLOYER_LECDN_USERNAME="your-username" \
--CERTIMATE_DEPLOYER_LECDN_PASSWORD="your-password" \ --CERTIMATE_DEPLOYER_LECDN_PASSWORD="your-password" \
--CERTIMATE_DEPLOYER_LECDN_CERTIFICATEID="your-cerficiate-id" --CERTIMATE_DEPLOYER_LECDN_CERTIFICATEID="your-cerficiate-id"
@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) {
"args:", "args:",
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
fmt.Sprintf("APIURL: %v", fApiUrl), fmt.Sprintf("SERVERURL: %v", fServerUrl),
fmt.Sprintf("APIVERSION: %v", fApiVersion), fmt.Sprintf("APIVERSION: %v", fApiVersion),
fmt.Sprintf("USERNAME: %v", fUsername), fmt.Sprintf("USERNAME: %v", fUsername),
fmt.Sprintf("PASSWORD: %v", fPassword), fmt.Sprintf("PASSWORD: %v", fPassword),
@ -60,7 +60,7 @@ func TestDeploy(t *testing.T) {
}, "\n")) }, "\n"))
deployer, err := provider.NewDeployer(&provider.DeployerConfig{ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
ApiUrl: fApiUrl, ServerUrl: fServerUrl,
ApiVersion: fApiVersion, ApiVersion: fApiVersion,
ApiRole: "user", ApiRole: "user",
Username: fUsername, Username: fUsername,

View File

@ -16,8 +16,8 @@ import (
) )
type DeployerConfig struct { type DeployerConfig struct {
// Proxmox VE 地址。 // Proxmox VE 服务地址。
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
// Proxmox VE API Token。 // Proxmox VE API Token。
ApiToken string `json:"apiToken"` ApiToken string `json:"apiToken"`
// Proxmox VE API Token Secret。 // Proxmox VE API Token Secret。
@ -43,7 +43,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
panic("config is nil") panic("config is nil")
} }
client, err := createSdkClient(config.ApiUrl, config.ApiToken, config.ApiTokenSecret, config.AllowInsecureConnections) client, err := createSdkClient(config.ServerUrl, config.ApiToken, config.ApiTokenSecret, config.AllowInsecureConnections)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create sdk client: %w", err) return nil, fmt.Errorf("failed to create sdk client: %w", err)
} }
@ -91,9 +91,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
return &deployer.DeployResult{}, nil return &deployer.DeployResult{}, nil
} }
func createSdkClient(apiUrl, apiToken, apiTokenSecret string, skipTlsVerify bool) (*proxmox.Client, error) { func createSdkClient(serverUrl, apiToken, apiTokenSecret string, skipTlsVerify bool) (*proxmox.Client, error) {
if _, err := url.Parse(apiUrl); err != nil { if _, err := url.Parse(serverUrl); err != nil {
return nil, errors.New("invalid pve api url") return nil, errors.New("invalid pve server url")
} }
if apiToken == "" { if apiToken == "" {
@ -112,7 +112,7 @@ func createSdkClient(apiUrl, apiToken, apiTokenSecret string, skipTlsVerify bool
} }
} }
client := proxmox.NewClient( client := proxmox.NewClient(
strings.TrimRight(apiUrl, "/")+"/api2/json", strings.TrimRight(serverUrl, "/")+"/api2/json",
proxmox.WithHTTPClient(httpClient), proxmox.WithHTTPClient(httpClient),
proxmox.WithAPIToken(apiToken, apiTokenSecret), proxmox.WithAPIToken(apiToken, apiTokenSecret),
) )

View File

@ -14,7 +14,7 @@ import (
var ( var (
fInputCertPath string fInputCertPath string
fInputKeyPath string fInputKeyPath string
fApiUrl string fServerUrl string
fApiToken string fApiToken string
fApiTokenSecret string fApiTokenSecret string
fNodeName string fNodeName string
@ -25,7 +25,7 @@ func init() {
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "")
flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "") flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "")
flag.StringVar(&fApiTokenSecret, argsPrefix+"APITOKENSECRET", "", "") flag.StringVar(&fApiTokenSecret, argsPrefix+"APITOKENSECRET", "", "")
flag.StringVar(&fNodeName, argsPrefix+"NODENAME", "", "") flag.StringVar(&fNodeName, argsPrefix+"NODENAME", "", "")
@ -37,7 +37,7 @@ Shell command to run this test:
go test -v ./proxmoxve_test.go -args \ go test -v ./proxmoxve_test.go -args \
--CERTIMATE_DEPLOYER_PROXMOXVE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_PROXMOXVE_INPUTCERTPATH="/path/to/your-input-cert.pem" \
--CERTIMATE_DEPLOYER_PROXMOXVE_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_PROXMOXVE_INPUTKEYPATH="/path/to/your-input-key.pem" \
--CERTIMATE_DEPLOYER_PROXMOXVE_APIURL="http://127.0.0.1:8006" \ --CERTIMATE_DEPLOYER_PROXMOXVE_SERVERURL="http://127.0.0.1:8006" \
--CERTIMATE_DEPLOYER_PROXMOXVE_APITOKEN="your-api-token" \ --CERTIMATE_DEPLOYER_PROXMOXVE_APITOKEN="your-api-token" \
--CERTIMATE_DEPLOYER_PROXMOXVE_APITOKENSECRET="your-api-token-secret" \ --CERTIMATE_DEPLOYER_PROXMOXVE_APITOKENSECRET="your-api-token-secret" \
--CERTIMATE_DEPLOYER_PROXMOXVE_NODENAME="your-cluster-node-name" --CERTIMATE_DEPLOYER_PROXMOXVE_NODENAME="your-cluster-node-name"
@ -50,14 +50,14 @@ func TestDeploy(t *testing.T) {
"args:", "args:",
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
fmt.Sprintf("APIURL: %v", fApiUrl), fmt.Sprintf("SERVERURL: %v", fServerUrl),
fmt.Sprintf("APITOKEN: %v", fApiToken), fmt.Sprintf("APITOKEN: %v", fApiToken),
fmt.Sprintf("APITOKENSECRET: %v", fApiTokenSecret), fmt.Sprintf("APITOKENSECRET: %v", fApiTokenSecret),
fmt.Sprintf("NODENAME: %v", fNodeName), fmt.Sprintf("NODENAME: %v", fNodeName),
}, "\n")) }, "\n"))
deployer, err := provider.NewDeployer(&provider.DeployerConfig{ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
ApiUrl: fApiUrl, ServerUrl: fServerUrl,
ApiToken: fApiToken, ApiToken: fApiToken,
ApiTokenSecret: fApiTokenSecret, ApiTokenSecret: fApiTokenSecret,
AllowInsecureConnections: true, AllowInsecureConnections: true,

View File

@ -13,8 +13,8 @@ import (
) )
type DeployerConfig struct { type DeployerConfig struct {
// 耗子面板地址。 // 耗子面板服务地址。
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
// 耗子面板访问令牌 ID。 // 耗子面板访问令牌 ID。
AccessTokenId int32 `json:"accessTokenId"` AccessTokenId int32 `json:"accessTokenId"`
// 耗子面板访问令牌。 // 耗子面板访问令牌。
@ -36,7 +36,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
panic("config is nil") panic("config is nil")
} }
client, err := createSdkClient(config.ApiUrl, config.AccessTokenId, config.AccessToken, config.AllowInsecureConnections) client, err := createSdkClient(config.ServerUrl, config.AccessTokenId, config.AccessToken, config.AllowInsecureConnections)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create sdk client: %w", err) return nil, fmt.Errorf("failed to create sdk client: %w", err)
} }
@ -72,9 +72,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
return &deployer.DeployResult{}, nil return &deployer.DeployResult{}, nil
} }
func createSdkClient(apiUrl string, accessTokenId int32, accessToken string, skipTlsVerify bool) (*rpsdk.Client, error) { func createSdkClient(serverUrl string, accessTokenId int32, accessToken string, skipTlsVerify bool) (*rpsdk.Client, error) {
if _, err := url.Parse(apiUrl); err != nil { if _, err := url.Parse(serverUrl); err != nil {
return nil, errors.New("invalid ratpanel api url") return nil, errors.New("invalid ratpanel server url")
} }
if accessTokenId == 0 { if accessTokenId == 0 {
@ -85,7 +85,7 @@ func createSdkClient(apiUrl string, accessTokenId int32, accessToken string, ski
return nil, errors.New("invalid ratpanel access token") return nil, errors.New("invalid ratpanel access token")
} }
client := rpsdk.NewClient(apiUrl, accessTokenId, accessToken) client := rpsdk.NewClient(serverUrl, accessTokenId, accessToken)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }

View File

@ -14,7 +14,7 @@ import (
var ( var (
fInputCertPath string fInputCertPath string
fInputKeyPath string fInputKeyPath string
fApiUrl string fServerUrl string
fAccessTokenId int64 fAccessTokenId int64
fAccessToken string fAccessToken string
) )
@ -24,7 +24,7 @@ func init() {
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "")
flag.Int64Var(&fAccessTokenId, argsPrefix+"ACCESSTOKENID", 0, "") flag.Int64Var(&fAccessTokenId, argsPrefix+"ACCESSTOKENID", 0, "")
flag.StringVar(&fAccessToken, argsPrefix+"ACCESSTOKEN", "", "") flag.StringVar(&fAccessToken, argsPrefix+"ACCESSTOKEN", "", "")
} }
@ -35,7 +35,7 @@ Shell command to run this test:
go test -v ./ratpanel_console_test.go -args \ go test -v ./ratpanel_console_test.go -args \
--CERTIMATE_DEPLOYER_RATPANELCONSOLE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_RATPANELCONSOLE_INPUTCERTPATH="/path/to/your-input-cert.pem" \
--CERTIMATE_DEPLOYER_RATPANELCONSOLE_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_RATPANELCONSOLE_INPUTKEYPATH="/path/to/your-input-key.pem" \
--CERTIMATE_DEPLOYER_RATPANELCONSOLE_APIURL="http://127.0.0.1:8888" \ --CERTIMATE_DEPLOYER_RATPANELCONSOLE_SERVERURL="http://127.0.0.1:8888" \
--CERTIMATE_DEPLOYER_RATPANELCONSOLE_ACCESSTOKENID="your-access-token-id" \ --CERTIMATE_DEPLOYER_RATPANELCONSOLE_ACCESSTOKENID="your-access-token-id" \
--CERTIMATE_DEPLOYER_RATPANELCONSOLE_ACCESSTOKEN="your-access-token" --CERTIMATE_DEPLOYER_RATPANELCONSOLE_ACCESSTOKEN="your-access-token"
*/ */
@ -47,13 +47,13 @@ func TestDeploy(t *testing.T) {
"args:", "args:",
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
fmt.Sprintf("APIURL: %v", fApiUrl), fmt.Sprintf("SERVERURL: %v", fServerUrl),
fmt.Sprintf("ACCESSTOKENID: %v", fAccessTokenId), fmt.Sprintf("ACCESSTOKENID: %v", fAccessTokenId),
fmt.Sprintf("ACCESSTOKEN: %v", fAccessToken), fmt.Sprintf("ACCESSTOKEN: %v", fAccessToken),
}, "\n")) }, "\n"))
deployer, err := provider.NewDeployer(&provider.DeployerConfig{ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
ApiUrl: fApiUrl, ServerUrl: fServerUrl,
AccessTokenId: int32(fAccessTokenId), AccessTokenId: int32(fAccessTokenId),
AccessToken: fAccessToken, AccessToken: fAccessToken,
AllowInsecureConnections: true, AllowInsecureConnections: true,

View File

@ -13,8 +13,8 @@ import (
) )
type DeployerConfig struct { type DeployerConfig struct {
// 耗子面板地址。 // 耗子面板服务地址。
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
// 耗子面板访问令牌 ID。 // 耗子面板访问令牌 ID。
AccessTokenId int32 `json:"accessTokenId"` AccessTokenId int32 `json:"accessTokenId"`
// 耗子面板访问令牌。 // 耗子面板访问令牌。
@ -38,7 +38,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
panic("config is nil") panic("config is nil")
} }
client, err := createSdkClient(config.ApiUrl, config.AccessTokenId, config.AccessToken, config.AllowInsecureConnections) client, err := createSdkClient(config.ServerUrl, config.AccessTokenId, config.AccessToken, config.AllowInsecureConnections)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create sdk client: %w", err) return nil, fmt.Errorf("failed to create sdk client: %w", err)
} }
@ -79,9 +79,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
return &deployer.DeployResult{}, nil return &deployer.DeployResult{}, nil
} }
func createSdkClient(apiUrl string, accessTokenId int32, accessToken string, skipTlsVerify bool) (*rpsdk.Client, error) { func createSdkClient(serverUrl string, accessTokenId int32, accessToken string, skipTlsVerify bool) (*rpsdk.Client, error) {
if _, err := url.Parse(apiUrl); err != nil { if _, err := url.Parse(serverUrl); err != nil {
return nil, errors.New("invalid ratpanel api url") return nil, errors.New("invalid ratpanel server url")
} }
if accessTokenId == 0 { if accessTokenId == 0 {
@ -92,7 +92,7 @@ func createSdkClient(apiUrl string, accessTokenId int32, accessToken string, ski
return nil, errors.New("invalid ratpanel access token") return nil, errors.New("invalid ratpanel access token")
} }
client := rpsdk.NewClient(apiUrl, accessTokenId, accessToken) client := rpsdk.NewClient(serverUrl, accessTokenId, accessToken)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }

View File

@ -14,7 +14,7 @@ import (
var ( var (
fInputCertPath string fInputCertPath string
fInputKeyPath string fInputKeyPath string
fApiUrl string fServerUrl string
fAccessTokenId int64 fAccessTokenId int64
fAccessToken string fAccessToken string
fSiteName string fSiteName string
@ -25,7 +25,7 @@ func init() {
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "")
flag.Int64Var(&fAccessTokenId, argsPrefix+"ACCESSTOKENID", 0, "") flag.Int64Var(&fAccessTokenId, argsPrefix+"ACCESSTOKENID", 0, "")
flag.StringVar(&fAccessToken, argsPrefix+"ACCESSTOKEN", "", "") flag.StringVar(&fAccessToken, argsPrefix+"ACCESSTOKEN", "", "")
flag.StringVar(&fSiteName, argsPrefix+"SITENAME", "", "") flag.StringVar(&fSiteName, argsPrefix+"SITENAME", "", "")
@ -37,7 +37,7 @@ Shell command to run this test:
go test -v ./ratpanel_site_test.go -args \ go test -v ./ratpanel_site_test.go -args \
--CERTIMATE_DEPLOYER_RATPANELSITE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_RATPANELSITE_INPUTCERTPATH="/path/to/your-input-cert.pem" \
--CERTIMATE_DEPLOYER_RATPANELSITE_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_RATPANELSITE_INPUTKEYPATH="/path/to/your-input-key.pem" \
--CERTIMATE_DEPLOYER_RATPANELSITE_APIURL="http://127.0.0.1:8888" \ --CERTIMATE_DEPLOYER_RATPANELSITE_SERVERURL="http://127.0.0.1:8888" \
--CERTIMATE_DEPLOYER_RATPANELSITE_ACCESSTOKENID="your-access-token-id" \ --CERTIMATE_DEPLOYER_RATPANELSITE_ACCESSTOKENID="your-access-token-id" \
--CERTIMATE_DEPLOYER_RATPANELSITE_ACCESSTOKEN="your-access-token" \ --CERTIMATE_DEPLOYER_RATPANELSITE_ACCESSTOKEN="your-access-token" \
--CERTIMATE_DEPLOYER_RATPANELSITE_SITENAME="your-site-name" --CERTIMATE_DEPLOYER_RATPANELSITE_SITENAME="your-site-name"
@ -50,14 +50,14 @@ func TestDeploy(t *testing.T) {
"args:", "args:",
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
fmt.Sprintf("APIURL: %v", fApiUrl), fmt.Sprintf("SERVERURL: %v", fServerUrl),
fmt.Sprintf("ACCESSTOKENID: %v", fAccessTokenId), fmt.Sprintf("ACCESSTOKENID: %v", fAccessTokenId),
fmt.Sprintf("ACCESSTOKEN: %v", fAccessToken), fmt.Sprintf("ACCESSTOKEN: %v", fAccessToken),
fmt.Sprintf("SITENAME: %v", fSiteName), fmt.Sprintf("SITENAME: %v", fSiteName),
}, "\n")) }, "\n"))
deployer, err := provider.NewDeployer(&provider.DeployerConfig{ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
ApiUrl: fApiUrl, ServerUrl: fServerUrl,
AccessTokenId: int32(fAccessTokenId), AccessTokenId: int32(fAccessTokenId),
AccessToken: fAccessToken, AccessToken: fAccessToken,
AllowInsecureConnections: true, AllowInsecureConnections: true,

View File

@ -13,8 +13,8 @@ import (
) )
type DeployerConfig struct { type DeployerConfig struct {
// 雷池 URL // 雷池服务地址
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
// 雷池 API Token。 // 雷池 API Token。
ApiToken string `json:"apiToken"` ApiToken string `json:"apiToken"`
// 是否允许不安全的连接。 // 是否允许不安全的连接。
@ -39,7 +39,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
panic("config is nil") panic("config is nil")
} }
client, err := createSdkClient(config.ApiUrl, config.ApiToken, config.AllowInsecureConnections) client, err := createSdkClient(config.ServerUrl, config.ApiToken, config.AllowInsecureConnections)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create sdk client: %w", err) return nil, fmt.Errorf("failed to create sdk client: %w", err)
} }
@ -98,16 +98,16 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri
return nil return nil
} }
func createSdkClient(apiUrl, apiToken string, skipTlsVerify bool) (*safelinesdk.Client, error) { func createSdkClient(serverUrl, apiToken string, skipTlsVerify bool) (*safelinesdk.Client, error) {
if _, err := url.Parse(apiUrl); err != nil { if _, err := url.Parse(serverUrl); err != nil {
return nil, errors.New("invalid safeline api url") return nil, errors.New("invalid safeline server url")
} }
if apiToken == "" { if apiToken == "" {
return nil, errors.New("invalid safeline api token") return nil, errors.New("invalid safeline api token")
} }
client := safelinesdk.NewClient(apiUrl, apiToken) client := safelinesdk.NewClient(serverUrl, apiToken)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }

View File

@ -14,7 +14,7 @@ import (
var ( var (
fInputCertPath string fInputCertPath string
fInputKeyPath string fInputKeyPath string
fApiUrl string fServerUrl string
fApiToken string fApiToken string
fCertificateId int64 fCertificateId int64
) )
@ -24,7 +24,7 @@ func init() {
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "")
flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "") flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "")
flag.Int64Var(&fCertificateId, argsPrefix+"CERTIFICATEID", 0, "") flag.Int64Var(&fCertificateId, argsPrefix+"CERTIFICATEID", 0, "")
} }
@ -35,7 +35,7 @@ Shell command to run this test:
go test -v ./safeline_test.go -args \ go test -v ./safeline_test.go -args \
--CERTIMATE_DEPLOYER_SAFELINE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_SAFELINE_INPUTCERTPATH="/path/to/your-input-cert.pem" \
--CERTIMATE_DEPLOYER_SAFELINE_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_SAFELINE_INPUTKEYPATH="/path/to/your-input-key.pem" \
--CERTIMATE_DEPLOYER_SAFELINE_APIURL="http://127.0.0.1:9443" \ --CERTIMATE_DEPLOYER_SAFELINE_SERVERURL="http://127.0.0.1:9443" \
--CERTIMATE_DEPLOYER_SAFELINE_APITOKEN="your-api-token" \ --CERTIMATE_DEPLOYER_SAFELINE_APITOKEN="your-api-token" \
--CERTIMATE_DEPLOYER_SAFELINE_CERTIFICATEID="your-cerficiate-id" --CERTIMATE_DEPLOYER_SAFELINE_CERTIFICATEID="your-cerficiate-id"
*/ */
@ -47,13 +47,13 @@ func TestDeploy(t *testing.T) {
"args:", "args:",
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
fmt.Sprintf("APIURL: %v", fApiUrl), fmt.Sprintf("SERVERURL: %v", fServerUrl),
fmt.Sprintf("APITOKEN: %v", fApiToken), fmt.Sprintf("APITOKEN: %v", fApiToken),
fmt.Sprintf("CERTIFICATEID: %v", fCertificateId), fmt.Sprintf("CERTIFICATEID: %v", fCertificateId),
}, "\n")) }, "\n"))
deployer, err := provider.NewDeployer(&provider.DeployerConfig{ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
ApiUrl: fApiUrl, ServerUrl: fServerUrl,
ApiToken: fApiToken, ApiToken: fApiToken,
AllowInsecureConnections: true, AllowInsecureConnections: true,
ResourceType: provider.RESOURCE_TYPE_CERTIFICATE, ResourceType: provider.RESOURCE_TYPE_CERTIFICATE,

View File

@ -0,0 +1,101 @@
package unicloudwebhost
import (
"context"
"errors"
"fmt"
"log/slog"
"net/url"
"github.com/usual2970/certimate/internal/pkg/core/deployer"
unisdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/dcloud/unicloud"
)
type DeployerConfig struct {
// uniCloud 控制台账号。
Username string `json:"username"`
// uniCloud 控制台密码。
Password string `json:"password"`
// 服务空间提供商。
// 可取值 "aliyun"、"tencent"。
SpaceProvider string `json:"spaceProvider"`
// 服务空间 ID。
SpaceId string `json:"spaceId"`
// 托管网站域名(不支持泛域名)。
Domain string `json:"domain"`
}
type DeployerProvider struct {
config *DeployerConfig
logger *slog.Logger
sdkClient *unisdk.Client
}
var _ deployer.Deployer = (*DeployerProvider)(nil)
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
panic("config is nil")
}
client, err := createSdkClient(config.Username, config.Password)
if err != nil {
return nil, fmt.Errorf("failed to create sdk client: %w", err)
}
return &DeployerProvider{
config: config,
logger: slog.Default(),
sdkClient: client,
}, nil
}
func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
if logger == nil {
d.logger = slog.Default()
} else {
d.logger = logger
}
return d
}
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
if d.config.SpaceProvider == "" {
return nil, errors.New("config `spaceProvider` is required")
}
if d.config.SpaceId == "" {
return nil, errors.New("config `spaceId` is required")
}
if d.config.Domain == "" {
return nil, errors.New("config `domain` is required")
}
// 变更网站证书
createDomainWithCertReq := &unisdk.CreateDomainWithCertRequest{
Provider: d.config.SpaceProvider,
SpaceId: d.config.SpaceId,
Domain: d.config.Domain,
Cert: url.QueryEscape(certPEM),
Key: url.QueryEscape(privkeyPEM),
}
createDomainWithCertResp, err := d.sdkClient.CreateDomainWithCert(createDomainWithCertReq)
d.logger.Debug("sdk request 'unicloud.host.CreateDomainWithCert'", slog.Any("request", createDomainWithCertReq), slog.Any("response", createDomainWithCertResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'unicloud.host.CreateDomainWithCert': %w", err)
}
return &deployer.DeployResult{}, nil
}
func createSdkClient(username, password string) (*unisdk.Client, error) {
if username == "" {
return nil, errors.New("invalid unicloud username")
}
if password == "" {
return nil, errors.New("invalid unicloud password")
}
client := unisdk.NewClient(username, password)
return client, nil
}

View File

@ -0,0 +1,85 @@
package unicloudwebhost_test
import (
"context"
"flag"
"fmt"
"os"
"strings"
"testing"
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/unicloud-webhost"
)
var (
fInputCertPath string
fInputKeyPath string
fUsername string
fPassword string
fSpaceProvider string
fSpaceId string
fDomain string
)
func init() {
argsPrefix := "CERTIMATE_DEPLOYER_UNICLOUDWEBHOST_"
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fUsername, argsPrefix+"USERNAME", "", "")
flag.StringVar(&fPassword, argsPrefix+"PASSWORD", "", "")
flag.StringVar(&fSpaceProvider, argsPrefix+"SPACEPROVIDER", "", "")
flag.StringVar(&fSpaceId, argsPrefix+"SPACEID", "", "")
flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "")
}
/*
Shell command to run this test:
go test -v ./unicloud_webhost_test.go -args \
--CERTIMATE_DEPLOYER_UNICLOUDWEBHOST_INPUTCERTPATH="/path/to/your-input-cert.pem" \
--CERTIMATE_DEPLOYER_UNICLOUDWEBHOST_INPUTKEYPATH="/path/to/your-input-key.pem" \
--CERTIMATE_DEPLOYER_UNICLOUDWEBHOST_USERNAME="your-username" \
--CERTIMATE_DEPLOYER_UNICLOUDWEBHOST_PASSWORD="your-password" \
--CERTIMATE_DEPLOYER_UNICLOUDWEBHOST_SPACEPROVIDER="aliyun/tencent" \
--CERTIMATE_DEPLOYER_UNICLOUDWEBHOST_SPACEID="your-space-id" \
--CERTIMATE_DEPLOYER_UNICLOUDWEBHOST_DOMAIN="example.com"
*/
func TestDeploy(t *testing.T) {
flag.Parse()
t.Run("Deploy", func(t *testing.T) {
t.Log(strings.Join([]string{
"args:",
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
fmt.Sprintf("USERNAME: %v", fUsername),
fmt.Sprintf("PASSWORD: %v", fPassword),
fmt.Sprintf("SPACEPROVIDER: %v", fSpaceProvider),
fmt.Sprintf("SPACEID: %v", fSpaceId),
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
deployer, err := provider.NewDeployer(&provider.DeployerConfig{
Username: fUsername,
Password: fPassword,
SpaceProvider: fSpaceProvider,
SpaceId: fSpaceId,
Domain: fDomain,
})
if err != nil {
t.Errorf("err: %+v", err)
return
}
fInputCertData, _ := os.ReadFile(fInputCertPath)
fInputKeyData, _ := os.ReadFile(fInputKeyPath)
res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData))
if err != nil {
t.Errorf("err: %+v", err)
return
}
t.Logf("ok: %v", res)
})
}

View File

@ -58,6 +58,7 @@ func (n *NotifierProvider) Notify(ctx context.Context, subject string, message s
// REF: https://bark.day.app/#/tutorial // REF: https://bark.day.app/#/tutorial
req := n.httpClient.R(). req := n.httpClient.R().
SetContext(ctx).
SetHeader("Content-Type", "application/json"). SetHeader("Content-Type", "application/json").
SetBody(map[string]any{ SetBody(map[string]any{
"title": subject, "title": subject,

View File

@ -0,0 +1,68 @@
package discordbot
import (
"context"
"fmt"
"log/slog"
"github.com/go-resty/resty/v2"
"github.com/usual2970/certimate/internal/pkg/core/notifier"
)
type NotifierConfig struct {
// Discord Bot API Token。
BotToken string `json:"botToken"`
// Discord Channel ID。
ChannelId string `json:"channelId"`
}
type NotifierProvider struct {
config *NotifierConfig
logger *slog.Logger
httpClient *resty.Client
}
var _ notifier.Notifier = (*NotifierProvider)(nil)
func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) {
if config == nil {
panic("config is nil")
}
client := resty.New()
return &NotifierProvider{
config: config,
logger: slog.Default(),
httpClient: client,
}, nil
}
func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier {
if logger == nil {
n.logger = slog.Default()
} else {
n.logger = logger
}
return n
}
func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
// REF: https://discord.com/developers/docs/resources/message#create-message
req := n.httpClient.R().
SetContext(ctx).
SetHeader("Content-Type", "application/json").
SetHeader("Authorization", "Bot "+n.config.BotToken).
SetBody(map[string]any{
"content": subject + "\n" + message,
})
resp, err := req.Post(fmt.Sprintf("https://discord.com/api/v9/channels/%s/messages", n.config.ChannelId))
if err != nil {
return nil, fmt.Errorf("discord api error: failed to send request: %w", err)
} else if resp.IsError() {
return nil, fmt.Errorf("discord api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
}
return &notifier.NotifyResult{}, nil
}

View File

@ -0,0 +1,64 @@
package discordbot_test
import (
"context"
"flag"
"fmt"
"strings"
"testing"
provider "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/discordbot"
)
const (
mockSubject = "test_subject"
mockMessage = "test_message"
)
var (
fApiToken string
fChannelId string
)
func init() {
argsPrefix := "CERTIMATE_NOTIFIER_DISCORDBOT_"
flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "")
flag.StringVar(&fChannelId, argsPrefix+"CHANNELID", 0, "")
}
/*
Shell command to run this test:
go test -v ./discordbot_test.go -args \
--CERTIMATE_NOTIFIER_DISCORDBOT_APITOKEN="your-bot-token" \
--CERTIMATE_NOTIFIER_DISCORDBOT_CHANNELID="your-channel-id"
*/
func TestNotify(t *testing.T) {
flag.Parse()
t.Run("Notify", func(t *testing.T) {
t.Log(strings.Join([]string{
"args:",
fmt.Sprintf("APITOKEN: %v", fApiToken),
fmt.Sprintf("CHANNELID: %v", fChannelId),
}, "\n"))
notifier, err := provider.NewNotifier(&provider.NotifierConfig{
BotToken: fApiToken,
ChannelId: fChannelId,
})
if err != nil {
t.Errorf("err: %+v", err)
return
}
res, err := notifier.Notify(context.Background(), mockSubject, mockMessage)
if err != nil {
t.Errorf("err: %+v", err)
return
}
t.Logf("ok: %v", res)
})
}

View File

@ -56,6 +56,7 @@ func (n *NotifierProvider) Notify(ctx context.Context, subject string, message s
// REF: https://gotify.net/api-docs#/message/createMessage // REF: https://gotify.net/api-docs#/message/createMessage
req := n.httpClient.R(). req := n.httpClient.R().
SetContext(ctx).
SetHeader("Content-Type", "application/json"). SetHeader("Content-Type", "application/json").
SetHeader("Authorization", "Bearer "+n.config.Token). SetHeader("Authorization", "Bearer "+n.config.Token).
SetBody(map[string]any{ SetBody(map[string]any{

View File

@ -12,13 +12,13 @@ import (
) )
type NotifierConfig struct { type NotifierConfig struct {
// 服务地址。 // Mattermost 服务地址。
ServerUrl string `json:"serverUrl"` ServerUrl string `json:"serverUrl"`
// 用户名。 // Mattermost 用户名。
Username string `json:"username"` Username string `json:"username"`
// 密码。 // Mattermost 密码。
Password string `json:"password"` Password string `json:"password"`
// 频道 ID。 // Mattermost 频道 ID。
ChannelId string `json:"channelId"` ChannelId string `json:"channelId"`
} }
@ -58,6 +58,7 @@ func (n *NotifierProvider) Notify(ctx context.Context, subject string, message s
// REF: https://developers.mattermost.com/api-documentation/#/operations/Login // REF: https://developers.mattermost.com/api-documentation/#/operations/Login
loginReq := n.httpClient.R(). loginReq := n.httpClient.R().
SetContext(ctx).
SetHeader("Content-Type", "application/json"). SetHeader("Content-Type", "application/json").
SetBody(map[string]any{ SetBody(map[string]any{
"login_id": n.config.Username, "login_id": n.config.Username,
@ -74,6 +75,7 @@ func (n *NotifierProvider) Notify(ctx context.Context, subject string, message s
// REF: https://developers.mattermost.com/api-documentation/#/operations/CreatePost // REF: https://developers.mattermost.com/api-documentation/#/operations/CreatePost
postReq := n.httpClient.R(). postReq := n.httpClient.R().
SetContext(ctx).
SetHeader("Content-Type", "application/json"). SetHeader("Content-Type", "application/json").
SetHeader("Authorization", "Bearer "+loginResp.Header().Get("Token")). SetHeader("Authorization", "Bearer "+loginResp.Header().Get("Token")).
SetBody(map[string]any{ SetBody(map[string]any{

View File

@ -51,6 +51,7 @@ func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier {
func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
// REF: https://pushover.net/api // REF: https://pushover.net/api
req := n.httpClient.R(). req := n.httpClient.R().
SetContext(ctx).
SetHeader("Content-Type", "application/json"). SetHeader("Content-Type", "application/json").
SetBody(map[string]any{ SetBody(map[string]any{
"title": subject, "title": subject,

View File

@ -50,6 +50,7 @@ func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier {
func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
// REF: https://pushplus.plus/doc/guide/api.html#%E4%B8%80%E3%80%81%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF%E6%8E%A5%E5%8F%A3 // REF: https://pushplus.plus/doc/guide/api.html#%E4%B8%80%E3%80%81%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF%E6%8E%A5%E5%8F%A3
req := n.httpClient.R(). req := n.httpClient.R().
SetContext(ctx).
SetHeader("Content-Type", "application/json"). SetHeader("Content-Type", "application/json").
SetBody(map[string]any{ SetBody(map[string]any{
"title": subject, "title": subject,

View File

@ -49,6 +49,7 @@ func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier {
func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
// REF: https://sct.ftqq.com/ // REF: https://sct.ftqq.com/
req := n.httpClient.R(). req := n.httpClient.R().
SetContext(ctx).
SetHeader("Content-Type", "application/json"). SetHeader("Content-Type", "application/json").
SetBody(map[string]any{ SetBody(map[string]any{
"text": subject, "text": subject,

View File

@ -0,0 +1,70 @@
package discordbot
import (
"context"
"fmt"
"log/slog"
"github.com/go-resty/resty/v2"
"github.com/usual2970/certimate/internal/pkg/core/notifier"
)
type NotifierConfig struct {
// Slack Bot API Token。
BotToken string `json:"botToken"`
// Slack Channel ID。
ChannelId string `json:"channelId"`
}
type NotifierProvider struct {
config *NotifierConfig
logger *slog.Logger
httpClient *resty.Client
}
var _ notifier.Notifier = (*NotifierProvider)(nil)
func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) {
if config == nil {
panic("config is nil")
}
client := resty.New()
return &NotifierProvider{
config: config,
logger: slog.Default(),
httpClient: client,
}, nil
}
func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier {
if logger == nil {
n.logger = slog.Default()
} else {
n.logger = logger
}
return n
}
func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
// REF: https://docs.slack.dev/messaging/sending-and-scheduling-messages#publishing
req := n.httpClient.R().
SetContext(ctx).
SetHeader("Content-Type", "application/json").
SetHeader("Authorization", "Bearer "+n.config.BotToken).
SetBody(map[string]any{
"token": n.config.BotToken,
"channel": n.config.ChannelId,
"text": subject + "\n" + message,
})
resp, err := req.Post("https://slack.com/api/chat.postMessage")
if err != nil {
return nil, fmt.Errorf("slack api error: failed to send request: %w", err)
} else if resp.IsError() {
return nil, fmt.Errorf("slack api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
}
return &notifier.NotifyResult{}, nil
}

View File

@ -0,0 +1,64 @@
package discordbot_test
import (
"context"
"flag"
"fmt"
"strings"
"testing"
provider "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/slackbot"
)
const (
mockSubject = "test_subject"
mockMessage = "test_message"
)
var (
fApiToken string
fChannelId string
)
func init() {
argsPrefix := "CERTIMATE_NOTIFIER_SLACKBOT_"
flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "")
flag.StringVar(&fChannelId, argsPrefix+"CHANNELID", 0, "")
}
/*
Shell command to run this test:
go test -v ./slackbot_test.go -args \
--CERTIMATE_NOTIFIER_SLACKBOT_APITOKEN="your-bot-token" \
--CERTIMATE_NOTIFIER_SLACKBOT_CHANNELID="your-channel-id"
*/
func TestNotify(t *testing.T) {
flag.Parse()
t.Run("Notify", func(t *testing.T) {
t.Log(strings.Join([]string{
"args:",
fmt.Sprintf("APITOKEN: %v", fApiToken),
fmt.Sprintf("CHANNELID: %v", fChannelId),
}, "\n"))
notifier, err := provider.NewNotifier(&provider.NotifierConfig{
BotToken: fApiToken,
ChannelId: fChannelId,
})
if err != nil {
t.Errorf("err: %+v", err)
return
}
res, err := notifier.Notify(context.Background(), mockSubject, mockMessage)
if err != nil {
t.Errorf("err: %+v", err)
return
}
t.Logf("ok: %v", res)
})
}

View File

@ -51,6 +51,7 @@ func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier {
func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
// REF: https://core.telegram.org/bots/api#sendmessage // REF: https://core.telegram.org/bots/api#sendmessage
req := n.httpClient.R(). req := n.httpClient.R().
SetContext(ctx).
SetHeader("Content-Type", "application/json"). SetHeader("Content-Type", "application/json").
SetBody(map[string]any{ SetBody(map[string]any{
"chat_id": n.config.ChatId, "chat_id": n.config.ChatId,

View File

@ -17,14 +17,14 @@ const (
var ( var (
fApiToken string fApiToken string
fChartId int64 fChatId int64
) )
func init() { func init() {
argsPrefix := "CERTIMATE_NOTIFIER_TELEGRAMBOT_" argsPrefix := "CERTIMATE_NOTIFIER_TELEGRAMBOT_"
flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "") flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "")
flag.Int64Var(&fChartId, argsPrefix+"CHATID", 0, "") flag.Int64Var(&fChatId, argsPrefix+"CHATID", 0, "")
} }
/* /*
@ -41,12 +41,12 @@ func TestNotify(t *testing.T) {
t.Log(strings.Join([]string{ t.Log(strings.Join([]string{
"args:", "args:",
fmt.Sprintf("APITOKEN: %v", fApiToken), fmt.Sprintf("APITOKEN: %v", fApiToken),
fmt.Sprintf("CHATID: %v", fChartId), fmt.Sprintf("CHATID: %v", fChatId),
}, "\n")) }, "\n"))
notifier, err := provider.NewNotifier(&provider.NotifierConfig{ notifier, err := provider.NewNotifier(&provider.NotifierConfig{
BotToken: fApiToken, BotToken: fApiToken,
ChatId: fChartId, ChatId: fChatId,
}) })
if err != nil { if err != nil {
t.Errorf("err: %+v", err) t.Errorf("err: %+v", err)

View File

@ -139,7 +139,7 @@ func (n *NotifierProvider) Notify(ctx context.Context, subject string, message s
// 生成请求 // 生成请求
// 其中 GET 请求需转换为查询参数 // 其中 GET 请求需转换为查询参数
req := n.httpClient.R().SetHeaderMultiValues(webhookHeaders) req := n.httpClient.R().SetContext(ctx).SetHeaderMultiValues(webhookHeaders)
req.URL = webhookUrl.String() req.URL = webhookUrl.String()
req.Method = webhookMethod req.Method = webhookMethod
if webhookMethod == http.MethodGet { if webhookMethod == http.MethodGet {

View File

@ -49,6 +49,7 @@ func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier {
func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
// REF: https://developer.work.weixin.qq.com/document/path/91770 // REF: https://developer.work.weixin.qq.com/document/path/91770
req := n.httpClient.R(). req := n.httpClient.R().
SetContext(ctx).
SetHeader("Content-Type", "application/json"). SetHeader("Content-Type", "application/json").
SetBody(map[string]any{ SetBody(map[string]any{
"msgtype": "text", "msgtype": "text",

View File

@ -2,6 +2,7 @@ package onepanelssl
import ( import (
"context" "context"
"crypto/tls"
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
@ -14,12 +15,14 @@ import (
) )
type UploaderConfig struct { type UploaderConfig struct {
// 1Panel 地址。 // 1Panel 服务地址。
ApiUrl string `json:"apiUrl"` ServerUrl string `json:"serverUrl"`
// 1Panel 版本。 // 1Panel 版本。
ApiVersion string `json:"apiVersion"` ApiVersion string `json:"apiVersion"`
// 1Panel 接口密钥。 // 1Panel 接口密钥。
ApiKey string `json:"apiKey"` ApiKey string `json:"apiKey"`
// 是否允许不安全的连接。
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
} }
type UploaderProvider struct { type UploaderProvider struct {
@ -35,7 +38,7 @@ func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
panic("config is nil") panic("config is nil")
} }
client, err := createSdkClient(config.ApiUrl, config.ApiVersion, config.ApiKey) client, err := createSdkClient(config.ServerUrl, config.ApiVersion, config.ApiKey, config.AllowInsecureConnections)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create sdk client: %w", err) return nil, fmt.Errorf("failed to create sdk client: %w", err)
} }
@ -132,9 +135,9 @@ func (u *UploaderProvider) getCertIfExists(ctx context.Context, certPEM string,
return nil, nil return nil, nil
} }
func createSdkClient(apiUrl, apiVersion, apiKey string) (*onepanelsdk.Client, error) { func createSdkClient(serverUrl, apiVersion, apiKey string, skipTlsVerify bool) (*onepanelsdk.Client, error) {
if _, err := url.Parse(apiUrl); err != nil { if _, err := url.Parse(serverUrl); err != nil {
return nil, errors.New("invalid 1panel api url") return nil, errors.New("invalid 1panel server url")
} }
if apiVersion == "" { if apiVersion == "" {
@ -145,6 +148,10 @@ func createSdkClient(apiUrl, apiVersion, apiKey string) (*onepanelsdk.Client, er
return nil, errors.New("invalid 1panel api key") return nil, errors.New("invalid 1panel api key")
} }
client := onepanelsdk.NewClient(apiUrl, apiVersion, apiKey) client := onepanelsdk.NewClient(serverUrl, apiVersion, apiKey)
if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
}
return client, nil return client, nil
} }

View File

@ -15,7 +15,7 @@ import (
var ( var (
fInputCertPath string fInputCertPath string
fInputKeyPath string fInputKeyPath string
fApiUrl string fServerUrl string
fApiVersion string fApiVersion string
fApiKey string fApiKey string
) )
@ -25,7 +25,7 @@ func init() {
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "")
flag.StringVar(&fApiVersion, argsPrefix+"APIVERSION", "v1", "") flag.StringVar(&fApiVersion, argsPrefix+"APIVERSION", "v1", "")
flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "") flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "")
} }
@ -36,7 +36,7 @@ Shell command to run this test:
go test -v ./1panel_ssl_test.go -args \ go test -v ./1panel_ssl_test.go -args \
--CERTIMATE_UPLOADER_1PANELSSL_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_UPLOADER_1PANELSSL_INPUTCERTPATH="/path/to/your-input-cert.pem" \
--CERTIMATE_UPLOADER_1PANELSSL_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_UPLOADER_1PANELSSL_INPUTKEYPATH="/path/to/your-input-key.pem" \
--CERTIMATE_UPLOADER_1PANELSSL_APIURL="http://127.0.0.1:20410" \ --CERTIMATE_UPLOADER_1PANELSSL_SERVERURL="http://127.0.0.1:20410" \
--CERTIMATE_UPLOADER_1PANELSSL_APIVERSION="v1" \ --CERTIMATE_UPLOADER_1PANELSSL_APIVERSION="v1" \
--CERTIMATE_UPLOADER_1PANELSSL_APIKEY="your-api-key" --CERTIMATE_UPLOADER_1PANELSSL_APIKEY="your-api-key"
*/ */
@ -48,13 +48,13 @@ func TestDeploy(t *testing.T) {
"args:", "args:",
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
fmt.Sprintf("APIURL: %v", fApiUrl), fmt.Sprintf("SERVERURL: %v", fServerUrl),
fmt.Sprintf("APIVERSION: %v", fApiVersion), fmt.Sprintf("APIVERSION: %v", fApiVersion),
fmt.Sprintf("APIKEY: %v", fApiKey), fmt.Sprintf("APIKEY: %v", fApiKey),
}, "\n")) }, "\n"))
uploader, err := provider.NewUploader(&provider.UploaderConfig{ uploader, err := provider.NewUploader(&provider.UploaderConfig{
ApiUrl: fApiUrl, ServerUrl: fServerUrl,
ApiVersion: fApiVersion, ApiVersion: fApiVersion,
ApiKey: fApiKey, ApiKey: fApiKey,
}) })

View File

@ -19,13 +19,13 @@ type Client struct {
client *resty.Client client *resty.Client
} }
func NewClient(apiHost, apiVersion, apiKey string) *Client { func NewClient(serverUrl, apiVersion, apiKey string) *Client {
if apiVersion == "" { if apiVersion == "" {
apiVersion = "v1" apiVersion = "v1"
} }
client := resty.New(). client := resty.New().
SetBaseURL(strings.TrimRight(apiHost, "/") + "/api/" + apiVersion). SetBaseURL(strings.TrimRight(serverUrl, "/") + "/api/" + apiVersion).
SetPreRequestHook(func(c *resty.Client, req *http.Request) error { SetPreRequestHook(func(c *resty.Client, req *http.Request) error {
timestamp := fmt.Sprintf("%d", time.Now().Unix()) timestamp := fmt.Sprintf("%d", time.Now().Unix())
tokenMd5 := md5.Sum([]byte("1panel" + apiKey + timestamp)) tokenMd5 := md5.Sum([]byte("1panel" + apiKey + timestamp))

View File

@ -19,9 +19,9 @@ type Client struct {
client *resty.Client client *resty.Client
} }
func NewClient(apiHost, apiKey string) *Client { func NewClient(serverUrl, apiKey string) *Client {
client := resty.New(). client := resty.New().
SetBaseURL(strings.TrimRight(apiHost, "/")) SetBaseURL(strings.TrimRight(serverUrl, "/"))
return &Client{ return &Client{
apiKey: apiKey, apiKey: apiKey,

View File

@ -17,9 +17,9 @@ type Client struct {
client *resty.Client client *resty.Client
} }
func NewClient(apiHost, apiKey string) *Client { func NewClient(serverUrl, apiKey string) *Client {
client := resty.New(). client := resty.New().
SetBaseURL(strings.TrimRight(apiHost, "/") + "/api"). SetBaseURL(strings.TrimRight(serverUrl, "/") + "/api").
SetPreRequestHook(func(c *resty.Client, req *http.Request) error { SetPreRequestHook(func(c *resty.Client, req *http.Request) error {
timestamp := fmt.Sprintf("%d", time.Now().Unix()) timestamp := fmt.Sprintf("%d", time.Now().Unix())
keyMd5 := md5.Sum([]byte(apiKey)) keyMd5 := md5.Sum([]byte(apiKey))

View File

@ -15,9 +15,9 @@ type Client struct {
client *resty.Client client *resty.Client
} }
func NewClient(apiHost, apiKey, apiSecret string) *Client { func NewClient(serverUrl, apiKey, apiSecret string) *Client {
client := resty.New(). client := resty.New().
SetBaseURL(strings.TrimRight(apiHost, "/")). SetBaseURL(strings.TrimRight(serverUrl, "/")).
SetHeader("api-key", apiKey). SetHeader("api-key", apiKey).
SetHeader("api-secret", apiSecret) SetHeader("api-secret", apiSecret)

View File

@ -0,0 +1,78 @@
package unicloud
import (
"fmt"
"net/http"
"regexp"
"time"
)
func (c *Client) ensureServerlessJwtTokenExists() error {
c.serverlessJwtTokenMtx.Lock()
defer c.serverlessJwtTokenMtx.Unlock()
if c.serverlessJwtToken != "" && c.serverlessJwtTokenExp.After(time.Now()) {
return nil
}
params := &loginParams{
Password: c.password,
}
if regexp.MustCompile("^1\\d{10}$").MatchString(c.username) {
params.Mobile = c.username
} else if regexp.MustCompile("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$").MatchString(c.username) {
params.Email = c.username
} else {
params.Username = c.username
}
resp := &loginResponse{}
if err := c.invokeServerlessWithResult(
uniIdentityEndpoint, uniIdentityClientSecret, uniIdentityAppId, uniIdentitySpaceId,
"uni-id-co", "login", "", params, nil,
resp); err != nil {
return err
} else if resp.Data == nil || resp.Data.NewToken == nil || resp.Data.NewToken.Token == "" {
return fmt.Errorf("unicloud api error: received empty token")
}
c.serverlessJwtToken = resp.Data.NewToken.Token
c.serverlessJwtTokenExp = time.UnixMilli(resp.Data.NewToken.TokenExpired)
return nil
}
func (c *Client) ensureApiUserTokenExists() error {
if err := c.ensureServerlessJwtTokenExists(); err != nil {
return err
}
c.apiUserTokenMtx.Lock()
defer c.apiUserTokenMtx.Unlock()
if c.apiUserToken != "" {
return nil
}
resp := &getUserTokenResponse{}
if err := c.invokeServerlessWithResult(
uniConsoleEndpoint, uniConsoleClientSecret, uniConsoleAppId, uniConsoleSpaceId,
"uni-cloud-kernel", "", "user/getUserToken", nil, map[string]any{"isLogin": true},
resp); err != nil {
return err
} else if resp.Data == nil || resp.Data.Data == nil || resp.Data.Data.Data == nil || resp.Data.Data.Data.Token == "" {
return fmt.Errorf("unicloud api error: received empty user token")
}
c.apiUserToken = resp.Data.Data.Data.Token
return nil
}
func (c *Client) CreateDomainWithCert(req *CreateDomainWithCertRequest) (*CreateDomainWithCertResponse, error) {
if err := c.ensureApiUserTokenExists(); err != nil {
return nil, err
}
resp := &CreateDomainWithCertResponse{}
err := c.sendRequestWithResult(http.MethodPost, "/host/create-domain-with-cert", req, resp)
return resp, err
}

View File

@ -0,0 +1,257 @@
package unicloud
import (
"crypto/hmac"
"crypto/md5"
"encoding/hex"
"encoding/json"
"fmt"
"net/http"
"runtime"
"sort"
"strings"
"sync"
"time"
"github.com/go-resty/resty/v2"
)
type Client struct {
username string
password string
serverlessJwtToken string
serverlessJwtTokenExp time.Time
serverlessJwtTokenMtx sync.Mutex
serverlessClient *resty.Client
apiUserToken string
apiUserTokenMtx sync.Mutex
apiClient *resty.Client
}
const (
uniIdentityEndpoint = "https://account.dcloud.net.cn/client"
uniIdentityClientSecret = "ba461799-fde8-429f-8cc4-4b6d306e2339"
uniIdentityAppId = "__UNI__uniid_server"
uniIdentitySpaceId = "uni-id-server"
uniConsoleEndpoint = "https://unicloud.dcloud.net.cn/client"
uniConsoleClientSecret = "4c1f7fbf-c732-42b0-ab10-4634a8bbe834"
uniConsoleAppId = "__UNI__unicloud_console"
uniConsoleSpaceId = "dc-6nfabcn6ada8d3dd"
)
func NewClient(username, password string) *Client {
client := &Client{
username: username,
password: password,
}
client.serverlessClient = resty.New()
client.apiClient = resty.New().
SetBaseURL("https://unicloud-api.dcloud.net.cn/unicloud/api").
SetPreRequestHook(func(c *resty.Client, req *http.Request) error {
if client.apiUserToken != "" {
req.Header.Set("Token", client.apiUserToken)
}
return nil
})
return client
}
func (c *Client) WithTimeout(timeout time.Duration) *Client {
c.serverlessClient.SetTimeout(timeout)
return c
}
func (c *Client) generateSignature(params map[string]any, secret string) string {
keys := make([]string, 0, len(params))
for k := range params {
keys = append(keys, k)
}
sort.Strings(keys)
canonicalStr := ""
for i, k := range keys {
if i > 0 {
canonicalStr += "&"
}
canonicalStr += k + "=" + fmt.Sprintf("%v", params[k])
}
mac := hmac.New(md5.New, []byte(secret))
mac.Write([]byte(canonicalStr))
sign := mac.Sum(nil)
signHex := hex.EncodeToString(sign)
return signHex
}
func (c *Client) buildServerlessClientInfo(appId string) (_clientInfo map[string]any, _err error) {
return map[string]any{
"PLATFORM": "web",
"OS": strings.ToUpper(runtime.GOOS),
"APPID": appId,
"DEVICEID": "certimate",
"LOCALE": "zh-Hans",
"osName": runtime.GOOS,
"appId": appId,
"appName": "uniCloud",
"deviceId": "certimate",
"deviceType": "pc",
"uniPlatform": "web",
"uniCompilerVersion": "4.45",
"uniRuntimeVersion": "4.45",
}, nil
}
func (c *Client) buildServerlessPayloadInfo(appId, spaceId, target, method, action string, params, data interface{}) (map[string]any, error) {
clientInfo, err := c.buildServerlessClientInfo(appId)
if err != nil {
return nil, err
}
functionArgsParams := make([]any, 0)
if params != nil {
functionArgsParams = append(functionArgsParams, params)
}
functionArgs := map[string]any{
"clientInfo": clientInfo,
"uniIdToken": c.serverlessJwtToken,
}
if method != "" {
functionArgs["method"] = method
functionArgs["params"] = make([]any, 0)
}
if action != "" {
type _obj struct{}
functionArgs["action"] = action
functionArgs["data"] = &_obj{}
}
if params != nil {
functionArgs["params"] = []any{params}
}
if data != nil {
functionArgs["data"] = data
}
jsonb, err := json.Marshal(map[string]any{
"functionTarget": target,
"functionArgs": functionArgs,
})
if err != nil {
return nil, err
}
payload := map[string]any{
"method": "serverless.function.runtime.invoke",
"params": string(jsonb),
"spaceId": spaceId,
"timestamp": time.Now().UnixMilli(),
}
return payload, nil
}
func (c *Client) invokeServerless(endpoint, clientSecret, appId, spaceId, target, method, action string, params, data interface{}) (*resty.Response, error) {
if endpoint == "" {
return nil, fmt.Errorf("unicloud api error: endpoint cannot be empty")
}
payload, err := c.buildServerlessPayloadInfo(appId, spaceId, target, method, action, params, data)
if err != nil {
return nil, fmt.Errorf("unicloud api error: failed to build request: %w", err)
}
clientInfo, _ := c.buildServerlessClientInfo(appId)
clientInfoJsonb, _ := json.Marshal(clientInfo)
sign := c.generateSignature(payload, clientSecret)
req := c.serverlessClient.R().
SetHeader("Origin", "https://unicloud.dcloud.net.cn").
SetHeader("Referer", "https://unicloud.dcloud.net.cn").
SetHeader("Content-Type", "application/json").
SetHeader("X-Client-Info", string(clientInfoJsonb)).
SetHeader("X-Client-Token", c.serverlessJwtToken).
SetHeader("X-Serverless-Sign", sign).
SetBody(payload)
resp, err := req.Post(endpoint)
if err != nil {
return resp, fmt.Errorf("unicloud api error: failed to send request: %w", err)
} else if resp.IsError() {
return resp, fmt.Errorf("unicloud api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
}
return resp, nil
}
func (c *Client) invokeServerlessWithResult(endpoint, clientSecret, appId, spaceId, target, method, action string, params, data interface{}, result BaseResponse) error {
resp, err := c.invokeServerless(endpoint, clientSecret, appId, spaceId, target, method, action, params, data)
if err != nil {
if resp != nil {
json.Unmarshal(resp.Body(), &result)
}
return err
}
if err := json.Unmarshal(resp.Body(), &result); err != nil {
return fmt.Errorf("unicloud api error: failed to unmarshal response: %w", err)
} else if success := result.GetSuccess(); !success {
return fmt.Errorf("unicloud api error: code='%s', message='%s'", result.GetErrorCode(), result.GetErrorMessage())
}
return nil
}
func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) {
req := c.apiClient.R()
if strings.EqualFold(method, http.MethodGet) {
qs := make(map[string]string)
if params != nil {
temp := make(map[string]any)
jsonb, _ := json.Marshal(params)
json.Unmarshal(jsonb, &temp)
for k, v := range temp {
if v != nil {
qs[k] = fmt.Sprintf("%v", v)
}
}
}
req = req.SetQueryParams(qs)
} else {
req = req.SetHeader("Content-Type", "application/json").SetBody(params)
}
resp, err := req.Execute(method, path)
if err != nil {
return resp, fmt.Errorf("unicloud api error: failed to send request: %w", err)
} else if resp.IsError() {
return resp, fmt.Errorf("unicloud api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
}
return resp, nil
}
func (c *Client) sendRequestWithResult(method string, path string, params interface{}, result BaseResponse) error {
resp, err := c.sendRequest(method, path, params)
if err != nil {
if resp != nil {
json.Unmarshal(resp.Body(), &result)
}
return err
}
if err := json.Unmarshal(resp.Body(), &result); err != nil {
return fmt.Errorf("unicloud api error: failed to unmarshal response: %w", err)
} else if retcode := result.GetReturnCode(); retcode != 0 {
return fmt.Errorf("unicloud api error: ret='%d', desc='%s'", retcode, result.GetReturnDesc())
}
return nil
}

View File

@ -0,0 +1,103 @@
package unicloud
type BaseResponse interface {
GetSuccess() bool
GetErrorCode() string
GetErrorMessage() string
GetReturnCode() int32
GetReturnDesc() string
}
type baseResponse struct {
Success *bool `json:"success,omitempty"`
Header *map[string]string `json:"header,omitempty"`
Error *struct {
Code string `json:"code"`
Message string `json:"message"`
} `json:"error,omitempty"`
ReturnCode *int32 `json:"ret,omitempty"`
ReturnDesc *string `json:"desc,omitempty"`
}
func (r *baseResponse) GetReturnCode() int32 {
if r.ReturnCode != nil {
return *r.ReturnCode
}
return 0
}
func (r *baseResponse) GetReturnDesc() string {
if r.ReturnDesc != nil {
return *r.ReturnDesc
}
return ""
}
func (r *baseResponse) GetSuccess() bool {
if r.Success != nil {
return *r.Success
}
return false
}
func (r *baseResponse) GetErrorCode() string {
if r.Error != nil {
return r.Error.Code
}
return ""
}
func (r *baseResponse) GetErrorMessage() string {
if r.Error != nil {
return r.Error.Message
}
return ""
}
type loginParams struct {
Email string `json:"email,omitempty"`
Mobile string `json:"mobile,omitempty"`
Username string `json:"username,omitempty"`
Password string `json:"password"`
}
type loginResponse struct {
baseResponse
Data *struct {
Code int32 `json:"errCode"`
UID string `json:"uid"`
NewToken *struct {
Token string `json:"token"`
TokenExpired int64 `json:"tokenExpired"`
} `json:"newToken,omitempty"`
} `json:"data,omitempty"`
}
type getUserTokenResponse struct {
baseResponse
Data *struct {
Code int32 `json:"code"`
Data *struct {
Result int32 `json:"ret"`
Description string `json:"desc"`
Data *struct {
Email string `json:"email"`
Token string `json:"token"`
} `json:"data,omitempty"`
} `json:"data,omitempty"`
} `json:"data,omitempty"`
}
type CreateDomainWithCertRequest struct {
Provider string `json:"provider"`
SpaceId string `json:"spaceId"`
Domain string `json:"domain"`
Cert string `json:"cert"`
Key string `json:"key"`
}
type CreateDomainWithCertResponse struct {
baseResponse
}

View File

@ -24,14 +24,14 @@ type Client struct {
client *resty.Client client *resty.Client
} }
func NewClient(apiHost, apiRole, accessKeyId, accessKey string) *Client { func NewClient(serverUrl, apiRole, accessKeyId, accessKey string) *Client {
client := &Client{ client := &Client{
apiRole: apiRole, apiRole: apiRole,
accessKeyId: accessKeyId, accessKeyId: accessKeyId,
accessKey: accessKey, accessKey: accessKey,
} }
client.client = resty.New(). client.client = resty.New().
SetBaseURL(strings.TrimRight(apiHost, "/")). SetBaseURL(strings.TrimRight(serverUrl, "/")).
SetPreRequestHook(func(c *resty.Client, req *http.Request) error { SetPreRequestHook(func(c *resty.Client, req *http.Request) error {
if client.accessToken != "" { if client.accessToken != "" {
req.Header.Set("X-Cloud-Access-Token", client.accessToken) req.Header.Set("X-Cloud-Access-Token", client.accessToken)

View File

@ -24,14 +24,14 @@ type Client struct {
client *resty.Client client *resty.Client
} }
func NewClient(apiHost, apiRole, accessKeyId, accessKey string) *Client { func NewClient(serverUrl, apiRole, accessKeyId, accessKey string) *Client {
client := &Client{ client := &Client{
apiRole: apiRole, apiRole: apiRole,
accessKeyId: accessKeyId, accessKeyId: accessKeyId,
accessKey: accessKey, accessKey: accessKey,
} }
client.client = resty.New(). client.client = resty.New().
SetBaseURL(strings.TrimRight(apiHost, "/")). SetBaseURL(strings.TrimRight(serverUrl, "/")).
SetPreRequestHook(func(c *resty.Client, req *http.Request) error { SetPreRequestHook(func(c *resty.Client, req *http.Request) error {
if client.accessToken != "" { if client.accessToken != "" {
req.Header.Set("X-Edge-Access-Token", client.accessToken) req.Header.Set("X-Edge-Access-Token", client.accessToken)

View File

@ -22,13 +22,13 @@ type Client struct {
client *resty.Client client *resty.Client
} }
func NewClient(apiHost, username, password string) *Client { func NewClient(serverUrl, username, password string) *Client {
client := &Client{ client := &Client{
username: username, username: username,
password: password, password: password,
} }
client.client = resty.New(). client.client = resty.New().
SetBaseURL(strings.TrimRight(apiHost, "/") + "/prod-api"). SetBaseURL(strings.TrimRight(serverUrl, "/") + "/prod-api").
SetPreRequestHook(func(c *resty.Client, req *http.Request) error { SetPreRequestHook(func(c *resty.Client, req *http.Request) error {
if client.accessToken != "" { if client.accessToken != "" {
req.Header.Set("Authorization", "Bearer "+client.accessToken) req.Header.Set("Authorization", "Bearer "+client.accessToken)

View File

@ -22,13 +22,13 @@ type Client struct {
client *resty.Client client *resty.Client
} }
func NewClient(apiHost, username, password string) *Client { func NewClient(serverUrl, username, password string) *Client {
client := &Client{ client := &Client{
username: username, username: username,
password: password, password: password,
} }
client.client = resty.New(). client.client = resty.New().
SetBaseURL(strings.TrimRight(apiHost, "/") + "/prod-api"). SetBaseURL(strings.TrimRight(serverUrl, "/") + "/prod-api").
SetPreRequestHook(func(c *resty.Client, req *http.Request) error { SetPreRequestHook(func(c *resty.Client, req *http.Request) error {
if client.accessToken != "" { if client.accessToken != "" {
req.Header.Set("Authorization", "Bearer "+client.accessToken) req.Header.Set("Authorization", "Bearer "+client.accessToken)

View File

@ -26,8 +26,8 @@ func (r *baseResponse) GetMessage() string {
type ProvisionSiteTLSCertificateParams struct { type ProvisionSiteTLSCertificateParams struct {
Certificate string `json:"certificate"` Certificate string `json:"certificate"`
CACertificates string `json:"key"` CACertificates string `json:"ca_certificates"`
Key string `json:"ca_certificates"` Key string `json:"key"`
} }
type ProvisionSiteTLSCertificateResponse struct { type ProvisionSiteTLSCertificateResponse struct {

View File

@ -20,9 +20,9 @@ type Client struct {
client *resty.Client client *resty.Client
} }
func NewClient(apiHost string, accessTokenId int32, accessToken string) *Client { func NewClient(serverUrl string, accessTokenId int32, accessToken string) *Client {
client := resty.New(). client := resty.New().
SetBaseURL(strings.TrimRight(apiHost, "/")+"/api"). SetBaseURL(strings.TrimRight(serverUrl, "/")+"/api").
SetHeader("Accept", "application/json"). SetHeader("Accept", "application/json").
SetHeader("Content-Type", "application/json"). SetHeader("Content-Type", "application/json").
SetPreRequestHook(func(c *resty.Client, req *http.Request) error { SetPreRequestHook(func(c *resty.Client, req *http.Request) error {

View File

@ -14,9 +14,9 @@ type Client struct {
client *resty.Client client *resty.Client
} }
func NewClient(apiHost, apiToken string) *Client { func NewClient(serverUrl, apiToken string) *Client {
client := resty.New(). client := resty.New().
SetBaseURL(strings.TrimRight(apiHost, "/")). SetBaseURL(strings.TrimRight(serverUrl, "/")).
SetHeader("X-SLCE-API-TOKEN", apiToken) SetHeader("X-SLCE-API-TOKEN", apiToken)
return &Client{ return &Client{

View File

@ -77,6 +77,25 @@ func (r *CertificateRepository) GetByWorkflowNodeId(ctx context.Context, workflo
return r.castRecordToModel(records[0]) return r.castRecordToModel(records[0])
} }
func (r *CertificateRepository) GetByWorkflowRunId(ctx context.Context, workflowRunId string) (*domain.Certificate, error) {
records, err := app.GetApp().FindRecordsByFilter(
domain.CollectionNameCertificate,
"workflowRunId={:workflowRunId} && deleted=null",
"-created",
1, 0,
dbx.Params{"workflowRunId": workflowRunId},
)
if err != nil {
return nil, err
}
if len(records) == 0 {
return nil, domain.ErrRecordNotFound
}
return r.castRecordToModel(records[0])
}
func (r *CertificateRepository) Save(ctx context.Context, certificate *domain.Certificate) (*domain.Certificate, error) { func (r *CertificateRepository) Save(ctx context.Context, certificate *domain.Certificate) (*domain.Certificate, error) {
collection, err := app.GetApp().FindCollectionByNameOrId(domain.CollectionNameCertificate) collection, err := app.GetApp().FindCollectionByNameOrId(domain.CollectionNameCertificate)
if err != nil { if err != nil {
@ -109,6 +128,7 @@ func (r *CertificateRepository) Save(ctx context.Context, certificate *domain.Ce
record.Set("acmeAccountUrl", certificate.ACMEAccountUrl) record.Set("acmeAccountUrl", certificate.ACMEAccountUrl)
record.Set("acmeCertUrl", certificate.ACMECertUrl) record.Set("acmeCertUrl", certificate.ACMECertUrl)
record.Set("acmeCertStableUrl", certificate.ACMECertStableUrl) record.Set("acmeCertStableUrl", certificate.ACMECertStableUrl)
record.Set("acmeRenewed", certificate.ACMERenewed)
record.Set("workflowId", certificate.WorkflowId) record.Set("workflowId", certificate.WorkflowId)
record.Set("workflowRunId", certificate.WorkflowRunId) record.Set("workflowRunId", certificate.WorkflowRunId)
record.Set("workflowNodeId", certificate.WorkflowNodeId) record.Set("workflowNodeId", certificate.WorkflowNodeId)
@ -170,6 +190,7 @@ func (r *CertificateRepository) castRecordToModel(record *core.Record) (*domain.
ACMEAccountUrl: record.GetString("acmeAccountUrl"), ACMEAccountUrl: record.GetString("acmeAccountUrl"),
ACMECertUrl: record.GetString("acmeCertUrl"), ACMECertUrl: record.GetString("acmeCertUrl"),
ACMECertStableUrl: record.GetString("acmeCertStableUrl"), ACMECertStableUrl: record.GetString("acmeCertStableUrl"),
ACMERenewed: record.GetBool("acmeRenewed"),
WorkflowId: record.GetString("workflowId"), WorkflowId: record.GetString("workflowId"),
WorkflowRunId: record.GetString("workflowRunId"), WorkflowRunId: record.GetString("workflowRunId"),
WorkflowNodeId: record.GetString("workflowNodeId"), WorkflowNodeId: record.GetString("workflowNodeId"),

View File

@ -96,6 +96,15 @@ func (n *applyNode) Process(ctx context.Context) error {
return err return err
} }
// 保存 ARI 记录
if applyResult.ARIReplaced {
lastCertificate, _ := n.certRepo.GetByWorkflowRunId(ctx, lastOutput.RunId)
if lastCertificate != nil {
lastCertificate.ACMERenewed = true
n.certRepo.Save(ctx, lastCertificate)
}
}
n.logger.Info("apply completed") n.logger.Info("apply completed")
return nil return nil
@ -134,7 +143,7 @@ func (n *applyNode) checkCanSkip(ctx context.Context, lastOutput *domain.Workflo
return false, "the configuration item 'KeyAlgorithm' changed" return false, "the configuration item 'KeyAlgorithm' changed"
} }
lastCertificate, _ := n.certRepo.GetByWorkflowNodeId(ctx, n.node.Id) lastCertificate, _ := n.certRepo.GetByWorkflowRunId(ctx, lastOutput.RunId)
if lastCertificate != nil { if lastCertificate != nil {
renewalInterval := time.Duration(currentNodeConfig.SkipBeforeExpiryDays) * time.Hour * 24 renewalInterval := time.Duration(currentNodeConfig.SkipBeforeExpiryDays) * time.Hour * 24
expirationTime := time.Until(lastCertificate.ExpireAt) expirationTime := time.Until(lastCertificate.ExpireAt)

View File

@ -34,6 +34,8 @@ func (n *nodeProcessor) SetLogger(logger *slog.Logger) {
type certificateRepository interface { type certificateRepository interface {
GetByWorkflowNodeId(ctx context.Context, workflowNodeId string) (*domain.Certificate, error) GetByWorkflowNodeId(ctx context.Context, workflowNodeId string) (*domain.Certificate, error)
GetByWorkflowRunId(ctx context.Context, workflowRunId string) (*domain.Certificate, error)
Save(ctx context.Context, certificate *domain.Certificate) (*domain.Certificate, error)
} }
type workflowOutputRepository interface { type workflowOutputRepository interface {

View File

@ -83,7 +83,7 @@ func (n *uploadNode) checkCanSkip(ctx context.Context, lastOutput *domain.Workfl
return false, "the configuration item 'PrivateKey' changed" return false, "the configuration item 'PrivateKey' changed"
} }
lastCertificate, _ := n.certRepo.GetByWorkflowNodeId(ctx, n.node.Id) lastCertificate, _ := n.certRepo.GetByWorkflowRunId(ctx, lastOutput.RunId)
if lastCertificate != nil { if lastCertificate != nil {
return true, "the certificate has already been uploaded" return true, "the certificate has already been uploaded"
} }

View File

@ -2,7 +2,6 @@ package migrations
import ( import (
x509 "crypto/x509" x509 "crypto/x509"
"log/slog"
"strings" "strings"
"github.com/pocketbase/pocketbase/core" "github.com/pocketbase/pocketbase/core"
@ -12,7 +11,8 @@ import (
func init() { func init() {
m.Register(func(app core.App) error { m.Register(func(app core.App) error {
slog.Info("[CERTIMATE] migration: ready ...") tracer := NewTracer("to v0.3")
tracer.Printf("go ...")
// backup collection records // backup collection records
collectionRecords := make([]*core.Record, 0) collectionRecords := make([]*core.Record, 0)
@ -30,7 +30,7 @@ func init() {
} }
collectionRecords = append(collectionRecords, records...) collectionRecords = append(collectionRecords, records...)
slog.Info("[CERTIMATE] migration: collection '" + collection.Name + "' backed up") tracer.Printf("collection '%s' backed up", collection.Name)
if collection.Name == "access" { if collection.Name == "access" {
collection.Fields.RemoveByName("usage") collection.Fields.RemoveByName("usage")
@ -107,7 +107,7 @@ func init() {
{ {
app.Delete(collection) app.Delete(collection)
slog.Info("[CERTIMATE] migration: collection '" + collection.Name + "' truncated") tracer.Printf("collection '%s' truncated", collection.Name)
} }
} }
} }
@ -1729,7 +1729,7 @@ func init() {
return err return err
} }
slog.Info("[CERTIMATE] migration: collections imported") tracer.Printf("collections imported")
// restore records // restore records
for _, record := range collectionRecords { for _, record := range collectionRecords {
@ -1795,12 +1795,11 @@ func init() {
return err return err
} }
slog.Info("[CERTIMATE] migration: collection '" + record.Collection().Name + "' record #" + record.Id + " updated") tracer.Printf("record #%s in collection '%s' updated", record.Id, record.Collection().Name)
} }
} }
slog.Info("[CERTIMATE] migration: done") tracer.Printf("done")
return nil return nil
}, func(app core.App) error { }, func(app core.App) error {
return nil return nil

View File

@ -7,14 +7,17 @@ import (
func init() { func init() {
m.Register(func(app core.App) error { m.Register(func(app core.App) error {
tracer := NewTracer("(v0.3)1740050400")
tracer.Printf("go ...")
// update collection `certificate` // update collection `certificate`
{ {
certimateCollection, err := app.FindCollectionByNameOrId("4szxr9x43tpj6np") collection, err := app.FindCollectionByNameOrId("4szxr9x43tpj6np")
if err != nil { if err != nil {
return err return err
} }
if err := certimateCollection.Fields.AddMarshaledJSONAt(4, []byte(`{ if err := collection.Fields.AddMarshaledJSONAt(4, []byte(`{
"autogeneratePattern": "", "autogeneratePattern": "",
"hidden": false, "hidden": false,
"id": "plmambpz", "id": "plmambpz",
@ -31,7 +34,7 @@ func init() {
return err return err
} }
if err := certimateCollection.Fields.AddMarshaledJSONAt(5, []byte(`{ if err := collection.Fields.AddMarshaledJSONAt(5, []byte(`{
"autogeneratePattern": "", "autogeneratePattern": "",
"hidden": false, "hidden": false,
"id": "49qvwxcg", "id": "49qvwxcg",
@ -48,7 +51,7 @@ func init() {
return err return err
} }
if err := certimateCollection.Fields.AddMarshaledJSONAt(7, []byte(`{ if err := collection.Fields.AddMarshaledJSONAt(7, []byte(`{
"autogeneratePattern": "", "autogeneratePattern": "",
"hidden": false, "hidden": false,
"id": "agt7n5bb", "id": "agt7n5bb",
@ -65,19 +68,21 @@ func init() {
return err return err
} }
if err := app.Save(certimateCollection); err != nil { if err := app.Save(collection); err != nil {
return err return err
} }
tracer.Printf("collection '%s' updated", collection.Name)
} }
// update collection `workflow` // update collection `workflow`
{ {
workflowCollection, err := app.FindCollectionByNameOrId("tovyif5ax6j62ur") collection, err := app.FindCollectionByNameOrId("tovyif5ax6j62ur")
if err != nil { if err != nil {
return err return err
} }
if err := workflowCollection.Fields.AddMarshaledJSONAt(6, []byte(`{ if err := collection.Fields.AddMarshaledJSONAt(6, []byte(`{
"hidden": false, "hidden": false,
"id": "awlphkfe", "id": "awlphkfe",
"maxSize": 5000000, "maxSize": 5000000,
@ -90,7 +95,7 @@ func init() {
return err return err
} }
if err := workflowCollection.Fields.AddMarshaledJSONAt(7, []byte(`{ if err := collection.Fields.AddMarshaledJSONAt(7, []byte(`{
"hidden": false, "hidden": false,
"id": "g9ohkk5o", "id": "g9ohkk5o",
"maxSize": 5000000, "maxSize": 5000000,
@ -103,19 +108,21 @@ func init() {
return err return err
} }
if err := app.Save(workflowCollection); err != nil { if err := app.Save(collection); err != nil {
return err return err
} }
tracer.Printf("collection '%s' updated", collection.Name)
} }
// update collection `workflow_output` // update collection `workflow_output`
{ {
workflowOutputCollection, err := app.FindCollectionByNameOrId("bqnxb95f2cooowp") collection, err := app.FindCollectionByNameOrId("bqnxb95f2cooowp")
if err != nil { if err != nil {
return err return err
} }
if err := workflowOutputCollection.Fields.AddMarshaledJSONAt(4, []byte(`{ if err := collection.Fields.AddMarshaledJSONAt(4, []byte(`{
"hidden": false, "hidden": false,
"id": "c2rm9omj", "id": "c2rm9omj",
"maxSize": 5000000, "maxSize": 5000000,
@ -128,11 +135,14 @@ func init() {
return err return err
} }
if err := app.Save(workflowOutputCollection); err != nil { if err := app.Save(collection); err != nil {
return err return err
} }
tracer.Printf("collection '%s' updated", collection.Name)
} }
tracer.Printf("done")
return nil return nil
}, func(app core.App) error { }, func(app core.App) error {
return nil return nil

View File

@ -11,6 +11,9 @@ import (
func init() { func init() {
m.Register(func(app core.App) error { m.Register(func(app core.App) error {
tracer := NewTracer("(v0.3)1742209200")
tracer.Printf("go ...")
// create collection `workflow_logs` // create collection `workflow_logs`
{ {
jsonData := `{ jsonData := `{
@ -167,6 +170,8 @@ func init() {
if err := app.Save(collection); err != nil { if err := app.Save(collection); err != nil {
return err return err
} }
tracer.Printf("collection '%s' created", collection.Name)
} }
// migrate data // migrate data
@ -215,6 +220,8 @@ func init() {
if err := app.Save(record); err != nil { if err := app.Save(record); err != nil {
return err return err
} }
tracer.Printf("record #%s in collection '%s' updated", record.Id, collection.Name)
} }
} }
} }
@ -243,6 +250,8 @@ func init() {
if err := app.Save(collection); err != nil { if err := app.Save(collection); err != nil {
return err return err
} }
tracer.Printf("collection '%s' updated", collection.Name)
} }
// migrate data // migrate data
@ -321,6 +330,8 @@ func init() {
if err := app.Save(workflowRun); err != nil { if err := app.Save(workflowRun); err != nil {
return err return err
} }
tracer.Printf("record #%s in collection '%s' updated", workflowRun.Id, workflowRun.Collection().Name)
} }
} }
@ -336,8 +347,11 @@ func init() {
if err := app.Save(collection); err != nil { if err := app.Save(collection); err != nil {
return err return err
} }
tracer.Printf("collection '%s' updated", collection.Name)
} }
tracer.Printf("done")
return nil return nil
}, func(app core.App) error { }, func(app core.App) error {
return nil return nil

View File

@ -7,12 +7,16 @@ import (
func init() { func init() {
m.Register(func(app core.App) error { m.Register(func(app core.App) error {
tracer := NewTracer("(v0.3)1742392800")
tracer.Printf("go ...")
// update collection `access`
{
collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e")
if err != nil { if err != nil {
return err return err
} }
// update field
if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{ if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{
"hidden": false, "hidden": false,
"id": "hwy7m03o", "id": "hwy7m03o",
@ -74,7 +78,15 @@ func init() {
return err return err
} }
return app.Save(collection) if err := app.Save(collection); err != nil {
return err
}
tracer.Printf("collection '%s' updated", collection.Name)
}
tracer.Printf("done")
return nil
}, func(app core.App) error { }, func(app core.App) error {
return nil return nil
}) })

View File

@ -7,6 +7,9 @@ import (
func init() { func init() {
m.Register(func(app core.App) error { m.Register(func(app core.App) error {
tracer := NewTracer("(v0.3)1742644800")
tracer.Printf("go ...")
// update collection `workflow_run` // update collection `workflow_run`
{ {
collection, err := app.FindCollectionByNameOrId("qjp8lygssgwyqyz") collection, err := app.FindCollectionByNameOrId("qjp8lygssgwyqyz")
@ -35,6 +38,8 @@ func init() {
if err := app.Save(collection); err != nil { if err := app.Save(collection); err != nil {
return err return err
} }
tracer.Printf("collection '%s' updated", collection.Name)
} }
// update collection `workflow_output` // update collection `workflow_output`
@ -61,6 +66,8 @@ func init() {
if err := app.Save(collection); err != nil { if err := app.Save(collection); err != nil {
return err return err
} }
tracer.Printf("collection '%s' updated", collection.Name)
} }
// update collection `workflow_logs` // update collection `workflow_logs`
@ -105,6 +112,8 @@ func init() {
if err := app.Save(collection); err != nil { if err := app.Save(collection); err != nil {
return err return err
} }
tracer.Printf("collection '%s' updated", collection.Name)
} }
// update collection `access` // update collection `access`
@ -182,8 +191,11 @@ func init() {
if err := app.Save(collection); err != nil { if err := app.Save(collection); err != nil {
return err return err
} }
tracer.Printf("collection '%s' updated", collection.Name)
} }
tracer.Printf("done")
return nil return nil
}, func(app core.App) error { }, func(app core.App) error {
return nil return nil

View File

@ -7,6 +7,9 @@ import (
func init() { func init() {
m.Register(func(app core.App) error { m.Register(func(app core.App) error {
tracer := NewTracer("(v0.3)1743264000")
tracer.Printf("go ...")
// update collection `settings` // update collection `settings`
{ {
collection, err := app.FindCollectionByNameOrId("dy6ccjb60spfy6p") collection, err := app.FindCollectionByNameOrId("dy6ccjb60spfy6p")
@ -52,6 +55,8 @@ func init() {
if err := app.Save(record); err != nil { if err := app.Save(record); err != nil {
return err return err
} }
tracer.Printf("record #%s in collection '%s' updated", record.Id, collection.Name)
} }
} }
@ -62,7 +67,6 @@ func init() {
return err return err
} }
// update field
if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{ if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{
"hidden": false, "hidden": false,
"id": "hwy7m03o", "id": "hwy7m03o",
@ -136,6 +140,8 @@ func init() {
if err := app.Save(collection); err != nil { if err := app.Save(collection); err != nil {
return err return err
} }
tracer.Printf("collection '%s' updated", collection.Name)
} }
// update collection `acme_accounts` // update collection `acme_accounts`
@ -163,9 +169,12 @@ func init() {
if err := app.Save(record); err != nil { if err := app.Save(record); err != nil {
return err return err
} }
tracer.Printf("record #%s in collection '%s' updated", record.Id, collection.Name)
} }
} }
tracer.Printf("done")
return nil return nil
}, func(app core.App) error { }, func(app core.App) error {
return nil return nil

View File

@ -7,12 +7,16 @@ import (
func init() { func init() {
m.Register(func(app core.App) error { m.Register(func(app core.App) error {
tracer := NewTracer("(v0.3)1744192800")
tracer.Printf("go ...")
// update collection `access`
{
collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e")
if err != nil { if err != nil {
return err return err
} }
// update field
if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{ if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{
"hidden": false, "hidden": false,
"id": "hwy7m03o", "id": "hwy7m03o",
@ -84,7 +88,15 @@ func init() {
return err return err
} }
return app.Save(collection) if err := app.Save(collection); err != nil {
return nil
}
tracer.Printf("collection '%s' updated", collection.Name)
}
tracer.Printf("done")
return nil
}, func(app core.App) error { }, func(app core.App) error {
return nil return nil
}) })

View File

@ -7,12 +7,16 @@ import (
func init() { func init() {
m.Register(func(app core.App) error { m.Register(func(app core.App) error {
tracer := NewTracer("(v0.3)1744459000")
tracer.Printf("go ...")
// update collection `access`
{
collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e")
if err != nil { if err != nil {
return err return err
} }
// update field
if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{ if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{
"hidden": false, "hidden": false,
"id": "hwy7m03o", "id": "hwy7m03o",
@ -85,7 +89,15 @@ func init() {
return err return err
} }
return app.Save(collection) if err := app.Save(collection); err != nil {
return err
}
tracer.Printf("collection '%s' updated", collection.Name)
}
tracer.Printf("done")
return nil
}, func(app core.App) error { }, func(app core.App) error {
return nil return nil
}) })

View File

@ -9,6 +9,11 @@ import (
func init() { func init() {
m.Register(func(app core.App) error { m.Register(func(app core.App) error {
tracer := NewTracer("(v0.3)1745308800")
tracer.Printf("go ...")
// update collection `access`
{
collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e")
if err != nil { if err != nil {
return err return err
@ -87,6 +92,10 @@ func init() {
return err return err
} }
tracer.Printf("collection '%s' updated", collection.Name)
}
tracer.Printf("done")
return nil return nil
}, func(app core.App) error { }, func(app core.App) error {
return nil return nil

View File

@ -7,6 +7,9 @@ import (
func init() { func init() {
m.Register(func(app core.App) error { m.Register(func(app core.App) error {
tracer := NewTracer("(v0.3)1745726400")
tracer.Printf("go ...")
// update collection `access` // update collection `access`
{ {
collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e")
@ -34,53 +37,62 @@ func init() {
if err := app.Save(collection); err != nil { if err := app.Save(collection); err != nil {
return err return err
} }
tracer.Printf("collection '%s' updated", collection.Name)
} }
// migrate data // migrate data
{ {
accesses, err := app.FindAllRecords("access") collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e")
if err != nil { if err != nil {
return err return err
} }
for _, access := range accesses { records, err := app.FindAllRecords(collection)
if err != nil {
return err
}
for _, record := range records {
changed := false changed := false
if access.GetString("provider") == "buypass" { if record.GetString("provider") == "buypass" {
access.Set("reserve", "ca") record.Set("reserve", "ca")
changed = true changed = true
} else if access.GetString("provider") == "googletrustservices" { } else if record.GetString("provider") == "googletrustservices" {
access.Set("reserve", "ca") record.Set("reserve", "ca")
changed = true changed = true
} else if access.GetString("provider") == "sslcom" { } else if record.GetString("provider") == "sslcom" {
access.Set("reserve", "ca") record.Set("reserve", "ca")
changed = true changed = true
} else if access.GetString("provider") == "zerossl" { } else if record.GetString("provider") == "zerossl" {
access.Set("reserve", "ca") record.Set("reserve", "ca")
changed = true changed = true
} }
if access.GetString("provider") == "webhook" { if record.GetString("provider") == "webhook" {
config := make(map[string]any) config := make(map[string]any)
if err := access.UnmarshalJSONField("config", &config); err != nil { if err := record.UnmarshalJSONField("config", &config); err != nil {
return err return err
} }
config["method"] = "POST" config["method"] = "POST"
config["headers"] = "Content-Type: application/json" config["headers"] = "Content-Type: application/json"
access.Set("config", config) record.Set("config", config)
changed = true changed = true
} }
if changed { if changed {
err = app.Save(access) if err := app.Save(record); err != nil {
if err != nil {
return err return err
} }
tracer.Printf("record #%s in collection '%s' updated", record.Id, collection.Name)
} }
} }
} }
tracer.Printf("done")
return nil return nil
}, func(app core.App) error { }, func(app core.App) error {
return nil return nil

View File

@ -7,36 +7,46 @@ import (
func init() { func init() {
m.Register(func(app core.App) error { m.Register(func(app core.App) error {
tracer := NewTracer("(v0.3)1747314000")
tracer.Printf("go ...")
// migrate data // migrate data
{ {
accesses, err := app.FindAllRecords("access") collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e")
if err != nil { if err != nil {
return err return err
} }
for _, access := range accesses { records, err := app.FindAllRecords(collection)
if err != nil {
return err
}
for _, record := range records {
changed := false changed := false
if access.GetString("provider") == "goedge" { if record.GetString("provider") == "goedge" {
config := make(map[string]any) config := make(map[string]any)
if err := access.UnmarshalJSONField("config", &config); err != nil { if err := record.UnmarshalJSONField("config", &config); err != nil {
return err return err
} }
config["apiRole"] = "user" config["apiRole"] = "user"
access.Set("config", config) record.Set("config", config)
changed = true changed = true
} }
if changed { if changed {
err = app.Save(access) if err := app.Save(record); err != nil {
if err != nil {
return err return err
} }
tracer.Printf("record #%s in collection '%s' updated", record.Id, collection.Name)
} }
} }
} }
tracer.Printf("done")
return nil return nil
}, func(app core.App) error { }, func(app core.App) error {
return nil return nil

View File

@ -7,6 +7,9 @@ import (
func init() { func init() {
m.Register(func(app core.App) error { m.Register(func(app core.App) error {
tracer := NewTracer("(v0.3)1747389600")
tracer.Printf("go ...")
// update collection `certificate` // update collection `certificate`
{ {
collection, err := app.FindCollectionByNameOrId("4szxr9x43tpj6np") collection, err := app.FindCollectionByNameOrId("4szxr9x43tpj6np")
@ -34,38 +37,47 @@ func init() {
if err := app.Save(collection); err != nil { if err := app.Save(collection); err != nil {
return err return err
} }
tracer.Printf("collection '%s' updated", collection.Name)
} }
// migrate data // migrate data
{ {
accesses, err := app.FindAllRecords("access") collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e")
if err != nil { if err != nil {
return err return err
} }
for _, access := range accesses { records, err := app.FindAllRecords(collection)
if err != nil {
return err
}
for _, record := range records {
changed := false changed := false
if access.GetString("provider") == "1panel" { if record.GetString("provider") == "1panel" {
config := make(map[string]any) config := make(map[string]any)
if err := access.UnmarshalJSONField("config", &config); err != nil { if err := record.UnmarshalJSONField("config", &config); err != nil {
return err return err
} }
config["apiVersion"] = "v1" config["apiVersion"] = "v1"
access.Set("config", config) record.Set("config", config)
changed = true changed = true
} }
if changed { if changed {
err = app.Save(access) if err := app.Save(record); err != nil {
if err != nil {
return err return err
} }
tracer.Printf("record #%s in collection '%s' updated", record.Id, collection.Name)
} }
} }
} }
tracer.Printf("done")
return nil return nil
}, func(app core.App) error { }, func(app core.App) error {
return nil return nil

View File

@ -0,0 +1,72 @@
package migrations
import (
"slices"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
tracer := NewTracer("(v0.3)1748178000")
tracer.Printf("go ...")
// migrate data
{
collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e")
if err != nil {
return err
}
records, err := app.FindAllRecords(collection)
if err != nil {
return err
}
providersToUpdate := []string{
"1panel",
"baotapanel",
"baotawaf",
"cdnfly",
"flexcdn",
"goedge",
"lecdn",
"powerdns",
"proxmoxve",
"ratpanel",
"safeline",
}
for _, record := range records {
changed := false
if slices.Contains(providersToUpdate, record.GetString("provider")) {
config := make(map[string]any)
if err := record.UnmarshalJSONField("config", &config); err != nil {
return err
}
if config["apiUrl"] != nil {
config["serverUrl"] = config["apiUrl"]
delete(config, "apiUrl")
record.Set("config", config)
changed = true
}
}
if changed {
if err := app.Save(record); err != nil {
return err
}
tracer.Printf("record #%s in collection '%s' updated", record.Id, collection.Name)
}
}
}
tracer.Printf("done")
return nil
}, func(app core.App) error {
return nil
})
}

View File

@ -0,0 +1,45 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
tracer := NewTracer("(v0.3)1748228400")
tracer.Printf("go ...")
// update collection `certificate`
{
collection, err := app.FindCollectionByNameOrId("4szxr9x43tpj6np")
if err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(14, []byte(`{
"hidden": false,
"id": "bool810050391",
"name": "acmeRenewed",
"presentable": false,
"required": false,
"system": false,
"type": "bool"
}`)); err != nil {
return err
}
if err := app.Save(collection); err != nil {
return err
}
tracer.Printf("collection '%s' updated", collection.Name)
}
tracer.Printf("done")
return nil
}, func(app core.App) error {
return nil
})
}

22
migrations/tracer.go Normal file
View File

@ -0,0 +1,22 @@
package migrations
import (
"fmt"
"log/slog"
)
type Tracer struct {
logger *slog.Logger
flag string
}
func NewTracer(flag string) *Tracer {
return &Tracer{
logger: slog.Default(),
flag: flag,
}
}
func (l *Tracer) Printf(format string, args ...any) {
l.logger.Info("[CERTIMATE] migration " + l.flag + ": " + fmt.Sprintf(format, args...))
}

226
ui/package-lock.json generated
View File

@ -17,27 +17,27 @@
"@uiw/codemirror-extensions-basic-setup": "^4.23.12", "@uiw/codemirror-extensions-basic-setup": "^4.23.12",
"@uiw/codemirror-theme-vscode": "^4.23.12", "@uiw/codemirror-theme-vscode": "^4.23.12",
"@uiw/react-codemirror": "^4.23.12", "@uiw/react-codemirror": "^4.23.12",
"ahooks": "^3.8.4", "ahooks": "^3.8.5",
"antd": "^5.25.1", "antd": "^5.25.3",
"antd-zod": "^6.1.0", "antd-zod": "^6.1.0",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"cron-parser": "^5.2.0", "cron-parser": "^5.2.0",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"i18next": "^25.1.2", "i18next": "^25.2.1",
"i18next-browser-languagedetector": "^8.1.0", "i18next-browser-languagedetector": "^8.1.0",
"immer": "^10.1.1", "immer": "^10.1.1",
"lucide-react": "^0.509.0", "lucide-react": "^0.511.0",
"nanoid": "^5.1.5", "nanoid": "^5.1.5",
"pocketbase": "^0.26.0", "pocketbase": "^0.26.0",
"radash": "^12.1.0", "radash": "^12.1.0",
"react": "^18.3.1", "react": "^18.3.1",
"react-copy-to-clipboard": "^5.1.0", "react-copy-to-clipboard": "^5.1.0",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-i18next": "^15.5.1", "react-i18next": "^15.5.2",
"react-router-dom": "^7.6.0", "react-router-dom": "^7.6.1",
"tailwind-merge": "^2.6.0", "tailwind-merge": "^2.6.0",
"zod": "^3.24.4", "zod": "^3.25.28",
"zustand": "^5.0.4" "zustand": "^5.0.5"
}, },
"devDependencies": { "devDependencies": {
"@types/file-saver": "^2.0.7", "@types/file-saver": "^2.0.7",
@ -46,10 +46,10 @@
"@types/react": "^18.3.12", "@types/react": "^18.3.12",
"@types/react-copy-to-clipboard": "^5.0.7", "@types/react-copy-to-clipboard": "^5.0.7",
"@types/react-dom": "^18.3.1", "@types/react-dom": "^18.3.1",
"@typescript-eslint/eslint-plugin": "^8.32.0", "@typescript-eslint/eslint-plugin": "^8.32.1",
"@typescript-eslint/parser": "^8.32.0", "@typescript-eslint/parser": "^8.32.1",
"@vitejs/plugin-legacy": "^6.1.1", "@vitejs/plugin-legacy": "^6.1.1",
"@vitejs/plugin-react": "^4.4.1", "@vitejs/plugin-react": "^4.5.0",
"autoprefixer": "^10.4.21", "autoprefixer": "^10.4.21",
"eslint": "^8.57.0", "eslint": "^8.57.0",
"eslint-config-prettier": "^10.1.5", "eslint-config-prettier": "^10.1.5",
@ -94,9 +94,9 @@
} }
}, },
"node_modules/@ant-design/colors": { "node_modules/@ant-design/colors": {
"version": "7.2.0", "version": "7.2.1",
"resolved": "https://registry.npmmirror.com/@ant-design/colors/-/colors-7.2.0.tgz", "resolved": "https://registry.npmmirror.com/@ant-design/colors/-/colors-7.2.1.tgz",
"integrity": "sha512-bjTObSnZ9C/O8MB/B4OUtd/q9COomuJAR2SYfhxLyHvCKn4EKwCN3e+fWGMo7H5InAyV0wL17jdE9ALrdOW/6A==", "integrity": "sha512-lCHDcEzieu4GA3n8ELeZ5VQ8pKQAWcGGLRTQ50aQM2iqPpq2evTxER84jfdPvsPAtEcZ7m44NI45edFMo8oOYQ==",
"dependencies": { "dependencies": {
"@ant-design/fast-color": "^2.0.6" "@ant-design/fast-color": "^2.0.6"
} }
@ -2047,12 +2047,9 @@
} }
}, },
"node_modules/@babel/runtime": { "node_modules/@babel/runtime": {
"version": "7.26.10", "version": "7.27.1",
"resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.26.10.tgz", "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.27.1.tgz",
"integrity": "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==", "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==",
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
@ -3225,6 +3222,12 @@
"react-dom": ">=18.0.0" "react-dom": ">=18.0.0"
} }
}, },
"node_modules/@rolldown/pluginutils": {
"version": "1.0.0-beta.9",
"resolved": "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.9.tgz",
"integrity": "sha512-e9MeMtVWo186sgvFFJOPGy7/d2j2mZhLJIdVW0C/xDluuOvymEATqz6zKsP0ZmXGzQtqlyjz5sC1sYQUoJG98w==",
"dev": true
},
"node_modules/@rollup/rollup-android-arm-eabi": { "node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.40.0", "version": "4.40.0",
"resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.0.tgz", "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.0.tgz",
@ -3613,18 +3616,18 @@
} }
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.32.0", "version": "8.32.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.1.tgz",
"integrity": "sha512-/jU9ettcntkBFmWUzzGgsClEi2ZFiikMX5eEQsmxIAWMOn4H3D4rvHssstmAHGVvrYnaMqdWWWg0b5M6IN/MTQ==", "integrity": "sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@eslint-community/regexpp": "^4.10.0", "@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.32.0", "@typescript-eslint/scope-manager": "8.32.1",
"@typescript-eslint/type-utils": "8.32.0", "@typescript-eslint/type-utils": "8.32.1",
"@typescript-eslint/utils": "8.32.0", "@typescript-eslint/utils": "8.32.1",
"@typescript-eslint/visitor-keys": "8.32.0", "@typescript-eslint/visitor-keys": "8.32.1",
"graphemer": "^1.4.0", "graphemer": "^1.4.0",
"ignore": "^5.3.1", "ignore": "^7.0.0",
"natural-compare": "^1.4.0", "natural-compare": "^1.4.0",
"ts-api-utils": "^2.1.0" "ts-api-utils": "^2.1.0"
}, },
@ -3641,16 +3644,25 @@
"typescript": ">=4.8.4 <5.9.0" "typescript": ">=4.8.4 <5.9.0"
} }
}, },
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
"version": "7.0.4",
"resolved": "https://registry.npmmirror.com/ignore/-/ignore-7.0.4.tgz",
"integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==",
"dev": true,
"engines": {
"node": ">= 4"
}
},
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "8.32.0", "version": "8.32.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.32.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.32.1.tgz",
"integrity": "sha512-B2MdzyWxCE2+SqiZHAjPphft+/2x2FlO9YBx7eKE1BCb+rqBlQdhtAEhzIEdozHd55DXPmxBdpMygFJjfjjA9A==", "integrity": "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.32.0", "@typescript-eslint/scope-manager": "8.32.1",
"@typescript-eslint/types": "8.32.0", "@typescript-eslint/types": "8.32.1",
"@typescript-eslint/typescript-estree": "8.32.0", "@typescript-eslint/typescript-estree": "8.32.1",
"@typescript-eslint/visitor-keys": "8.32.0", "@typescript-eslint/visitor-keys": "8.32.1",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@ -3666,13 +3678,13 @@
} }
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "8.32.0", "version": "8.32.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.32.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz",
"integrity": "sha512-jc/4IxGNedXkmG4mx4nJTILb6TMjL66D41vyeaPWvDUmeYQzF3lKtN15WsAeTr65ce4mPxwopPSo1yUUAWw0hQ==", "integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.32.0", "@typescript-eslint/types": "8.32.1",
"@typescript-eslint/visitor-keys": "8.32.0" "@typescript-eslint/visitor-keys": "8.32.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -3683,13 +3695,13 @@
} }
}, },
"node_modules/@typescript-eslint/type-utils": { "node_modules/@typescript-eslint/type-utils": {
"version": "8.32.0", "version": "8.32.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.32.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.32.1.tgz",
"integrity": "sha512-t2vouuYQKEKSLtJaa5bB4jHeha2HJczQ6E5IXPDPgIty9EqcJxpr1QHQ86YyIPwDwxvUmLfP2YADQ5ZY4qddZg==", "integrity": "sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/typescript-estree": "8.32.0", "@typescript-eslint/typescript-estree": "8.32.1",
"@typescript-eslint/utils": "8.32.0", "@typescript-eslint/utils": "8.32.1",
"debug": "^4.3.4", "debug": "^4.3.4",
"ts-api-utils": "^2.1.0" "ts-api-utils": "^2.1.0"
}, },
@ -3706,9 +3718,9 @@
} }
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "8.32.0", "version": "8.32.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.32.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.32.1.tgz",
"integrity": "sha512-O5Id6tGadAZEMThM6L9HmVf5hQUXNSxLVKeGJYWNhhVseps/0LddMkp7//VDkzwJ69lPL0UmZdcZwggj9akJaA==", "integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -3719,13 +3731,13 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "8.32.0", "version": "8.32.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz",
"integrity": "sha512-pU9VD7anSCOIoBFnhTGfOzlVFQIA1XXiQpH/CezqOBaDppRwTglJzCC6fUQGpfwey4T183NKhF1/mfatYmjRqQ==", "integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.32.0", "@typescript-eslint/types": "8.32.1",
"@typescript-eslint/visitor-keys": "8.32.0", "@typescript-eslint/visitor-keys": "8.32.1",
"debug": "^4.3.4", "debug": "^4.3.4",
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@ -3745,15 +3757,15 @@
} }
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "8.32.0", "version": "8.32.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.32.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.32.1.tgz",
"integrity": "sha512-8S9hXau6nQ/sYVtC3D6ISIDoJzS1NsCK+gluVhLN2YkBPX+/1wkwyUiDKnxRh15579WoOIyVWnoyIf3yGI9REw==", "integrity": "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.7.0", "@eslint-community/eslint-utils": "^4.7.0",
"@typescript-eslint/scope-manager": "8.32.0", "@typescript-eslint/scope-manager": "8.32.1",
"@typescript-eslint/types": "8.32.0", "@typescript-eslint/types": "8.32.1",
"@typescript-eslint/typescript-estree": "8.32.0" "@typescript-eslint/typescript-estree": "8.32.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -3768,12 +3780,12 @@
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "8.32.0", "version": "8.32.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz",
"integrity": "sha512-1rYQTCLFFzOI5Nl0c8LUpJT8HxpwVRn9E4CkMsYfuN6ctmQqExjSTzzSk0Tz2apmXy7WU6/6fyaZVVA/thPN+w==", "integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.32.0", "@typescript-eslint/types": "8.32.1",
"eslint-visitor-keys": "^4.2.0" "eslint-visitor-keys": "^4.2.0"
}, },
"engines": { "engines": {
@ -3922,14 +3934,15 @@
} }
}, },
"node_modules/@vitejs/plugin-react": { "node_modules/@vitejs/plugin-react": {
"version": "4.4.1", "version": "4.5.0",
"resolved": "https://registry.npmmirror.com/@vitejs/plugin-react/-/plugin-react-4.4.1.tgz", "resolved": "https://registry.npmmirror.com/@vitejs/plugin-react/-/plugin-react-4.5.0.tgz",
"integrity": "sha512-IpEm5ZmeXAP/osiBXVVP5KjFMzbWOonMs0NaQQl+xYnUAcq4oHUBsF2+p4MgKWG4YMmFYJU8A6sxRPuowllm6w==", "integrity": "sha512-JuLWaEqypaJmOJPLWwO335Ig6jSgC1FTONCWAxnqcQthLTK/Yc9aH6hr9z/87xciejbQcnP3GnA1FWUSWeXaeg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/core": "^7.26.10", "@babel/core": "^7.26.10",
"@babel/plugin-transform-react-jsx-self": "^7.25.9", "@babel/plugin-transform-react-jsx-self": "^7.25.9",
"@babel/plugin-transform-react-jsx-source": "^7.25.9", "@babel/plugin-transform-react-jsx-source": "^7.25.9",
"@rolldown/pluginutils": "1.0.0-beta.9",
"@types/babel__core": "^7.20.5", "@types/babel__core": "^7.20.5",
"react-refresh": "^0.17.0" "react-refresh": "^0.17.0"
}, },
@ -3970,9 +3983,9 @@
} }
}, },
"node_modules/ahooks": { "node_modules/ahooks": {
"version": "3.8.4", "version": "3.8.5",
"resolved": "https://registry.npmmirror.com/ahooks/-/ahooks-3.8.4.tgz", "resolved": "https://registry.npmmirror.com/ahooks/-/ahooks-3.8.5.tgz",
"integrity": "sha512-39wDEw2ZHvypaT14EpMMk4AzosHWt0z9bulY0BeDsvc9PqJEV+Kjh/4TZfftSsotBMq52iYIOFPd3PR56e0ZJg==", "integrity": "sha512-Y+MLoJpBXVdjsnnBjE5rOSPkQ4DK+8i5aPDzLJdIOsCpo/fiAeXcBY1Y7oWgtOK0TpOz0gFa/XcyO1UGdoqLcw==",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.21.0", "@babel/runtime": "^7.21.0",
"dayjs": "^1.9.1", "dayjs": "^1.9.1",
@ -3988,7 +4001,7 @@
"node": ">=8.0.0" "node": ">=8.0.0"
}, },
"peerDependencies": { "peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0" "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
} }
}, },
"node_modules/ajv": { "node_modules/ajv": {
@ -4017,11 +4030,11 @@
} }
}, },
"node_modules/antd": { "node_modules/antd": {
"version": "5.25.1", "version": "5.25.3",
"resolved": "https://registry.npmmirror.com/antd/-/antd-5.25.1.tgz", "resolved": "https://registry.npmmirror.com/antd/-/antd-5.25.3.tgz",
"integrity": "sha512-4KC7KuPCjr0z3Vuw9DsF+ceqJaPLbuUI3lOX1sY8ix25ceamp+P8yxOmk3Y2JHCD2ZAhq+5IQ/DTJRN2adWYKQ==", "integrity": "sha512-tBBcAFRjmWM3sitxrL/FEbQL+MTQntYY5bGa5c1ZZZHXWCynkhS3Ch/gy25mGMUY1M/9Uw3pH029v/RGht1x3w==",
"dependencies": { "dependencies": {
"@ant-design/colors": "^7.2.0", "@ant-design/colors": "^7.2.1",
"@ant-design/cssinjs": "^1.23.0", "@ant-design/cssinjs": "^1.23.0",
"@ant-design/cssinjs-utils": "^1.1.3", "@ant-design/cssinjs-utils": "^1.1.3",
"@ant-design/fast-color": "^2.0.6", "@ant-design/fast-color": "^2.0.6",
@ -4056,11 +4069,11 @@
"rc-rate": "~2.13.1", "rc-rate": "~2.13.1",
"rc-resize-observer": "^1.4.3", "rc-resize-observer": "^1.4.3",
"rc-segmented": "~2.7.0", "rc-segmented": "~2.7.0",
"rc-select": "~14.16.7", "rc-select": "~14.16.8",
"rc-slider": "~11.1.8", "rc-slider": "~11.1.8",
"rc-steps": "~6.0.1", "rc-steps": "~6.0.1",
"rc-switch": "~4.1.0", "rc-switch": "~4.1.0",
"rc-table": "~7.50.4", "rc-table": "~7.50.5",
"rc-tabs": "~15.6.1", "rc-tabs": "~15.6.1",
"rc-textarea": "~1.10.0", "rc-textarea": "~1.10.0",
"rc-tooltip": "~6.4.0", "rc-tooltip": "~6.4.0",
@ -6081,9 +6094,9 @@
} }
}, },
"node_modules/i18next": { "node_modules/i18next": {
"version": "25.1.2", "version": "25.2.1",
"resolved": "https://registry.npmmirror.com/i18next/-/i18next-25.1.2.tgz", "resolved": "https://registry.npmmirror.com/i18next/-/i18next-25.2.1.tgz",
"integrity": "sha512-SP63m8LzdjkrAjruH7SCI3ndPSgjt4/wX7ouUUOzCW/eY+HzlIo19IQSfYA9X3qRiRP1SYtaTsg/Oz/PGsfD8w==", "integrity": "sha512-+UoXK5wh+VlE1Zy5p6MjcvctHXAhRwQKCxiJD8noKZzIXmnAX8gdHX5fLPA3MEVxEN4vbZkQFy8N0LyD9tUqPw==",
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@ -6099,7 +6112,7 @@
} }
], ],
"dependencies": { "dependencies": {
"@babel/runtime": "^7.26.10" "@babel/runtime": "^7.27.1"
}, },
"peerDependencies": { "peerDependencies": {
"typescript": "^5" "typescript": "^5"
@ -6797,9 +6810,9 @@
} }
}, },
"node_modules/lucide-react": { "node_modules/lucide-react": {
"version": "0.509.0", "version": "0.511.0",
"resolved": "https://registry.npmmirror.com/lucide-react/-/lucide-react-0.509.0.tgz", "resolved": "https://registry.npmmirror.com/lucide-react/-/lucide-react-0.511.0.tgz",
"integrity": "sha512-xCJHn6Uh5qF6PGml25vveCTrHJZcqS1G1MVzWZK54ZQsOiCVJk4fwY3oyo5EXS2S+aqvTpWYIfJN+PesJ0quxg==", "integrity": "sha512-VK5a2ydJ7xm8GvBeKLS9mu1pVK6ucef9780JVUjw6bAjJL/QXnd4Y0p7SPeOUMC27YhzNCZvm5d/QX0Tp3rc0w==",
"peerDependencies": { "peerDependencies": {
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
} }
@ -7874,9 +7887,9 @@
} }
}, },
"node_modules/rc-select": { "node_modules/rc-select": {
"version": "14.16.7", "version": "14.16.8",
"resolved": "https://registry.npmmirror.com/rc-select/-/rc-select-14.16.7.tgz", "resolved": "https://registry.npmmirror.com/rc-select/-/rc-select-14.16.8.tgz",
"integrity": "sha512-lT9kO5gFHQdJzu9a0btcOtNaJHkhenSl8H5mcpgXN9VIMXP59rnkpbdHmPrteixWs1D5zFOTyoTYX3b7joADIQ==", "integrity": "sha512-NOV5BZa1wZrsdkKaiK7LHRuo5ZjZYMDxPP6/1+09+FB4KoNi8jcG1ZqLE3AVCxEsYMBe65OBx71wFoHRTP3LRg==",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.10.1", "@babel/runtime": "^7.10.1",
"@rc-component/trigger": "^2.1.1", "@rc-component/trigger": "^2.1.1",
@ -7943,9 +7956,9 @@
} }
}, },
"node_modules/rc-table": { "node_modules/rc-table": {
"version": "7.50.4", "version": "7.50.5",
"resolved": "https://registry.npmmirror.com/rc-table/-/rc-table-7.50.4.tgz", "resolved": "https://registry.npmmirror.com/rc-table/-/rc-table-7.50.5.tgz",
"integrity": "sha512-Y+YuncnQqoS5e7yHvfvlv8BmCvwDYDX/2VixTBEhkMDk9itS9aBINp4nhzXFKiBP/frG4w0pS9d9Rgisl0T1Bw==", "integrity": "sha512-FDZu8aolhSYd3v9KOc3lZOVAU77wmRRu44R0Wfb8Oj1dXRUsloFaXMSl6f7yuWZUxArJTli7k8TEOX2mvhDl4A==",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.10.1", "@babel/runtime": "^7.10.1",
"@rc-component/context": "^1.4.0", "@rc-component/context": "^1.4.0",
@ -8135,9 +8148,9 @@
"integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="
}, },
"node_modules/react-i18next": { "node_modules/react-i18next": {
"version": "15.5.1", "version": "15.5.2",
"resolved": "https://registry.npmmirror.com/react-i18next/-/react-i18next-15.5.1.tgz", "resolved": "https://registry.npmmirror.com/react-i18next/-/react-i18next-15.5.2.tgz",
"integrity": "sha512-C8RZ7N7H0L+flitiX6ASjq9p5puVJU1Z8VyL3OgM/QOMRf40BMZX+5TkpxzZVcTmOLPX5zlti4InEX5pFyiVeA==", "integrity": "sha512-ePODyXgmZQAOYTbZXQn5rRsSBu3Gszo69jxW6aKmlSgxKAI1fOhDwSu6bT4EKHciWPKQ7v7lPrjeiadR6Gi+1A==",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.25.0", "@babel/runtime": "^7.25.0",
"html-parse-stringify": "^3.0.1" "html-parse-stringify": "^3.0.1"
@ -8179,9 +8192,9 @@
} }
}, },
"node_modules/react-router": { "node_modules/react-router": {
"version": "7.6.0", "version": "7.6.1",
"resolved": "https://registry.npmmirror.com/react-router/-/react-router-7.6.0.tgz", "resolved": "https://registry.npmmirror.com/react-router/-/react-router-7.6.1.tgz",
"integrity": "sha512-GGufuHIVCJDbnIAXP3P9Sxzq3UUsddG3rrI3ut1q6m0FI6vxVBF3JoPQ38+W/blslLH4a5Yutp8drkEpXoddGQ==", "integrity": "sha512-hPJXXxHJZEsPFNVbtATH7+MMX43UDeOauz+EAU4cgqTn7ojdI9qQORqS8Z0qmDlL1TclO/6jLRYUEtbWidtdHQ==",
"dependencies": { "dependencies": {
"cookie": "^1.0.1", "cookie": "^1.0.1",
"set-cookie-parser": "^2.6.0" "set-cookie-parser": "^2.6.0"
@ -8200,11 +8213,11 @@
} }
}, },
"node_modules/react-router-dom": { "node_modules/react-router-dom": {
"version": "7.6.0", "version": "7.6.1",
"resolved": "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-7.6.0.tgz", "resolved": "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-7.6.1.tgz",
"integrity": "sha512-DYgm6RDEuKdopSyGOWZGtDfSm7Aofb8CCzgkliTjtu/eDuB0gcsv6qdFhhi8HdtmA+KHkt5MfZ5K2PdzjugYsA==", "integrity": "sha512-vxU7ei//UfPYQ3iZvHuO1D/5fX3/JOqhNTbRR+WjSBWxf9bIvpWK+ftjmdfJHzPOuMQKe2fiEdG+dZX6E8uUpA==",
"dependencies": { "dependencies": {
"react-router": "7.6.0" "react-router": "7.6.1"
}, },
"engines": { "engines": {
"node": ">=20.0.0" "node": ">=20.0.0"
@ -8286,7 +8299,8 @@
"node_modules/regenerator-runtime": { "node_modules/regenerator-runtime": {
"version": "0.14.1", "version": "0.14.1",
"resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
"dev": true
}, },
"node_modules/regenerator-transform": { "node_modules/regenerator-transform": {
"version": "0.15.2", "version": "0.15.2",
@ -9926,17 +9940,17 @@
} }
}, },
"node_modules/zod": { "node_modules/zod": {
"version": "3.24.4", "version": "3.25.28",
"resolved": "https://registry.npmmirror.com/zod/-/zod-3.24.4.tgz", "resolved": "https://registry.npmmirror.com/zod/-/zod-3.25.28.tgz",
"integrity": "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==", "integrity": "sha512-/nt/67WYKnr5by3YS7LroZJbtcCBurDKKPBPWWzaxvVCGuG/NOsiKkrjoOhI8mJ+SQUXEbUzeB3S+6XDUEEj7Q==",
"funding": { "funding": {
"url": "https://github.com/sponsors/colinhacks" "url": "https://github.com/sponsors/colinhacks"
} }
}, },
"node_modules/zustand": { "node_modules/zustand": {
"version": "5.0.4", "version": "5.0.5",
"resolved": "https://registry.npmmirror.com/zustand/-/zustand-5.0.4.tgz", "resolved": "https://registry.npmmirror.com/zustand/-/zustand-5.0.5.tgz",
"integrity": "sha512-39VFTN5InDtMd28ZhjLyuTnlytDr9HfwO512Ai4I8ZABCoyAj4F1+sr7sD1jP/+p7k77Iko0Pb5NhgBFDCX0kQ==", "integrity": "sha512-mILtRfKW9xM47hqxGIxCv12gXusoY/xTSHBYApXozR0HmQv299whhBeeAcRy+KrPPybzosvJBCOmVjq6x12fCg==",
"engines": { "engines": {
"node": ">=12.20.0" "node": ">=12.20.0"
}, },

View File

@ -19,27 +19,27 @@
"@uiw/codemirror-extensions-basic-setup": "^4.23.12", "@uiw/codemirror-extensions-basic-setup": "^4.23.12",
"@uiw/codemirror-theme-vscode": "^4.23.12", "@uiw/codemirror-theme-vscode": "^4.23.12",
"@uiw/react-codemirror": "^4.23.12", "@uiw/react-codemirror": "^4.23.12",
"ahooks": "^3.8.4", "ahooks": "^3.8.5",
"antd": "^5.25.1", "antd": "^5.25.3",
"antd-zod": "^6.1.0", "antd-zod": "^6.1.0",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"cron-parser": "^5.2.0", "cron-parser": "^5.2.0",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"i18next": "^25.1.2", "i18next": "^25.2.1",
"i18next-browser-languagedetector": "^8.1.0", "i18next-browser-languagedetector": "^8.1.0",
"immer": "^10.1.1", "immer": "^10.1.1",
"lucide-react": "^0.509.0", "lucide-react": "^0.511.0",
"nanoid": "^5.1.5", "nanoid": "^5.1.5",
"pocketbase": "^0.26.0", "pocketbase": "^0.26.0",
"radash": "^12.1.0", "radash": "^12.1.0",
"react": "^18.3.1", "react": "^18.3.1",
"react-copy-to-clipboard": "^5.1.0", "react-copy-to-clipboard": "^5.1.0",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-i18next": "^15.5.1", "react-i18next": "^15.5.2",
"react-router-dom": "^7.6.0", "react-router-dom": "^7.6.1",
"tailwind-merge": "^2.6.0", "tailwind-merge": "^2.6.0",
"zod": "^3.24.4", "zod": "^3.25.28",
"zustand": "^5.0.4" "zustand": "^5.0.5"
}, },
"devDependencies": { "devDependencies": {
"@types/file-saver": "^2.0.7", "@types/file-saver": "^2.0.7",
@ -48,10 +48,10 @@
"@types/react": "^18.3.12", "@types/react": "^18.3.12",
"@types/react-copy-to-clipboard": "^5.0.7", "@types/react-copy-to-clipboard": "^5.0.7",
"@types/react-dom": "^18.3.1", "@types/react-dom": "^18.3.1",
"@typescript-eslint/eslint-plugin": "^8.32.0", "@typescript-eslint/eslint-plugin": "^8.32.1",
"@typescript-eslint/parser": "^8.32.0", "@typescript-eslint/parser": "^8.32.1",
"@vitejs/plugin-legacy": "^6.1.1", "@vitejs/plugin-legacy": "^6.1.1",
"@vitejs/plugin-react": "^4.4.1", "@vitejs/plugin-react": "^4.5.0",
"autoprefixer": "^10.4.21", "autoprefixer": "^10.4.21",
"eslint": "^8.57.0", "eslint": "^8.57.0",
"eslint-config-prettier": "^10.1.5", "eslint-config-prettier": "^10.1.5",

View File

@ -0,0 +1 @@
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="-16 -16 1600 1600" width="200" height="200"><path fill-rule="evenodd" fill="#0069ff" d="m784.5 1562v-302.5c322.4 0 570.3-317.3 447.3-655-44.7-124.3-145.4-224.5-270.2-269-339.2-122.5-657.8 126.1-657.8 445.3h-303.8c0-510.3 495.7-909.2 1032.4-742.2 234.8 72.3 421.2 259.7 495.7 493.6 167.7 536.2-231.1 1029.8-743.6 1029.8zm-301.9-601.2h301.9v300.6h-301.9zm-232.9 300.6h232.9v231.9h-232.9zm-195.6 0.1v-193h193.8v193z"/></svg>

After

Width:  |  Height:  |  Size: 484 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M0 512C0 229.2224 229.2224 0 512 0c282.7776 0 512 229.2224 512 512 0 282.7776-229.2224 512-512 512C229.2224 1024 0 794.7776 0 512z" fill="#7A8CD2"></path><path d="M758.613333 281.207467a1.792 1.792 0 0 0-0.938666-0.8192 591.598933 591.598933 0 0 0-144.298667-44.032 2.218667 2.218667 0 0 0-2.321067 1.0752 398.114133 398.114133 0 0 0-17.954133 36.3008 548.437333 548.437333 0 0 0-162.082133 0 364.663467 364.663467 0 0 0-18.244267-36.317867 2.269867 2.269867 0 0 0-2.321067-1.0752 589.943467 589.943467 0 0 0-144.298666 44.032 2.048 2.048 0 0 0-0.955734 0.8192c-91.904 135.099733-117.077333 266.888533-104.721066 397.038933a2.3552 2.3552 0 0 0 0.9216 1.621334 591.5648 591.5648 0 0 0 177.015466 88.064 2.321067 2.321067 0 0 0 2.491734-0.8192 412.16 412.16 0 0 0 36.215466-57.9584 2.184533 2.184533 0 0 0-1.2288-3.072 390.212267 390.212267 0 0 1-55.296-25.941334 2.269867 2.269867 0 0 1-1.1264-1.792 2.218667 2.218667 0 0 1 0.887467-1.911466c3.7376-2.730667 7.389867-5.563733 10.990933-8.465067a2.2016 2.2016 0 0 1 2.286934-0.3072c116.0192 52.1216 241.629867 52.1216 356.266666 0a2.218667 2.218667 0 0 1 2.321067 0.273067c3.601067 2.9184 7.2704 5.751467 11.008 8.4992a2.2528 2.2528 0 0 1 0.904533 1.911466 2.2016 2.2016 0 0 1-1.092266 1.792 366.0288 366.0288 0 0 1-55.330134 25.9072 2.269867 2.269867 0 0 0-1.314133 1.297067 2.184533 2.184533 0 0 0 0.1024 1.809067 462.506667 462.506667 0 0 0 36.181333 57.941333 2.286933 2.286933 0 0 0 2.491734 0.836267 589.636267 589.636267 0 0 0 177.322666-88.064 2.269867 2.269867 0 0 0 0.904534-1.604267c14.7968-150.459733-24.746667-281.173333-104.789334-397.038933z m-364.168533 317.781333c-34.935467 0-63.709867-31.573333-63.709867-70.314667s28.2112-70.314667 63.709867-70.314666c35.771733 0 64.273067 31.829333 63.709867 70.314666 0 38.741333-28.228267 70.314667-63.709867 70.314667z m235.554133 0c-34.9184 0-63.709867-31.573333-63.709866-70.314667s28.228267-70.314667 63.709866-70.314666c35.771733 0 64.273067 31.829333 63.709867 70.314666 0 38.741333-27.938133 70.314667-63.709867 70.314667z" fill="#FFFFFF"></path></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

Some files were not shown because too many files have changed in this diff Show More