Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fef8c3cb1a | ||
|
|
41abc8cab8 | ||
|
|
4d3b3834f5 | ||
|
|
9b1ba574ff | ||
|
|
ee7d950c15 | ||
|
|
8ca41f18be | ||
|
|
9d522bd9ef | ||
|
|
f9633616e2 | ||
|
|
9a0dd53cd7 | ||
|
|
6bbcec6163 | ||
|
|
fdee69bdaf | ||
|
|
7936c34472 | ||
|
|
365fd0bd5b | ||
|
|
f63ee41405 | ||
|
|
26359b9d16 | ||
|
|
5abdb577fb | ||
|
|
0a73ba1a53 | ||
|
|
a4d397f24b | ||
|
|
809f231981 | ||
|
|
1499c637ee | ||
|
|
e5805a028b | ||
|
|
5cb0463cf6 | ||
|
|
12c208cad4 |
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ">=1.23.0"
|
||||
go-version: ">=1.24.0"
|
||||
|
||||
- name: Build WebUI
|
||||
run: npm --prefix=./ui ci && npm --prefix=./ui run build
|
||||
|
||||
@@ -8,7 +8,7 @@ RUN \
|
||||
|
||||
|
||||
|
||||
FROM golang:1.23-alpine AS builder
|
||||
FROM golang:1.24-alpine AS builder
|
||||
WORKDIR /app
|
||||
COPY ../. /app/
|
||||
RUN rm -rf /app/ui/dist
|
||||
|
||||
105
go.mod
105
go.mod
@@ -1,69 +1,71 @@
|
||||
module github.com/usual2970/certimate
|
||||
|
||||
go 1.23.0
|
||||
go 1.24.0
|
||||
|
||||
toolchain go1.23.2
|
||||
toolchain go1.24.3
|
||||
|
||||
require (
|
||||
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/security/keyvault/azcertificates v1.3.1
|
||||
github.com/Edgio/edgio-api v0.0.0-workspace
|
||||
github.com/G-Core/gcorelabscdn-go v1.0.29
|
||||
github.com/G-Core/gcorelabscdn-go v1.0.31
|
||||
github.com/alibabacloud-go/alb-20200616/v2 v2.2.8
|
||||
github.com/alibabacloud-go/apig-20240327/v3 v3.2.2
|
||||
github.com/alibabacloud-go/cas-20200407/v3 v3.0.4
|
||||
github.com/alibabacloud-go/cdn-20180510/v5 v5.2.2
|
||||
github.com/alibabacloud-go/cloudapi-20160714/v5 v5.7.2
|
||||
github.com/alibabacloud-go/cloudapi-20160714/v5 v5.7.3
|
||||
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.7
|
||||
github.com/alibabacloud-go/esa-20240910/v2 v2.31.1
|
||||
github.com/alibabacloud-go/fc-20230330/v4 v4.3.4
|
||||
github.com/alibabacloud-go/ddoscoo-20200101/v4 v4.0.0
|
||||
github.com/alibabacloud-go/esa-20240910/v2 v2.32.0
|
||||
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/live-20161101 v1.1.1
|
||||
github.com/alibabacloud-go/nlb-20220430/v2 v2.0.3
|
||||
github.com/alibabacloud-go/slb-20140515/v4 v4.0.10
|
||||
github.com/alibabacloud-go/tea v1.3.9
|
||||
github.com/alibabacloud-go/vod-20170321/v4 v4.8.3
|
||||
github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.1
|
||||
github.com/alibabacloud-go/vod-20170321/v4 v4.8.4
|
||||
github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.2
|
||||
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
|
||||
github.com/aws/aws-sdk-go-v2/service/acm v1.31.3
|
||||
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.45.3
|
||||
github.com/baidubce/bce-sdk-go v0.9.224
|
||||
github.com/byteplus-sdk/byteplus-sdk-golang v1.0.44
|
||||
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/baidubce/bce-sdk-go v0.9.226
|
||||
github.com/byteplus-sdk/byteplus-sdk-golang v1.0.46
|
||||
github.com/go-acme/lego/v4 v4.23.1
|
||||
github.com/go-resty/resty/v2 v2.16.5
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1
|
||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.141
|
||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.148
|
||||
github.com/jdcloud-api/jdcloud-sdk-go v1.64.0
|
||||
github.com/libdns/dynv6 v1.0.0
|
||||
github.com/libdns/libdns v0.2.3
|
||||
github.com/luthermonson/go-proxmox v0.2.2
|
||||
github.com/nikoksr/notify v1.3.0
|
||||
github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0
|
||||
github.com/pkg/sftp v1.13.9
|
||||
github.com/pocketbase/dbx v1.11.0
|
||||
github.com/pocketbase/pocketbase v0.27.1
|
||||
github.com/povsister/scp v0.0.0-20240802064259-28781e87b246
|
||||
github.com/pocketbase/pocketbase v0.28.0
|
||||
github.com/povsister/scp v0.0.0-20250504051308-e467f71ea63c
|
||||
github.com/qiniu/go-sdk/v7 v7.25.3
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1136
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1143
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1147
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1143
|
||||
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/common v1.0.1162
|
||||
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/ssl v1.0.1124
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1138
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1136
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1147
|
||||
github.com/ucloud/ucloud-sdk-go v0.22.33
|
||||
github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.11
|
||||
github.com/volcengine/volc-sdk-golang v1.0.204
|
||||
github.com/volcengine/volcengine-go-sdk v1.1.4
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1162
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1160
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1162
|
||||
github.com/ucloud/ucloud-sdk-go v0.22.35
|
||||
github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.12
|
||||
github.com/volcengine/volc-sdk-golang v1.0.207
|
||||
github.com/volcengine/volcengine-go-sdk v1.1.7
|
||||
gitlab.ecloud.com/ecloud/ecloudsdkclouddns v1.0.1
|
||||
gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0
|
||||
golang.org/x/crypto v0.37.0
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0
|
||||
k8s.io/api v0.32.3
|
||||
k8s.io/apimachinery v0.32.3
|
||||
k8s.io/client-go v0.32.3
|
||||
golang.org/x/crypto v0.38.0
|
||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6
|
||||
k8s.io/api v0.33.0
|
||||
k8s.io/apimachinery v0.33.0
|
||||
k8s.io/client-go v0.33.0
|
||||
software.sslmate.com/src/go-pkcs12 v0.5.0
|
||||
)
|
||||
|
||||
@@ -77,12 +79,15 @@ require (
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-fc-util v0.0.7 // indirect
|
||||
github.com/alibabacloud-go/openplatform-20191219/v2 v2.0.1 // indirect
|
||||
github.com/alibabacloud-go/tea-fileform v1.1.1 // indirect
|
||||
github.com/alibabacloud-go/tea-oss-sdk v1.1.3 // indirect
|
||||
github.com/alibabacloud-go/tea-oss-sdk v1.1.5 // indirect
|
||||
github.com/alibabacloud-go/tea-oss-utils v1.1.0 // indirect
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.7 // indirect
|
||||
github.com/avast/retry-go v3.0.0+incompatible // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.50.0 // indirect
|
||||
github.com/blinkbean/dingtalk v1.1.3 // indirect
|
||||
github.com/buger/goterm v1.0.4 // indirect
|
||||
github.com/diskfs/go-diskfs v1.5.0 // indirect
|
||||
github.com/djherbis/times v1.6.0 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.12.1 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||
github.com/go-lark/lark v1.15.1 // indirect
|
||||
@@ -98,15 +103,16 @@ require (
|
||||
github.com/gofrs/uuid v4.4.0+incompatible // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/gnostic-models v0.6.9 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
||||
github.com/jinzhu/copier v0.3.4 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/magefile/mage v1.14.0 // indirect
|
||||
github.com/mailru/easyjson v0.9.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 // indirect
|
||||
@@ -119,7 +125,7 @@ require (
|
||||
github.com/qiniu/dyn v1.3.0 // indirect
|
||||
github.com/qiniu/x v1.10.5 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af // indirect
|
||||
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
go.mongodb.org/mongo-driver v1.17.2 // indirect
|
||||
@@ -128,10 +134,11 @@ require (
|
||||
gopkg.in/ns1/ns1-go.v2 v2.13.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect
|
||||
k8s.io/utils v0.0.0-20241210054802-24370beab758 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect
|
||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
)
|
||||
|
||||
@@ -145,7 +152,7 @@ require (
|
||||
github.com/alibabacloud-go/tea-utils v1.4.5 // indirect
|
||||
github.com/alibabacloud-go/tea-xml v1.1.3 // indirect
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.63.100 // indirect
|
||||
github.com/aliyun/credentials-go v1.4.5 // indirect
|
||||
github.com/aliyun/credentials-go v1.4.6 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.36.3
|
||||
github.com/aws/aws-sdk-go-v2/config v1.29.9
|
||||
@@ -168,7 +175,7 @@ require (
|
||||
github.com/domodwyer/mailyak/v3 v3.6.2
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
|
||||
github.com/ganigeorgiev/fexpr v0.5.0 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.0.5 // indirect
|
||||
github.com/go-ozzo/ozzo-validation/v4 v4.3.0 // indirect
|
||||
@@ -189,23 +196,23 @@ require (
|
||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/spf13/cast v1.7.1 // indirect
|
||||
github.com/spf13/cast v1.8.0 // indirect
|
||||
github.com/spf13/cobra v1.9.1 // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.10.0 // indirect
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1128 // indirect
|
||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||
golang.org/x/image v0.26.0 // indirect
|
||||
golang.org/x/image v0.27.0 // indirect
|
||||
golang.org/x/mod v0.24.0 // indirect
|
||||
golang.org/x/net v0.39.0 // indirect
|
||||
golang.org/x/oauth2 v0.29.0 // indirect
|
||||
golang.org/x/sync v0.13.0
|
||||
golang.org/x/sys v0.32.0 // indirect
|
||||
golang.org/x/term v0.31.0 // indirect
|
||||
golang.org/x/text v0.24.0 // indirect
|
||||
golang.org/x/net v0.40.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sync v0.14.0
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/term v0.32.0 // indirect
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
golang.org/x/time v0.11.0
|
||||
golang.org/x/tools v0.32.0 // indirect
|
||||
golang.org/x/tools v0.33.0 // indirect
|
||||
google.golang.org/protobuf v1.36.5 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
||||
230
go.sum
230
go.sum
@@ -67,8 +67,8 @@ github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg
|
||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/G-Core/gcorelabscdn-go v1.0.29 h1:9jNCwzNZAgihTPe+nrsLD2c0GHjxvpuV3VEA74L5Kkk=
|
||||
github.com/G-Core/gcorelabscdn-go v1.0.29/go.mod h1:iSGXaTvZBzDHQW+rKFS918BgFVpONcyLEijwh8WsXpE=
|
||||
github.com/G-Core/gcorelabscdn-go v1.0.31 h1:0ulvvM3yMDQ+Q5089tLsQxffL7I4pqf2bFCurU+DeHw=
|
||||
github.com/G-Core/gcorelabscdn-go v1.0.31/go.mod h1:iSGXaTvZBzDHQW+rKFS918BgFVpONcyLEijwh8WsXpE=
|
||||
github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
|
||||
github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
@@ -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/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/cloudapi-20160714/v5 v5.7.2 h1:Ug50clztqiQAy5t0R9Vejibz2Xgxm1Tpw2Y6A9eAwRE=
|
||||
github.com/alibabacloud-go/cloudapi-20160714/v5 v5.7.2/go.mod h1:l9Zd2FanDUO2UqHJSPnOv+cY9DVT+YXcr97zfpSHywo=
|
||||
github.com/alibabacloud-go/cloudapi-20160714/v5 v5.7.3 h1:OTLn0ShbE0jJj+5Z+P76zeHsZYxZjO7YVThQoeaBM9M=
|
||||
github.com/alibabacloud-go/cloudapi-20160714/v5 v5.7.3/go.mod h1:eUmD1G4BjEBOAHIeJrHJL7pyLGgXSRTPLjBmYY7uPEg=
|
||||
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-encode-util v0.0.2 h1:1uJGrbsGEVqWcWxrS9MyC2NG0Ax+GpOM5gtupki31XE=
|
||||
@@ -122,6 +122,8 @@ github.com/alibabacloud-go/darabonba-string v1.0.2 h1:E714wms5ibdzCqGeYJ9JCFywE5
|
||||
github.com/alibabacloud-go/darabonba-string v1.0.2/go.mod h1:93cTfV3vuPhhEwGGpKKqhVW4jLe7tDpo3LUM0i0g6mA=
|
||||
github.com/alibabacloud-go/dcdn-20180115/v3 v3.5.0 h1:EQmKhYju6y38kJ1ZvZROeJG2Q1Wk6hlc8KQrVhvGyaw=
|
||||
github.com/alibabacloud-go/dcdn-20180115/v3 v3.5.0/go.mod h1:b9qzvr/2V1f0r1Z6xUmkLqEouKcPGy4LCC22yV+6HQo=
|
||||
github.com/alibabacloud-go/ddoscoo-20200101/v4 v4.0.0 h1:z9dPOvBRxzpD+FQ2uu/p2Z92I+PY9MUZMauwC+8AC6M=
|
||||
github.com/alibabacloud-go/ddoscoo-20200101/v4 v4.0.0/go.mod h1:Cdg3Fu4jFByamRzt3AkeiBssoVPRNDs+EPYMP2fIj78=
|
||||
github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68/go.mod h1:6pb/Qy8c+lqua8cFpEy7g39NRRqOWc3rOwAy8m5Y2BY=
|
||||
github.com/alibabacloud-go/debug v1.0.0/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc=
|
||||
github.com/alibabacloud-go/debug v1.0.1 h1:MsW9SmUtbb1Fnt3ieC6NNZi6aEwrXfDksD4QA6GSbPg=
|
||||
@@ -129,10 +131,10 @@ 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.1 h1:ZkBv2/jnghxtU0p+upSU0GGzW1VL9GQdZO3mcSUTUy8=
|
||||
github.com/alibabacloud-go/endpoint-util v1.1.1/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE=
|
||||
github.com/alibabacloud-go/esa-20240910/v2 v2.31.1 h1:LACf71RxZjaystAfcWXa3EMtueVKNGxsCR3L+UihKtU=
|
||||
github.com/alibabacloud-go/esa-20240910/v2 v2.31.1/go.mod h1:qa4hC7W/BQOc9liuJckLnBLxILEzYjg2xhAZ+UVeUUQ=
|
||||
github.com/alibabacloud-go/fc-20230330/v4 v4.3.4 h1:DMUkeW24CWuvChy9uOD1DzMh3ToVARCB6m3xxWBslic=
|
||||
github.com/alibabacloud-go/fc-20230330/v4 v4.3.4/go.mod h1:vEJimQ6E/e+m2z0/oXdeQWlFw/Pi/Ar6NKcMrSvcILE=
|
||||
github.com/alibabacloud-go/esa-20240910/v2 v2.32.0 h1:eudSgNIkCg6huIu3HuF16BJG6+CA6bIuIddxpuPydpg=
|
||||
github.com/alibabacloud-go/esa-20240910/v2 v2.32.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/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/go.mod h1:F5c0E5UB3k8v6neTtw3FBcJ1YCNFzVoL1JPRHTe33u4=
|
||||
github.com/alibabacloud-go/live-20161101 v1.1.1 h1:rUGfA8RHmCMtQ5M3yMSyRde+yRXWqVecmiXBU3XrGJ8=
|
||||
@@ -163,8 +165,9 @@ github.com/alibabacloud-go/tea v1.3.9 h1:bjgt1bvdY780vz/17iWNNtbXl4A77HWntWMeaUF
|
||||
github.com/alibabacloud-go/tea v1.3.9/go.mod h1:A560v/JTQ1n5zklt2BEpurJzZTI8TUT+Psg2drWlxRg=
|
||||
github.com/alibabacloud-go/tea-fileform v1.1.1 h1:1YG6erAP3joQ0XdCXYIotuD7zyOM6qCR49xkp5FZDeU=
|
||||
github.com/alibabacloud-go/tea-fileform v1.1.1/go.mod h1:ZeCV91o4ISmxidd686f0ebdS5EDHWU+vW+TkjLhrsFE=
|
||||
github.com/alibabacloud-go/tea-oss-sdk v1.1.3 h1:EhAHI6edMeqgkZEqP7r4nc9iMWAUBKGxJHoBsOSKTtU=
|
||||
github.com/alibabacloud-go/tea-oss-sdk v1.1.3/go.mod h1:yUnodpR3Bf2rudLE7V/Gft5txjJF30Pk+hH77K/Eab0=
|
||||
github.com/alibabacloud-go/tea-oss-sdk v1.1.5 h1:CFUFcqanvBaoGN/CyTHUZrVNtFZd1WTjem46m0HTTV0=
|
||||
github.com/alibabacloud-go/tea-oss-sdk v1.1.5/go.mod h1:5fhlKMa/kWRJNgPYRt+5qSg3UidRvNbf9Z2bI8Dp5/s=
|
||||
github.com/alibabacloud-go/tea-oss-utils v1.1.0 h1:y65crjjcZ2Pbb6UZtC2deuIZHDVTS3IaDWE7M9nVLRc=
|
||||
github.com/alibabacloud-go/tea-oss-utils v1.1.0/go.mod h1:PFCF12e9yEKyBUIn7X1IrF/pNjvxgkHy0CgxX4+xRuY=
|
||||
github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE=
|
||||
@@ -182,10 +185,10 @@ github.com/alibabacloud-go/tea-xml v1.1.1/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCE
|
||||
github.com/alibabacloud-go/tea-xml v1.1.2/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8=
|
||||
github.com/alibabacloud-go/tea-xml v1.1.3 h1:7LYnm+JbOq2B+T/B0fHC4Ies4/FofC4zHzYtqw7dgt0=
|
||||
github.com/alibabacloud-go/tea-xml v1.1.3/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8=
|
||||
github.com/alibabacloud-go/vod-20170321/v4 v4.8.3 h1:IXDfINF3Wc88SKIijYgqy9HF3NiA68F97wgVeiRRwkc=
|
||||
github.com/alibabacloud-go/vod-20170321/v4 v4.8.3/go.mod h1:5ocQ6hIc9tpGixD2iy099aOGwIgpzjT2le4Krd4aLn8=
|
||||
github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.1 h1:7gHYtb2swx96tG7rflKoiFOdjKZ/W3N7azS6LT1TVFI=
|
||||
github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.1/go.mod h1:DohGoS8BnMxHXghHebtjPP7+GMdxPsRN19T3nn2HcCU=
|
||||
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/waf-openapi-20211001/v5 v5.1.2 h1:CmhJzCZ5RiSiWU6BV2XJUtIMD2LDo9FFfqlYGtx1aAw=
|
||||
github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.2/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/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ=
|
||||
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible h1:8psS8a+wKfiLt1iVDX79F7Y6wUM49Lcha2FMXt4UM8g=
|
||||
@@ -194,8 +197,9 @@ github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6q
|
||||
github.com/aliyun/credentials-go v1.3.1/go.mod h1:8jKYhQuDawt8x2+fusqa1Y6mPxemTsBEN04dgcAcYz0=
|
||||
github.com/aliyun/credentials-go v1.3.6/go.mod h1:1LxUuX7L5YrZUWzBrRyk0SwSdH4OmPrib8NVePL3fxM=
|
||||
github.com/aliyun/credentials-go v1.3.10/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U=
|
||||
github.com/aliyun/credentials-go v1.4.5 h1:O76WYKgdy1oQYYiJkERjlA2dxGuvLRrzuO2ScrtGWSk=
|
||||
github.com/aliyun/credentials-go v1.4.5/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U=
|
||||
github.com/aliyun/credentials-go v1.4.6 h1:CG8rc/nxCNKfXbZWpWDzI9GjF4Tuu3Es14qT8Y0ClOk=
|
||||
github.com/aliyun/credentials-go v1.4.6/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
@@ -223,10 +227,10 @@ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0io
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo=
|
||||
github.com/aws/aws-sdk-go-v2/service/acm v1.31.3 h1:GwlU39usxM7E1LIhZchk93PtTQm2j3jb63of/YkBd+o=
|
||||
github.com/aws/aws-sdk-go-v2/service/acm v1.31.3/go.mod h1:3sKYAgRbuBa2QMYGh/WEclwnmfx+QoPhhX25PdSQSQM=
|
||||
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.45.3 h1:xQnjN34F4I3a/I3Xj0g9vmD5hAqC7u5y3SC3eC6T1E8=
|
||||
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.45.3/go.mod h1:FIBJ48TS+qJb+Ne4qJ+0NeIhtPTVXItXooTeNeVI4Po=
|
||||
github.com/aws/aws-sdk-go-v2/service/acm v1.32.0 h1:Ik/TAn4TBw/t3JhQJKtwjgoOf6kg5nXc190TiGhNrmI=
|
||||
github.com/aws/aws-sdk-go-v2/service/acm v1.32.0/go.mod h1:3sKYAgRbuBa2QMYGh/WEclwnmfx+QoPhhX25PdSQSQM=
|
||||
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.46.1 h1:6xZNYtuVwzBs8k+TmraERt0vL68Ppg9aUi+aTQmPaVM=
|
||||
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.46.1/go.mod h1:FIBJ48TS+qJb+Ne4qJ+0NeIhtPTVXItXooTeNeVI4Po=
|
||||
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA=
|
||||
@@ -243,8 +247,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.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ=
|
||||
github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
|
||||
github.com/baidubce/bce-sdk-go v0.9.224 h1:z2L8alGw/y3IUHjrLRyrxrgCvMssYTjgCd7OQdb4gt0=
|
||||
github.com/baidubce/bce-sdk-go v0.9.224/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
|
||||
github.com/baidubce/bce-sdk-go v0.9.226 h1:VKEKcJC9P33yIfYJZr12Q/4Bvj18RFbgO8w8XOfU8AI=
|
||||
github.com/baidubce/bce-sdk-go v0.9.226/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
|
||||
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 v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
@@ -252,8 +256,10 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/blinkbean/dingtalk v1.1.3 h1:MbidFZYom7DTFHD/YIs+eaI7kRy52kmWE/sy0xjo6E4=
|
||||
github.com/blinkbean/dingtalk v1.1.3/go.mod h1:9BaLuGSBqY3vT5hstValh48DbsKO7vaHaJnG9pXwbto=
|
||||
github.com/byteplus-sdk/byteplus-sdk-golang v1.0.44 h1:men5pKZNho+cw9/YU7TFerTspS3lKayS64zctl/D7Fk=
|
||||
github.com/byteplus-sdk/byteplus-sdk-golang v1.0.44/go.mod h1:CIL/T2dxgbIA79os+wl0Fq0vCbADTZNIddV6PNYB6DY=
|
||||
github.com/buger/goterm v1.0.4 h1:Z9YvGmOih81P0FbVtEYTFF6YsSgxSUKEhf/f9bTMXbY=
|
||||
github.com/buger/goterm v1.0.4/go.mod h1:HiFWV3xnkolgrBV3mY8m0X0Pumt4zg4QhbdOzQtB8tE=
|
||||
github.com/byteplus-sdk/byteplus-sdk-golang v1.0.46 h1:Z0TagIjBDaoCZuJANP/P8+z+ef8dStVCBPjMZcI/y8s=
|
||||
github.com/byteplus-sdk/byteplus-sdk-golang v1.0.46/go.mod h1:CIL/T2dxgbIA79os+wl0Fq0vCbADTZNIddV6PNYB6DY=
|
||||
github.com/casbin/casbin/v2 v2.37.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
|
||||
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||
github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||
@@ -295,6 +301,10 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
||||
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
||||
github.com/diskfs/go-diskfs v1.5.0 h1:0SANkrab4ifiZBytk380gIesYh5Gc+3i40l7qsrYP4s=
|
||||
github.com/diskfs/go-diskfs v1.5.0/go.mod h1:bRFumZeGFCO8C2KNswrQeuj2m1WCVr4Ms5IjWMczMDk=
|
||||
github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c=
|
||||
github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0=
|
||||
github.com/domodwyer/mailyak/v3 v3.6.2 h1:x3tGMsyFhTCaxp6ycgR0FE/bu5QiNp+hetUuCOBXMn8=
|
||||
github.com/domodwyer/mailyak/v3 v3.6.2/go.mod h1:lOm/u9CyCVWHeaAmHIdF4RiKVxKUT/H5XX10lIKAL6c=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
@@ -305,6 +315,8 @@ github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5m
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/elliotwutingfeng/asciiset v0.0.0-20230602022725-51bbb787efab h1:h1UgjJdAAhj+uPL68n7XASS6bU+07ZX1WJvVS2eyoeY=
|
||||
github.com/elliotwutingfeng/asciiset v0.0.0-20230602022725-51bbb787efab/go.mod h1:GLo/8fDswSAniFG+BFIaiSPcK610jyzgEhWYPQwuQdw=
|
||||
github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU=
|
||||
github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
@@ -330,8 +342,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
|
||||
github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
|
||||
github.com/gammazero/toposort v0.1.1/go.mod h1:H2cozTnNpMw0hg2VHAYsAxmkHXBYroNangj2NTBQDvw=
|
||||
github.com/ganigeorgiev/fexpr v0.5.0 h1:XA9JxtTE/Xm+g/JFI6RfZEHSiQlk+1glLvRK1Lpv/Tk=
|
||||
github.com/ganigeorgiev/fexpr v0.5.0/go.mod h1:RyGiGqmeXhEQ6+mlGdnUleLHgtzzu/VGO2WtJkF5drE=
|
||||
@@ -390,6 +402,8 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU=
|
||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM=
|
||||
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
|
||||
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
|
||||
@@ -435,8 +449,6 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
@@ -458,14 +470,13 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
@@ -492,8 +503,14 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/h2non/gock v1.2.0 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE=
|
||||
github.com/h2non/gock v1.2.0/go.mod h1:tNhoxHYW2W42cYkYb1WqzdbYIieALC99kpYr7rH/BQk=
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
||||
github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
|
||||
github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
@@ -527,8 +544,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/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.141 h1:8i57QAi5u+iPAYze92bkIvZoHiS0J45ndul5glr/NE8=
|
||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.141/go.mod h1:Y/+YLCFCJtS29i2MbYPTUlNNfwXvkzEsZKR0imY/2aY=
|
||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.148 h1:PdWSbniKnPhKe1B19KUHW/9ahYbFH2EY6Iq6sxOnomo=
|
||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.148/go.mod h1:Y/+YLCFCJtS29i2MbYPTUlNNfwXvkzEsZKR0imY/2aY=
|
||||
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/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
@@ -544,6 +561,8 @@ github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJk
|
||||
github.com/jdcloud-api/jdcloud-sdk-go v1.64.0 h1:xZc/ZRcrOhDx9Ra9htu6ui2gUUttmLsXIqH61LcvY4U=
|
||||
github.com/jdcloud-api/jdcloud-sdk-go v1.64.0/go.mod h1:UrKjuULIWLjHFlG6aSPunArE5QX57LftMmStAZJBEX8=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jinzhu/copier v0.3.4 h1:mfU6jI9PtCeUjkjQ322dlff9ELjGDu975C2p/nrubVI=
|
||||
github.com/jinzhu/copier v0.3.4/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||
@@ -574,6 +593,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
|
||||
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
|
||||
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
@@ -600,6 +621,10 @@ github.com/libdns/dynv6 v1.0.0/go.mod h1:65PL/bAlyH0J+0WGlOJYnMpoIuXcg/FmW4dTBYW
|
||||
github.com/libdns/libdns v0.1.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
|
||||
github.com/libdns/libdns v0.2.3 h1:ba30K4ObwMGB/QTmqUxf3H4/GmUrCAIkMWejeGl12v8=
|
||||
github.com/libdns/libdns v0.2.3/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
|
||||
github.com/luthermonson/go-proxmox v0.2.2 h1:BZ7VEj302wxw2i/EwTcyEiBzQib8teocB2SSkLHyySY=
|
||||
github.com/luthermonson/go-proxmox v0.2.2/go.mod h1:oyFgg2WwTEIF0rP6ppjiixOHa5ebK1p8OaRiFhvICBQ=
|
||||
github.com/magefile/mage v1.14.0 h1:6QDX3g6z1YvJ4olPhT1wksUcSa/V0a1B+pJb73fBjyo=
|
||||
github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
|
||||
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
|
||||
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
@@ -694,7 +719,10 @@ github.com/performancecopilot/speed/v4 v4.0.0/go.mod h1:qxrSyuDGrTOWfV+uKRFhfxw6
|
||||
github.com/peterhellberg/link v1.2.0 h1:UA5pg3Gp/E0F2WdX7GERiNrPQrM1K6CVJUUWfHa4t6c=
|
||||
github.com/peterhellberg/link v1.2.0/go.mod h1:gYfAh+oJgQu2SrZHg5hROVRQe1ICoK0/HHJTcE0edxc=
|
||||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
||||
github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
|
||||
github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc=
|
||||
github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
@@ -705,17 +733,19 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
||||
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||
github.com/pkg/sftp v1.13.9 h1:4NGkvGudBL7GteO3m6qnaQ4pC0Kvf0onSVc9gR3EWBw=
|
||||
github.com/pkg/sftp v1.13.9/go.mod h1:OBN7bVXdstkFFN/gdnHPUb5TE8eb8G1Rp9wCItqjkkA=
|
||||
github.com/pkg/xattr v0.4.9 h1:5883YPCtkSd8LFbs13nXplj9g9tlrwoJRjgpgMu1/fE=
|
||||
github.com/pkg/xattr v0.4.9/go.mod h1:di8WF84zAKk8jzR1UBTEWh9AUlIZZ7M/JNt8e9B6ktU=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
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/go.mod h1:xXRCIAKTHMgUCyCKZm55pUOdvFziJjQfXaWKhu2vhMs=
|
||||
github.com/pocketbase/pocketbase v0.27.1 h1:KGCsS8idUVTC5QHxTj91qHDhIXOb5Yb50wwHhNvJRTQ=
|
||||
github.com/pocketbase/pocketbase v0.27.1/go.mod h1:aTpwwloVJzeJ7MlwTRrbI/x62QNR2/kkCrovmyrXpqs=
|
||||
github.com/pocketbase/pocketbase v0.28.0 h1:dnMHSO0wuYpKs6oP3X5buw1lY9ptd8zy1fTjN+Ae+mA=
|
||||
github.com/pocketbase/pocketbase v0.28.0/go.mod h1:WE6xMM4+pxKIVNl4B1mcOEZXlDvPGl7cZ64TW2iXHdI=
|
||||
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/povsister/scp v0.0.0-20240802064259-28781e87b246 h1:c4D8BPWLOxxdaxQLfLKQXH2YXY/E9yo3jrDSL54XrTw=
|
||||
github.com/povsister/scp v0.0.0-20240802064259-28781e87b246/go.mod h1:i1Au86ZXK0ZalQNyBp2njCcyhSCR/QP/AMfILip+zNI=
|
||||
github.com/povsister/scp v0.0.0-20250504051308-e467f71ea63c h1:1+j5JHz9mUzYSp0scuF6hzvJP28EDBFe5eBJb0xnGk4=
|
||||
github.com/povsister/scp v0.0.0-20250504051308-e467f71ea63c/go.mod h1:CiJNEeV6v0tUCNul/+gTjl+FgjfImoiuptJB9AEzqjE=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
|
||||
@@ -752,8 +782,8 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
@@ -765,15 +795,15 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af h1:Sp5TG9f7K39yfB+If0vjp97vuT74F72r8hfRpP8jLU0=
|
||||
github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
|
||||
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cast v1.8.0 h1:gEN9K4b8Xws4EX0+a0reLmhq8moKn7ntRlQYgjPeCDk=
|
||||
github.com/spf13/cast v1.8.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
@@ -802,32 +832,33 @@ 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/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
|
||||
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1136 h1:H1pjtH5uZ4XZPj9qQ9tt9jzeWqZzrd8qYIw01Q60/08=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1136/go.mod h1:K6absuzpElv6mw2d7j8xkphOkwd23qvG0Rcmhl4rqlk=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1143 h1:7OL/ThUCqkntItSiqbY1g3s0Ua26Qr08G8fcSzyrAqA=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1143/go.mod h1:XO18PkKinF17cQOSlhbP7GOnj04N5L2iCaHn64yiMtE=
|
||||
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/clb v1.0.1161 h1:yGFg9/6j3NP10r9PfSWHfekuq4SwPyqblWnfISfKANo=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1161/go.mod h1:9MzQSEULYm5wHAKz8R3oQ8ovg4vWeLFzn0DmRWTc6zg=
|
||||
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.1136/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1138/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1143/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1147 h1:6v559jM1v6A4KJinNZ28RqVZs+ipKMzCWtYWcWy+zZ4=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1147/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.1160/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.1162 h1:bscCBygP9JRl6iNabF+vmBOhY+xayFFGYV5Wa0NzH0A=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1162/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/go.mod h1:zbsYIBT+VTX4z4ocjTAdLBIWyNYj3z0BRqd0iPdnjsk=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1143 h1:fvK9kOsPquDTWrT2aXLWVnAMUokr4gFK7uYeY3JMB6U=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1143/go.mod h1:SLYgasv8DdvRnesG+SLdqFdEBIJzietfVDytke8ASKQ=
|
||||
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/scf v1.0.1120 h1:z0t0lb5h1mZirXftO8MRg25COYZHx0ubQjSPhZT/LY0=
|
||||
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/ssl v1.0.1124 h1:LQKAlxFb0sYiE8ojK5h9+seuFzogoJtYnXmiRF+4F4Q=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1124/go.mod h1:tYbK0FbHVG+78od7eZpzczE8qk0JWKO/osTQWuiJ3Fo=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1138 h1:SrQ+rlWLwnXU/6S8ULGhFaiV5faAeqL0ysdsqV6P1AA=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1138/go.mod h1:XvXgF+4yO4Ni6gYoqMszSkNNqFLkOxx2j5F7+u3lpKQ=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1136 h1:9GqM1URHNySj0f8TkUcKT6qSDiGep3IB1hWWu1ti6rY=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1136/go.mod h1:b5JZEbM4ROYUSVcgNkDHuHWdTJX5Qe4wC1asq2n0yes=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1147 h1:SxZsn9N4c1yx40kZOINIh9AnUKcgChUWbZoDiv6VvmQ=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1147/go.mod h1:T4sxG9+SJ038MBsam2upsEYRpQ82JpX+IkZ08+P9RlE=
|
||||
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.1162/go.mod h1:rsO8JCP+WQeLQ32wAB4oRRjsEz0O+kvCGDqc7Ze1jc4=
|
||||
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.1160/go.mod h1:kf6NQmKK6sh1ACwh8iliBy7I/burd+AWusNz6zbDvLM=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1162 h1:gnmuUaoFAShc9FKj3Omswu3n08bHM/sGsl8xjFAkFNs=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1162/go.mod h1:bu3KAFeoJ1xDGQp72h9Le3FqbOcCcdomOUig3OqgcE4=
|
||||
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/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
|
||||
@@ -836,16 +867,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-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/ucloud/ucloud-sdk-go v0.22.33 h1:YKY8VpFNttdnVNb0o3owGeZRoUtRJmoWPJYJPfcCf9A=
|
||||
github.com/ucloud/ucloud-sdk-go v0.22.33/go.mod h1:dyLmFHmUfgb4RZKYQP9IArlvQ2pxzFthfhwxRzOEPIw=
|
||||
github.com/ucloud/ucloud-sdk-go v0.22.35 h1:Q4CY3Ae5813jmNUrGdCjc8tlyleL5Lyl0APnpK5L4sk=
|
||||
github.com/ucloud/ucloud-sdk-go v0.22.35/go.mod h1:dyLmFHmUfgb4RZKYQP9IArlvQ2pxzFthfhwxRzOEPIw=
|
||||
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/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.11 h1:J4AweXxLqlSwb1Aam9npcb5optZmszDIrKWa/hs+e4U=
|
||||
github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.11/go.mod h1:IrjK84IJJTuOZOTMv/P18Ydjy/x+ow7fF7q11jAxXLM=
|
||||
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/volc-sdk-golang v1.0.23/go.mod h1:AfG/PZRUkHJ9inETvbjNifTDgut25Wbkm2QoYBTbvyU=
|
||||
github.com/volcengine/volc-sdk-golang v1.0.204 h1:Njid6coReHV2gWc3bsqWMQf+K8jveauzW8zEX08CTzI=
|
||||
github.com/volcengine/volc-sdk-golang v1.0.204/go.mod h1:stZX+EPgv1vF4nZwOlEe8iGcriUPRBKX8zA19gXycOQ=
|
||||
github.com/volcengine/volcengine-go-sdk v1.1.4 h1:xPT4KOy8VkXxhY7dbXzzvLvKQXUe4J6AtkQdNQU3wRY=
|
||||
github.com/volcengine/volcengine-go-sdk v1.1.4/go.mod h1:gfEDc1s7SYaGoY+WH2dRrS3qiuDJMkwqyfXWCa7+7oA=
|
||||
github.com/volcengine/volc-sdk-golang v1.0.207 h1:1OJ/nC92dF1URRoyO1AHSghCob12NT1PAA/GoK8uU18=
|
||||
github.com/volcengine/volc-sdk-golang v1.0.207/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.7/go.mod h1:EyKoi6t6eZxoPNGr2GdFCZti2Skd7MO3eUzx7TtSvNo=
|
||||
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/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
@@ -913,8 +946,8 @@ golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOM
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@@ -928,14 +961,14 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=
|
||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI=
|
||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
|
||||
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.26.0 h1:4XjIFEZWQmCZi6Wv8BoxsDhRU3RVnLX04dToTDAEPlY=
|
||||
golang.org/x/image v0.26.0/go.mod h1:lcxbMFAovzpnJxzXS3nyL83K27tmqtKzIJpctK8YO5c=
|
||||
golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w=
|
||||
golang.org/x/image v0.27.0/go.mod h1:xbdrClrAUway1MUTEZDq9mz/UpRwYAkFFNUslZtcB+g=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@@ -1018,16 +1051,16 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
|
||||
golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -1045,8 +1078,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
||||
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -1099,6 +1132,7 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -1107,6 +1141,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -1123,8 +1158,8 @@ golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
@@ -1140,8 +1175,8 @@ golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
|
||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||
golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
|
||||
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
|
||||
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -1160,8 +1195,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@@ -1223,8 +1258,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
|
||||
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
|
||||
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
|
||||
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -1364,16 +1399,16 @@ 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-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=
|
||||
k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls=
|
||||
k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k=
|
||||
k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U=
|
||||
k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
|
||||
k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU=
|
||||
k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY=
|
||||
k8s.io/api v0.33.0 h1:yTgZVn1XEe6opVpP1FylmNrIFWuDqe2H0V8CT5gxfIU=
|
||||
k8s.io/api v0.33.0/go.mod h1:CTO61ECK/KU7haa3qq8sarQ0biLq2ju405IZAd9zsiM=
|
||||
k8s.io/apimachinery v0.33.0 h1:1a6kHrJxb2hs4t8EE5wuR/WxKDwGN1FKH3JvDtA0CIQ=
|
||||
k8s.io/apimachinery v0.33.0/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
|
||||
k8s.io/client-go v0.33.0 h1:UASR0sAYVUzs2kYuKn/ZakZlcs2bEHaizrrHUZg0G98=
|
||||
k8s.io/client-go v0.33.0/go.mod h1:kGkd+l/gNGg8GYWAPr0xF1rRKvVWvzh9vmZAMXtaKOg=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 h1:hcha5B1kVACrLujCKLbr8XWMxCxzQx42DY8QKYJrDLg=
|
||||
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas=
|
||||
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/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0=
|
||||
k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
modernc.org/cc/v4 v4.25.2 h1:T2oH7sZdGvTaie0BRNFbIYsabzCxUQg8nLqCdQ2i0ic=
|
||||
@@ -1407,8 +1442,11 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 h1:nbCitCK2hfnhyiKo6uf2HxUPTCodY6Qaf85SbDIaMBk=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.5.0/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
|
||||
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
||||
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/usual2970/certimate/internal/domain"
|
||||
pACMEHttpReq "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/acmehttpreq"
|
||||
pAliyun "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun"
|
||||
pAliyunESA "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun-esa"
|
||||
pAWSRoute53 "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aws-route53"
|
||||
pAzureDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/azure-dns"
|
||||
pBaiduCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud"
|
||||
@@ -80,20 +81,36 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
||||
return applicant, err
|
||||
}
|
||||
|
||||
case domain.ACMEDns01ProviderTypeAliyun, domain.ACMEDns01ProviderTypeAliyunDNS:
|
||||
case domain.ACMEDns01ProviderTypeAliyun, domain.ACMEDns01ProviderTypeAliyunDNS, domain.ACMEDns01ProviderTypeAliyunESA:
|
||||
{
|
||||
access := domain.AccessConfigForAliyun{}
|
||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||
}
|
||||
|
||||
applicant, err := pAliyun.NewChallengeProvider(&pAliyun.ChallengeProviderConfig{
|
||||
AccessKeyId: access.AccessKeyId,
|
||||
AccessKeySecret: access.AccessKeySecret,
|
||||
DnsPropagationTimeout: options.DnsPropagationTimeout,
|
||||
DnsTTL: options.DnsTTL,
|
||||
})
|
||||
return applicant, err
|
||||
switch options.Provider {
|
||||
case domain.ACMEDns01ProviderTypeAliyun, domain.ACMEDns01ProviderTypeAliyunDNS:
|
||||
applicant, err := pAliyun.NewChallengeProvider(&pAliyun.ChallengeProviderConfig{
|
||||
AccessKeyId: access.AccessKeyId,
|
||||
AccessKeySecret: access.AccessKeySecret,
|
||||
DnsPropagationTimeout: options.DnsPropagationTimeout,
|
||||
DnsTTL: options.DnsTTL,
|
||||
})
|
||||
return applicant, err
|
||||
|
||||
case domain.ACMEDns01ProviderTypeAliyunESA:
|
||||
applicant, err := pAliyunESA.NewChallengeProvider(&pAliyunESA.ChallengeProviderConfig{
|
||||
AccessKeyId: access.AccessKeyId,
|
||||
AccessKeySecret: access.AccessKeySecret,
|
||||
Region: maputil.GetString(options.ProviderExtendedConfig, "region"),
|
||||
DnsPropagationTimeout: options.DnsPropagationTimeout,
|
||||
DnsTTL: options.DnsTTL,
|
||||
})
|
||||
return applicant, err
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
case domain.ACMEDns01ProviderTypeAWS, domain.ACMEDns01ProviderTypeAWSRoute53:
|
||||
@@ -424,10 +441,11 @@ func createApplicantProvider(options *applicantProviderOptions) (challenge.Provi
|
||||
}
|
||||
|
||||
applicant, err := pPowerDNS.NewChallengeProvider(&pPowerDNS.ChallengeProviderConfig{
|
||||
ApiUrl: access.ApiUrl,
|
||||
ApiKey: access.ApiKey,
|
||||
DnsPropagationTimeout: options.DnsPropagationTimeout,
|
||||
DnsTTL: options.DnsTTL,
|
||||
ApiUrl: access.ApiUrl,
|
||||
ApiKey: access.ApiKey,
|
||||
AllowInsecureConnections: access.AllowInsecureConnections,
|
||||
DnsPropagationTimeout: options.DnsPropagationTimeout,
|
||||
DnsTTL: options.DnsTTL,
|
||||
})
|
||||
return applicant, err
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
pAliyunCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-cdn"
|
||||
pAliyunCLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-clb"
|
||||
pAliyunDCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-dcdn"
|
||||
pAliyunDDoS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-ddos"
|
||||
pAliyunESA "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-esa"
|
||||
pAliyunFC "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-fc"
|
||||
pAliyunLive "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-live"
|
||||
@@ -40,6 +41,7 @@ import (
|
||||
pDogeCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/dogecloud-cdn"
|
||||
pEdgioApplications "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/edgio-applications"
|
||||
pGcoreCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/gcore-cdn"
|
||||
pGoEdge "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/goedge"
|
||||
pHuaweiCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-cdn"
|
||||
pHuaweiCloudELB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-elb"
|
||||
pHuaweiCloudSCM "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-scm"
|
||||
@@ -50,6 +52,7 @@ import (
|
||||
pJDCloudVOD "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-vod"
|
||||
pK8sSecret "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/k8s-secret"
|
||||
pLocal "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/local"
|
||||
pProxmoxVE "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/proxmoxve"
|
||||
pQiniuCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/qiniu-cdn"
|
||||
pQiniuPili "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/qiniu-pili"
|
||||
pRainYunRCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/rainyun-rcdn"
|
||||
@@ -129,7 +132,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
|
||||
}
|
||||
}
|
||||
|
||||
case domain.DeploymentProviderTypeAliyunALB, domain.DeploymentProviderTypeAliyunAPIGW, domain.DeploymentProviderTypeAliyunCAS, domain.DeploymentProviderTypeAliyunCASDeploy, domain.DeploymentProviderTypeAliyunCDN, domain.DeploymentProviderTypeAliyunCLB, domain.DeploymentProviderTypeAliyunDCDN, domain.DeploymentProviderTypeAliyunESA, domain.DeploymentProviderTypeAliyunFC, domain.DeploymentProviderTypeAliyunLive, domain.DeploymentProviderTypeAliyunNLB, domain.DeploymentProviderTypeAliyunOSS, domain.DeploymentProviderTypeAliyunVOD, domain.DeploymentProviderTypeAliyunWAF:
|
||||
case domain.DeploymentProviderTypeAliyunALB, domain.DeploymentProviderTypeAliyunAPIGW, domain.DeploymentProviderTypeAliyunCAS, domain.DeploymentProviderTypeAliyunCASDeploy, domain.DeploymentProviderTypeAliyunCDN, domain.DeploymentProviderTypeAliyunCLB, domain.DeploymentProviderTypeAliyunDCDN, domain.DeploymentProviderTypeAliyunDDoS, domain.DeploymentProviderTypeAliyunESA, domain.DeploymentProviderTypeAliyunFC, domain.DeploymentProviderTypeAliyunLive, domain.DeploymentProviderTypeAliyunNLB, domain.DeploymentProviderTypeAliyunOSS, domain.DeploymentProviderTypeAliyunVOD, domain.DeploymentProviderTypeAliyunWAF:
|
||||
{
|
||||
access := domain.AccessConfigForAliyun{}
|
||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||
@@ -207,6 +210,15 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
|
||||
})
|
||||
return deployer, err
|
||||
|
||||
case domain.DeploymentProviderTypeAliyunDDoS:
|
||||
deployer, err := pAliyunDDoS.NewDeployer(&pAliyunDDoS.DeployerConfig{
|
||||
AccessKeyId: access.AccessKeyId,
|
||||
AccessKeySecret: access.AccessKeySecret,
|
||||
Region: maputil.GetString(options.ProviderExtendedConfig, "region"),
|
||||
Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"),
|
||||
})
|
||||
return deployer, err
|
||||
|
||||
case domain.DeploymentProviderTypeAliyunESA:
|
||||
deployer, err := pAliyunESA.NewDeployer(&pAliyunESA.DeployerConfig{
|
||||
AccessKeyId: access.AccessKeyId,
|
||||
@@ -498,12 +510,13 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
|
||||
}
|
||||
|
||||
deployer, err := pCdnfly.NewDeployer(&pCdnfly.DeployerConfig{
|
||||
ApiUrl: access.ApiUrl,
|
||||
ApiKey: access.ApiKey,
|
||||
ApiSecret: access.ApiSecret,
|
||||
ResourceType: pCdnfly.ResourceType(maputil.GetOrDefaultString(options.ProviderExtendedConfig, "resourceType", string(pCdnfly.RESOURCE_TYPE_SITE))),
|
||||
SiteId: maputil.GetString(options.ProviderExtendedConfig, "siteId"),
|
||||
CertificateId: maputil.GetString(options.ProviderExtendedConfig, "certificateId"),
|
||||
ApiUrl: access.ApiUrl,
|
||||
ApiKey: access.ApiKey,
|
||||
ApiSecret: access.ApiSecret,
|
||||
AllowInsecureConnections: access.AllowInsecureConnections,
|
||||
ResourceType: pCdnfly.ResourceType(maputil.GetOrDefaultString(options.ProviderExtendedConfig, "resourceType", string(pCdnfly.RESOURCE_TYPE_SITE))),
|
||||
SiteId: maputil.GetString(options.ProviderExtendedConfig, "siteId"),
|
||||
CertificateId: maputil.GetString(options.ProviderExtendedConfig, "certificateId"),
|
||||
})
|
||||
return deployer, err
|
||||
}
|
||||
@@ -548,8 +561,9 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
|
||||
switch options.Provider {
|
||||
case domain.DeploymentProviderTypeGcoreCDN:
|
||||
deployer, err := pGcoreCDN.NewDeployer(&pGcoreCDN.DeployerConfig{
|
||||
ApiToken: access.ApiToken,
|
||||
ResourceId: maputil.GetInt64(options.ProviderExtendedConfig, "resourceId"),
|
||||
ApiToken: access.ApiToken,
|
||||
ResourceId: maputil.GetInt64(options.ProviderExtendedConfig, "resourceId"),
|
||||
CertificateId: maputil.GetInt64(options.ProviderExtendedConfig, "certificateId"),
|
||||
})
|
||||
return deployer, err
|
||||
|
||||
@@ -558,6 +572,24 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
|
||||
}
|
||||
}
|
||||
|
||||
case domain.DeploymentProviderTypeGoEdge:
|
||||
{
|
||||
access := domain.AccessConfigForGoEdge{}
|
||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||
}
|
||||
|
||||
deployer, err := pGoEdge.NewDeployer(&pGoEdge.DeployerConfig{
|
||||
ApiUrl: access.ApiUrl,
|
||||
AccessKeyId: access.AccessKeyId,
|
||||
AccessKey: access.AccessKey,
|
||||
AllowInsecureConnections: access.AllowInsecureConnections,
|
||||
ResourceType: pGoEdge.ResourceType(maputil.GetString(options.ProviderExtendedConfig, "resourceType")),
|
||||
CertificateId: maputil.GetInt64(options.ProviderExtendedConfig, "certificateId"),
|
||||
})
|
||||
return deployer, err
|
||||
}
|
||||
|
||||
case domain.DeploymentProviderTypeHuaweiCloudCDN, domain.DeploymentProviderTypeHuaweiCloudELB, domain.DeploymentProviderTypeHuaweiCloudSCM, domain.DeploymentProviderTypeHuaweiCloudWAF:
|
||||
{
|
||||
access := domain.AccessConfigForHuaweiCloud{}
|
||||
@@ -693,6 +725,24 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
|
||||
return deployer, err
|
||||
}
|
||||
|
||||
case domain.DeploymentProviderTypeProxmoxVE:
|
||||
{
|
||||
access := domain.AccessConfigForProxmoxVE{}
|
||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||
}
|
||||
|
||||
deployer, err := pProxmoxVE.NewDeployer(&pProxmoxVE.DeployerConfig{
|
||||
ApiUrl: access.ApiUrl,
|
||||
ApiToken: access.ApiToken,
|
||||
ApiTokenSecret: access.ApiTokenSecret,
|
||||
AllowInsecureConnections: access.AllowInsecureConnections,
|
||||
NodeName: maputil.GetString(options.ProviderExtendedConfig, "nodeName"),
|
||||
AutoRestart: maputil.GetBool(options.ProviderExtendedConfig, "autoRestart"),
|
||||
})
|
||||
return deployer, err
|
||||
}
|
||||
|
||||
case domain.DeploymentProviderTypeQiniuCDN, domain.DeploymentProviderTypeQiniuKodo, domain.DeploymentProviderTypeQiniuPili:
|
||||
{
|
||||
access := domain.AccessConfigForQiniu{}
|
||||
|
||||
@@ -74,9 +74,10 @@ type AccessConfigForCacheFly struct {
|
||||
}
|
||||
|
||||
type AccessConfigForCdnfly struct {
|
||||
ApiUrl string `json:"apiUrl"`
|
||||
ApiKey string `json:"apiKey"`
|
||||
ApiSecret string `json:"apiSecret"`
|
||||
ApiUrl string `json:"apiUrl"`
|
||||
ApiKey string `json:"apiKey"`
|
||||
ApiSecret string `json:"apiSecret"`
|
||||
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
|
||||
}
|
||||
|
||||
type AccessConfigForCloudflare struct {
|
||||
@@ -146,6 +147,13 @@ type AccessConfigForGoDaddy struct {
|
||||
ApiSecret string `json:"apiSecret"`
|
||||
}
|
||||
|
||||
type AccessConfigForGoEdge struct {
|
||||
ApiUrl string `json:"apiUrl"`
|
||||
AccessKeyId string `json:"accessKeyId"`
|
||||
AccessKey string `json:"accessKey"`
|
||||
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
|
||||
}
|
||||
|
||||
type AccessConfigForGoogleTrustServices struct {
|
||||
EabKid string `json:"eabKid"`
|
||||
EabHmacKey string `json:"eabHmacKey"`
|
||||
@@ -200,8 +208,16 @@ type AccessConfigForPorkbun struct {
|
||||
}
|
||||
|
||||
type AccessConfigForPowerDNS struct {
|
||||
ApiUrl string `json:"apiUrl"`
|
||||
ApiKey string `json:"apiKey"`
|
||||
ApiUrl string `json:"apiUrl"`
|
||||
ApiKey string `json:"apiKey"`
|
||||
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
|
||||
}
|
||||
|
||||
type AccessConfigForProxmoxVE struct {
|
||||
ApiUrl string `json:"apiUrl"`
|
||||
ApiToken string `json:"apiToken"`
|
||||
ApiTokenSecret string `json:"apiTokenSecret,omitempty"`
|
||||
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
|
||||
}
|
||||
|
||||
type AccessConfigForQiniu struct {
|
||||
|
||||
@@ -26,8 +26,8 @@ const (
|
||||
AccessProviderTypeCloudflare = AccessProviderType("cloudflare")
|
||||
AccessProviderTypeClouDNS = AccessProviderType("cloudns")
|
||||
AccessProviderTypeCMCCCloud = AccessProviderType("cmcccloud")
|
||||
AccessProviderTypeCTCCCloud = AccessProviderType("ctcccloud") // 联通云(预留)
|
||||
AccessProviderTypeCUCCCloud = AccessProviderType("cucccloud") // 天翼云(预留)
|
||||
AccessProviderTypeCTCCCloud = AccessProviderType("ctcccloud") // 天翼云(预留)
|
||||
AccessProviderTypeCUCCCloud = AccessProviderType("cucccloud") // 联通云(预留)
|
||||
AccessProviderTypeDeSEC = AccessProviderType("desec")
|
||||
AccessProviderTypeDingTalkBot = AccessProviderType("dingtalkbot")
|
||||
AccessProviderTypeDNSLA = AccessProviderType("dnsla")
|
||||
@@ -39,7 +39,7 @@ const (
|
||||
AccessProviderTypeGname = AccessProviderType("gname")
|
||||
AccessProviderTypeGcore = AccessProviderType("gcore")
|
||||
AccessProviderTypeGoDaddy = AccessProviderType("godaddy")
|
||||
AccessProviderTypeGoEdge = AccessProviderType("goedge") // GoEdge(预留)
|
||||
AccessProviderTypeGoEdge = AccessProviderType("goedge")
|
||||
AccessProviderTypeGoogleTrustServices = AccessProviderType("googletrustservices")
|
||||
AccessProviderTypeHuaweiCloud = AccessProviderType("huaweicloud")
|
||||
AccessProviderTypeJDCloud = AccessProviderType("jdcloud")
|
||||
@@ -55,6 +55,7 @@ const (
|
||||
AccessProviderTypeNS1 = AccessProviderType("ns1")
|
||||
AccessProviderTypePorkbun = AccessProviderType("porkbun")
|
||||
AccessProviderTypePowerDNS = AccessProviderType("powerdns")
|
||||
AccessProviderTypeProxmoxVE = AccessProviderType("proxmoxve")
|
||||
AccessProviderTypeQiniu = AccessProviderType("qiniu")
|
||||
AccessProviderTypeQingCloud = AccessProviderType("qingcloud") // 青云(预留)
|
||||
AccessProviderTypeRainYun = AccessProviderType("rainyun")
|
||||
@@ -105,6 +106,7 @@ const (
|
||||
ACMEDns01ProviderTypeACMEHttpReq = ACMEDns01ProviderType(AccessProviderTypeACMEHttpReq)
|
||||
ACMEDns01ProviderTypeAliyun = ACMEDns01ProviderType(AccessProviderTypeAliyun) // 兼容旧值,等同于 [ACMEDns01ProviderTypeAliyunDNS]
|
||||
ACMEDns01ProviderTypeAliyunDNS = ACMEDns01ProviderType(AccessProviderTypeAliyun + "-dns")
|
||||
ACMEDns01ProviderTypeAliyunESA = ACMEDns01ProviderType(AccessProviderTypeAliyun + "-esa")
|
||||
ACMEDns01ProviderTypeAWS = ACMEDns01ProviderType(AccessProviderTypeAWS) // 兼容旧值,等同于 [ACMEDns01ProviderTypeAWSRoute53]
|
||||
ACMEDns01ProviderTypeAWSRoute53 = ACMEDns01ProviderType(AccessProviderTypeAWS + "-route53")
|
||||
ACMEDns01ProviderTypeAzure = ACMEDns01ProviderType(AccessProviderTypeAzure) // 兼容旧值,等同于 [ACMEDns01ProviderTypeAzure]
|
||||
@@ -160,6 +162,7 @@ const (
|
||||
DeploymentProviderTypeAliyunCDN = DeploymentProviderType(AccessProviderTypeAliyun + "-cdn")
|
||||
DeploymentProviderTypeAliyunCLB = DeploymentProviderType(AccessProviderTypeAliyun + "-clb")
|
||||
DeploymentProviderTypeAliyunDCDN = DeploymentProviderType(AccessProviderTypeAliyun + "-dcdn")
|
||||
DeploymentProviderTypeAliyunDDoS = DeploymentProviderType(AccessProviderTypeAliyun + "-ddos")
|
||||
DeploymentProviderTypeAliyunESA = DeploymentProviderType(AccessProviderTypeAliyun + "-esa")
|
||||
DeploymentProviderTypeAliyunFC = DeploymentProviderType(AccessProviderTypeAliyun + "-fc")
|
||||
DeploymentProviderTypeAliyunLive = DeploymentProviderType(AccessProviderTypeAliyun + "-live")
|
||||
@@ -184,6 +187,7 @@ const (
|
||||
DeploymentProviderTypeDogeCloudCDN = DeploymentProviderType(AccessProviderTypeDogeCloud + "-cdn")
|
||||
DeploymentProviderTypeEdgioApplications = DeploymentProviderType(AccessProviderTypeEdgio + "-applications")
|
||||
DeploymentProviderTypeGcoreCDN = DeploymentProviderType(AccessProviderTypeGcore + "-cdn")
|
||||
DeploymentProviderTypeGoEdge = DeploymentProviderType(AccessProviderTypeGoEdge)
|
||||
DeploymentProviderTypeHuaweiCloudCDN = DeploymentProviderType(AccessProviderTypeHuaweiCloud + "-cdn")
|
||||
DeploymentProviderTypeHuaweiCloudELB = DeploymentProviderType(AccessProviderTypeHuaweiCloud + "-elb")
|
||||
DeploymentProviderTypeHuaweiCloudSCM = DeploymentProviderType(AccessProviderTypeHuaweiCloud + "-scm")
|
||||
@@ -194,6 +198,7 @@ const (
|
||||
DeploymentProviderTypeJDCloudVOD = DeploymentProviderType(AccessProviderTypeJDCloud + "-vod")
|
||||
DeploymentProviderTypeKubernetesSecret = DeploymentProviderType(AccessProviderTypeKubernetes + "-secret")
|
||||
DeploymentProviderTypeLocal = DeploymentProviderType(AccessProviderTypeLocal)
|
||||
DeploymentProviderTypeProxmoxVE = DeploymentProviderType(AccessProviderTypeProxmoxVE)
|
||||
DeploymentProviderTypeQiniuCDN = DeploymentProviderType(AccessProviderTypeQiniu + "-cdn")
|
||||
DeploymentProviderTypeQiniuKodo = DeploymentProviderType(AccessProviderTypeQiniu + "-kodo")
|
||||
DeploymentProviderTypeQiniuPili = DeploymentProviderType(AccessProviderTypeQiniu + "-pili")
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package aliyunesa
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/go-acme/lego/v4/challenge"
|
||||
|
||||
internal "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun-esa/internal"
|
||||
)
|
||||
|
||||
type ChallengeProviderConfig struct {
|
||||
AccessKeyId string `json:"accessKeyId"`
|
||||
AccessKeySecret string `json:"accessKeySecret"`
|
||||
Region string `json:"region"`
|
||||
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 := internal.NewDefaultConfig()
|
||||
providerConfig.SecretID = config.AccessKeyId
|
||||
providerConfig.SecretKey = config.AccessKeySecret
|
||||
if config.DnsPropagationTimeout != 0 {
|
||||
providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second
|
||||
}
|
||||
if config.DnsTTL != 0 {
|
||||
providerConfig.TTL = config.DnsTTL
|
||||
}
|
||||
|
||||
provider, err := internal.NewDNSProviderConfig(providerConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return provider, nil
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
package lego_aliyunesa
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client"
|
||||
aliesa "github.com/alibabacloud-go/esa-20240910/v2/client"
|
||||
"github.com/alibabacloud-go/tea/tea"
|
||||
"github.com/go-acme/lego/v4/challenge"
|
||||
"github.com/go-acme/lego/v4/challenge/dns01"
|
||||
"github.com/go-acme/lego/v4/platform/config/env"
|
||||
)
|
||||
|
||||
const (
|
||||
envNamespace = "ALICLOUDESA_"
|
||||
|
||||
EnvAccessKey = envNamespace + "ACCESS_KEY"
|
||||
EnvSecretKey = envNamespace + "SECRET_KEY"
|
||||
EnvRegionID = envNamespace + "REGION_ID"
|
||||
|
||||
EnvTTL = envNamespace + "TTL"
|
||||
EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
|
||||
EnvPollingInterval = envNamespace + "POLLING_INTERVAL"
|
||||
EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT"
|
||||
)
|
||||
|
||||
var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
|
||||
|
||||
type Config struct {
|
||||
SecretID string
|
||||
SecretKey string
|
||||
RegionID string
|
||||
|
||||
PropagationTimeout time.Duration
|
||||
PollingInterval time.Duration
|
||||
TTL int32
|
||||
HTTPTimeout time.Duration
|
||||
}
|
||||
|
||||
type DNSProvider struct {
|
||||
client *aliesa.Client
|
||||
config *Config
|
||||
|
||||
siteIDs map[string]int64
|
||||
siteIDsMtx sync.Mutex
|
||||
}
|
||||
|
||||
func NewDefaultConfig() *Config {
|
||||
return &Config{
|
||||
TTL: int32(env.GetOrDefaultInt(EnvTTL, 300)),
|
||||
PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, 2*time.Minute),
|
||||
PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval),
|
||||
HTTPTimeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second),
|
||||
}
|
||||
}
|
||||
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
values, err := env.Get(EnvAccessKey, EnvSecretKey, EnvRegionID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("alicloud-esa: %w", err)
|
||||
}
|
||||
|
||||
config := NewDefaultConfig()
|
||||
config.SecretID = values[EnvAccessKey]
|
||||
config.SecretKey = values[EnvSecretKey]
|
||||
config.RegionID = values[EnvRegionID]
|
||||
|
||||
return NewDNSProviderConfig(config)
|
||||
}
|
||||
|
||||
func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("alicloud-esa: the configuration of the DNS provider is nil")
|
||||
}
|
||||
|
||||
client, err := aliesa.NewClient(&aliopen.Config{
|
||||
AccessKeyId: tea.String(config.SecretID),
|
||||
AccessKeySecret: tea.String(config.SecretKey),
|
||||
Endpoint: tea.String(fmt.Sprintf("esa.%s.aliyuncs.com", config.RegionID)),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("alicloud-esa: %w", err)
|
||||
}
|
||||
|
||||
return &DNSProvider{
|
||||
client: client,
|
||||
config: config,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
info := dns01.GetChallengeInfo(domain, keyAuth)
|
||||
|
||||
authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
|
||||
if err != nil {
|
||||
return fmt.Errorf("alicloud-esa: could not find zone for domain %q: %w", domain, err)
|
||||
}
|
||||
|
||||
siteId, err := d.getSiteId(authZone)
|
||||
if err != nil {
|
||||
return fmt.Errorf("alicloud-esa: could not find site for zone %q: %w", authZone, err)
|
||||
}
|
||||
|
||||
if err := d.addOrUpdateDNSRecord(siteId, strings.TrimRight(info.EffectiveFQDN, "."), info.Value); err != nil {
|
||||
return fmt.Errorf("alicloud-esa: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
info := dns01.GetChallengeInfo(domain, keyAuth)
|
||||
|
||||
authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
|
||||
if err != nil {
|
||||
return fmt.Errorf("alicloud-esa: could not find zone for domain %q: %w", domain, err)
|
||||
}
|
||||
|
||||
siteId, err := d.getSiteId(authZone)
|
||||
if err != nil {
|
||||
return fmt.Errorf("alicloud-esa: could not find site for zone %q: %w", authZone, err)
|
||||
}
|
||||
|
||||
if err := d.removeDNSRecord(siteId, strings.TrimRight(info.EffectiveFQDN, ".")); err != nil {
|
||||
return fmt.Errorf("alicloud-esa: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||
}
|
||||
|
||||
func (d *DNSProvider) getSiteId(siteName string) (int64, error) {
|
||||
d.siteIDsMtx.Lock()
|
||||
siteID, ok := d.siteIDs[siteName]
|
||||
d.siteIDsMtx.Unlock()
|
||||
if ok {
|
||||
return siteID, nil
|
||||
}
|
||||
|
||||
pageNumber := 1
|
||||
pageSize := 500
|
||||
for {
|
||||
request := &aliesa.ListSitesRequest{
|
||||
SiteName: tea.String(siteName),
|
||||
PageNumber: tea.Int32(int32(pageNumber)),
|
||||
PageSize: tea.Int32(int32(pageNumber)),
|
||||
AccessType: tea.String("NS"),
|
||||
}
|
||||
response, err := d.client.ListSites(request)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if response.Body == nil {
|
||||
break
|
||||
} else {
|
||||
for _, record := range response.Body.Sites {
|
||||
if tea.StringValue(record.SiteName) == siteName {
|
||||
d.siteIDsMtx.Lock()
|
||||
d.siteIDs[siteName] = *record.SiteId
|
||||
d.siteIDsMtx.Unlock()
|
||||
return *record.SiteId, nil
|
||||
}
|
||||
}
|
||||
|
||||
if len(response.Body.Sites) < pageSize {
|
||||
break
|
||||
}
|
||||
|
||||
pageNumber++
|
||||
}
|
||||
}
|
||||
|
||||
return 0, errors.New("failed to get site id")
|
||||
}
|
||||
|
||||
func (d *DNSProvider) findDNSRecord(siteId int64, effectiveFQDN string) (*aliesa.ListRecordsResponseBodyRecords, error) {
|
||||
pageNumber := 1
|
||||
pageSize := 500
|
||||
for {
|
||||
request := &aliesa.ListRecordsRequest{
|
||||
SiteId: tea.Int64(siteId),
|
||||
Type: tea.String("TXT"),
|
||||
RecordName: tea.String(effectiveFQDN),
|
||||
PageNumber: tea.Int32(int32(pageNumber)),
|
||||
PageSize: tea.Int32(int32(pageNumber)),
|
||||
}
|
||||
response, err := d.client.ListRecords(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if response.Body == nil {
|
||||
break
|
||||
} else {
|
||||
for _, record := range response.Body.Records {
|
||||
if tea.StringValue(record.RecordName) == effectiveFQDN {
|
||||
return record, nil
|
||||
}
|
||||
}
|
||||
|
||||
if len(response.Body.Records) < pageSize {
|
||||
break
|
||||
}
|
||||
|
||||
pageNumber++
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (d *DNSProvider) addOrUpdateDNSRecord(siteId int64, effectiveFQDN, value string) error {
|
||||
record, err := d.findDNSRecord(siteId, effectiveFQDN)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if record == nil {
|
||||
request := &aliesa.CreateRecordRequest{
|
||||
SiteId: tea.Int64(siteId),
|
||||
Type: tea.String("TXT"),
|
||||
RecordName: tea.String(effectiveFQDN),
|
||||
Data: &aliesa.CreateRecordRequestData{
|
||||
Value: tea.String(value),
|
||||
},
|
||||
Ttl: tea.Int32(d.config.TTL),
|
||||
}
|
||||
_, err := d.client.CreateRecord(request)
|
||||
return err
|
||||
} else {
|
||||
request := &aliesa.UpdateRecordRequest{
|
||||
RecordId: record.RecordId,
|
||||
Ttl: tea.Int32(d.config.TTL),
|
||||
Data: &aliesa.UpdateRecordRequestData{
|
||||
Value: tea.String(value),
|
||||
},
|
||||
}
|
||||
_, err := d.client.UpdateRecord(request)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DNSProvider) removeDNSRecord(siteId int64, effectiveFQDN string) error {
|
||||
record, err := d.findDNSRecord(siteId, effectiveFQDN)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if record == nil {
|
||||
return nil
|
||||
} else {
|
||||
request := &aliesa.DeleteRecordRequest{
|
||||
RecordId: record.RecordId,
|
||||
}
|
||||
_, err = d.client.DeleteRecord(request)
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -128,7 +128,7 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||
}
|
||||
|
||||
func (d *DNSProvider) getDNSRecord(zoneName, subDomain string) (*bcedns.Record, error) {
|
||||
func (d *DNSProvider) findDNSRecord(zoneName, subDomain string) (*bcedns.Record, error) {
|
||||
pageMarker := ""
|
||||
pageSize := 1000
|
||||
for {
|
||||
@@ -159,7 +159,7 @@ func (d *DNSProvider) getDNSRecord(zoneName, subDomain string) (*bcedns.Record,
|
||||
}
|
||||
|
||||
func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) error {
|
||||
record, err := d.getDNSRecord(zoneName, subDomain)
|
||||
record, err := d.findDNSRecord(zoneName, subDomain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -186,7 +186,7 @@ func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) er
|
||||
}
|
||||
|
||||
func (d *DNSProvider) removeDNSRecord(zoneName, subDomain string) error {
|
||||
record, err := d.getDNSRecord(zoneName, subDomain)
|
||||
record, err := d.findDNSRecord(zoneName, subDomain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||
}
|
||||
|
||||
func (d *DNSProvider) getDNSRecord(zoneName, subDomain string) (*libdns.Record, error) {
|
||||
func (d *DNSProvider) findDNSRecord(zoneName, subDomain string) (*libdns.Record, error) {
|
||||
records, err := d.client.GetRecords(context.Background(), zoneName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -131,7 +131,7 @@ func (d *DNSProvider) getDNSRecord(zoneName, subDomain string) (*libdns.Record,
|
||||
}
|
||||
|
||||
func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) error {
|
||||
record, err := d.getDNSRecord(zoneName, subDomain)
|
||||
record, err := d.findDNSRecord(zoneName, subDomain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -153,7 +153,7 @@ func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) er
|
||||
}
|
||||
|
||||
func (d *DNSProvider) removeDNSRecord(zoneName, subDomain string) error {
|
||||
record, err := d.getDNSRecord(zoneName, subDomain)
|
||||
record, err := d.findDNSRecord(zoneName, subDomain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||
}
|
||||
|
||||
func (d *DNSProvider) getDNSRecord(zoneName, subDomain string) (*gnamesdk.ResolutionRecord, error) {
|
||||
func (d *DNSProvider) findDNSRecord(zoneName, subDomain string) (*gnamesdk.ResolutionRecord, error) {
|
||||
page := int32(1)
|
||||
pageSize := int32(20)
|
||||
for {
|
||||
@@ -155,7 +155,7 @@ func (d *DNSProvider) getDNSRecord(zoneName, subDomain string) (*gnamesdk.Resolu
|
||||
}
|
||||
|
||||
func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) error {
|
||||
record, err := d.getDNSRecord(zoneName, subDomain)
|
||||
record, err := d.findDNSRecord(zoneName, subDomain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -186,7 +186,7 @@ func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) er
|
||||
}
|
||||
|
||||
func (d *DNSProvider) removeDNSRecord(zoneName, subDomain string) error {
|
||||
record, err := d.getDNSRecord(zoneName, subDomain)
|
||||
record, err := d.findDNSRecord(zoneName, subDomain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package powerdns
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
@@ -9,10 +11,11 @@ import (
|
||||
)
|
||||
|
||||
type ChallengeProviderConfig struct {
|
||||
ApiUrl string `json:"apiUrl"`
|
||||
ApiKey string `json:"apiKey"`
|
||||
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
|
||||
DnsTTL int32 `json:"dnsTTL,omitempty"`
|
||||
ApiUrl string `json:"apiUrl"`
|
||||
ApiKey string `json:"apiKey"`
|
||||
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
|
||||
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
|
||||
DnsTTL int32 `json:"dnsTTL,omitempty"`
|
||||
}
|
||||
|
||||
func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
|
||||
@@ -24,6 +27,13 @@ func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider,
|
||||
providerConfig := pdns.NewDefaultConfig()
|
||||
providerConfig.Host = host
|
||||
providerConfig.APIKey = config.ApiKey
|
||||
if config.AllowInsecureConnections {
|
||||
providerConfig.HTTPClient.Transport = &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
if config.DnsPropagationTimeout != 0 {
|
||||
providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ const (
|
||||
|
||||
EnvSecretID = envNamespace + "SECRET_ID"
|
||||
EnvSecretKey = envNamespace + "SECRET_KEY"
|
||||
EnvZoneId = envNamespace + "ZONE_ID"
|
||||
EnvZoneID = envNamespace + "ZONE_ID"
|
||||
|
||||
EnvTTL = envNamespace + "TTL"
|
||||
EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
|
||||
@@ -33,7 +33,7 @@ var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
|
||||
type Config struct {
|
||||
SecretID string
|
||||
SecretKey string
|
||||
ZoneId string
|
||||
ZoneID string
|
||||
|
||||
PropagationTimeout time.Duration
|
||||
PollingInterval time.Duration
|
||||
@@ -56,7 +56,7 @@ func NewDefaultConfig() *Config {
|
||||
}
|
||||
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
values, err := env.Get(EnvSecretID, EnvSecretKey, EnvZoneId)
|
||||
values, err := env.Get(EnvSecretID, EnvSecretKey, EnvZoneID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("tencentcloud-eo: %w", err)
|
||||
}
|
||||
@@ -64,7 +64,7 @@ func NewDNSProvider() (*DNSProvider, error) {
|
||||
config := NewDefaultConfig()
|
||||
config.SecretID = values[EnvSecretID]
|
||||
config.SecretKey = values[EnvSecretKey]
|
||||
config.ZoneId = values[EnvSecretKey]
|
||||
config.ZoneID = values[EnvSecretKey]
|
||||
|
||||
return NewDNSProviderConfig(config)
|
||||
}
|
||||
@@ -112,12 +112,12 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||
}
|
||||
|
||||
func (d *DNSProvider) getDNSRecord(effectiveFQDN string) (*teo.DnsRecord, error) {
|
||||
func (d *DNSProvider) findDNSRecord(effectiveFQDN string) (*teo.DnsRecord, error) {
|
||||
pageOffset := 0
|
||||
pageLimit := 1000
|
||||
for {
|
||||
request := teo.NewDescribeDnsRecordsRequest()
|
||||
request.ZoneId = common.StringPtr(d.config.ZoneId)
|
||||
request.ZoneId = common.StringPtr(d.config.ZoneID)
|
||||
request.Offset = common.Int64Ptr(int64(pageOffset))
|
||||
request.Limit = common.Int64Ptr(int64(pageLimit))
|
||||
request.Filters = []*teo.AdvancedFilter{
|
||||
@@ -141,7 +141,7 @@ func (d *DNSProvider) getDNSRecord(effectiveFQDN string) (*teo.DnsRecord, error)
|
||||
}
|
||||
}
|
||||
|
||||
if len(response.Response.DnsRecords) < int(pageLimit) {
|
||||
if len(response.Response.DnsRecords) < pageLimit {
|
||||
break
|
||||
}
|
||||
|
||||
@@ -153,14 +153,14 @@ func (d *DNSProvider) getDNSRecord(effectiveFQDN string) (*teo.DnsRecord, error)
|
||||
}
|
||||
|
||||
func (d *DNSProvider) addOrUpdateDNSRecord(effectiveFQDN, value string) error {
|
||||
record, err := d.getDNSRecord(effectiveFQDN)
|
||||
record, err := d.findDNSRecord(effectiveFQDN)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if record == nil {
|
||||
request := teo.NewCreateDnsRecordRequest()
|
||||
request.ZoneId = common.StringPtr(d.config.ZoneId)
|
||||
request.ZoneId = common.StringPtr(d.config.ZoneID)
|
||||
request.Name = common.StringPtr(effectiveFQDN)
|
||||
request.Type = common.StringPtr("TXT")
|
||||
request.Content = common.StringPtr(value)
|
||||
@@ -169,8 +169,9 @@ func (d *DNSProvider) addOrUpdateDNSRecord(effectiveFQDN, value string) error {
|
||||
return err
|
||||
} else {
|
||||
record.Content = common.StringPtr(value)
|
||||
record.TTL = common.Int64Ptr(int64(d.config.TTL))
|
||||
request := teo.NewModifyDnsRecordsRequest()
|
||||
request.ZoneId = common.StringPtr(d.config.ZoneId)
|
||||
request.ZoneId = common.StringPtr(d.config.ZoneID)
|
||||
request.DnsRecords = []*teo.DnsRecord{record}
|
||||
if _, err := d.client.ModifyDnsRecords(request); err != nil {
|
||||
return err
|
||||
@@ -178,7 +179,7 @@ func (d *DNSProvider) addOrUpdateDNSRecord(effectiveFQDN, value string) error {
|
||||
|
||||
if *record.Status == "disable" {
|
||||
request := teo.NewModifyDnsRecordsStatusRequest()
|
||||
request.ZoneId = common.StringPtr(d.config.ZoneId)
|
||||
request.ZoneId = common.StringPtr(d.config.ZoneID)
|
||||
request.RecordsToEnable = []*string{record.RecordId}
|
||||
if _, err = d.client.ModifyDnsRecordsStatus(request); err != nil {
|
||||
return err
|
||||
@@ -190,7 +191,7 @@ func (d *DNSProvider) addOrUpdateDNSRecord(effectiveFQDN, value string) error {
|
||||
}
|
||||
|
||||
func (d *DNSProvider) removeDNSRecord(effectiveFQDN string) error {
|
||||
record, err := d.getDNSRecord(effectiveFQDN)
|
||||
record, err := d.findDNSRecord(effectiveFQDN)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -199,7 +200,7 @@ func (d *DNSProvider) removeDNSRecord(effectiveFQDN string) error {
|
||||
return nil
|
||||
} else {
|
||||
request := teo.NewDeleteDnsRecordsRequest()
|
||||
request.ZoneId = common.StringPtr(d.config.ZoneId)
|
||||
request.ZoneId = common.StringPtr(d.config.ZoneID)
|
||||
request.RecordIds = []*string{record.RecordId}
|
||||
_, err = d.client.DeleteDnsRecords(request)
|
||||
return err
|
||||
|
||||
@@ -24,7 +24,7 @@ func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider,
|
||||
providerConfig := internal.NewDefaultConfig()
|
||||
providerConfig.SecretID = config.SecretId
|
||||
providerConfig.SecretKey = config.SecretKey
|
||||
providerConfig.ZoneId = config.ZoneId
|
||||
providerConfig.ZoneID = config.ZoneId
|
||||
if config.DnsPropagationTimeout != 0 {
|
||||
providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
|
||||
return &deployer.DeployResult{}, nil
|
||||
}
|
||||
|
||||
func createSdkClient(apiUrl, apiKey string, allowInsecure bool) (*opsdk.Client, error) {
|
||||
func createSdkClient(apiUrl, apiKey string, skipTlsVerify bool) (*opsdk.Client, error) {
|
||||
if _, err := url.Parse(apiUrl); err != nil {
|
||||
return nil, errors.New("invalid 1panel api url")
|
||||
}
|
||||
@@ -89,7 +89,7 @@ func createSdkClient(apiUrl, apiKey string, allowInsecure bool) (*opsdk.Client,
|
||||
}
|
||||
|
||||
client := opsdk.NewClient(apiUrl, apiKey)
|
||||
if allowInsecure {
|
||||
if skipTlsVerify {
|
||||
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
|
||||
}
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri
|
||||
return nil
|
||||
}
|
||||
|
||||
func createSdkClient(apiUrl, apiKey string, allowInsecure bool) (*opsdk.Client, error) {
|
||||
func createSdkClient(apiUrl, apiKey string, skipTlsVerify bool) (*opsdk.Client, error) {
|
||||
if _, err := url.Parse(apiUrl); err != nil {
|
||||
return nil, errors.New("invalid 1panel api url")
|
||||
}
|
||||
@@ -183,7 +183,7 @@ func createSdkClient(apiUrl, apiKey string, allowInsecure bool) (*opsdk.Client,
|
||||
}
|
||||
|
||||
client := opsdk.NewClient(apiUrl, apiKey)
|
||||
if allowInsecure {
|
||||
if skipTlsVerify {
|
||||
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
|
||||
}
|
||||
|
||||
|
||||
@@ -464,7 +464,7 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up
|
||||
// 阿里云 CAS 服务接入点是独立于 ALB 服务的
|
||||
// 国内版固定接入点:华东一杭州
|
||||
// 国际版固定接入点:亚太东南一新加坡
|
||||
if casRegion != "" && !strings.HasPrefix(casRegion, "cn-") {
|
||||
if !strings.HasPrefix(casRegion, "cn-") {
|
||||
casRegion = "ap-southeast-1"
|
||||
} else {
|
||||
casRegion = "cn-hangzhou"
|
||||
|
||||
@@ -258,7 +258,7 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up
|
||||
// 阿里云 CAS 服务接入点是独立于 APIGateway 服务的
|
||||
// 国内版固定接入点:华东一杭州
|
||||
// 国际版固定接入点:亚太东南一新加坡
|
||||
if casRegion != "" && !strings.HasPrefix(casRegion, "cn-") {
|
||||
if !strings.HasPrefix(casRegion, "cn-") {
|
||||
casRegion = "ap-southeast-1"
|
||||
} else {
|
||||
casRegion = "cn-hangzhou"
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
||||
aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client"
|
||||
alislb "github.com/alibabacloud-go/slb-20140515/v4/client"
|
||||
@@ -54,11 +55,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
||||
return nil, fmt.Errorf("failed to create sdk client: %w", err)
|
||||
}
|
||||
|
||||
uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
|
||||
AccessKeyId: config.AccessKeyId,
|
||||
AccessKeySecret: config.AccessKeySecret,
|
||||
Region: config.Region,
|
||||
})
|
||||
uploader, err := createSslUploader(config.AccessKeyId, config.AccessKeySecret, config.Region)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create ssl uploader: %w", err)
|
||||
}
|
||||
@@ -311,3 +308,24 @@ func createSdkClient(accessKeyId, accessKeySecret, region string) (*alislb.Clien
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Uploader, error) {
|
||||
casRegion := region
|
||||
if casRegion != "" {
|
||||
// 阿里云 CAS 服务接入点是独立于 CLB 服务的
|
||||
// 国内版固定接入点:华东一杭州
|
||||
// 国际版固定接入点:亚太东南一新加坡
|
||||
if !strings.HasPrefix(casRegion, "cn-") {
|
||||
casRegion = "ap-southeast-1"
|
||||
} else {
|
||||
casRegion = "cn-hangzhou"
|
||||
}
|
||||
}
|
||||
|
||||
uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
|
||||
AccessKeyId: accessKeyId,
|
||||
AccessKeySecret: accessKeySecret,
|
||||
Region: casRegion,
|
||||
})
|
||||
return uploader, err
|
||||
}
|
||||
|
||||
137
internal/pkg/core/deployer/providers/aliyun-ddos/aliyun_ddos.go
Normal file
137
internal/pkg/core/deployer/providers/aliyun-ddos/aliyun_ddos.go
Normal file
@@ -0,0 +1,137 @@
|
||||
package aliyunddos
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client"
|
||||
aliddos "github.com/alibabacloud-go/ddoscoo-20200101/v4/client"
|
||||
"github.com/alibabacloud-go/tea/tea"
|
||||
|
||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
||||
uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-slb"
|
||||
)
|
||||
|
||||
type DeployerConfig struct {
|
||||
// 阿里云 AccessKeyId。
|
||||
AccessKeyId string `json:"accessKeyId"`
|
||||
// 阿里云 AccessKeySecret。
|
||||
AccessKeySecret string `json:"accessKeySecret"`
|
||||
// 阿里云地域。
|
||||
Region string `json:"region"`
|
||||
// 网站域名(支持泛域名)。
|
||||
Domain string `json:"domain"`
|
||||
}
|
||||
|
||||
type DeployerProvider struct {
|
||||
config *DeployerConfig
|
||||
logger *slog.Logger
|
||||
sdkClient *aliddos.Client
|
||||
sslUploader uploader.Uploader
|
||||
}
|
||||
|
||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
||||
|
||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
||||
if config == nil {
|
||||
panic("config is nil")
|
||||
}
|
||||
|
||||
client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create sdk client: %w", err)
|
||||
}
|
||||
|
||||
uploader, err := createSslUploader(config.AccessKeyId, config.AccessKeySecret, config.Region)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create ssl uploader: %w", err)
|
||||
}
|
||||
|
||||
return &DeployerProvider{
|
||||
config: config,
|
||||
logger: slog.Default(),
|
||||
sdkClient: client,
|
||||
sslUploader: uploader,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
|
||||
if logger == nil {
|
||||
d.logger = slog.Default()
|
||||
} else {
|
||||
d.logger = logger
|
||||
}
|
||||
d.sslUploader.WithLogger(logger)
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
|
||||
if d.config.Domain == "" {
|
||||
return nil, errors.New("config `domain` is required")
|
||||
}
|
||||
|
||||
// 上传证书到 CAS
|
||||
upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to upload certificate file: %w", err)
|
||||
} else {
|
||||
d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
|
||||
}
|
||||
|
||||
// 为网站业务转发规则关联 SSL 证书
|
||||
// REF: https://help.aliyun.com/zh/anti-ddos/anti-ddos-pro-and-premium/developer-reference/api-ddoscoo-2020-01-01-associatewebcert
|
||||
certId, _ := strconv.Atoi(upres.CertId)
|
||||
associateWebCertReq := &aliddos.AssociateWebCertRequest{
|
||||
Domain: tea.String(d.config.Domain),
|
||||
CertId: tea.Int32(int32(certId)),
|
||||
}
|
||||
associateWebCertResp, err := d.sdkClient.AssociateWebCert(associateWebCertReq)
|
||||
d.logger.Debug("sdk request 'dcdn.AssociateWebCert'", slog.Any("request", associateWebCertReq), slog.Any("response", associateWebCertResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'dcdn.AssociateWebCert': %w", err)
|
||||
}
|
||||
|
||||
return &deployer.DeployResult{}, nil
|
||||
}
|
||||
|
||||
func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliddos.Client, error) {
|
||||
// 接入点一览 https://api.aliyun.com/product/ddoscoo
|
||||
config := &aliopen.Config{
|
||||
AccessKeyId: tea.String(accessKeyId),
|
||||
AccessKeySecret: tea.String(accessKeySecret),
|
||||
Endpoint: tea.String(fmt.Sprintf("ddoscoo.%s.aliyuncs.com", region)),
|
||||
}
|
||||
|
||||
client, err := aliddos.NewClient(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Uploader, error) {
|
||||
casRegion := region
|
||||
if casRegion != "" {
|
||||
// 阿里云 CAS 服务接入点是独立于 Anti-DDoS 服务的
|
||||
// 国内版固定接入点:华东一杭州
|
||||
// 国际版固定接入点:亚太东南一新加坡
|
||||
if !strings.HasPrefix(casRegion, "cn-") {
|
||||
casRegion = "ap-southeast-1"
|
||||
} else {
|
||||
casRegion = "cn-hangzhou"
|
||||
}
|
||||
}
|
||||
|
||||
uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
|
||||
AccessKeyId: accessKeyId,
|
||||
AccessKeySecret: accessKeySecret,
|
||||
Region: casRegion,
|
||||
})
|
||||
return uploader, err
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package aliyunddos_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-ddos"
|
||||
)
|
||||
|
||||
var (
|
||||
fInputCertPath string
|
||||
fInputKeyPath string
|
||||
fAccessKeyId string
|
||||
fAccessKeySecret string
|
||||
fRegion string
|
||||
fDomain string
|
||||
)
|
||||
|
||||
func init() {
|
||||
argsPrefix := "CERTIMATE_DEPLOYER_ALIYUNDDOS_"
|
||||
|
||||
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
|
||||
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
|
||||
flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "")
|
||||
flag.StringVar(&fAccessKeySecret, argsPrefix+"ACCESSKEYSECRET", "", "")
|
||||
flag.StringVar(&fRegion, argsPrefix+"REGION", "", "")
|
||||
flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v ./aliyun_ddos_test.go -args \
|
||||
--CERTIMATE_DEPLOYER_ALIYUNDDOS_INPUTCERTPATH="/path/to/your-input-cert.pem" \
|
||||
--CERTIMATE_DEPLOYER_ALIYUNDDOS_INPUTKEYPATH="/path/to/your-input-key.pem" \
|
||||
--CERTIMATE_DEPLOYER_ALIYUNDDOS_ACCESSKEYID="your-access-key-id" \
|
||||
--CERTIMATE_DEPLOYER_ALIYUNDDOS_ACCESSKEYSECRET="your-access-key-secret" \
|
||||
--CERTIMATE_DEPLOYER_ALIYUNDDOS_REGION="cn-hangzhou" \
|
||||
--CERTIMATE_DEPLOYER_ALIYUNDDOS_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("ACCESSKEYID: %v", fAccessKeyId),
|
||||
fmt.Sprintf("ACCESSKEYSECRET: %v", fAccessKeySecret),
|
||||
fmt.Sprintf("REGION: %v", fRegion),
|
||||
fmt.Sprintf("DOMAIN: %v", fDomain),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := provider.NewDeployer(&provider.DeployerConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
AccessKeySecret: fAccessKeySecret,
|
||||
Region: fRegion,
|
||||
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)
|
||||
})
|
||||
}
|
||||
@@ -122,7 +122,7 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up
|
||||
// 阿里云 CAS 服务接入点是独立于 ESA 服务的
|
||||
// 国内版固定接入点:华东一杭州
|
||||
// 国际版固定接入点:亚太东南一新加坡
|
||||
if casRegion != "" && !strings.HasPrefix(casRegion, "cn-") {
|
||||
if !strings.HasPrefix(casRegion, "cn-") {
|
||||
casRegion = "ap-southeast-1"
|
||||
} else {
|
||||
casRegion = "cn-hangzhou"
|
||||
|
||||
@@ -251,7 +251,7 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up
|
||||
// 阿里云 CAS 服务接入点是独立于 NLB 服务的
|
||||
// 国内版固定接入点:华东一杭州
|
||||
// 国际版固定接入点:亚太东南一新加坡
|
||||
if casRegion != "" && !strings.HasPrefix(casRegion, "cn-") {
|
||||
if !strings.HasPrefix(casRegion, "cn-") {
|
||||
casRegion = "ap-southeast-1"
|
||||
} else {
|
||||
casRegion = "cn-hangzhou"
|
||||
|
||||
@@ -192,7 +192,7 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up
|
||||
// 阿里云 CAS 服务接入点是独立于 WAF 服务的
|
||||
// 国内版固定接入点:华东一杭州
|
||||
// 国际版固定接入点:亚太东南一新加坡
|
||||
if casRegion != "" && !strings.HasPrefix(casRegion, "cn-") {
|
||||
if !strings.HasPrefix(casRegion, "cn-") {
|
||||
casRegion = "ap-southeast-1"
|
||||
} else {
|
||||
casRegion = "cn-hangzhou"
|
||||
|
||||
@@ -63,6 +63,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
|
||||
return nil, errors.New("config `domain` is required")
|
||||
}
|
||||
|
||||
// 如果原证书 ID 为空,则新增证书;否则替换证书。
|
||||
if d.config.CertificateId == "" {
|
||||
// 新增证书
|
||||
// REF: https://portal.baishancloud.com/track/document/downloadPdf/1441
|
||||
|
||||
@@ -82,7 +82,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
|
||||
return &deployer.DeployResult{}, nil
|
||||
}
|
||||
|
||||
func createSdkClient(apiUrl, apiKey string, allowInsecure bool) (*btsdk.Client, error) {
|
||||
func createSdkClient(apiUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) {
|
||||
if _, err := url.Parse(apiUrl); err != nil {
|
||||
return nil, errors.New("invalid baota api url")
|
||||
}
|
||||
@@ -92,7 +92,7 @@ func createSdkClient(apiUrl, apiKey string, allowInsecure bool) (*btsdk.Client,
|
||||
}
|
||||
|
||||
client := btsdk.NewClient(apiUrl, apiKey)
|
||||
if allowInsecure {
|
||||
if skipTlsVerify {
|
||||
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
|
||||
}
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
|
||||
return &deployer.DeployResult{}, nil
|
||||
}
|
||||
|
||||
func createSdkClient(apiUrl, apiKey string, allowInsecure bool) (*btsdk.Client, error) {
|
||||
func createSdkClient(apiUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) {
|
||||
if _, err := url.Parse(apiUrl); err != nil {
|
||||
return nil, errors.New("invalid baota api url")
|
||||
}
|
||||
@@ -134,7 +134,7 @@ func createSdkClient(apiUrl, apiKey string, allowInsecure bool) (*btsdk.Client,
|
||||
}
|
||||
|
||||
client := btsdk.NewClient(apiUrl, apiKey)
|
||||
if allowInsecure {
|
||||
if skipTlsVerify {
|
||||
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package cdnfly
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -20,6 +21,8 @@ type DeployerConfig struct {
|
||||
ApiKey string `json:"apiKey"`
|
||||
// Cdnfly 用户端 API Secret。
|
||||
ApiSecret string `json:"apiSecret"`
|
||||
// 是否允许不安全的连接。
|
||||
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
|
||||
// 部署资源类型。
|
||||
ResourceType ResourceType `json:"resourceType"`
|
||||
// 网站 ID。
|
||||
@@ -43,7 +46,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
||||
panic("config is nil")
|
||||
}
|
||||
|
||||
client, err := createSdkClient(config.ApiUrl, config.ApiKey, config.ApiSecret)
|
||||
client, err := createSdkClient(config.ApiUrl, config.ApiKey, config.ApiSecret, config.AllowInsecureConnections)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create sdk client: %w", err)
|
||||
}
|
||||
@@ -157,7 +160,7 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri
|
||||
return nil
|
||||
}
|
||||
|
||||
func createSdkClient(apiUrl, apiKey, apiSecret string) (*cfsdk.Client, error) {
|
||||
func createSdkClient(apiUrl, apiKey, apiSecret string, skipTlsVerify bool) (*cfsdk.Client, error) {
|
||||
if _, err := url.Parse(apiUrl); err != nil {
|
||||
return nil, errors.New("invalid cachefly api url")
|
||||
}
|
||||
@@ -171,5 +174,9 @@ func createSdkClient(apiUrl, apiKey, apiSecret string) (*cfsdk.Client, error) {
|
||||
}
|
||||
|
||||
client := cfsdk.NewClient(apiUrl, apiKey, apiSecret)
|
||||
if skipTlsVerify {
|
||||
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
@@ -57,11 +57,12 @@ func TestDeploy(t *testing.T) {
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := provider.NewDeployer(&provider.DeployerConfig{
|
||||
ApiUrl: fApiUrl,
|
||||
ApiKey: fApiKey,
|
||||
ApiSecret: fApiSecret,
|
||||
ResourceType: provider.RESOURCE_TYPE_CERTIFICATE,
|
||||
CertificateId: fCertificateId,
|
||||
ApiUrl: fApiUrl,
|
||||
ApiKey: fApiKey,
|
||||
ApiSecret: fApiSecret,
|
||||
AllowInsecureConnections: true,
|
||||
ResourceType: provider.RESOURCE_TYPE_CERTIFICATE,
|
||||
CertificateId: fCertificateId,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
|
||||
@@ -7,8 +7,10 @@ import (
|
||||
"log/slog"
|
||||
"strconv"
|
||||
|
||||
gprovider "github.com/G-Core/gcorelabscdn-go/gcore/provider"
|
||||
gresources "github.com/G-Core/gcorelabscdn-go/resources"
|
||||
"github.com/G-Core/gcorelabscdn-go/gcore"
|
||||
"github.com/G-Core/gcorelabscdn-go/gcore/provider"
|
||||
"github.com/G-Core/gcorelabscdn-go/resources"
|
||||
"github.com/G-Core/gcorelabscdn-go/sslcerts"
|
||||
|
||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
||||
@@ -21,25 +23,33 @@ type DeployerConfig struct {
|
||||
ApiToken string `json:"apiToken"`
|
||||
// CDN 资源 ID。
|
||||
ResourceId int64 `json:"resourceId"`
|
||||
// 证书 ID。
|
||||
// 选填。
|
||||
CertificateId int64 `json:"certificateId,omitempty"`
|
||||
}
|
||||
|
||||
type DeployerProvider struct {
|
||||
config *DeployerConfig
|
||||
logger *slog.Logger
|
||||
sdkClient *gresources.Service
|
||||
sdkClients *wSdkClients
|
||||
sslUploader uploader.Uploader
|
||||
}
|
||||
|
||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
||||
|
||||
type wSdkClients struct {
|
||||
Resources *resources.Service
|
||||
SSLCerts *sslcerts.Service
|
||||
}
|
||||
|
||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
||||
if config == nil {
|
||||
panic("config is nil")
|
||||
}
|
||||
|
||||
client, err := createSdkClient(config.ApiToken)
|
||||
clients, err := createSdkClients(config.ApiToken)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create sdk client: %w", err)
|
||||
return nil, fmt.Errorf("failed to create sdk clients: %w", err)
|
||||
}
|
||||
|
||||
uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
|
||||
@@ -52,7 +62,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
||||
return &DeployerProvider{
|
||||
config: config,
|
||||
logger: slog.Default(),
|
||||
sdkClient: client,
|
||||
sdkClients: clients,
|
||||
sslUploader: uploader,
|
||||
}, nil
|
||||
}
|
||||
@@ -72,17 +82,47 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
|
||||
return nil, errors.New("config `resourceId` is required")
|
||||
}
|
||||
|
||||
// 上传证书到 CDN
|
||||
upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to upload certificate file: %w", err)
|
||||
// 如果原证书 ID 为空,则创建证书;否则更新证书。
|
||||
var cloudCertId int64
|
||||
if d.config.CertificateId == 0 {
|
||||
// 上传证书到 CDN
|
||||
upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to upload certificate file: %w", err)
|
||||
} else {
|
||||
d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
|
||||
}
|
||||
|
||||
cloudCertId, _ = strconv.ParseInt(upres.CertId, 10, 64)
|
||||
} else {
|
||||
d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
|
||||
// 获取证书
|
||||
// REF: https://api.gcore.com/docs/cdn#tag/SSL-certificates/paths/~1cdn~1sslData~1%7Bssl_id%7D/get
|
||||
getCertificateDetailResp, err := d.sdkClients.SSLCerts.Get(context.TODO(), d.config.CertificateId)
|
||||
d.logger.Debug("sdk request 'sslcerts.Get'", slog.Any("sslId", d.config.CertificateId), slog.Any("response", getCertificateDetailResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'sslcerts.Get': %w", err)
|
||||
}
|
||||
|
||||
// 更新证书
|
||||
// REF: https://api.gcore.com/docs/cdn#tag/SSL-certificates/paths/~1cdn~1sslData~1%7Bssl_id%7D/get
|
||||
changeCertificateReq := &sslcerts.UpdateRequest{
|
||||
Name: getCertificateDetailResp.Name,
|
||||
Cert: certPEM,
|
||||
PrivateKey: privkeyPEM,
|
||||
ValidateRootCA: false,
|
||||
}
|
||||
changeCertificateResp, err := d.sdkClients.SSLCerts.Update(context.TODO(), getCertificateDetailResp.ID, changeCertificateReq)
|
||||
d.logger.Debug("sdk request 'sslcerts.Create'", slog.Any("request", changeCertificateReq), slog.Any("response", changeCertificateResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'sslcerts.Update': %w", err)
|
||||
}
|
||||
|
||||
cloudCertId = changeCertificateResp.ID
|
||||
}
|
||||
|
||||
// 获取 CDN 资源详情
|
||||
// REF: https://api.gcore.com/docs/cdn#tag/CDN-resources/paths/~1cdn~1resources~1%7Bresource_id%7D/get
|
||||
getResourceResp, err := d.sdkClient.Get(context.TODO(), d.config.ResourceId)
|
||||
getResourceResp, err := d.sdkClients.Resources.Get(context.TODO(), d.config.ResourceId)
|
||||
d.logger.Debug("sdk request 'resources.Get'", slog.Any("resourceId", d.config.ResourceId), slog.Any("response", getResourceResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'resources.Get': %w", err)
|
||||
@@ -90,16 +130,16 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
|
||||
|
||||
// 更新 CDN 资源详情
|
||||
// REF: https://api.gcore.com/docs/cdn#tag/CDN-resources/operation/change_cdn_resource
|
||||
updateResourceCertId, _ := strconv.ParseInt(upres.CertId, 10, 64)
|
||||
updateResourceReq := &gresources.UpdateRequest{
|
||||
updateResourceReq := &resources.UpdateRequest{
|
||||
Description: getResourceResp.Description,
|
||||
Active: getResourceResp.Active,
|
||||
OriginGroup: int(getResourceResp.OriginGroup),
|
||||
OriginProtocol: getResourceResp.OriginProtocol,
|
||||
SecondaryHostnames: getResourceResp.SecondaryHostnames,
|
||||
SSlEnabled: true,
|
||||
SSLData: int(updateResourceCertId),
|
||||
SSLData: int(cloudCertId),
|
||||
ProxySSLEnabled: getResourceResp.ProxySSLEnabled,
|
||||
Options: &gcore.Options{},
|
||||
}
|
||||
if getResourceResp.ProxySSLCA != 0 {
|
||||
updateResourceReq.ProxySSLCA = &getResourceResp.ProxySSLCA
|
||||
@@ -107,10 +147,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
|
||||
if getResourceResp.ProxySSLData != 0 {
|
||||
updateResourceReq.ProxySSLData = &getResourceResp.ProxySSLData
|
||||
}
|
||||
if getResourceResp.Options != nil {
|
||||
updateResourceReq.Options = getResourceResp.Options
|
||||
}
|
||||
updateResourceResp, err := d.sdkClient.Update(context.TODO(), d.config.ResourceId, updateResourceReq)
|
||||
updateResourceResp, err := d.sdkClients.Resources.Update(context.TODO(), d.config.ResourceId, updateResourceReq)
|
||||
d.logger.Debug("sdk request 'resources.Update'", slog.Int64("resourceId", d.config.ResourceId), slog.Any("request", updateResourceReq), slog.Any("response", updateResourceResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'resources.Update': %w", err)
|
||||
@@ -119,15 +156,19 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
|
||||
return &deployer.DeployResult{}, nil
|
||||
}
|
||||
|
||||
func createSdkClient(apiToken string) (*gresources.Service, error) {
|
||||
func createSdkClients(apiToken string) (*wSdkClients, error) {
|
||||
if apiToken == "" {
|
||||
return nil, errors.New("invalid gcore api token")
|
||||
}
|
||||
|
||||
requester := gprovider.NewClient(
|
||||
requester := provider.NewClient(
|
||||
gcoresdk.BASE_URL,
|
||||
gprovider.WithSigner(gcoresdk.NewAuthRequestSigner(apiToken)),
|
||||
provider.WithSigner(gcoresdk.NewAuthRequestSigner(apiToken)),
|
||||
)
|
||||
service := gresources.NewService(requester)
|
||||
return service, nil
|
||||
resourcesSrv := resources.NewService(requester)
|
||||
sslCertsSrv := sslcerts.NewService(requester)
|
||||
return &wSdkClients{
|
||||
Resources: resourcesSrv,
|
||||
SSLCerts: sslCertsSrv,
|
||||
}, nil
|
||||
}
|
||||
|
||||
8
internal/pkg/core/deployer/providers/goedge/consts.go
Normal file
8
internal/pkg/core/deployer/providers/goedge/consts.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package goedge
|
||||
|
||||
type ResourceType string
|
||||
|
||||
const (
|
||||
// 资源类型:替换指定证书。
|
||||
RESOURCE_TYPE_CERTIFICATE = ResourceType("certificate")
|
||||
)
|
||||
138
internal/pkg/core/deployer/providers/goedge/goedge.go
Normal file
138
internal/pkg/core/deployer/providers/goedge/goedge.go
Normal file
@@ -0,0 +1,138 @@
|
||||
package goedge
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
||||
goedgesdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/goedge"
|
||||
certutil "github.com/usual2970/certimate/internal/pkg/utils/cert"
|
||||
)
|
||||
|
||||
type DeployerConfig struct {
|
||||
// GoEdge URL。
|
||||
ApiUrl string `json:"apiUrl"`
|
||||
// GoEdge 用户 AccessKeyId。
|
||||
AccessKeyId string `json:"accessKeyId"`
|
||||
// GoEdge 用户 AccessKey。
|
||||
AccessKey string `json:"accessKey"`
|
||||
// 是否允许不安全的连接。
|
||||
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
|
||||
// 部署资源类型。
|
||||
ResourceType ResourceType `json:"resourceType"`
|
||||
// 证书 ID。
|
||||
// 部署资源类型为 [RESOURCE_TYPE_CERTIFICATE] 时必填。
|
||||
CertificateId int64 `json:"certificateId,omitempty"`
|
||||
}
|
||||
|
||||
type DeployerProvider struct {
|
||||
config *DeployerConfig
|
||||
logger *slog.Logger
|
||||
sdkClient *goedgesdk.Client
|
||||
}
|
||||
|
||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
||||
|
||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
||||
if config == nil {
|
||||
panic("config is nil")
|
||||
}
|
||||
|
||||
client, err := createSdkClient(config.ApiUrl, config.AccessKeyId, config.AccessKey, config.AllowInsecureConnections)
|
||||
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) {
|
||||
// 根据部署资源类型决定部署方式
|
||||
switch d.config.ResourceType {
|
||||
case RESOURCE_TYPE_CERTIFICATE:
|
||||
if err := d.deployToCertificate(ctx, certPEM, privkeyPEM); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported resource type '%s'", d.config.ResourceType)
|
||||
}
|
||||
|
||||
return &deployer.DeployResult{}, nil
|
||||
}
|
||||
|
||||
func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM string, privkeyPEM string) error {
|
||||
if d.config.CertificateId == 0 {
|
||||
return errors.New("config `certificateId` is required")
|
||||
}
|
||||
|
||||
// 解析证书内容
|
||||
certX509, err := certutil.ParseCertificateFromPEM(certPEM)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 修改证书
|
||||
// REF: https://goedge.cloud/dev/api/service/SSLCertService?role=user#updateSSLCert
|
||||
updateSSLCertReq := &goedgesdk.UpdateSSLCertRequest{
|
||||
SSLCertId: d.config.CertificateId,
|
||||
IsOn: true,
|
||||
Name: fmt.Sprintf("certimate-%d", time.Now().UnixMilli()),
|
||||
Description: "upload from certimate",
|
||||
ServerName: certX509.Subject.CommonName,
|
||||
IsCA: false,
|
||||
CertData: base64.StdEncoding.EncodeToString([]byte(certPEM)),
|
||||
KeyData: base64.StdEncoding.EncodeToString([]byte(privkeyPEM)),
|
||||
TimeBeginAt: certX509.NotBefore.Unix(),
|
||||
TimeEndAt: certX509.NotAfter.Unix(),
|
||||
DNSNames: certX509.DNSNames,
|
||||
CommonNames: []string{certX509.Subject.CommonName},
|
||||
}
|
||||
updateSSLCertResp, err := d.sdkClient.UpdateSSLCert(updateSSLCertReq)
|
||||
d.logger.Debug("sdk request 'goedge.UpdateSSLCert'", slog.Any("request", updateSSLCertReq), slog.Any("response", updateSSLCertResp))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute sdk request 'goedge.UpdateSSLCert': %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createSdkClient(apiUrl, accessKeyId, accessKey string, skipTlsVerify bool) (*goedgesdk.Client, error) {
|
||||
if _, err := url.Parse(apiUrl); err != nil {
|
||||
return nil, errors.New("invalid goedge api url")
|
||||
}
|
||||
|
||||
if accessKeyId == "" {
|
||||
return nil, errors.New("invalid goedge access key id")
|
||||
}
|
||||
|
||||
if accessKey == "" {
|
||||
return nil, errors.New("invalid goedge access key")
|
||||
}
|
||||
|
||||
client := goedgesdk.NewClient(apiUrl, "user", accessKeyId, accessKey)
|
||||
if skipTlsVerify {
|
||||
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
82
internal/pkg/core/deployer/providers/goedge/goedge_test.go
Normal file
82
internal/pkg/core/deployer/providers/goedge/goedge_test.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package goedge_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/goedge"
|
||||
)
|
||||
|
||||
var (
|
||||
fInputCertPath string
|
||||
fInputKeyPath string
|
||||
fApiUrl string
|
||||
fAccessKeyId string
|
||||
fAccessKey string
|
||||
fCertificateId int
|
||||
)
|
||||
|
||||
func init() {
|
||||
argsPrefix := "CERTIMATE_DEPLOYER_GOEDGE_"
|
||||
|
||||
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
|
||||
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
|
||||
flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "")
|
||||
flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "")
|
||||
flag.StringVar(&fAccessKey, argsPrefix+"ACCESSKEY", "", "")
|
||||
flag.IntVar(&fCertificateId, argsPrefix+"CERTIFICATEID", 0, "")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v ./goedge_test.go -args \
|
||||
--CERTIMATE_DEPLOYER_GOEDGE_INPUTCERTPATH="/path/to/your-input-cert.pem" \
|
||||
--CERTIMATE_DEPLOYER_GOEDGE_INPUTKEYPATH="/path/to/your-input-key.pem" \
|
||||
--CERTIMATE_DEPLOYER_GOEDGE_APIURL="http://127.0.0.1:7788" \
|
||||
--CERTIMATE_DEPLOYER_GOEDGE_ACCESSKEYID="your-access-key-id" \
|
||||
--CERTIMATE_DEPLOYER_GOEDGE_ACCESSKEY="your-access-key" \
|
||||
--CERTIMATE_DEPLOYER_GOEDGE_CERTIFICATEID="your-cerficiate-id"
|
||||
*/
|
||||
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("APIURL: %v", fApiUrl),
|
||||
fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId),
|
||||
fmt.Sprintf("ACCESSKEY: %v", fAccessKey),
|
||||
fmt.Sprintf("CERTIFICATEID: %v", fCertificateId),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := provider.NewDeployer(&provider.DeployerConfig{
|
||||
ApiUrl: fApiUrl,
|
||||
AccessKeyId: fAccessKeyId,
|
||||
AccessKey: fAccessKey,
|
||||
AllowInsecureConnections: true,
|
||||
ResourceType: provider.RESOURCE_TYPE_CERTIFICATE,
|
||||
CertificateId: int64(fCertificateId),
|
||||
})
|
||||
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)
|
||||
})
|
||||
}
|
||||
121
internal/pkg/core/deployer/providers/proxmoxve/proxmoxve.go
Normal file
121
internal/pkg/core/deployer/providers/proxmoxve/proxmoxve.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package proxmoxve
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/luthermonson/go-proxmox"
|
||||
|
||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
||||
)
|
||||
|
||||
type DeployerConfig struct {
|
||||
// Proxmox VE 地址。
|
||||
ApiUrl string `json:"apiUrl"`
|
||||
// Proxmox VE API Token。
|
||||
ApiToken string `json:"apiToken"`
|
||||
// Proxmox VE API Token Secret。
|
||||
ApiTokenSecret string `json:"apiTokenSecret,omitempty"`
|
||||
// 是否允许不安全的连接。
|
||||
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
|
||||
// 集群节点名称。
|
||||
NodeName string `json:"nodeName"`
|
||||
// 是否自动重启。
|
||||
AutoRestart bool `json:"autoRestart"`
|
||||
}
|
||||
|
||||
type DeployerProvider struct {
|
||||
config *DeployerConfig
|
||||
logger *slog.Logger
|
||||
sdkClient *proxmox.Client
|
||||
}
|
||||
|
||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
||||
|
||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
||||
if config == nil {
|
||||
panic("config is nil")
|
||||
}
|
||||
|
||||
client, err := createSdkClient(config.ApiUrl, config.ApiToken, config.ApiTokenSecret, config.AllowInsecureConnections)
|
||||
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.NodeName == "" {
|
||||
return nil, errors.New("config `nodeName` is required")
|
||||
}
|
||||
|
||||
// 获取节点信息
|
||||
// REF: https://pve.proxmox.com/pve-docs/api-viewer/index.html#/nodes/{node}
|
||||
node, err := d.sdkClient.Node(context.TODO(), d.config.NodeName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get node '%s': %w", d.config.NodeName, err)
|
||||
}
|
||||
|
||||
// 上传自定义证书
|
||||
// REF: https://pve.proxmox.com/pve-docs/api-viewer/index.html#/nodes/{node}/certificates/custom
|
||||
err = node.UploadCustomCertificate(context.TODO(), &proxmox.CustomCertificate{
|
||||
Certificates: certPEM,
|
||||
Key: privkeyPEM,
|
||||
Force: true,
|
||||
Restart: d.config.AutoRestart,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to upload custom certificate to node '%s': %w", node.Name, err)
|
||||
}
|
||||
|
||||
return &deployer.DeployResult{}, nil
|
||||
}
|
||||
|
||||
func createSdkClient(apiUrl, apiToken, apiTokenSecret string, skipTlsVerify bool) (*proxmox.Client, error) {
|
||||
if _, err := url.Parse(apiUrl); err != nil {
|
||||
return nil, errors.New("invalid pve api url")
|
||||
}
|
||||
|
||||
if apiToken == "" {
|
||||
return nil, errors.New("invalid pve api token")
|
||||
}
|
||||
|
||||
httpClient := &http.Client{
|
||||
Transport: http.DefaultTransport,
|
||||
Timeout: http.DefaultClient.Timeout,
|
||||
}
|
||||
if skipTlsVerify {
|
||||
httpClient.Transport = &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
client := proxmox.NewClient(
|
||||
strings.TrimRight(apiUrl, "/")+"/api2/json",
|
||||
proxmox.WithHTTPClient(httpClient),
|
||||
proxmox.WithAPIToken(apiToken, apiTokenSecret),
|
||||
)
|
||||
|
||||
return client, nil
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package proxmoxve_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/proxmoxve"
|
||||
)
|
||||
|
||||
var (
|
||||
fInputCertPath string
|
||||
fInputKeyPath string
|
||||
fApiUrl string
|
||||
fApiToken string
|
||||
fApiTokenSecret string
|
||||
fNodeName string
|
||||
)
|
||||
|
||||
func init() {
|
||||
argsPrefix := "CERTIMATE_DEPLOYER_PROXMOXVE_"
|
||||
|
||||
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
|
||||
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
|
||||
flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "")
|
||||
flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "")
|
||||
flag.StringVar(&fApiTokenSecret, argsPrefix+"APITOKENSECRET", "", "")
|
||||
flag.StringVar(&fNodeName, argsPrefix+"NODENAME", "", "")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v ./proxmoxve_test.go -args \
|
||||
--CERTIMATE_DEPLOYER_PROXMOXVE_INPUTCERTPATH="/path/to/your-input-cert.pem" \
|
||||
--CERTIMATE_DEPLOYER_PROXMOXVE_INPUTKEYPATH="/path/to/your-input-key.pem" \
|
||||
--CERTIMATE_DEPLOYER_PROXMOXVE_APIURL="http://127.0.0.1:8006" \
|
||||
--CERTIMATE_DEPLOYER_PROXMOXVE_APITOKEN="your-api-token" \
|
||||
--CERTIMATE_DEPLOYER_PROXMOXVE_APITOKENSECRET="your-api-token-secret" \
|
||||
--CERTIMATE_DEPLOYER_PROXMOXVE_NODENAME="your-cluster-node-name"
|
||||
*/
|
||||
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("APIURL: %v", fApiUrl),
|
||||
fmt.Sprintf("APITOKEN: %v", fApiToken),
|
||||
fmt.Sprintf("APITOKENSECRET: %v", fApiTokenSecret),
|
||||
fmt.Sprintf("NODENAME: %v", fNodeName),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := provider.NewDeployer(&provider.DeployerConfig{
|
||||
ApiUrl: fApiUrl,
|
||||
ApiToken: fApiToken,
|
||||
ApiTokenSecret: fApiTokenSecret,
|
||||
AllowInsecureConnections: true,
|
||||
NodeName: fNodeName,
|
||||
AutoRestart: true,
|
||||
})
|
||||
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)
|
||||
})
|
||||
}
|
||||
@@ -98,7 +98,7 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri
|
||||
return nil
|
||||
}
|
||||
|
||||
func createSdkClient(apiUrl, apiToken string, allowInsecure bool) (*safelinesdk.Client, error) {
|
||||
func createSdkClient(apiUrl, apiToken string, skipTlsVerify bool) (*safelinesdk.Client, error) {
|
||||
if _, err := url.Parse(apiUrl); err != nil {
|
||||
return nil, errors.New("invalid safeline api url")
|
||||
}
|
||||
@@ -108,7 +108,7 @@ func createSdkClient(apiUrl, apiToken string, allowInsecure bool) (*safelinesdk.
|
||||
}
|
||||
|
||||
client := safelinesdk.NewClient(apiUrl, apiToken)
|
||||
if allowInsecure {
|
||||
if skipTlsVerify {
|
||||
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ func TestDeploy(t *testing.T) {
|
||||
ApiUrl: fApiUrl,
|
||||
ApiToken: fApiToken,
|
||||
AllowInsecureConnections: true,
|
||||
ResourceType: provider.ResourceType("certificate"),
|
||||
ResourceType: provider.RESOURCE_TYPE_CERTIFICATE,
|
||||
CertificateId: int32(fCertificateId),
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
gprovider "github.com/G-Core/gcorelabscdn-go/gcore/provider"
|
||||
gsslcerts "github.com/G-Core/gcorelabscdn-go/sslcerts"
|
||||
"github.com/G-Core/gcorelabscdn-go/gcore/provider"
|
||||
"github.com/G-Core/gcorelabscdn-go/sslcerts"
|
||||
|
||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
||||
gcoresdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/gcore/common"
|
||||
@@ -22,7 +22,7 @@ type UploaderConfig struct {
|
||||
type UploaderProvider struct {
|
||||
config *UploaderConfig
|
||||
logger *slog.Logger
|
||||
sdkClient *gsslcerts.Service
|
||||
sdkClient *sslcerts.Service
|
||||
}
|
||||
|
||||
var _ uploader.Uploader = (*UploaderProvider)(nil)
|
||||
@@ -59,8 +59,8 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPE
|
||||
certName = fmt.Sprintf("certimate_%d", time.Now().UnixMilli())
|
||||
|
||||
// 新增证书
|
||||
// REF: https://api.gcore.com/docs/cdn#tag/CA-certificates/operation/ca_certificates-add
|
||||
createCertificateReq := &gsslcerts.CreateRequest{
|
||||
// REF: https://api.gcore.com/docs/cdn#tag/SSL-certificates/operation/add_ssl_certificates
|
||||
createCertificateReq := &sslcerts.CreateRequest{
|
||||
Name: certName,
|
||||
Cert: certPEM,
|
||||
PrivateKey: privkeyPEM,
|
||||
@@ -81,15 +81,15 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPE
|
||||
}, nil
|
||||
}
|
||||
|
||||
func createSdkClient(apiToken string) (*gsslcerts.Service, error) {
|
||||
func createSdkClient(apiToken string) (*sslcerts.Service, error) {
|
||||
if apiToken == "" {
|
||||
return nil, errors.New("invalid gcore api token")
|
||||
}
|
||||
|
||||
requester := gprovider.NewClient(
|
||||
requester := provider.NewClient(
|
||||
gcoresdk.BASE_URL,
|
||||
gprovider.WithSigner(gcoresdk.NewAuthRequestSigner(apiToken)),
|
||||
provider.WithSigner(gcoresdk.NewAuthRequestSigner(apiToken)),
|
||||
)
|
||||
service := gsslcerts.NewService(requester)
|
||||
service := sslcerts.NewService(requester)
|
||||
return service, nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cdnflysdk
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
@@ -34,6 +35,11 @@ func (c *Client) WithTimeout(timeout time.Duration) *Client {
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Client) WithTLSConfig(config *tls.Config) *Client {
|
||||
c.client.SetTLSClientConfig(config)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) {
|
||||
req := c.client.R()
|
||||
req.Method = method
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module gitlab.ecloud.com/ecloud/ecloudsdkclouddns
|
||||
|
||||
go 1.23.0
|
||||
go 1.24.0
|
||||
|
||||
require gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
module gitlab.ecloud.com/ecloud/ecloudsdkcore
|
||||
|
||||
go 1.23.0
|
||||
go 1.24.0
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
module github.com/Edgio/edgio-api
|
||||
|
||||
go 1.23.0
|
||||
go 1.24.0
|
||||
|
||||
46
internal/pkg/sdk3rd/goedge/api.go
Normal file
46
internal/pkg/sdk3rd/goedge/api.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package goedge
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (c *Client) getAccessToken() error {
|
||||
req := &getAPIAccessTokenRequest{
|
||||
Type: c.apiUserType,
|
||||
AccessKeyId: c.accessKeyId,
|
||||
AccessKey: c.accessKey,
|
||||
}
|
||||
res, err := c.sendRequest(http.MethodPost, "/APIAccessTokenService/getAPIAccessToken", req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp := &getAPIAccessTokenResponse{}
|
||||
if err := json.Unmarshal(res.Body(), &resp); err != nil {
|
||||
return fmt.Errorf("goedge api error: failed to parse response: %w", err)
|
||||
} else if resp.GetCode() != 200 {
|
||||
return fmt.Errorf("goedge get access token failed: code: %d, message: %s", resp.GetCode(), resp.GetMessage())
|
||||
}
|
||||
|
||||
c.accessTokenMtx.Lock()
|
||||
c.accessToken = resp.Data.Token
|
||||
c.accessTokenExp = time.Unix(resp.Data.ExpiresAt, 0)
|
||||
c.accessTokenMtx.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) UpdateSSLCert(req *UpdateSSLCertRequest) (*UpdateSSLCertResponse, error) {
|
||||
if c.accessToken == "" || c.accessTokenExp.Before(time.Now()) {
|
||||
if err := c.getAccessToken(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
resp := &UpdateSSLCertResponse{}
|
||||
err := c.sendRequestWithResult(http.MethodPost, "/SSLCertService/updateSSLCert", req, resp)
|
||||
return resp, err
|
||||
}
|
||||
103
internal/pkg/sdk3rd/goedge/client.go
Normal file
103
internal/pkg/sdk3rd/goedge/client.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package goedge
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
apiHost string
|
||||
apiUserType string
|
||||
accessKeyId string
|
||||
accessKey string
|
||||
|
||||
accessToken string
|
||||
accessTokenExp time.Time
|
||||
accessTokenMtx sync.Mutex
|
||||
|
||||
client *resty.Client
|
||||
}
|
||||
|
||||
func NewClient(apiHost, apiUserType, accessKeyId, accessKey string) *Client {
|
||||
client := resty.New()
|
||||
|
||||
return &Client{
|
||||
apiHost: strings.TrimRight(apiHost, "/"),
|
||||
apiUserType: apiUserType,
|
||||
accessKeyId: accessKeyId,
|
||||
accessKey: accessKey,
|
||||
client: client,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) WithTimeout(timeout time.Duration) *Client {
|
||||
c.client.SetTimeout(timeout)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Client) WithTLSConfig(config *tls.Config) *Client {
|
||||
c.client.SetTLSClientConfig(config)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) {
|
||||
req := c.client.R().SetBasicAuth(c.accessKeyId, c.accessKey)
|
||||
req.Method = method
|
||||
req.URL = c.apiHost + path
|
||||
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).
|
||||
SetHeader("X-Edge-Access-Token", c.accessToken)
|
||||
} else {
|
||||
req = req.
|
||||
SetHeader("Content-Type", "application/json").
|
||||
SetHeader("X-Edge-Access-Token", c.accessToken).
|
||||
SetBody(params)
|
||||
}
|
||||
|
||||
resp, err := req.Send()
|
||||
if err != nil {
|
||||
return resp, fmt.Errorf("goedge api error: failed to send request: %w", err)
|
||||
} else if resp.IsError() {
|
||||
return resp, fmt.Errorf("goedge api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.Body())
|
||||
}
|
||||
|
||||
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("goedge api error: failed to parse response: %w", err)
|
||||
} else if errcode := result.GetCode(); errcode != 200 {
|
||||
return fmt.Errorf("goedge api error: %d - %s", errcode, result.GetMessage())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
52
internal/pkg/sdk3rd/goedge/models.go
Normal file
52
internal/pkg/sdk3rd/goedge/models.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package goedge
|
||||
|
||||
type BaseResponse interface {
|
||||
GetCode() int32
|
||||
GetMessage() string
|
||||
}
|
||||
|
||||
type baseResponse struct {
|
||||
Code int32 `json:"code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func (r *baseResponse) GetCode() int32 {
|
||||
return r.Code
|
||||
}
|
||||
|
||||
func (r *baseResponse) GetMessage() string {
|
||||
return r.Message
|
||||
}
|
||||
|
||||
type getAPIAccessTokenRequest struct {
|
||||
Type string `json:"type"`
|
||||
AccessKeyId string `json:"accessKeyId"`
|
||||
AccessKey string `json:"accessKey"`
|
||||
}
|
||||
|
||||
type getAPIAccessTokenResponse struct {
|
||||
baseResponse
|
||||
Data *struct {
|
||||
Token string `json:"token"`
|
||||
ExpiresAt int64 `json:"expiresAt"`
|
||||
} `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
type UpdateSSLCertRequest struct {
|
||||
SSLCertId int64 `json:"sslCertId"`
|
||||
IsOn bool `json:"isOn"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
ServerName string `json:"serverName"`
|
||||
IsCA bool `json:"isCA"`
|
||||
CertData string `json:"certData"`
|
||||
KeyData string `json:"keyData"`
|
||||
TimeBeginAt int64 `json:"timeBeginAt"`
|
||||
TimeEndAt int64 `json:"timeEndAt"`
|
||||
DNSNames []string `json:"dnsNames"`
|
||||
CommonNames []string `json:"commonNames"`
|
||||
}
|
||||
|
||||
type UpdateSSLCertResponse struct {
|
||||
baseResponse
|
||||
}
|
||||
@@ -11,8 +11,9 @@ import (
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
username string
|
||||
password string
|
||||
username string
|
||||
password string
|
||||
|
||||
loginCookie string
|
||||
|
||||
client *resty.Client
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -14,12 +15,17 @@ import (
|
||||
sliceutil "github.com/usual2970/certimate/internal/pkg/utils/slice"
|
||||
)
|
||||
|
||||
var maxWorkers = 16
|
||||
var maxWorkers = 1
|
||||
|
||||
func init() {
|
||||
envMaxWorkers := os.Getenv("CERTIMATE_WORKFLOW_MAX_WORKERS")
|
||||
if n, err := strconv.Atoi(envMaxWorkers); err != nil && n > 0 {
|
||||
maxWorkers = n
|
||||
} else {
|
||||
maxWorkers = runtime.GOMAXPROCS(0)
|
||||
if maxWorkers == 0 {
|
||||
maxWorkers = max(1, runtime.NumCPU())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
308
ui/package-lock.json
generated
308
ui/package-lock.json
generated
@@ -11,44 +11,44 @@
|
||||
"@ant-design/icons": "^6.0.0",
|
||||
"@ant-design/pro-components": "^2.8.7",
|
||||
"ahooks": "^3.8.4",
|
||||
"antd": "^5.24.8",
|
||||
"antd": "^5.25.1",
|
||||
"antd-zod": "^6.1.0",
|
||||
"clsx": "^2.1.1",
|
||||
"cron-parser": "^5.1.1",
|
||||
"cron-parser": "^5.2.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"i18next": "^25.0.1",
|
||||
"i18next-browser-languagedetector": "^8.0.5",
|
||||
"i18next": "^25.1.2",
|
||||
"i18next-browser-languagedetector": "^8.1.0",
|
||||
"immer": "^10.1.1",
|
||||
"lucide-react": "^0.503.0",
|
||||
"lucide-react": "^0.509.0",
|
||||
"nanoid": "^5.1.5",
|
||||
"pocketbase": "^0.26.0",
|
||||
"radash": "^12.1.0",
|
||||
"react": "^18.3.1",
|
||||
"react-copy-to-clipboard": "^5.1.0",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-i18next": "^15.4.1",
|
||||
"react-router-dom": "^7.5.1",
|
||||
"react-i18next": "^15.5.1",
|
||||
"react-router-dom": "^7.6.0",
|
||||
"tailwind-merge": "^2.6.0",
|
||||
"zod": "^3.24.3",
|
||||
"zustand": "^5.0.3"
|
||||
"zod": "^3.24.4",
|
||||
"zustand": "^5.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@types/node": "^22.14.1",
|
||||
"@types/node": "^22.15.17",
|
||||
"@types/react": "^18.3.12",
|
||||
"@types/react-copy-to-clipboard": "^5.0.7",
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"@typescript-eslint/eslint-plugin": "^8.31.0",
|
||||
"@typescript-eslint/parser": "^8.31.0",
|
||||
"@vitejs/plugin-legacy": "^6.1.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.32.0",
|
||||
"@typescript-eslint/parser": "^8.32.0",
|
||||
"@vitejs/plugin-legacy": "^6.1.1",
|
||||
"@vitejs/plugin-react": "^4.4.1",
|
||||
"autoprefixer": "^10.4.21",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^10.1.2",
|
||||
"eslint-config-prettier": "^10.1.5",
|
||||
"eslint-import-resolver-typescript": "^3.8.3",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-prettier": "^5.2.6",
|
||||
"eslint-plugin-prettier": "^5.4.0",
|
||||
"eslint-plugin-react-hooks": "^5.2.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.20",
|
||||
"eslint-plugin-tailwindcss": "^3.18.0",
|
||||
@@ -58,7 +58,7 @@
|
||||
"tailwindcss": "^3.4.17",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"typescript": "^5.8.3",
|
||||
"vite": "^6.3.2"
|
||||
"vite": "^6.3.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@alloc/quick-lru": {
|
||||
@@ -2588,16 +2588,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint-community/eslint-utils": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
|
||||
"integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
|
||||
"version": "4.7.0",
|
||||
"resolved": "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
|
||||
"integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"eslint-visitor-keys": "^3.3.0"
|
||||
"eslint-visitor-keys": "^3.4.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
|
||||
}
|
||||
@@ -3399,9 +3402,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.14.1",
|
||||
"resolved": "https://registry.npmmirror.com/@types/node/-/node-22.14.1.tgz",
|
||||
"integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==",
|
||||
"version": "22.15.17",
|
||||
"resolved": "https://registry.npmmirror.com/@types/node/-/node-22.15.17.tgz",
|
||||
"integrity": "sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
@@ -3442,20 +3445,20 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "8.31.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.31.0.tgz",
|
||||
"integrity": "sha512-evaQJZ/J/S4wisevDvC1KFZkPzRetH8kYZbkgcTRyql3mcKsf+ZFDV1BVWUGTCAW5pQHoqn5gK5b8kn7ou9aFQ==",
|
||||
"version": "8.32.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.0.tgz",
|
||||
"integrity": "sha512-/jU9ettcntkBFmWUzzGgsClEi2ZFiikMX5eEQsmxIAWMOn4H3D4rvHssstmAHGVvrYnaMqdWWWg0b5M6IN/MTQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/regexpp": "^4.10.0",
|
||||
"@typescript-eslint/scope-manager": "8.31.0",
|
||||
"@typescript-eslint/type-utils": "8.31.0",
|
||||
"@typescript-eslint/utils": "8.31.0",
|
||||
"@typescript-eslint/visitor-keys": "8.31.0",
|
||||
"@typescript-eslint/scope-manager": "8.32.0",
|
||||
"@typescript-eslint/type-utils": "8.32.0",
|
||||
"@typescript-eslint/utils": "8.32.0",
|
||||
"@typescript-eslint/visitor-keys": "8.32.0",
|
||||
"graphemer": "^1.4.0",
|
||||
"ignore": "^5.3.1",
|
||||
"natural-compare": "^1.4.0",
|
||||
"ts-api-utils": "^2.0.1"
|
||||
"ts-api-utils": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -3471,15 +3474,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "8.31.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.31.0.tgz",
|
||||
"integrity": "sha512-67kYYShjBR0jNI5vsf/c3WG4u+zDnCTHTPqVMQguffaWWFs7artgwKmfwdifl+r6XyM5LYLas/dInj2T0SgJyw==",
|
||||
"version": "8.32.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.32.0.tgz",
|
||||
"integrity": "sha512-B2MdzyWxCE2+SqiZHAjPphft+/2x2FlO9YBx7eKE1BCb+rqBlQdhtAEhzIEdozHd55DXPmxBdpMygFJjfjjA9A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.31.0",
|
||||
"@typescript-eslint/types": "8.31.0",
|
||||
"@typescript-eslint/typescript-estree": "8.31.0",
|
||||
"@typescript-eslint/visitor-keys": "8.31.0",
|
||||
"@typescript-eslint/scope-manager": "8.32.0",
|
||||
"@typescript-eslint/types": "8.32.0",
|
||||
"@typescript-eslint/typescript-estree": "8.32.0",
|
||||
"@typescript-eslint/visitor-keys": "8.32.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
@@ -3495,13 +3498,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "8.31.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.31.0.tgz",
|
||||
"integrity": "sha512-knO8UyF78Nt8O/B64i7TlGXod69ko7z6vJD9uhSlm0qkAbGeRUSudcm0+K/4CrRjrpiHfBCjMWlc08Vav1xwcw==",
|
||||
"version": "8.32.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.32.0.tgz",
|
||||
"integrity": "sha512-jc/4IxGNedXkmG4mx4nJTILb6TMjL66D41vyeaPWvDUmeYQzF3lKtN15WsAeTr65ce4mPxwopPSo1yUUAWw0hQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.31.0",
|
||||
"@typescript-eslint/visitor-keys": "8.31.0"
|
||||
"@typescript-eslint/types": "8.32.0",
|
||||
"@typescript-eslint/visitor-keys": "8.32.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -3512,15 +3515,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils": {
|
||||
"version": "8.31.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.31.0.tgz",
|
||||
"integrity": "sha512-DJ1N1GdjI7IS7uRlzJuEDCgDQix3ZVYVtgeWEyhyn4iaoitpMBX6Ndd488mXSx0xah/cONAkEaYyylDyAeHMHg==",
|
||||
"version": "8.32.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.32.0.tgz",
|
||||
"integrity": "sha512-t2vouuYQKEKSLtJaa5bB4jHeha2HJczQ6E5IXPDPgIty9EqcJxpr1QHQ86YyIPwDwxvUmLfP2YADQ5ZY4qddZg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/typescript-estree": "8.31.0",
|
||||
"@typescript-eslint/utils": "8.31.0",
|
||||
"@typescript-eslint/typescript-estree": "8.32.0",
|
||||
"@typescript-eslint/utils": "8.32.0",
|
||||
"debug": "^4.3.4",
|
||||
"ts-api-utils": "^2.0.1"
|
||||
"ts-api-utils": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -3535,9 +3538,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "8.31.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.31.0.tgz",
|
||||
"integrity": "sha512-Ch8oSjVyYyJxPQk8pMiP2FFGYatqXQfQIaMp+TpuuLlDachRWpUAeEu1u9B/v/8LToehUIWyiKcA/w5hUFRKuQ==",
|
||||
"version": "8.32.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.32.0.tgz",
|
||||
"integrity": "sha512-O5Id6tGadAZEMThM6L9HmVf5hQUXNSxLVKeGJYWNhhVseps/0LddMkp7//VDkzwJ69lPL0UmZdcZwggj9akJaA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -3548,19 +3551,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "8.31.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.0.tgz",
|
||||
"integrity": "sha512-xLmgn4Yl46xi6aDSZ9KkyfhhtnYI15/CvHbpOy/eR5NWhK/BK8wc709KKwhAR0m4ZKRP7h07bm4BWUYOCuRpQQ==",
|
||||
"version": "8.32.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.0.tgz",
|
||||
"integrity": "sha512-pU9VD7anSCOIoBFnhTGfOzlVFQIA1XXiQpH/CezqOBaDppRwTglJzCC6fUQGpfwey4T183NKhF1/mfatYmjRqQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.31.0",
|
||||
"@typescript-eslint/visitor-keys": "8.31.0",
|
||||
"@typescript-eslint/types": "8.32.0",
|
||||
"@typescript-eslint/visitor-keys": "8.32.0",
|
||||
"debug": "^4.3.4",
|
||||
"fast-glob": "^3.3.2",
|
||||
"is-glob": "^4.0.3",
|
||||
"minimatch": "^9.0.4",
|
||||
"semver": "^7.6.0",
|
||||
"ts-api-utils": "^2.0.1"
|
||||
"ts-api-utils": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -3574,15 +3577,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/utils": {
|
||||
"version": "8.31.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.31.0.tgz",
|
||||
"integrity": "sha512-qi6uPLt9cjTFxAb1zGNgTob4x9ur7xC6mHQJ8GwEzGMGE9tYniublmJaowOJ9V2jUzxrltTPfdG2nKlWsq0+Ww==",
|
||||
"version": "8.32.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.32.0.tgz",
|
||||
"integrity": "sha512-8S9hXau6nQ/sYVtC3D6ISIDoJzS1NsCK+gluVhLN2YkBPX+/1wkwyUiDKnxRh15579WoOIyVWnoyIf3yGI9REw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.4.0",
|
||||
"@typescript-eslint/scope-manager": "8.31.0",
|
||||
"@typescript-eslint/types": "8.31.0",
|
||||
"@typescript-eslint/typescript-estree": "8.31.0"
|
||||
"@eslint-community/eslint-utils": "^4.7.0",
|
||||
"@typescript-eslint/scope-manager": "8.32.0",
|
||||
"@typescript-eslint/types": "8.32.0",
|
||||
"@typescript-eslint/typescript-estree": "8.32.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -3597,12 +3600,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "8.31.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.0.tgz",
|
||||
"integrity": "sha512-QcGHmlRHWOl93o64ZUMNewCdwKGU6WItOU52H0djgNmn1EOrhVudrDzXz4OycCRSCPwFCDrE2iIt5vmuUdHxuQ==",
|
||||
"version": "8.32.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.0.tgz",
|
||||
"integrity": "sha512-1rYQTCLFFzOI5Nl0c8LUpJT8HxpwVRn9E4CkMsYfuN6ctmQqExjSTzzSk0Tz2apmXy7WU6/6fyaZVVA/thPN+w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.31.0",
|
||||
"@typescript-eslint/types": "8.32.0",
|
||||
"eslint-visitor-keys": "^4.2.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -3645,9 +3648,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@vitejs/plugin-legacy": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/@vitejs/plugin-legacy/-/plugin-legacy-6.1.0.tgz",
|
||||
"integrity": "sha512-D5/33NZFBDdlXvCoRbdGe3DcnSY4TZIDkQpolbMdMXBtUNgwJc03X1LHmEov4Igi4f5z2l9/lC0te74R8iHn5A==",
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmmirror.com/@vitejs/plugin-legacy/-/plugin-legacy-6.1.1.tgz",
|
||||
"integrity": "sha512-BvusL+mYZ0q5qS5Rq3D70QxZBmhyiHRaXLtYJHH5AEsAmdSqJR4xe5KwMi1H3w8/9lVJwhkLYqFQ9vmWYWy6kA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.26.10",
|
||||
@@ -3766,9 +3769,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/antd": {
|
||||
"version": "5.24.8",
|
||||
"resolved": "https://registry.npmmirror.com/antd/-/antd-5.24.8.tgz",
|
||||
"integrity": "sha512-vJcW81WSRq+ymBKTiA3NE+FddmiqTAKxdWVRZU+HnLLrRrIz896svcUxXFPa7M4mH9HqyeJ5JPOHsne4sQAC1A==",
|
||||
"version": "5.25.1",
|
||||
"resolved": "https://registry.npmmirror.com/antd/-/antd-5.25.1.tgz",
|
||||
"integrity": "sha512-4KC7KuPCjr0z3Vuw9DsF+ceqJaPLbuUI3lOX1sY8ix25ceamp+P8yxOmk3Y2JHCD2ZAhq+5IQ/DTJRN2adWYKQ==",
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^7.2.0",
|
||||
"@ant-design/cssinjs": "^1.23.0",
|
||||
@@ -3785,14 +3788,14 @@
|
||||
"classnames": "^2.5.1",
|
||||
"copy-to-clipboard": "^3.3.3",
|
||||
"dayjs": "^1.11.11",
|
||||
"rc-cascader": "~3.33.1",
|
||||
"rc-cascader": "~3.34.0",
|
||||
"rc-checkbox": "~3.5.0",
|
||||
"rc-collapse": "~3.9.0",
|
||||
"rc-dialog": "~9.6.0",
|
||||
"rc-drawer": "~7.2.0",
|
||||
"rc-dropdown": "~4.2.1",
|
||||
"rc-field-form": "~2.7.0",
|
||||
"rc-image": "~7.11.1",
|
||||
"rc-image": "~7.12.0",
|
||||
"rc-input": "~1.8.0",
|
||||
"rc-input-number": "~9.5.0",
|
||||
"rc-mentions": "~2.20.0",
|
||||
@@ -3805,17 +3808,17 @@
|
||||
"rc-rate": "~2.13.1",
|
||||
"rc-resize-observer": "^1.4.3",
|
||||
"rc-segmented": "~2.7.0",
|
||||
"rc-select": "~14.16.6",
|
||||
"rc-select": "~14.16.7",
|
||||
"rc-slider": "~11.1.8",
|
||||
"rc-steps": "~6.0.1",
|
||||
"rc-switch": "~4.1.0",
|
||||
"rc-table": "~7.50.4",
|
||||
"rc-tabs": "~15.6.0",
|
||||
"rc-tabs": "~15.6.1",
|
||||
"rc-textarea": "~1.10.0",
|
||||
"rc-tooltip": "~6.4.0",
|
||||
"rc-tree": "~5.13.1",
|
||||
"rc-tree-select": "~5.27.0",
|
||||
"rc-upload": "~4.8.1",
|
||||
"rc-upload": "~4.9.0",
|
||||
"rc-util": "^5.44.4",
|
||||
"scroll-into-view-if-needed": "^3.1.0",
|
||||
"throttle-debounce": "^5.0.2"
|
||||
@@ -4401,9 +4404,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/cron-parser": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmmirror.com/cron-parser/-/cron-parser-5.1.1.tgz",
|
||||
"integrity": "sha512-xNhwjTUTJcvevF4EvOxB3xYpEKC/qOAmykR+2Qf91ARIfdbjStUwo8qpem6jjzdwFgoo4pnf3sS264xG0G858w==",
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/cron-parser/-/cron-parser-5.2.0.tgz",
|
||||
"integrity": "sha512-ED2qJtcjelmUEuoV3btwxiOm3NI8H4/eCZNX3adUkrm+/b3Xq05+YoDXyjIN57VGhskuHx/KzC367GAklo1lRg==",
|
||||
"dependencies": {
|
||||
"luxon": "^3.6.1"
|
||||
},
|
||||
@@ -4870,13 +4873,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-config-prettier": {
|
||||
"version": "10.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/eslint-config-prettier/-/eslint-config-prettier-10.1.2.tgz",
|
||||
"integrity": "sha512-Epgp/EofAUeEpIdZkW60MHKvPyru1ruQJxPL+WIycnaPApuseK0Zpkrh/FwL9oIpQvIhJwV7ptOy0DWUjTlCiA==",
|
||||
"version": "10.1.5",
|
||||
"resolved": "https://registry.npmmirror.com/eslint-config-prettier/-/eslint-config-prettier-10.1.5.tgz",
|
||||
"integrity": "sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"eslint-config-prettier": "bin/cli.js"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint-config-prettier"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": ">=7.0.0"
|
||||
}
|
||||
@@ -5047,9 +5053,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-prettier": {
|
||||
"version": "5.2.6",
|
||||
"resolved": "https://registry.npmmirror.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.6.tgz",
|
||||
"integrity": "sha512-mUcf7QG2Tjk7H055Jk0lGBjbgDnfrvqjhXh9t2xLMSCjZVcw9Rb1V6sVNXO0th3jgeO7zllWPTNRil3JW94TnQ==",
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.0.tgz",
|
||||
"integrity": "sha512-BvQOvUhkVQM1i63iMETK9Hjud9QhqBnbtT1Zc642p9ynzBuCe5pybkOnvqZIBypXmMlsGcnU4HZ8sCTPfpAexA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"prettier-linter-helpers": "^1.0.0",
|
||||
@@ -5808,9 +5814,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/i18next": {
|
||||
"version": "25.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/i18next/-/i18next-25.0.1.tgz",
|
||||
"integrity": "sha512-8S8PyZbrymJZn3DaN70/34JYWNhsqrU6yA4MuzcygJBv+41dgNMocEA8h+kV1P7MCc1ll03lOTOIXE7mpNCicw==",
|
||||
"version": "25.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/i18next/-/i18next-25.1.2.tgz",
|
||||
"integrity": "sha512-SP63m8LzdjkrAjruH7SCI3ndPSgjt4/wX7ouUUOzCW/eY+HzlIo19IQSfYA9X3qRiRP1SYtaTsg/Oz/PGsfD8w==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
@@ -5838,9 +5844,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/i18next-browser-languagedetector": {
|
||||
"version": "8.0.5",
|
||||
"resolved": "https://registry.npmmirror.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.5.tgz",
|
||||
"integrity": "sha512-OstebRKqKiQw8xEvQF5aRyUujsCatanj7Q9eo5iiH2gJpoXGZ7483ol3sVBwfqbobTQPNH1J+NAyJ1aCQoEC+w==",
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.1.0.tgz",
|
||||
"integrity": "sha512-mHZxNx1Lq09xt5kCauZ/4bsXOEA2pfpwSoU11/QTJB+pD94iONFwp+ohqi///PwiFvjFOxe1akYCdHyFo1ng5Q==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.2"
|
||||
}
|
||||
@@ -6524,9 +6530,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/lucide-react": {
|
||||
"version": "0.503.0",
|
||||
"resolved": "https://registry.npmmirror.com/lucide-react/-/lucide-react-0.503.0.tgz",
|
||||
"integrity": "sha512-HGGkdlPWQ0vTF8jJ5TdIqhQXZi6uh3LnNgfZ8MHiuxFfX3RZeA79r2MW2tHAZKlAVfoNE8esm3p+O6VkIvpj6w==",
|
||||
"version": "0.509.0",
|
||||
"resolved": "https://registry.npmmirror.com/lucide-react/-/lucide-react-0.509.0.tgz",
|
||||
"integrity": "sha512-xCJHn6Uh5qF6PGml25vveCTrHJZcqS1G1MVzWZK54ZQsOiCVJk4fwY3oyo5EXS2S+aqvTpWYIfJN+PesJ0quxg==",
|
||||
"peerDependencies": {
|
||||
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
@@ -7250,9 +7256,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rc-cascader": {
|
||||
"version": "3.33.1",
|
||||
"resolved": "https://registry.npmmirror.com/rc-cascader/-/rc-cascader-3.33.1.tgz",
|
||||
"integrity": "sha512-Kyl4EJ7ZfCBuidmZVieegcbFw0RcU5bHHSbtEdmuLYd0fYHCAiYKZ6zon7fWAVyC6rWWOOib0XKdTSf7ElC9rg==",
|
||||
"version": "3.34.0",
|
||||
"resolved": "https://registry.npmmirror.com/rc-cascader/-/rc-cascader-3.34.0.tgz",
|
||||
"integrity": "sha512-KpXypcvju9ptjW9FaN2NFcA2QH9E9LHKq169Y0eWtH4e/wHQ5Wh5qZakAgvb8EKZ736WZ3B0zLLOBsrsja5Dag==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.25.7",
|
||||
"classnames": "^2.3.1",
|
||||
@@ -7359,9 +7365,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rc-image": {
|
||||
"version": "7.11.1",
|
||||
"resolved": "https://registry.npmmirror.com/rc-image/-/rc-image-7.11.1.tgz",
|
||||
"integrity": "sha512-XuoWx4KUXg7hNy5mRTy1i8c8p3K8boWg6UajbHpDXS5AlRVucNfTi5YxTtPBTBzegxAZpvuLfh3emXFt6ybUdA==",
|
||||
"version": "7.12.0",
|
||||
"resolved": "https://registry.npmmirror.com/rc-image/-/rc-image-7.12.0.tgz",
|
||||
"integrity": "sha512-cZ3HTyyckPnNnUb9/DRqduqzLfrQRyi+CdHjdqgsyDpI3Ln5UX1kXnAhPBSJj9pVRzwRFgqkN7p9b6HBDjmu/Q==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.11.2",
|
||||
"@rc-component/portal": "^1.0.2",
|
||||
@@ -7601,9 +7607,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rc-select": {
|
||||
"version": "14.16.6",
|
||||
"resolved": "https://registry.npmmirror.com/rc-select/-/rc-select-14.16.6.tgz",
|
||||
"integrity": "sha512-YPMtRPqfZWOm2XGTbx5/YVr1HT0vn//8QS77At0Gjb3Lv+Lbut0IORJPKLWu1hQ3u4GsA0SrDzs7nI8JG7Zmyg==",
|
||||
"version": "14.16.7",
|
||||
"resolved": "https://registry.npmmirror.com/rc-select/-/rc-select-14.16.7.tgz",
|
||||
"integrity": "sha512-lT9kO5gFHQdJzu9a0btcOtNaJHkhenSl8H5mcpgXN9VIMXP59rnkpbdHmPrteixWs1D5zFOTyoTYX3b7joADIQ==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.10.1",
|
||||
"@rc-component/trigger": "^2.1.1",
|
||||
@@ -7690,9 +7696,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rc-tabs": {
|
||||
"version": "15.6.0",
|
||||
"resolved": "https://registry.npmmirror.com/rc-tabs/-/rc-tabs-15.6.0.tgz",
|
||||
"integrity": "sha512-SQ99Yjc9ewrJCUwoWPKq0FeGL2znWsqPhfcZgsHz1R7bkA2rMNe7CPgOiJkwppdJ98wkLhzs9vPrv21QOE1RyQ==",
|
||||
"version": "15.6.1",
|
||||
"resolved": "https://registry.npmmirror.com/rc-tabs/-/rc-tabs-15.6.1.tgz",
|
||||
"integrity": "sha512-/HzDV1VqOsUWyuC0c6AkxVYFjvx9+rFPKZ32ejxX0Uc7QCzcEjTA9/xMgv4HemPKwzBNX8KhGVbbumDjnj92aA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.11.2",
|
||||
"classnames": "2.x",
|
||||
@@ -7777,9 +7783,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rc-upload": {
|
||||
"version": "4.8.1",
|
||||
"resolved": "https://registry.npmmirror.com/rc-upload/-/rc-upload-4.8.1.tgz",
|
||||
"integrity": "sha512-toEAhwl4hjLAI1u8/CgKWt30BR06ulPa4iGQSMvSXoHzO88gPCslxqV/mnn4gJU7PDoltGIC9Eh+wkeudqgHyw==",
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmmirror.com/rc-upload/-/rc-upload-4.9.0.tgz",
|
||||
"integrity": "sha512-pAzlPnyiFn1GCtEybEG2m9nXNzQyWXqWV2xFYCmDxjN9HzyjS5Pz2F+pbNdYw8mMJsixLEKLG0wVy9vOGxJMJA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.18.3",
|
||||
"classnames": "^2.2.5",
|
||||
@@ -7862,16 +7868,17 @@
|
||||
"integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="
|
||||
},
|
||||
"node_modules/react-i18next": {
|
||||
"version": "15.4.1",
|
||||
"resolved": "https://registry.npmmirror.com/react-i18next/-/react-i18next-15.4.1.tgz",
|
||||
"integrity": "sha512-ahGab+IaSgZmNPYXdV1n+OYky95TGpFwnKRflX/16dY04DsYYKHtVLjeny7sBSCREEcoMbAgSkFiGLF5g5Oofw==",
|
||||
"version": "15.5.1",
|
||||
"resolved": "https://registry.npmmirror.com/react-i18next/-/react-i18next-15.5.1.tgz",
|
||||
"integrity": "sha512-C8RZ7N7H0L+flitiX6ASjq9p5puVJU1Z8VyL3OgM/QOMRf40BMZX+5TkpxzZVcTmOLPX5zlti4InEX5pFyiVeA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.25.0",
|
||||
"html-parse-stringify": "^3.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"i18next": ">= 23.2.3",
|
||||
"react": ">= 16.8.0"
|
||||
"react": ">= 16.8.0",
|
||||
"typescript": "^5"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react-dom": {
|
||||
@@ -7879,6 +7886,9 @@
|
||||
},
|
||||
"react-native": {
|
||||
"optional": true
|
||||
},
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -7902,13 +7912,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react-router": {
|
||||
"version": "7.5.1",
|
||||
"resolved": "https://registry.npmmirror.com/react-router/-/react-router-7.5.1.tgz",
|
||||
"integrity": "sha512-/jjU3fcYNd2bwz9Q0xt5TwyiyoO8XjSEFXJY4O/lMAlkGTHWuHRAbR9Etik+lSDqMC7A7mz3UlXzgYT6Vl58sA==",
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmmirror.com/react-router/-/react-router-7.6.0.tgz",
|
||||
"integrity": "sha512-GGufuHIVCJDbnIAXP3P9Sxzq3UUsddG3rrI3ut1q6m0FI6vxVBF3JoPQ38+W/blslLH4a5Yutp8drkEpXoddGQ==",
|
||||
"dependencies": {
|
||||
"cookie": "^1.0.1",
|
||||
"set-cookie-parser": "^2.6.0",
|
||||
"turbo-stream": "2.4.0"
|
||||
"set-cookie-parser": "^2.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
@@ -7924,11 +7933,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react-router-dom": {
|
||||
"version": "7.5.1",
|
||||
"resolved": "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-7.5.1.tgz",
|
||||
"integrity": "sha512-5DPSPc7ENrt2tlKPq0FtpG80ZbqA9aIKEyqX6hSNJDlol/tr6iqCK4crqdsusmOSSotq6zDsn0y3urX9TuTNmA==",
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-7.6.0.tgz",
|
||||
"integrity": "sha512-DYgm6RDEuKdopSyGOWZGtDfSm7Aofb8CCzgkliTjtu/eDuB0gcsv6qdFhhi8HdtmA+KHkt5MfZ5K2PdzjugYsA==",
|
||||
"dependencies": {
|
||||
"react-router": "7.5.1"
|
||||
"react-router": "7.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
@@ -8904,12 +8913,12 @@
|
||||
"integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw=="
|
||||
},
|
||||
"node_modules/tinyglobby": {
|
||||
"version": "0.2.12",
|
||||
"resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.12.tgz",
|
||||
"integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==",
|
||||
"version": "0.2.13",
|
||||
"resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.13.tgz",
|
||||
"integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fdir": "^6.4.3",
|
||||
"fdir": "^6.4.4",
|
||||
"picomatch": "^4.0.2"
|
||||
},
|
||||
"engines": {
|
||||
@@ -8920,9 +8929,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tinyglobby/node_modules/fdir": {
|
||||
"version": "6.4.3",
|
||||
"resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.4.3.tgz",
|
||||
"integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==",
|
||||
"version": "6.4.4",
|
||||
"resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.4.4.tgz",
|
||||
"integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"picomatch": "^3 || ^4"
|
||||
@@ -8963,9 +8972,9 @@
|
||||
"integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ=="
|
||||
},
|
||||
"node_modules/ts-api-utils": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-2.0.1.tgz",
|
||||
"integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==",
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
|
||||
"integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=18.12"
|
||||
@@ -9009,11 +9018,6 @@
|
||||
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
|
||||
},
|
||||
"node_modules/turbo-stream": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/turbo-stream/-/turbo-stream-2.4.0.tgz",
|
||||
"integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g=="
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz",
|
||||
@@ -9252,17 +9256,17 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "6.3.2",
|
||||
"resolved": "https://registry.npmmirror.com/vite/-/vite-6.3.2.tgz",
|
||||
"integrity": "sha512-ZSvGOXKGceizRQIZSz7TGJ0pS3QLlVY/9hwxVh17W3re67je1RKYzFHivZ/t0tubU78Vkyb9WnHPENSBCzbckg==",
|
||||
"version": "6.3.5",
|
||||
"resolved": "https://registry.npmmirror.com/vite/-/vite-6.3.5.tgz",
|
||||
"integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"fdir": "^6.4.3",
|
||||
"fdir": "^6.4.4",
|
||||
"picomatch": "^4.0.2",
|
||||
"postcss": "^8.5.3",
|
||||
"rollup": "^4.34.9",
|
||||
"tinyglobby": "^0.2.12"
|
||||
"tinyglobby": "^0.2.13"
|
||||
},
|
||||
"bin": {
|
||||
"vite": "bin/vite.js"
|
||||
@@ -9645,17 +9649,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "3.24.3",
|
||||
"resolved": "https://registry.npmmirror.com/zod/-/zod-3.24.3.tgz",
|
||||
"integrity": "sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==",
|
||||
"version": "3.24.4",
|
||||
"resolved": "https://registry.npmmirror.com/zod/-/zod-3.24.4.tgz",
|
||||
"integrity": "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
},
|
||||
"node_modules/zustand": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/zustand/-/zustand-5.0.3.tgz",
|
||||
"integrity": "sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==",
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmmirror.com/zustand/-/zustand-5.0.4.tgz",
|
||||
"integrity": "sha512-39VFTN5InDtMd28ZhjLyuTnlytDr9HfwO512Ai4I8ZABCoyAj4F1+sr7sD1jP/+p7k77Iko0Pb5NhgBFDCX0kQ==",
|
||||
"engines": {
|
||||
"node": ">=12.20.0"
|
||||
},
|
||||
|
||||
@@ -13,44 +13,44 @@
|
||||
"@ant-design/icons": "^6.0.0",
|
||||
"@ant-design/pro-components": "^2.8.7",
|
||||
"ahooks": "^3.8.4",
|
||||
"antd": "^5.24.8",
|
||||
"antd": "^5.25.1",
|
||||
"antd-zod": "^6.1.0",
|
||||
"clsx": "^2.1.1",
|
||||
"cron-parser": "^5.1.1",
|
||||
"cron-parser": "^5.2.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"i18next": "^25.0.1",
|
||||
"i18next-browser-languagedetector": "^8.0.5",
|
||||
"i18next": "^25.1.2",
|
||||
"i18next-browser-languagedetector": "^8.1.0",
|
||||
"immer": "^10.1.1",
|
||||
"lucide-react": "^0.503.0",
|
||||
"lucide-react": "^0.509.0",
|
||||
"nanoid": "^5.1.5",
|
||||
"pocketbase": "^0.26.0",
|
||||
"radash": "^12.1.0",
|
||||
"react": "^18.3.1",
|
||||
"react-copy-to-clipboard": "^5.1.0",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-i18next": "^15.4.1",
|
||||
"react-router-dom": "^7.5.1",
|
||||
"react-i18next": "^15.5.1",
|
||||
"react-router-dom": "^7.6.0",
|
||||
"tailwind-merge": "^2.6.0",
|
||||
"zod": "^3.24.3",
|
||||
"zustand": "^5.0.3"
|
||||
"zod": "^3.24.4",
|
||||
"zustand": "^5.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@types/node": "^22.14.1",
|
||||
"@types/node": "^22.15.17",
|
||||
"@types/react": "^18.3.12",
|
||||
"@types/react-copy-to-clipboard": "^5.0.7",
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"@typescript-eslint/eslint-plugin": "^8.31.0",
|
||||
"@typescript-eslint/parser": "^8.31.0",
|
||||
"@vitejs/plugin-legacy": "^6.1.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.32.0",
|
||||
"@typescript-eslint/parser": "^8.32.0",
|
||||
"@vitejs/plugin-legacy": "^6.1.1",
|
||||
"@vitejs/plugin-react": "^4.4.1",
|
||||
"autoprefixer": "^10.4.21",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^10.1.2",
|
||||
"eslint-config-prettier": "^10.1.5",
|
||||
"eslint-import-resolver-typescript": "^3.8.3",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-prettier": "^5.2.6",
|
||||
"eslint-plugin-prettier": "^5.4.0",
|
||||
"eslint-plugin-react-hooks": "^5.2.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.20",
|
||||
"eslint-plugin-tailwindcss": "^3.18.0",
|
||||
@@ -60,6 +60,6 @@
|
||||
"tailwindcss": "^3.4.17",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"typescript": "^5.8.3",
|
||||
"vite": "^6.3.2"
|
||||
"vite": "^6.3.5"
|
||||
}
|
||||
}
|
||||
|
||||
BIN
ui/public/imgs/providers/goedge.png
Normal file
BIN
ui/public/imgs/providers/goedge.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
1
ui/public/imgs/providers/proxmoxve.svg
Normal file
1
ui/public/imgs/providers/proxmoxve.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="200" height="200"><path d="M93.866667 234.666667c-34.133333 12.8-51.2 25.6-51.2 34.133333 0 4.266667 51.2 64 115.2 136.533333 64 68.266667 115.2 128 115.2 128s-51.2 59.733333-115.2 128S42.666667 793.6 42.666667 797.866667c4.266667 17.066667 59.733333 42.666667 98.133333 42.666666 64 0 81.066667-12.8 217.6-162.133333 68.266667-76.8 128-140.8 128-140.8 0-4.266667-55.466667-64-123.733333-140.8-85.333333-102.4-132.266667-145.066667-153.6-157.866667-29.866667-12.8-81.066667-17.066667-115.2-4.266666z m725.333333 4.266666c-21.333333 8.533333-68.266667 59.733333-153.6 153.6-68.266667 76.8-123.733333 140.8-123.733333 140.8 0 4.266667 55.466667 68.266667 128 140.8 136.533333 153.6 153.6 162.133333 217.6 162.133334 42.666667 0 98.133333-21.333333 98.133333-42.666667 0-4.266667-51.2-68.266667-115.2-136.533333s-115.2-128-115.2-128 51.2-59.733333 115.2-128 115.2-128 115.2-136.533334c-4.266667-17.066667-55.466667-38.4-98.133333-38.4-34.133333 0-46.933333 4.266667-68.266667 12.8z" fill="#E57000"></path><path d="M238.933333 136.533333c-42.666667 21.333333-42.666667 25.6-4.266666 68.266667 221.866667 243.2 273.066667 302.933333 277.333333 302.933333s311.466667-332.8 315.733333-341.333333c0-4.266667-8.533333-12.8-21.333333-21.333333-17.066667-12.8-34.133333-17.066667-68.266667-17.066667-64-4.266667-85.333333 8.533333-162.133333 93.866667-34.133333 38.4-64 72.533333-64 72.533333s-29.866667-29.866667-64-68.266667-72.533333-76.8-89.6-85.333333c-25.6-17.066667-89.6-21.333333-119.466667-4.266667zM354.133333 725.333333c-85.333333 93.866667-153.6 170.666667-153.6 174.933334s8.533333 12.8 21.333334 21.333333c17.066667 12.8 34.133333 17.066667 68.266666 17.066667 59.733333 4.266667 85.333333-8.533333 162.133334-98.133334 34.133333-38.4 64-68.266667 64-68.266666s29.866667 29.866667 64 68.266666c81.066667 89.6 98.133333 102.4 162.133333 98.133334 34.133333 0 51.2-4.266667 68.266667-17.066667 12.8-8.533333 21.333333-17.066667 21.333333-21.333333-4.266667-8.533333-311.466667-345.6-315.733333-341.333334-8.533333 0-76.8 76.8-162.133334 166.4z"></path></svg>
|
||||
@@ -66,7 +66,7 @@ const DrawerForm = <T extends NonNullable<unknown> = any>({
|
||||
});
|
||||
|
||||
const mergedFormProps: FormProps = {
|
||||
clearOnDestroy: drawerProps?.destroyOnClose ? true : undefined,
|
||||
clearOnDestroy: drawerProps?.destroyOnHidden ? true : undefined,
|
||||
...formProps,
|
||||
...props,
|
||||
};
|
||||
|
||||
@@ -75,7 +75,7 @@ const ModalForm = <T extends NonNullable<unknown> = any>({
|
||||
});
|
||||
|
||||
const mergedFormProps: FormProps = {
|
||||
clearOnDestroy: modalProps?.destroyOnClose ? true : undefined,
|
||||
clearOnDestroy: modalProps?.destroyOnHidden ? true : undefined,
|
||||
...formProps,
|
||||
...props,
|
||||
};
|
||||
|
||||
@@ -93,7 +93,7 @@ const AccessEditDrawer = ({ data, loading, trigger, scene, usage, afterSubmit, .
|
||||
<Drawer
|
||||
afterOpenChange={setOpen}
|
||||
closable={!formPending}
|
||||
destroyOnClose
|
||||
destroyOnHidden
|
||||
footer={
|
||||
<Space className="w-full justify-end">
|
||||
<Button onClick={handleCancelClick}>{t("common.button.cancel")}</Button>
|
||||
|
||||
@@ -91,11 +91,18 @@ const AccessEditModal = ({ data, loading, trigger, scene, usage, afterSubmit, ..
|
||||
{triggerEl}
|
||||
|
||||
<Modal
|
||||
styles={{
|
||||
content: {
|
||||
maxHeight: "calc(80vh - 64px)",
|
||||
overflowX: "hidden",
|
||||
overflowY: "auto",
|
||||
},
|
||||
}}
|
||||
afterClose={() => setOpen(false)}
|
||||
cancelButtonProps={{ disabled: formPending }}
|
||||
closable
|
||||
confirmLoading={formPending}
|
||||
destroyOnClose
|
||||
destroyOnHidden
|
||||
loading={loading}
|
||||
okText={scene === "edit" ? t("common.button.save") : t("common.button.submit")}
|
||||
open={open}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import { forwardRef, useImperativeHandle, useMemo } from "react";
|
||||
import { forwardRef, useImperativeHandle, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, type FormInstance, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import AccessProviderPicker from "@/components/provider/AccessProviderPicker";
|
||||
import AccessProviderSelect from "@/components/provider/AccessProviderSelect";
|
||||
import Show from "@/components/Show";
|
||||
import { type AccessModel } from "@/domain/access";
|
||||
import { ACCESS_PROVIDERS, ACCESS_USAGES } from "@/domain/provider";
|
||||
import { ACCESS_PROVIDERS, ACCESS_USAGES, type AccessProvider } from "@/domain/provider";
|
||||
import { useAntdForm, useAntdFormName } from "@/hooks";
|
||||
|
||||
import AccessForm1PanelConfig from "./AccessForm1PanelConfig";
|
||||
@@ -34,6 +36,7 @@ import AccessFormEmailConfig from "./AccessFormEmailConfig";
|
||||
import AccessFormGcoreConfig from "./AccessFormGcoreConfig";
|
||||
import AccessFormGnameConfig from "./AccessFormGnameConfig";
|
||||
import AccessFormGoDaddyConfig from "./AccessFormGoDaddyConfig";
|
||||
import AccessFormGoEdgeConfig from "./AccessFormGoEdgeConfig";
|
||||
import AccessFormGoogleTrustServicesConfig from "./AccessFormGoogleTrustServicesConfig";
|
||||
import AccessFormHuaweiCloudConfig from "./AccessFormHuaweiCloudConfig";
|
||||
import AccessFormJDCloudConfig from "./AccessFormJDCloudConfig";
|
||||
@@ -46,6 +49,7 @@ import AccessFormNameSiloConfig from "./AccessFormNameSiloConfig";
|
||||
import AccessFormNS1Config from "./AccessFormNS1Config";
|
||||
import AccessFormPorkbunConfig from "./AccessFormPorkbunConfig";
|
||||
import AccessFormPowerDNSConfig from "./AccessFormPowerDNSConfig";
|
||||
import AccessFormProxmoxVEConfig from "./AccessFormProxmoxVEConfig";
|
||||
import AccessFormQiniuConfig from "./AccessFormQiniuConfig";
|
||||
import AccessFormRainYunConfig from "./AccessFormRainYunConfig";
|
||||
import AccessFormSafeLineConfig from "./AccessFormSafeLineConfig";
|
||||
@@ -105,9 +109,22 @@ const AccessForm = forwardRef<AccessFormInstance, AccessFormProps>(({ className,
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const { form: formInst, formProps } = useAntdForm({
|
||||
name: "accessForm",
|
||||
initialValues: initialValues,
|
||||
});
|
||||
|
||||
const providerFilter = useMemo(() => {
|
||||
switch (usage) {
|
||||
case "both-dns-hosting":
|
||||
return (record: AccessProvider) => record.usages.includes(ACCESS_USAGES.DNS) || record.usages.includes(ACCESS_USAGES.HOSTING);
|
||||
case "ca-only":
|
||||
return (record: AccessProvider) => record.usages.includes(ACCESS_USAGES.CA);
|
||||
case "notification-only":
|
||||
return (record: AccessProvider) => record.usages.includes(ACCESS_USAGES.NOTIFICATION);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}, [usage]);
|
||||
const providerLabel = useMemo(() => {
|
||||
switch (usage) {
|
||||
case "ca-only":
|
||||
@@ -137,10 +154,11 @@ const AccessForm = forwardRef<AccessFormInstance, AccessFormProps>(({ className,
|
||||
return undefined;
|
||||
}, [usage]);
|
||||
|
||||
const fieldProvider = Form.useWatch("provider", formInst);
|
||||
const fieldProvider = Form.useWatch<z.infer<typeof formSchema>["provider"]>("provider", formInst);
|
||||
const [fieldProviderPicked, setFieldProviderPicked] = useState<string>(initialValues?.provider); // bugfix: Form.useWatch 在条件渲染下不生效,这里用单独的变量存放 Picker 组件选择的值
|
||||
|
||||
const [nestedFormInst] = Form.useForm();
|
||||
const nestedFormName = useAntdFormName({ form: nestedFormInst, name: "accessEditFormConfigForm" });
|
||||
const nestedFormName = useAntdFormName({ form: nestedFormInst, name: "accessConfigForm" });
|
||||
const nestedFormEl = useMemo(() => {
|
||||
const nestedFormProps = {
|
||||
form: nestedFormInst,
|
||||
@@ -200,6 +218,8 @@ const AccessForm = forwardRef<AccessFormInstance, AccessFormProps>(({ className,
|
||||
return <AccessFormGnameConfig {...nestedFormProps} />;
|
||||
case ACCESS_PROVIDERS.GODADDY:
|
||||
return <AccessFormGoDaddyConfig {...nestedFormProps} />;
|
||||
case ACCESS_PROVIDERS.GOEDGE:
|
||||
return <AccessFormGoEdgeConfig {...nestedFormProps} />;
|
||||
case ACCESS_PROVIDERS.GOOGLETRUSTSERVICES:
|
||||
return <AccessFormGoogleTrustServicesConfig {...nestedFormProps} />;
|
||||
case ACCESS_PROVIDERS.EDGIO:
|
||||
@@ -228,6 +248,8 @@ const AccessForm = forwardRef<AccessFormInstance, AccessFormProps>(({ className,
|
||||
return <AccessFormPorkbunConfig {...nestedFormProps} />;
|
||||
case ACCESS_PROVIDERS.POWERDNS:
|
||||
return <AccessFormPowerDNSConfig {...nestedFormProps} />;
|
||||
case ACCESS_PROVIDERS.PROXMOXVE:
|
||||
return <AccessFormProxmoxVEConfig {...nestedFormProps} />;
|
||||
case ACCESS_PROVIDERS.QINIU:
|
||||
return <AccessFormQiniuConfig {...nestedFormProps} />;
|
||||
case ACCESS_PROVIDERS.RAINYUN:
|
||||
@@ -266,7 +288,13 @@ const AccessForm = forwardRef<AccessFormInstance, AccessFormProps>(({ className,
|
||||
case ACCESS_PROVIDERS.ZEROSSL:
|
||||
return <AccessFormZeroSSLConfig {...nestedFormProps} />;
|
||||
}
|
||||
}, [disabled, initialValues?.config, fieldProvider, nestedFormInst, nestedFormName]);
|
||||
}, [usage, disabled, initialValues?.config, fieldProvider, nestedFormInst, nestedFormName]);
|
||||
|
||||
const handleProviderPick = (value: string) => {
|
||||
setFieldProviderPicked(value);
|
||||
formInst.setFieldValue("provider", value);
|
||||
onValuesChange?.(formInst.getFieldsValue(true));
|
||||
};
|
||||
|
||||
const handleFormProviderChange = (name: string) => {
|
||||
if (name === nestedFormName) {
|
||||
@@ -306,30 +334,32 @@ const AccessForm = forwardRef<AccessFormInstance, AccessFormProps>(({ className,
|
||||
<Form.Provider onFormChange={handleFormProviderChange}>
|
||||
<div className={className} style={style}>
|
||||
<Form {...formProps} disabled={disabled} layout="vertical" scrollToFirstError onValuesChange={handleFormChange}>
|
||||
<Form.Item name="name" label={t("access.form.name.label")} rules={[formRule]}>
|
||||
<Input placeholder={t("access.form.name.placeholder")} />
|
||||
</Form.Item>
|
||||
<Show
|
||||
when={!!fieldProvider || !!fieldProviderPicked}
|
||||
fallback={
|
||||
<AccessProviderPicker
|
||||
autoFocus
|
||||
filter={providerFilter}
|
||||
placeholder={t("access.form.provider.search.placeholder")}
|
||||
showOptionTags={usage == null || (usage === "both-dns-hosting" ? { [ACCESS_USAGES.DNS]: true, [ACCESS_USAGES.HOSTING]: true } : false)}
|
||||
onSelect={handleProviderPick}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Form.Item name="name" label={t("access.form.name.label")} rules={[formRule]}>
|
||||
<Input placeholder={t("access.form.name.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="provider" label={providerLabel} rules={[formRule]} tooltip={providerTooltip}>
|
||||
<AccessProviderSelect
|
||||
filter={(record) => {
|
||||
if (usage == null) return true;
|
||||
|
||||
switch (usage) {
|
||||
case "both-dns-hosting":
|
||||
return record.usages.includes(ACCESS_USAGES.DNS) || record.usages.includes(ACCESS_USAGES.HOSTING);
|
||||
case "ca-only":
|
||||
return record.usages.includes(ACCESS_USAGES.CA);
|
||||
case "notification-only":
|
||||
return record.usages.includes(ACCESS_USAGES.NOTIFICATION);
|
||||
}
|
||||
}}
|
||||
disabled={scene !== "add"}
|
||||
placeholder={providerPlaceholder}
|
||||
showOptionTags={usage == null || (usage === "both-dns-hosting" ? { [ACCESS_USAGES.DNS]: true, [ACCESS_USAGES.HOSTING]: true } : false)}
|
||||
showSearch={!disabled}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="provider" label={providerLabel} rules={[formRule]} tooltip={providerTooltip}>
|
||||
<AccessProviderSelect
|
||||
filter={providerFilter}
|
||||
disabled={scene !== "add"}
|
||||
placeholder={providerPlaceholder}
|
||||
showOptionTags={usage == null || (usage === "both-dns-hosting" ? { [ACCESS_USAGES.DNS]: true, [ACCESS_USAGES.HOSTING]: true } : false)}
|
||||
showSearch={!disabled}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Show>
|
||||
</Form>
|
||||
|
||||
{nestedFormEl}
|
||||
|
||||
@@ -49,12 +49,7 @@ const AccessForm1PanelConfig = ({ form: formInst, formName, disabled, initialVal
|
||||
name={formName}
|
||||
onValuesChange={handleFormChange}
|
||||
>
|
||||
<Form.Item
|
||||
name="apiUrl"
|
||||
label={t("access.form.1panel_api_url.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.1panel_api_url.tooltip") }}></span>}
|
||||
>
|
||||
<Form.Item name="apiUrl" label={t("access.form.1panel_api_url.label")} rules={[formRule]}>
|
||||
<Input placeholder={t("access.form.1panel_api_url.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
@@ -67,12 +62,7 @@ const AccessForm1PanelConfig = ({ form: formInst, formName, disabled, initialVal
|
||||
<Input.Password autoComplete="new-password" placeholder={t("access.form.1panel_api_key.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="allowInsecureConnections"
|
||||
label={t("access.form.1panel_allow_insecure_conns.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.1panel_allow_insecure_conns.tooltip") }}></span>}
|
||||
>
|
||||
<Form.Item name="allowInsecureConnections" label={t("access.form.1panel_allow_insecure_conns.label")} rules={[formRule]}>
|
||||
<Switch
|
||||
checkedChildren={t("access.form.1panel_allow_insecure_conns.switch.on")}
|
||||
unCheckedChildren={t("access.form.1panel_allow_insecure_conns.switch.off")}
|
||||
|
||||
@@ -49,12 +49,7 @@ const AccessFormBaotaPanelConfig = ({ form: formInst, formName, disabled, initia
|
||||
name={formName}
|
||||
onValuesChange={handleFormChange}
|
||||
>
|
||||
<Form.Item
|
||||
name="apiUrl"
|
||||
label={t("access.form.baotapanel_api_url.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.baotapanel_api_url.tooltip") }}></span>}
|
||||
>
|
||||
<Form.Item name="apiUrl" label={t("access.form.baotapanel_api_url.label")} rules={[formRule]}>
|
||||
<Input placeholder={t("access.form.baotapanel_api_url.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
@@ -67,12 +62,7 @@ const AccessFormBaotaPanelConfig = ({ form: formInst, formName, disabled, initia
|
||||
<Input.Password autoComplete="new-password" placeholder={t("access.form.baotapanel_api_key.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="allowInsecureConnections"
|
||||
label={t("access.form.baotapanel_allow_insecure_conns.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.baotapanel_allow_insecure_conns.tooltip") }}></span>}
|
||||
>
|
||||
<Form.Item name="allowInsecureConnections" label={t("access.form.baotapanel_allow_insecure_conns.label")} rules={[formRule]}>
|
||||
<Switch
|
||||
checkedChildren={t("access.form.baotapanel_allow_insecure_conns.switch.on")}
|
||||
unCheckedChildren={t("access.form.baotapanel_allow_insecure_conns.switch.off")}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, type FormInstance, Input } from "antd";
|
||||
import { Form, type FormInstance, Input, Switch } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
@@ -38,6 +38,7 @@ const AccessFormCdnflyConfig = ({ form: formInst, formName, disabled, initialVal
|
||||
.min(1, t("access.form.cdnfly_api_secret.placeholder"))
|
||||
.max(64, t("common.errmsg.string_max", { max: 64 }))
|
||||
.trim(),
|
||||
allowInsecureConnections: z.boolean().nullish(),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
@@ -54,12 +55,7 @@ const AccessFormCdnflyConfig = ({ form: formInst, formName, disabled, initialVal
|
||||
name={formName}
|
||||
onValuesChange={handleFormChange}
|
||||
>
|
||||
<Form.Item
|
||||
name="apiUrl"
|
||||
label={t("access.form.cdnfly_api_url.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.cdnfly_api_url.tooltip") }}></span>}
|
||||
>
|
||||
<Form.Item name="apiUrl" label={t("access.form.cdnfly_api_url.label")} rules={[formRule]}>
|
||||
<Input placeholder={t("access.form.cdnfly_api_url.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
@@ -80,6 +76,13 @@ const AccessFormCdnflyConfig = ({ form: formInst, formName, disabled, initialVal
|
||||
>
|
||||
<Input.Password autoComplete="new-password" placeholder={t("access.form.cdnfly_api_secret.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="allowInsecureConnections" label={t("access.form.cdnfly_allow_insecure_conns.label")} rules={[formRule]}>
|
||||
<Switch
|
||||
checkedChildren={t("access.form.cdnfly_allow_insecure_conns.switch.on")}
|
||||
unCheckedChildren={t("access.form.cdnfly_allow_insecure_conns.switch.off")}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
90
ui/src/components/access/AccessFormGoEdgeConfig.tsx
Normal file
90
ui/src/components/access/AccessFormGoEdgeConfig.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, type FormInstance, Input, Switch } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { type AccessConfigForGoEdge } from "@/domain/access";
|
||||
|
||||
type AccessFormGoEdgeConfigFieldValues = Nullish<AccessConfigForGoEdge>;
|
||||
|
||||
export type AccessFormGoEdgeConfigProps = {
|
||||
form: FormInstance;
|
||||
formName: string;
|
||||
disabled?: boolean;
|
||||
initialValues?: AccessFormGoEdgeConfigFieldValues;
|
||||
onValuesChange?: (values: AccessFormGoEdgeConfigFieldValues) => void;
|
||||
};
|
||||
|
||||
const initFormModel = (): AccessFormGoEdgeConfigFieldValues => {
|
||||
return {
|
||||
apiUrl: "http://<your-host-addr>:7788/",
|
||||
accessKeyId: "",
|
||||
accessKey: "",
|
||||
};
|
||||
};
|
||||
|
||||
const AccessFormGoEdgeConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormGoEdgeConfigProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
apiUrl: z.string().url(t("common.errmsg.url_invalid")),
|
||||
accessKeyId: z
|
||||
.string()
|
||||
.min(1, t("access.form.goedge_access_key_id.placeholder"))
|
||||
.max(64, t("common.errmsg.string_max", { max: 64 }))
|
||||
.trim(),
|
||||
accessKey: z
|
||||
.string()
|
||||
.min(1, t("access.form.goedge_access_key.placeholder"))
|
||||
.max(64, t("common.errmsg.string_max", { max: 64 }))
|
||||
.trim(),
|
||||
allowInsecureConnections: z.boolean().nullish(),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
|
||||
onValuesChange?.(values);
|
||||
};
|
||||
|
||||
return (
|
||||
<Form
|
||||
form={formInst}
|
||||
disabled={disabled}
|
||||
initialValues={initialValues ?? initFormModel()}
|
||||
layout="vertical"
|
||||
name={formName}
|
||||
onValuesChange={handleFormChange}
|
||||
>
|
||||
<Form.Item name="apiUrl" label={t("access.form.goedge_api_url.label")} rules={[formRule]}>
|
||||
<Input placeholder={t("access.form.goedge_api_url.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="accessKeyId"
|
||||
label={t("access.form.goedge_access_key_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.goedge_access_key_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input autoComplete="new-password" placeholder={t("access.form.goedge_access_key_id.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="accessKey"
|
||||
label={t("access.form.goedge_access_key.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.goedge_access_key.tooltip") }}></span>}
|
||||
>
|
||||
<Input.Password autoComplete="new-password" placeholder={t("access.form.goedge_access_key.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="allowInsecureConnections" label={t("access.form.goedge_allow_insecure_conns.label")} rules={[formRule]}>
|
||||
<Switch
|
||||
checkedChildren={t("access.form.goedge_allow_insecure_conns.switch.on")}
|
||||
unCheckedChildren={t("access.form.goedge_allow_insecure_conns.switch.off")}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default AccessFormGoEdgeConfig;
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, type FormInstance, Input } from "antd";
|
||||
import { Form, type FormInstance, Input, Switch } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
@@ -32,6 +32,7 @@ const AccessFormPowerDNSConfig = ({ form: formInst, formName, disabled, initialV
|
||||
.min(1, t("access.form.powerdns_api_key.placeholder"))
|
||||
.max(64, t("common.errmsg.string_max", { max: 64 }))
|
||||
.trim(),
|
||||
allowInsecureConnections: z.boolean().nullish(),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
@@ -48,12 +49,7 @@ const AccessFormPowerDNSConfig = ({ form: formInst, formName, disabled, initialV
|
||||
name={formName}
|
||||
onValuesChange={handleFormChange}
|
||||
>
|
||||
<Form.Item
|
||||
name="apiUrl"
|
||||
label={t("access.form.powerdns_api_url.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.powerdns_api_url.tooltip") }}></span>}
|
||||
>
|
||||
<Form.Item name="apiUrl" label={t("access.form.powerdns_api_url.label")} rules={[formRule]}>
|
||||
<Input placeholder={t("access.form.powerdns_api_url.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
@@ -65,6 +61,13 @@ const AccessFormPowerDNSConfig = ({ form: formInst, formName, disabled, initialV
|
||||
>
|
||||
<Input.Password autoComplete="new-password" placeholder={t("access.form.powerdns_api_key.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="allowInsecureConnections" label={t("access.form.powerdns_allow_insecure_conns.label")} rules={[formRule]}>
|
||||
<Switch
|
||||
checkedChildren={t("access.form.powerdns_allow_insecure_conns.switch.on")}
|
||||
unCheckedChildren={t("access.form.powerdns_allow_insecure_conns.switch.off")}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
81
ui/src/components/access/AccessFormProxmoxVEConfig.tsx
Normal file
81
ui/src/components/access/AccessFormProxmoxVEConfig.tsx
Normal file
@@ -0,0 +1,81 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, type FormInstance, Input, Switch } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { type AccessConfigForProxmoxVE } from "@/domain/access";
|
||||
|
||||
type AccessFormProxmoxVEConfigFieldValues = Nullish<AccessConfigForProxmoxVE>;
|
||||
|
||||
export type AccessFormProxmoxVEConfigProps = {
|
||||
form: FormInstance;
|
||||
formName: string;
|
||||
disabled?: boolean;
|
||||
initialValues?: AccessFormProxmoxVEConfigFieldValues;
|
||||
onValuesChange?: (values: AccessFormProxmoxVEConfigFieldValues) => void;
|
||||
};
|
||||
|
||||
const initFormModel = (): AccessFormProxmoxVEConfigFieldValues => {
|
||||
return {
|
||||
apiUrl: "http://<your-host-addr>:8006/",
|
||||
apiToken: "",
|
||||
};
|
||||
};
|
||||
|
||||
const AccessFormProxmoxVEConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormProxmoxVEConfigProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
apiUrl: z.string().url(t("common.errmsg.url_invalid")),
|
||||
apiToken: z.string().nonempty(t("access.form.proxmoxve_api_token.placeholder")).trim(),
|
||||
apiTokenSecret: z.string().nullish(),
|
||||
allowInsecureConnections: z.boolean().nullish(),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
|
||||
onValuesChange?.(values);
|
||||
};
|
||||
|
||||
return (
|
||||
<Form
|
||||
form={formInst}
|
||||
disabled={disabled}
|
||||
initialValues={initialValues ?? initFormModel()}
|
||||
layout="vertical"
|
||||
name={formName}
|
||||
onValuesChange={handleFormChange}
|
||||
>
|
||||
<Form.Item name="apiUrl" label={t("access.form.proxmoxve_api_url.label")} rules={[formRule]}>
|
||||
<Input placeholder={t("access.form.proxmoxve_api_url.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="apiToken"
|
||||
label={t("access.form.proxmoxve_api_token.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.proxmoxve_api_token.tooltip") }}></span>}
|
||||
>
|
||||
<Input.Password autoComplete="new-password" placeholder={t("access.form.proxmoxve_api_token.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="apiTokenSecret"
|
||||
label={t("access.form.proxmoxve_api_token_secret.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.proxmoxve_api_token_secret.tooltip") }}></span>}
|
||||
>
|
||||
<Input.Password autoComplete="new-password" placeholder={t("access.form.proxmoxve_api_token_secret.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="allowInsecureConnections" label={t("access.form.proxmoxve_allow_insecure_conns.label")} rules={[formRule]}>
|
||||
<Switch
|
||||
checkedChildren={t("access.form.proxmoxve_allow_insecure_conns.switch.on")}
|
||||
unCheckedChildren={t("access.form.proxmoxve_allow_insecure_conns.switch.off")}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default AccessFormProxmoxVEConfig;
|
||||
@@ -49,12 +49,7 @@ const AccessFormSafeLineConfig = ({ form: formInst, formName, disabled, initialV
|
||||
name={formName}
|
||||
onValuesChange={handleFormChange}
|
||||
>
|
||||
<Form.Item
|
||||
name="apiUrl"
|
||||
label={t("access.form.safeline_api_url.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.safeline_api_url.tooltip") }}></span>}
|
||||
>
|
||||
<Form.Item name="apiUrl" label={t("access.form.safeline_api_url.label")} rules={[formRule]}>
|
||||
<Input placeholder={t("access.form.safeline_api_url.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
@@ -67,12 +62,7 @@ const AccessFormSafeLineConfig = ({ form: formInst, formName, disabled, initialV
|
||||
<Input.Password autoComplete="new-password" placeholder={t("access.form.safeline_api_token.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="allowInsecureConnections"
|
||||
label={t("access.form.safeline_allow_insecure_conns.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.safeline_allow_insecure_conns.tooltip") }}></span>}
|
||||
>
|
||||
<Form.Item name="allowInsecureConnections" label={t("access.form.safeline_allow_insecure_conns.label")} rules={[formRule]}>
|
||||
<Switch
|
||||
checkedChildren={t("access.form.safeline_allow_insecure_conns.switch.on")}
|
||||
unCheckedChildren={t("access.form.safeline_allow_insecure_conns.switch.off")}
|
||||
|
||||
@@ -283,7 +283,7 @@ const AccessFormWebhookConfig = ({ form: formInst, formName, disabled, initialVa
|
||||
</Form.Item>
|
||||
|
||||
<Show when={!usage || usage === "deployment"}>
|
||||
<Form.Item className="mb-0">
|
||||
<Form.Item className="mb-0" htmlFor="null">
|
||||
<label className="mb-1 block">
|
||||
<div className="flex w-full items-center justify-between gap-4">
|
||||
<div className="max-w-full grow truncate">
|
||||
@@ -312,7 +312,7 @@ const AccessFormWebhookConfig = ({ form: formInst, formName, disabled, initialVa
|
||||
</Show>
|
||||
|
||||
<Show when={!usage || usage === "notification"}>
|
||||
<Form.Item className="mb-0">
|
||||
<Form.Item className="mb-0" htmlFor="null">
|
||||
<label className="mb-1 block">
|
||||
<div className="flex w-full items-center justify-between gap-4">
|
||||
<div className="max-w-full grow truncate">
|
||||
@@ -352,12 +352,7 @@ const AccessFormWebhookConfig = ({ form: formInst, formName, disabled, initialVa
|
||||
</Form.Item>
|
||||
</Show>
|
||||
|
||||
<Form.Item
|
||||
name="allowInsecureConnections"
|
||||
label={t("access.form.webhook_allow_insecure_conns.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.webhook_allow_insecure_conns.tooltip") }}></span>}
|
||||
>
|
||||
<Form.Item name="allowInsecureConnections" label={t("access.form.webhook_allow_insecure_conns.label")} rules={[formRule]}>
|
||||
<Switch
|
||||
checkedChildren={t("access.form.webhook_allow_insecure_conns.switch.on")}
|
||||
unCheckedChildren={t("access.form.webhook_allow_insecure_conns.switch.off")}
|
||||
|
||||
@@ -59,6 +59,12 @@ const AccessSelect = ({ filter, ...props }: AccessTypeSelectProps) => {
|
||||
return (
|
||||
<Select
|
||||
{...props}
|
||||
filterOption={(inputValue, option) => {
|
||||
if (!option) return false;
|
||||
|
||||
const value = inputValue.toLowerCase();
|
||||
return option.label.toLowerCase().includes(value);
|
||||
}}
|
||||
labelRender={({ label, value }) => {
|
||||
if (label) {
|
||||
return renderOption(value as string);
|
||||
|
||||
@@ -29,7 +29,7 @@ const CertificateDetailDrawer = ({ data, loading, trigger, ...props }: Certifica
|
||||
|
||||
<Drawer
|
||||
afterOpenChange={setOpen}
|
||||
destroyOnClose
|
||||
destroyOnHidden
|
||||
open={open}
|
||||
loading={loading}
|
||||
placement="right"
|
||||
|
||||
@@ -3,17 +3,18 @@ import { useTranslation } from "react-i18next";
|
||||
import { Avatar, Card, Col, Empty, Flex, Input, type InputRef, Row, Typography } from "antd";
|
||||
|
||||
import Show from "@/components/Show";
|
||||
import { acmeDns01ProvidersMap } from "@/domain/provider";
|
||||
import { type ACMEDns01Provider, acmeDns01ProvidersMap } from "@/domain/provider";
|
||||
|
||||
export type ACMEDns01ProviderPickerProps = {
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
autoFocus?: boolean;
|
||||
filter?: (record: ACMEDns01Provider) => boolean;
|
||||
placeholder?: string;
|
||||
onSelect?: (value: string) => void;
|
||||
};
|
||||
|
||||
const ACMEDns01ProviderPicker = ({ className, style, autoFocus, placeholder, onSelect }: ACMEDns01ProviderPickerProps) => {
|
||||
const ACMEDns01ProviderPicker = ({ className, style, autoFocus, filter, placeholder, onSelect }: ACMEDns01ProviderPickerProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [keyword, setKeyword] = useState<string>();
|
||||
@@ -25,15 +26,23 @@ const ACMEDns01ProviderPicker = ({ className, style, autoFocus, placeholder, onS
|
||||
}, []);
|
||||
|
||||
const providers = useMemo(() => {
|
||||
return Array.from(acmeDns01ProvidersMap.values()).filter((provider) => {
|
||||
if (keyword) {
|
||||
const value = keyword.toLowerCase();
|
||||
return provider.type.toLowerCase().includes(value) || t(provider.name).toLowerCase().includes(value);
|
||||
}
|
||||
return Array.from(acmeDns01ProvidersMap.values())
|
||||
.filter((provider) => {
|
||||
if (filter) {
|
||||
return filter(provider);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}, [keyword]);
|
||||
return true;
|
||||
})
|
||||
.filter((provider) => {
|
||||
if (keyword) {
|
||||
const value = keyword.toLowerCase();
|
||||
return provider.type.toLowerCase().includes(value) || t(provider.name).toLowerCase().includes(value);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}, [filter, keyword]);
|
||||
|
||||
const handleProviderTypeSelect = (value: string) => {
|
||||
onSelect?.(value);
|
||||
|
||||
117
ui/src/components/provider/AccessProviderPicker.tsx
Normal file
117
ui/src/components/provider/AccessProviderPicker.tsx
Normal file
@@ -0,0 +1,117 @@
|
||||
import { memo, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Avatar, Card, Col, Empty, Flex, Input, type InputRef, Row, Tag, Typography } from "antd";
|
||||
|
||||
import Show from "@/components/Show";
|
||||
import { ACCESS_USAGES, type AccessProvider, type AccessUsageType, accessProvidersMap } from "@/domain/provider";
|
||||
|
||||
export type AccessProviderPickerProps = {
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
autoFocus?: boolean;
|
||||
filter?: (record: AccessProvider) => boolean;
|
||||
placeholder?: string;
|
||||
showOptionTags?: boolean | { [key in AccessUsageType]?: boolean };
|
||||
onSelect?: (value: string) => void;
|
||||
};
|
||||
|
||||
const AccessProviderPicker = ({ className, style, autoFocus, filter, placeholder, showOptionTags, onSelect }: AccessProviderPickerProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [keyword, setKeyword] = useState<string>();
|
||||
const keywordInputRef = useRef<InputRef>(null);
|
||||
useEffect(() => {
|
||||
if (autoFocus) {
|
||||
setTimeout(() => keywordInputRef.current?.focus(), 1);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const providers = useMemo(() => {
|
||||
return Array.from(accessProvidersMap.values())
|
||||
.filter((provider) => {
|
||||
if (filter) {
|
||||
return filter(provider);
|
||||
}
|
||||
|
||||
return true;
|
||||
})
|
||||
.filter((provider) => {
|
||||
if (keyword) {
|
||||
const value = keyword.toLowerCase();
|
||||
return provider.type.toLowerCase().includes(value) || t(provider.name).toLowerCase().includes(value);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}, [filter, keyword]);
|
||||
|
||||
const showOptionTagForDNS = useMemo(() => {
|
||||
return typeof showOptionTags === "object" ? !!showOptionTags[ACCESS_USAGES.DNS] : !!showOptionTags;
|
||||
}, [showOptionTags]);
|
||||
const showOptionTagForHosting = useMemo(() => {
|
||||
return typeof showOptionTags === "object" ? !!showOptionTags[ACCESS_USAGES.HOSTING] : !!showOptionTags;
|
||||
}, [showOptionTags]);
|
||||
const showOptionTagForCA = useMemo(() => {
|
||||
return typeof showOptionTags === "object" ? !!showOptionTags[ACCESS_USAGES.CA] : !!showOptionTags;
|
||||
}, [showOptionTags]);
|
||||
const showOptionTagForNotification = useMemo(() => {
|
||||
return typeof showOptionTags === "object" ? !!showOptionTags[ACCESS_USAGES.NOTIFICATION] : !!showOptionTags;
|
||||
}, [showOptionTags]);
|
||||
|
||||
const handleProviderTypeSelect = (value: string) => {
|
||||
onSelect?.(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={className} style={style}>
|
||||
<Input.Search ref={keywordInputRef} placeholder={placeholder ?? t("common.text.search")} onChange={(e) => setKeyword(e.target.value.trim())} />
|
||||
|
||||
<div className="mt-4">
|
||||
<Show when={providers.length > 0} fallback={<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />}>
|
||||
<Row gutter={[16, 16]}>
|
||||
{providers.map((provider, index) => {
|
||||
return (
|
||||
<Col key={index} xs={24} md={12} span={8}>
|
||||
<Card
|
||||
className="h-20 w-full overflow-hidden shadow-sm"
|
||||
styles={{ body: { height: "100%", padding: "0.5rem 1rem" } }}
|
||||
hoverable
|
||||
onClick={() => {
|
||||
handleProviderTypeSelect(provider.type);
|
||||
}}
|
||||
>
|
||||
<Flex className="size-full overflow-hidden" align="center" gap={8}>
|
||||
<Avatar src={provider.icon} size="small" />
|
||||
<div className="flex-1 overflow-hidden">
|
||||
<Typography.Text className="mb-1 line-clamp-1">{t(provider.name)}</Typography.Text>
|
||||
<div className="origin-left scale-[80%]">
|
||||
<Show when={provider.builtin}>
|
||||
<Tag>{t("access.props.provider.builtin")}</Tag>
|
||||
</Show>
|
||||
<Show when={showOptionTagForDNS && provider.usages.includes(ACCESS_USAGES.DNS)}>
|
||||
<Tag color="orange">{t("access.props.provider.usage.dns")}</Tag>
|
||||
</Show>
|
||||
<Show when={showOptionTagForHosting && provider.usages.includes(ACCESS_USAGES.HOSTING)}>
|
||||
<Tag color="geekblue">{t("access.props.provider.usage.hosting")}</Tag>
|
||||
</Show>
|
||||
<Show when={showOptionTagForCA && provider.usages.includes(ACCESS_USAGES.CA)}>
|
||||
<Tag color="magenta">{t("access.props.provider.usage.ca")}</Tag>
|
||||
</Show>
|
||||
<Show when={showOptionTagForNotification && provider.usages.includes(ACCESS_USAGES.NOTIFICATION)}>
|
||||
<Tag color="cyan">{t("access.props.provider.usage.notification")}</Tag>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
</Flex>
|
||||
</Card>
|
||||
</Col>
|
||||
);
|
||||
})}
|
||||
</Row>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(AccessProviderPicker);
|
||||
@@ -54,21 +54,21 @@ const AccessProviderSelect = ({ filter, showOptionTags, ...props }: AccessProvid
|
||||
{t(provider.name)}
|
||||
</Typography.Text>
|
||||
</Space>
|
||||
<div>
|
||||
<div className="origin-right scale-[80%]">
|
||||
<Show when={provider.builtin}>
|
||||
<Tag color="grey">{t("access.props.provider.builtin")}</Tag>
|
||||
<Tag>{t("access.props.provider.builtin")}</Tag>
|
||||
</Show>
|
||||
<Show when={showOptionTagForDNS && provider.usages.includes(ACCESS_USAGES.DNS)}>
|
||||
<Tag color="peru">{t("access.props.provider.usage.dns")}</Tag>
|
||||
<Tag color="orange">{t("access.props.provider.usage.dns")}</Tag>
|
||||
</Show>
|
||||
<Show when={showOptionTagForHosting && provider.usages.includes(ACCESS_USAGES.HOSTING)}>
|
||||
<Tag color="royalblue">{t("access.props.provider.usage.hosting")}</Tag>
|
||||
<Tag color="geekblue">{t("access.props.provider.usage.hosting")}</Tag>
|
||||
</Show>
|
||||
<Show when={showOptionTagForCA && provider.usages.includes(ACCESS_USAGES.CA)}>
|
||||
<Tag color="crimson">{t("access.props.provider.usage.ca")}</Tag>
|
||||
<Tag color="magenta">{t("access.props.provider.usage.ca")}</Tag>
|
||||
</Show>
|
||||
<Show when={showOptionTagForNotification && provider.usages.includes(ACCESS_USAGES.NOTIFICATION)}>
|
||||
<Tag color="mediumaquamarine">{t("access.props.provider.usage.notification")}</Tag>
|
||||
<Tag color="cyan">{t("access.props.provider.usage.notification")}</Tag>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,17 +3,18 @@ import { useTranslation } from "react-i18next";
|
||||
import { Avatar, Card, Col, Empty, Flex, Input, type InputRef, Row, Tabs, Tooltip, Typography } from "antd";
|
||||
|
||||
import Show from "@/components/Show";
|
||||
import { DEPLOYMENT_CATEGORIES, deploymentProvidersMap } from "@/domain/provider";
|
||||
import { DEPLOYMENT_CATEGORIES, type DeploymentProvider, deploymentProvidersMap } from "@/domain/provider";
|
||||
|
||||
export type DeploymentProviderPickerProps = {
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
autoFocus?: boolean;
|
||||
filter?: (record: DeploymentProvider) => boolean;
|
||||
placeholder?: string;
|
||||
onSelect?: (value: string) => void;
|
||||
};
|
||||
|
||||
const DeploymentProviderPicker = ({ className, style, autoFocus, placeholder, onSelect }: DeploymentProviderPickerProps) => {
|
||||
const DeploymentProviderPicker = ({ className, style, autoFocus, filter, placeholder, onSelect }: DeploymentProviderPickerProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [category, setCategory] = useState<string>(DEPLOYMENT_CATEGORIES.ALL);
|
||||
@@ -28,6 +29,13 @@ const DeploymentProviderPicker = ({ className, style, autoFocus, placeholder, on
|
||||
|
||||
const providers = useMemo(() => {
|
||||
return Array.from(deploymentProvidersMap.values())
|
||||
.filter((provider) => {
|
||||
if (filter) {
|
||||
return filter(provider);
|
||||
}
|
||||
|
||||
return true;
|
||||
})
|
||||
.filter((provider) => {
|
||||
if (category && category !== DEPLOYMENT_CATEGORIES.ALL) {
|
||||
return provider.category === category;
|
||||
@@ -43,7 +51,7 @@ const DeploymentProviderPicker = ({ className, style, autoFocus, placeholder, on
|
||||
|
||||
return true;
|
||||
});
|
||||
}, [category, keyword]);
|
||||
}, [filter, category, keyword]);
|
||||
|
||||
const handleProviderTypeSelect = (value: string) => {
|
||||
onSelect?.(value);
|
||||
@@ -66,6 +74,7 @@ const DeploymentProviderPicker = ({ className, style, autoFocus, placeholder, on
|
||||
DEPLOYMENT_CATEGORIES.AV,
|
||||
DEPLOYMENT_CATEGORIES.SERVERLESS,
|
||||
DEPLOYMENT_CATEGORIES.WEBSITE,
|
||||
DEPLOYMENT_CATEGORIES.NAS,
|
||||
DEPLOYMENT_CATEGORIES.OTHER,
|
||||
].map((key) => ({
|
||||
key: key,
|
||||
|
||||
@@ -30,7 +30,7 @@ const WorkflowRunDetailDrawer = ({ data, loading, trigger, ...props }: WorkflowR
|
||||
|
||||
<Drawer
|
||||
afterOpenChange={setOpen}
|
||||
destroyOnClose
|
||||
destroyOnHidden
|
||||
open={open}
|
||||
loading={loading}
|
||||
placement="right"
|
||||
|
||||
@@ -41,6 +41,7 @@ import { useAccessesStore } from "@/stores/access";
|
||||
import { useContactEmailsStore } from "@/stores/contact";
|
||||
import { validDomainName, validIPv4Address, validIPv6Address } from "@/utils/validators";
|
||||
|
||||
import ApplyNodeConfigFormAliyunESAConfig from "./ApplyNodeConfigFormAliyunESAConfig";
|
||||
import ApplyNodeConfigFormAWSRoute53Config from "./ApplyNodeConfigFormAWSRoute53Config";
|
||||
import ApplyNodeConfigFormHuaweiCloudDNSConfig from "./ApplyNodeConfigFormHuaweiCloudDNSConfig";
|
||||
import ApplyNodeConfigFormJDCloudDNSConfig from "./ApplyNodeConfigFormJDCloudDNSConfig";
|
||||
@@ -160,7 +161,7 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
|
||||
const [showProvider, setShowProvider] = useState(false);
|
||||
useEffect(() => {
|
||||
// 通常情况下每个授权信息只对应一个 DNS 提供商,此时无需显示 DNS 提供商字段;
|
||||
// 如果对应多个(如 AWS 的 Route53、Lightsail,腾讯云的 DNS、EdgeOne 等),则显示。
|
||||
// 如果对应多个(如 AWS 的 Route53、Lightsail,阿里云的 DNS、ESA,腾讯云的 DNS、EdgeOne 等),则显示。
|
||||
if (fieldProviderAccessId) {
|
||||
const access = accesses.find((e) => e.id === fieldProviderAccessId);
|
||||
const providers = Array.from(acmeDns01ProvidersMap.values()).filter((e) => e.provider === access?.provider);
|
||||
@@ -196,6 +197,8 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
|
||||
NOTICE: If you add new child component, please keep ASCII order.
|
||||
*/
|
||||
switch (fieldProvider) {
|
||||
case ACME_DNS01_PROVIDERS.ALIYUN_ESA:
|
||||
return <ApplyNodeConfigFormAliyunESAConfig {...nestedFormProps} />;
|
||||
case ACME_DNS01_PROVIDERS.AWS:
|
||||
case ACME_DNS01_PROVIDERS.AWS_ROUTE53:
|
||||
return <ApplyNodeConfigFormAWSRoute53Config {...nestedFormProps} />;
|
||||
@@ -347,7 +350,7 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item className="mb-0">
|
||||
<Form.Item className="mb-0" htmlFor="null">
|
||||
<label className="mb-1 block">
|
||||
<div className="flex w-full items-center justify-between gap-4">
|
||||
<div className="max-w-full grow truncate">
|
||||
@@ -388,6 +391,7 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
|
||||
return !!provider?.usages?.includes(ACCESS_USAGES.DNS);
|
||||
}}
|
||||
placeholder={t("workflow_node.apply.form.provider_access.placeholder")}
|
||||
showSearch
|
||||
onChange={handleProviderAccessSelect}
|
||||
/>
|
||||
</Form.Item>
|
||||
@@ -396,14 +400,14 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
|
||||
|
||||
{nestedFormEl}
|
||||
|
||||
<Divider className="my-1">
|
||||
<Divider size="small">
|
||||
<Typography.Text className="text-xs font-normal" type="secondary">
|
||||
{t("workflow_node.apply.form.certificate_config.label")}
|
||||
</Typography.Text>
|
||||
</Divider>
|
||||
|
||||
<Form className={className} style={style} {...formProps} disabled={disabled} layout="vertical" scrollToFirstError onValuesChange={handleFormChange}>
|
||||
<Form.Item className="mb-0">
|
||||
<Form.Item className="mb-0" htmlFor="null">
|
||||
<label className="mb-1 block">
|
||||
<div className="flex w-full items-center justify-between gap-4">
|
||||
<div className="max-w-full grow truncate">
|
||||
@@ -432,7 +436,7 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item className="mb-0" hidden={!showCAProviderAccess}>
|
||||
<Form.Item className="mb-0" htmlFor="null" hidden={!showCAProviderAccess}>
|
||||
<label className="mb-1 block">
|
||||
<div className="flex w-full items-center justify-between gap-4">
|
||||
<div className="max-w-full grow truncate">
|
||||
@@ -469,6 +473,7 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
|
||||
return !!provider?.usages?.includes(ACCESS_USAGES.CA);
|
||||
}}
|
||||
placeholder={t("workflow_node.apply.form.ca_provider_access.placeholder")}
|
||||
showSearch
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
@@ -484,7 +489,7 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
|
||||
</Form.Item>
|
||||
</Form>
|
||||
|
||||
<Divider className="my-1">
|
||||
<Divider size="small">
|
||||
<Typography.Text className="text-xs font-normal" type="secondary">
|
||||
{t("workflow_node.apply.form.advanced_config.label")}
|
||||
</Typography.Text>
|
||||
@@ -591,7 +596,7 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
|
||||
</Form.Item>
|
||||
</Form>
|
||||
|
||||
<Divider className="my-1">
|
||||
<Divider size="small">
|
||||
<Typography.Text className="text-xs font-normal" type="secondary">
|
||||
{t("workflow_node.apply.form.strategy_config.label")}
|
||||
</Typography.Text>
|
||||
@@ -700,7 +705,7 @@ const DomainsModalInput = memo(({ value, trigger, onChange }: { value?: string;
|
||||
{...formProps}
|
||||
layout="vertical"
|
||||
form={formInst}
|
||||
modalProps={{ destroyOnClose: true }}
|
||||
modalProps={{ destroyOnHidden: true }}
|
||||
title={t("workflow_node.apply.form.domains.multiple_input_modal.title")}
|
||||
trigger={trigger}
|
||||
validateTrigger="onSubmit"
|
||||
@@ -740,7 +745,7 @@ const NameserversModalInput = memo(({ trigger, value, onChange }: { trigger?: Re
|
||||
{...formProps}
|
||||
layout="vertical"
|
||||
form={formInst}
|
||||
modalProps={{ destroyOnClose: true }}
|
||||
modalProps={{ destroyOnHidden: true }}
|
||||
title={t("workflow_node.apply.form.nameservers.multiple_input_modal.title")}
|
||||
trigger={trigger}
|
||||
validateTrigger="onSubmit"
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, type FormInstance, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
type ApplyNodeConfigFormAliyunESAConfigFieldValues = Nullish<{
|
||||
region: string;
|
||||
}>;
|
||||
|
||||
export type ApplyNodeConfigFormAliyunESAConfigProps = {
|
||||
form: FormInstance;
|
||||
formName: string;
|
||||
disabled?: boolean;
|
||||
initialValues?: ApplyNodeConfigFormAliyunESAConfigFieldValues;
|
||||
onValuesChange?: (values: ApplyNodeConfigFormAliyunESAConfigFieldValues) => void;
|
||||
};
|
||||
|
||||
const initFormModel = (): ApplyNodeConfigFormAliyunESAConfigFieldValues => {
|
||||
return {};
|
||||
};
|
||||
|
||||
const ApplyNodeConfigFormAliyunESAConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: ApplyNodeConfigFormAliyunESAConfigProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
region: z
|
||||
.string({ message: t("workflow_node.apply.form.aliyun_esa_region.placeholder") })
|
||||
.nonempty(t("workflow_node.apply.form.aliyun_esa_region.placeholder"))
|
||||
.trim(),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
|
||||
onValuesChange?.(values);
|
||||
};
|
||||
|
||||
return (
|
||||
<Form
|
||||
form={formInst}
|
||||
disabled={disabled}
|
||||
initialValues={initialValues ?? initFormModel()}
|
||||
layout="vertical"
|
||||
name={formName}
|
||||
onValuesChange={handleFormChange}
|
||||
>
|
||||
<Form.Item
|
||||
name="region"
|
||||
label={t("workflow_node.apply.form.aliyun_esa_region.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.apply.form.aliyun_esa_region.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.apply.form.aliyun_esa_region.placeholder")} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default ApplyNodeConfigFormAliyunESAConfig;
|
||||
@@ -1,7 +1,7 @@
|
||||
import { forwardRef, memo, useEffect, useImperativeHandle, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { PlusOutlined as PlusOutlinedIcon, QuestionCircleOutlined as QuestionCircleOutlinedIcon } from "@ant-design/icons";
|
||||
import { Alert, Button, Divider, Flex, Form, type FormInstance, Select, Switch, Tooltip, Typography } from "antd";
|
||||
import { Button, Divider, Flex, Form, type FormInstance, Select, Switch, Tooltip, Typography } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
@@ -24,6 +24,7 @@ import DeployNodeConfigFormAliyunCASDeployConfig from "./DeployNodeConfigFormAli
|
||||
import DeployNodeConfigFormAliyunCDNConfig from "./DeployNodeConfigFormAliyunCDNConfig";
|
||||
import DeployNodeConfigFormAliyunCLBConfig from "./DeployNodeConfigFormAliyunCLBConfig";
|
||||
import DeployNodeConfigFormAliyunDCDNConfig from "./DeployNodeConfigFormAliyunDCDNConfig";
|
||||
import DeployNodeConfigFormAliyunDDoSConfig from "./DeployNodeConfigFormAliyunDDoSConfig";
|
||||
import DeployNodeConfigFormAliyunESAConfig from "./DeployNodeConfigFormAliyunESAConfig";
|
||||
import DeployNodeConfigFormAliyunFCConfig from "./DeployNodeConfigFormAliyunFCConfig";
|
||||
import DeployNodeConfigFormAliyunLiveConfig from "./DeployNodeConfigFormAliyunLiveConfig";
|
||||
@@ -46,6 +47,7 @@ import DeployNodeConfigFormCdnflyConfig from "./DeployNodeConfigFormCdnflyConfig
|
||||
import DeployNodeConfigFormDogeCloudCDNConfig from "./DeployNodeConfigFormDogeCloudCDNConfig";
|
||||
import DeployNodeConfigFormEdgioApplicationsConfig from "./DeployNodeConfigFormEdgioApplicationsConfig";
|
||||
import DeployNodeConfigFormGcoreCDNConfig from "./DeployNodeConfigFormGcoreCDNConfig";
|
||||
import DeployNodeConfigFormGoEdgeConfig from "./DeployNodeConfigFormGoEdgeConfig";
|
||||
import DeployNodeConfigFormHuaweiCloudCDNConfig from "./DeployNodeConfigFormHuaweiCloudCDNConfig";
|
||||
import DeployNodeConfigFormHuaweiCloudELBConfig from "./DeployNodeConfigFormHuaweiCloudELBConfig";
|
||||
import DeployNodeConfigFormHuaweiCloudWAFConfig from "./DeployNodeConfigFormHuaweiCloudWAFConfig";
|
||||
@@ -55,6 +57,7 @@ import DeployNodeConfigFormJDCloudLiveConfig from "./DeployNodeConfigFormJDCloud
|
||||
import DeployNodeConfigFormJDCloudVODConfig from "./DeployNodeConfigFormJDCloudVODConfig";
|
||||
import DeployNodeConfigFormKubernetesSecretConfig from "./DeployNodeConfigFormKubernetesSecretConfig";
|
||||
import DeployNodeConfigFormLocalConfig from "./DeployNodeConfigFormLocalConfig";
|
||||
import DeployNodeConfigFormProxmoxVEConfig from "./DeployNodeConfigFormProxmoxVEConfig";
|
||||
import DeployNodeConfigFormQiniuCDNConfig from "./DeployNodeConfigFormQiniuCDNConfig";
|
||||
import DeployNodeConfigFormQiniuKodoConfig from "./DeployNodeConfigFormQiniuKodoConfig";
|
||||
import DeployNodeConfigFormQiniuPiliConfig from "./DeployNodeConfigFormQiniuPiliConfig";
|
||||
@@ -191,6 +194,8 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
|
||||
return <DeployNodeConfigFormAliyunCDNConfig {...nestedFormProps} />;
|
||||
case DEPLOYMENT_PROVIDERS.ALIYUN_DCDN:
|
||||
return <DeployNodeConfigFormAliyunDCDNConfig {...nestedFormProps} />;
|
||||
case DEPLOYMENT_PROVIDERS.ALIYUN_DDOS:
|
||||
return <DeployNodeConfigFormAliyunDDoSConfig {...nestedFormProps} />;
|
||||
case DEPLOYMENT_PROVIDERS.ALIYUN_ESA:
|
||||
return <DeployNodeConfigFormAliyunESAConfig {...nestedFormProps} />;
|
||||
case DEPLOYMENT_PROVIDERS.ALIYUN_FC:
|
||||
@@ -235,6 +240,8 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
|
||||
return <DeployNodeConfigFormEdgioApplicationsConfig {...nestedFormProps} />;
|
||||
case DEPLOYMENT_PROVIDERS.GCORE_CDN:
|
||||
return <DeployNodeConfigFormGcoreCDNConfig {...nestedFormProps} />;
|
||||
case DEPLOYMENT_PROVIDERS.GOEDGE:
|
||||
return <DeployNodeConfigFormGoEdgeConfig {...nestedFormProps} />;
|
||||
case DEPLOYMENT_PROVIDERS.HUAWEICLOUD_CDN:
|
||||
return <DeployNodeConfigFormHuaweiCloudCDNConfig {...nestedFormProps} />;
|
||||
case DEPLOYMENT_PROVIDERS.HUAWEICLOUD_ELB:
|
||||
@@ -253,6 +260,8 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
|
||||
return <DeployNodeConfigFormKubernetesSecretConfig {...nestedFormProps} />;
|
||||
case DEPLOYMENT_PROVIDERS.LOCAL:
|
||||
return <DeployNodeConfigFormLocalConfig {...nestedFormProps} />;
|
||||
case DEPLOYMENT_PROVIDERS.PROXMOXVE:
|
||||
return <DeployNodeConfigFormProxmoxVEConfig {...nestedFormProps} />;
|
||||
case DEPLOYMENT_PROVIDERS.QINIU_CDN:
|
||||
return <DeployNodeConfigFormQiniuCDNConfig {...nestedFormProps} />;
|
||||
case DEPLOYMENT_PROVIDERS.QINIU_KODO:
|
||||
@@ -382,7 +391,9 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
|
||||
<Form className={className} style={style} {...formProps} disabled={disabled} layout="vertical" scrollToFirstError onValuesChange={handleFormChange}>
|
||||
<Show
|
||||
when={!!fieldProvider}
|
||||
fallback={<DeploymentProviderPicker autoFocus placeholder={t("workflow_node.deploy.search.provider.placeholder")} onSelect={handleProviderPick} />}
|
||||
fallback={
|
||||
<DeploymentProviderPicker autoFocus placeholder={t("workflow_node.deploy.form.provider.search.placeholder")} onSelect={handleProviderPick} />
|
||||
}
|
||||
>
|
||||
<Form.Item name="provider" label={t("workflow_node.deploy.form.provider.label")} rules={[formRule]}>
|
||||
<DeploymentProviderSelect
|
||||
@@ -395,7 +406,7 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item className="mb-0" hidden={!showProviderAccess}>
|
||||
<Form.Item className="mb-0" htmlFor="null" hidden={!showProviderAccess}>
|
||||
<label className="mb-1 block">
|
||||
<div className="flex w-full items-center justify-between gap-4">
|
||||
<div className="max-w-full grow truncate">
|
||||
@@ -437,19 +448,11 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
|
||||
return !!provider?.usages?.includes(ACCESS_USAGES.HOSTING);
|
||||
}}
|
||||
placeholder={t("workflow_node.deploy.form.provider_access.placeholder")}
|
||||
showSearch
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
|
||||
<Show when={fieldProvider === DEPLOYMENT_PROVIDERS.LOCAL}>
|
||||
<Form.Item>
|
||||
<Alert
|
||||
type="info"
|
||||
message={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.provider_access.guide_for_local") }}></span>}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Show>
|
||||
|
||||
<Form.Item
|
||||
name="certificate"
|
||||
label={t("workflow_node.deploy.form.certificate.label")}
|
||||
@@ -475,7 +478,7 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
|
||||
</Form>
|
||||
|
||||
<Show when={!!nestedFormEl}>
|
||||
<Divider className="my-1">
|
||||
<Divider size="small">
|
||||
<Typography.Text className="text-xs font-normal" type="secondary">
|
||||
{t("workflow_node.deploy.form.params_config.label")}
|
||||
</Typography.Text>
|
||||
@@ -485,7 +488,7 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
|
||||
</Show>
|
||||
|
||||
<Show when={!!fieldProvider}>
|
||||
<Divider className="my-1">
|
||||
<Divider size="small">
|
||||
<Typography.Text className="text-xs font-normal" type="secondary">
|
||||
{t("workflow_node.deploy.form.strategy_config.label")}
|
||||
</Typography.Text>
|
||||
|
||||
@@ -186,7 +186,7 @@ const ResourceIdsModalInput = memo(({ value, trigger, onChange }: { value?: stri
|
||||
{...formProps}
|
||||
layout="vertical"
|
||||
form={formInst}
|
||||
modalProps={{ destroyOnClose: true }}
|
||||
modalProps={{ destroyOnHidden: true }}
|
||||
title={t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.multiple_input_modal.title")}
|
||||
trigger={trigger}
|
||||
validateTrigger="onSubmit"
|
||||
@@ -226,7 +226,7 @@ const ContactIdsModalInput = memo(({ value, trigger, onChange }: { value?: strin
|
||||
{...formProps}
|
||||
layout="vertical"
|
||||
form={formInst}
|
||||
modalProps={{ destroyOnClose: true }}
|
||||
modalProps={{ destroyOnHidden: true }}
|
||||
title={t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.multiple_input_modal.title")}
|
||||
trigger={trigger}
|
||||
validateTrigger="onSubmit"
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, type FormInstance, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { validDomainName } from "@/utils/validators";
|
||||
|
||||
type DeployNodeConfigFormAliyunDDoSConfigFieldValues = Nullish<{
|
||||
region: string;
|
||||
domain: string;
|
||||
}>;
|
||||
|
||||
export type DeployNodeConfigFormAliyunDDoSConfigProps = {
|
||||
form: FormInstance;
|
||||
formName: string;
|
||||
disabled?: boolean;
|
||||
initialValues?: DeployNodeConfigFormAliyunDDoSConfigFieldValues;
|
||||
onValuesChange?: (values: DeployNodeConfigFormAliyunDDoSConfigFieldValues) => void;
|
||||
};
|
||||
|
||||
const initFormModel = (): DeployNodeConfigFormAliyunDDoSConfigFieldValues => {
|
||||
return {};
|
||||
};
|
||||
|
||||
const DeployNodeConfigFormAliyunDDoSConfig = ({
|
||||
form: formInst,
|
||||
formName,
|
||||
disabled,
|
||||
initialValues,
|
||||
onValuesChange,
|
||||
}: DeployNodeConfigFormAliyunDDoSConfigProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
region: z
|
||||
.string({ message: t("workflow_node.deploy.form.aliyun_ddos_region.placeholder") })
|
||||
.nonempty(t("workflow_node.deploy.form.aliyun_ddos_region.placeholder"))
|
||||
.trim(),
|
||||
domain: z
|
||||
.string({ message: t("workflow_node.deploy.form.aliyun_ddos_domain.placeholder") })
|
||||
.refine((v) => validDomainName(v, { allowWildcard: true }), t("common.errmsg.domain_invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
|
||||
onValuesChange?.(values);
|
||||
};
|
||||
|
||||
return (
|
||||
<Form
|
||||
form={formInst}
|
||||
disabled={disabled}
|
||||
initialValues={initialValues ?? initFormModel()}
|
||||
layout="vertical"
|
||||
name={formName}
|
||||
onValuesChange={handleFormChange}
|
||||
>
|
||||
<Form.Item
|
||||
name="region"
|
||||
label={t("workflow_node.deploy.form.aliyun_ddos_region.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_ddos_region.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.aliyun_ddos_region.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="domain"
|
||||
label={t("workflow_node.deploy.form.aliyun_ddos_domain.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_ddos_domain.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.aliyun_ddos_domain.placeholder")} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeConfigFormAliyunDDoSConfig;
|
||||
@@ -173,7 +173,7 @@ const SiteNamesModalInput = memo(({ value, trigger, onChange }: { value?: string
|
||||
{...formProps}
|
||||
layout="vertical"
|
||||
form={formInst}
|
||||
modalProps={{ destroyOnClose: true }}
|
||||
modalProps={{ destroyOnHidden: true }}
|
||||
title={t("workflow_node.deploy.form.baotapanel_site_names.multiple_input_modal.title")}
|
||||
trigger={trigger}
|
||||
validateTrigger="onSubmit"
|
||||
|
||||
@@ -5,6 +5,7 @@ import { z } from "zod";
|
||||
|
||||
type DeployNodeConfigFormGcoreCDNConfigFieldValues = Nullish<{
|
||||
resourceId: string | number;
|
||||
certificateId?: string | number;
|
||||
}>;
|
||||
|
||||
export type DeployNodeConfigFormGcoreCDNConfigProps = {
|
||||
@@ -28,6 +29,13 @@ const DeployNodeConfigFormGcoreCDNConfig = ({ form: formInst, formName, disabled
|
||||
resourceId: z.union([z.string(), z.number()]).refine((v) => {
|
||||
return /^\d+$/.test(v + "") && +v > 0;
|
||||
}, t("workflow_node.deploy.form.gcore_cdn_resource_id.placeholder")),
|
||||
certificateId: z
|
||||
.union([z.string(), z.number().int()])
|
||||
.nullish()
|
||||
.refine((v) => {
|
||||
if (!v) return true;
|
||||
return /^\d+$/.test(v + "") && +v > 0;
|
||||
}, t("workflow_node.deploy.form.gcore_cdn_certificate_id.placeholder")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
@@ -52,6 +60,15 @@ const DeployNodeConfigFormGcoreCDNConfig = ({ form: formInst, formName, disabled
|
||||
>
|
||||
<Input type="number" placeholder={t("workflow_node.deploy.form.gcore_cdn_resource_id.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="certificateId"
|
||||
label={t("workflow_node.deploy.form.gcore_cdn_certificate_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.gcore_cdn_certificate_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input type="number" placeholder={t("workflow_node.deploy.form.gcore_cdn_certificate_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, type FormInstance, Input, Select } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import Show from "@/components/Show";
|
||||
|
||||
type DeployNodeConfigFormGoEdgeConfigFieldValues = Nullish<{
|
||||
resourceType: string;
|
||||
certificateId?: string | number;
|
||||
}>;
|
||||
|
||||
export type DeployNodeConfigFormGoEdgeConfigProps = {
|
||||
form: FormInstance;
|
||||
formName: string;
|
||||
disabled?: boolean;
|
||||
initialValues?: DeployNodeConfigFormGoEdgeConfigFieldValues;
|
||||
onValuesChange?: (values: DeployNodeConfigFormGoEdgeConfigFieldValues) => void;
|
||||
};
|
||||
|
||||
const RESOURCE_TYPE_CERTIFICATE = "certificate" as const;
|
||||
|
||||
const initFormModel = (): DeployNodeConfigFormGoEdgeConfigFieldValues => {
|
||||
return {
|
||||
resourceType: RESOURCE_TYPE_CERTIFICATE,
|
||||
certificateId: "",
|
||||
};
|
||||
};
|
||||
|
||||
const DeployNodeConfigFormGoEdgeConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: DeployNodeConfigFormGoEdgeConfigProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
resourceType: z.literal(RESOURCE_TYPE_CERTIFICATE, {
|
||||
message: t("workflow_node.deploy.form.goedge_resource_type.placeholder"),
|
||||
}),
|
||||
certificateId: z
|
||||
.union([z.string(), z.number().int()])
|
||||
.nullish()
|
||||
.refine((v) => {
|
||||
if (fieldResourceType !== RESOURCE_TYPE_CERTIFICATE) return true;
|
||||
return /^\d+$/.test(v + "") && +v! > 0;
|
||||
}, t("workflow_node.deploy.form.goedge_certificate_id.placeholder")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
const fieldResourceType = Form.useWatch("resourceType", formInst);
|
||||
|
||||
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
|
||||
onValuesChange?.(values);
|
||||
};
|
||||
|
||||
return (
|
||||
<Form
|
||||
form={formInst}
|
||||
disabled={disabled}
|
||||
initialValues={initialValues ?? initFormModel()}
|
||||
layout="vertical"
|
||||
name={formName}
|
||||
onValuesChange={handleFormChange}
|
||||
>
|
||||
<Form.Item name="resourceType" label={t("workflow_node.deploy.form.goedge_resource_type.label")} rules={[formRule]}>
|
||||
<Select placeholder={t("workflow_node.deploy.form.goedge_resource_type.placeholder")}>
|
||||
<Select.Option key={RESOURCE_TYPE_CERTIFICATE} value={RESOURCE_TYPE_CERTIFICATE}>
|
||||
{t("workflow_node.deploy.form.goedge_resource_type.option.certificate.label")}
|
||||
</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Show when={fieldResourceType === RESOURCE_TYPE_CERTIFICATE}>
|
||||
<Form.Item name="certificateId" label={t("workflow_node.deploy.form.goedge_certificate_id.label")} rules={[formRule]}>
|
||||
<Input type="number" placeholder={t("workflow_node.deploy.form.goedge_certificate_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeConfigFormGoEdgeConfig;
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { DownOutlined as DownOutlinedIcon } from "@ant-design/icons";
|
||||
import { Button, Dropdown, Form, type FormInstance, Input, Select } from "antd";
|
||||
import { Alert, Button, Dropdown, Form, type FormInstance, Input, Select } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
@@ -45,6 +45,108 @@ const initFormModel = (): DeployNodeConfigFormLocalConfigFieldValues => {
|
||||
};
|
||||
};
|
||||
|
||||
export const initPresetScript = (
|
||||
key: "sh_backup_files" | "ps_backup_files" | "sh_reload_nginx" | "ps_binding_iis" | "ps_binding_netsh" | "ps_binding_rdp",
|
||||
params?: {
|
||||
certPath?: string;
|
||||
keyPath?: string;
|
||||
pfxPassword?: string;
|
||||
jksAlias?: string;
|
||||
jksKeypass?: string;
|
||||
jksStorepass?: string;
|
||||
}
|
||||
) => {
|
||||
switch (key) {
|
||||
case "sh_backup_files":
|
||||
return `# 请将以下路径替换为实际值
|
||||
cp "${params?.certPath || "<your-cert-path>"}" "${params?.certPath || "<your-cert-path>"}.bak" 2>/dev/null || :
|
||||
cp "${params?.keyPath || "<your-key-path>"}" "${params?.keyPath || "<your-key-path>"}.bak" 2>/dev/null || :
|
||||
`.trim();
|
||||
|
||||
case "ps_backup_files":
|
||||
return `# 请将以下路径替换为实际值
|
||||
if (Test-Path -Path "${params?.certPath || "<your-cert-path>"}" -PathType Leaf) {
|
||||
Copy-Item -Path "${params?.certPath || "<your-cert-path>"}" -Destination "${params?.certPath || "<your-cert-path>"}.bak" -Force
|
||||
}
|
||||
if (Test-Path -Path "${params?.keyPath || "<your-key-path>"}" -PathType Leaf) {
|
||||
Copy-Item -Path "${params?.keyPath || "<your-key-path>"}" -Destination "${params?.keyPath || "<your-key-path>"}.bak" -Force
|
||||
}
|
||||
`.trim();
|
||||
|
||||
case "sh_reload_nginx":
|
||||
return `sudo service nginx reload`;
|
||||
|
||||
case "ps_binding_iis":
|
||||
return `# 需要管理员权限
|
||||
# 请将以下变量替换为实际值
|
||||
$pfxPath = "${params?.certPath || "<your-cert-path>"}" # PFX 文件路径
|
||||
$pfxPassword = "${params?.pfxPassword || "<your-pfx-password>"}" # PFX 密码
|
||||
$siteName = "<your-site-name>" # IIS 网站名称
|
||||
$domain = "<your-domain-name>" # 域名
|
||||
$ipaddr = "<your-binding-ip>" # 绑定 IP,“*”表示所有 IP 绑定
|
||||
$port = "<your-binding-port>" # 绑定端口
|
||||
|
||||
|
||||
# 导入证书到本地计算机的个人存储区
|
||||
$cert = Import-PfxCertificate -FilePath "$pfxPath" -CertStoreLocation Cert:\\LocalMachine\\My -Password (ConvertTo-SecureString -String "$pfxPassword" -AsPlainText -Force) -Exportable
|
||||
# 获取 Thumbprint
|
||||
$thumbprint = $cert.Thumbprint
|
||||
# 导入 WebAdministration 模块
|
||||
Import-Module WebAdministration
|
||||
# 检查是否已存在 HTTPS 绑定
|
||||
$existingBinding = Get-WebBinding -Name "$siteName" -Protocol "https" -Port $port -HostHeader "$domain" -ErrorAction SilentlyContinue
|
||||
if (!$existingBinding) {
|
||||
# 添加新的 HTTPS 绑定
|
||||
New-WebBinding -Name "$siteName" -Protocol "https" -Port $port -IPAddress "$ipaddr" -HostHeader "$domain"
|
||||
}
|
||||
# 获取绑定对象
|
||||
$binding = Get-WebBinding -Name "$siteName" -Protocol "https" -Port $port -IPAddress "$ipaddr" -HostHeader "$domain"
|
||||
# 绑定 SSL 证书
|
||||
$binding.AddSslCertificate($thumbprint, "My")
|
||||
# 删除目录下的证书文件
|
||||
Remove-Item -Path "$pfxPath" -Force
|
||||
`.trim();
|
||||
|
||||
case "ps_binding_netsh":
|
||||
return `# 需要管理员权限
|
||||
# 请将以下变量替换为实际值
|
||||
$pfxPath = "${params?.certPath || "<your-cert-path>"}" # PFX 文件路径
|
||||
$pfxPassword = "${params?.pfxPassword || "<your-pfx-password>"}" # PFX 密码
|
||||
$ipaddr = "<your-binding-ip>" # 绑定 IP,“0.0.0.0”表示所有 IP 绑定,可填入域名。
|
||||
$port = "<your-binding-port>" # 绑定端口
|
||||
|
||||
$addr = $ipaddr + ":" + $port
|
||||
|
||||
# 导入证书到本地计算机的个人存储区
|
||||
$cert = Import-PfxCertificate -FilePath "$pfxPath" -CertStoreLocation Cert:\\LocalMachine\\My -Password (ConvertTo-SecureString -String "$pfxPassword" -AsPlainText -Force) -Exportable
|
||||
# 获取 Thumbprint
|
||||
$thumbprint = $cert.Thumbprint
|
||||
# 检测端口是否绑定证书,如绑定则删除绑定
|
||||
$isExist = netsh http show sslcert ipport=$addr
|
||||
if ($isExist -like "*$addr*"){ netsh http delete sslcert ipport=$addr }
|
||||
# 绑定到端口
|
||||
netsh http add sslcert ipport=$addr certhash=$thumbprint
|
||||
# 删除目录下的证书文件
|
||||
Remove-Item -Path "$pfxPath" -Force
|
||||
`.trim();
|
||||
|
||||
case "ps_binding_rdp":
|
||||
return `# 需要管理员权限
|
||||
# 请将以下变量替换为实际值
|
||||
$pfxPath = "${params?.certPath || "<your-cert-path>"}" # PFX 文件路径
|
||||
$pfxPassword = "${params?.pfxPassword || "<your-pfx-password>"}" # PFX 密码
|
||||
|
||||
# 导入证书到本地计算机的个人存储区
|
||||
$cert = Import-PfxCertificate -FilePath "$pfxPath" -CertStoreLocation Cert:\\LocalMachine\\My -Password (ConvertTo-SecureString -String "$pfxPassword" -AsPlainText -Force) -Exportable
|
||||
# 获取 Thumbprint
|
||||
$thumbprint = $cert.Thumbprint
|
||||
# 绑定到 RDP
|
||||
$rdpCertPath = "HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp"
|
||||
Set-ItemProperty -Path $rdpCertPath -Name "SSLCertificateSHA1Hash" -Value "$thumbprint"
|
||||
`.trim();
|
||||
}
|
||||
};
|
||||
|
||||
const DeployNodeConfigFormLocalConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: DeployNodeConfigFormLocalConfigProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -136,16 +238,15 @@ const DeployNodeConfigFormLocalConfig = ({ form: formInst, formName, disabled, i
|
||||
|
||||
const handlePresetPreScriptClick = (key: string) => {
|
||||
switch (key) {
|
||||
case "backup_files":
|
||||
case "sh_backup_files":
|
||||
case "ps_backup_files":
|
||||
{
|
||||
const presetScriptParams = {
|
||||
certPath: formInst.getFieldValue("certPath"),
|
||||
keyPath: formInst.getFieldValue("keyPath"),
|
||||
};
|
||||
formInst.setFieldValue("shellEnv", SHELLENV_SH);
|
||||
formInst.setFieldValue(
|
||||
"preCommand",
|
||||
`# 请将以下路径替换为实际值
|
||||
cp "${formInst.getFieldValue("certPath") || "<your-cert-path>"}" "${formInst.getFieldValue("certPath") || "<your-cert-path>"}.bak" 2>/dev/null || :
|
||||
cp "${formInst.getFieldValue("keyPath") || "<your-key-path>"}" "${formInst.getFieldValue("keyPath") || "<your-key-path>"}.bak" 2>/dev/null || :
|
||||
`.trim()
|
||||
);
|
||||
formInst.setFieldValue("preCommand", initPresetScript(key, presetScriptParams));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -153,97 +254,23 @@ cp "${formInst.getFieldValue("keyPath") || "<your-key-path>"}" "${formInst.getFi
|
||||
|
||||
const handlePresetPostScriptClick = (key: string) => {
|
||||
switch (key) {
|
||||
case "reload_nginx":
|
||||
case "sh_reload_nginx":
|
||||
{
|
||||
formInst.setFieldValue("shellEnv", SHELLENV_SH);
|
||||
formInst.setFieldValue("postCommand", "sudo service nginx reload");
|
||||
formInst.setFieldValue("postCommand", initPresetScript(key));
|
||||
}
|
||||
break;
|
||||
|
||||
case "binding_iis":
|
||||
case "ps_binding_iis":
|
||||
case "ps_binding_netsh":
|
||||
case "ps_binding_rdp":
|
||||
{
|
||||
const presetScriptParams = {
|
||||
certPath: formInst.getFieldValue("certPath"),
|
||||
pfxPassword: formInst.getFieldValue("pfxPassword"),
|
||||
};
|
||||
formInst.setFieldValue("shellEnv", SHELLENV_POWERSHELL);
|
||||
formInst.setFieldValue(
|
||||
"postCommand",
|
||||
`# 请将以下变量替换为实际值
|
||||
$pfxPath = "${formInst.getFieldValue("certPath") || "<your-cert-path>"}" # PFX 文件路径
|
||||
$pfxPassword = "${formInst.getFieldValue("pfxPassword") || "<your-pfx-password>"}" # PFX 密码
|
||||
$siteName = "<your-site-name>" # IIS 网站名称
|
||||
$domain = "<your-domain-name>" # 域名
|
||||
$ipaddr = "<your-binding-ip>" # 绑定 IP,“*”表示所有 IP 绑定
|
||||
$port = "<your-binding-port>" # 绑定端口
|
||||
|
||||
|
||||
# 导入证书到本地计算机的个人存储区
|
||||
$cert = Import-PfxCertificate -FilePath "$pfxPath" -CertStoreLocation Cert:\\LocalMachine\\My -Password (ConvertTo-SecureString -String "$pfxPassword" -AsPlainText -Force) -Exportable
|
||||
# 获取 Thumbprint
|
||||
$thumbprint = $cert.Thumbprint
|
||||
# 导入 WebAdministration 模块
|
||||
Import-Module WebAdministration
|
||||
# 检查是否已存在 HTTPS 绑定
|
||||
$existingBinding = Get-WebBinding -Name "$siteName" -Protocol "https" -Port $port -HostHeader "$domain" -ErrorAction SilentlyContinue
|
||||
if (!$existingBinding) {
|
||||
# 添加新的 HTTPS 绑定
|
||||
New-WebBinding -Name "$siteName" -Protocol "https" -Port $port -IPAddress "$ipaddr" -HostHeader "$domain"
|
||||
}
|
||||
# 获取绑定对象
|
||||
$binding = Get-WebBinding -Name "$siteName" -Protocol "https" -Port $port -IPAddress "$ipaddr" -HostHeader "$domain"
|
||||
# 绑定 SSL 证书
|
||||
$binding.AddSslCertificate($thumbprint, "My")
|
||||
# 删除目录下的证书文件
|
||||
Remove-Item -Path "$pfxPath" -Force
|
||||
`.trim()
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case "binding_netsh":
|
||||
{
|
||||
formInst.setFieldValue("shellEnv", SHELLENV_POWERSHELL);
|
||||
formInst.setFieldValue(
|
||||
"postCommand",
|
||||
`# 请将以下变量替换为实际值
|
||||
$pfxPath = "${formInst.getFieldValue("certPath") || "<your-cert-path>"}" # PFX 文件路径
|
||||
$pfxPassword = "${formInst.getFieldValue("pfxPassword") || "<your-pfx-password>"}" # PFX 密码
|
||||
$ipaddr = "<your-binding-ip>" # 绑定 IP,“0.0.0.0”表示所有 IP 绑定,可填入域名。
|
||||
$port = "<your-binding-port>" # 绑定端口
|
||||
|
||||
$addr = $ipaddr + ":" + $port
|
||||
|
||||
# 导入证书到本地计算机的个人存储区
|
||||
$cert = Import-PfxCertificate -FilePath "$pfxPath" -CertStoreLocation Cert:\\LocalMachine\\My -Password (ConvertTo-SecureString -String "$pfxPassword" -AsPlainText -Force) -Exportable
|
||||
# 获取 Thumbprint
|
||||
$thumbprint = $cert.Thumbprint
|
||||
# 检测端口是否绑定证书,如绑定则删除绑定
|
||||
$isExist = netsh http show sslcert ipport=$addr
|
||||
if ($isExist -like "*$addr*"){ netsh http delete sslcert ipport=$addr }
|
||||
# 绑定到端口
|
||||
netsh http add sslcert ipport=$addr certhash=$thumbprint
|
||||
# 删除目录下的证书文件
|
||||
Remove-Item -Path "$pfxPath" -Force
|
||||
`.trim()
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case "binding_rdp":
|
||||
{
|
||||
formInst.setFieldValue("shellEnv", SHELLENV_POWERSHELL);
|
||||
formInst.setFieldValue(
|
||||
"postCommand",
|
||||
`# 请将以下变量替换为实际值
|
||||
$pfxPath = "${formInst.getFieldValue("certPath") || "<your-cert-path>"}" # PFX 文件路径
|
||||
$pfxPassword = "${formInst.getFieldValue("pfxPassword") || "<your-pfx-password>"}" # PFX 密码
|
||||
|
||||
# 导入证书到本地计算机的个人存储区
|
||||
$cert = Import-PfxCertificate -FilePath "$pfxPath" -CertStoreLocation Cert:\\LocalMachine\\My -Password (ConvertTo-SecureString -String "$pfxPassword" -AsPlainText -Force) -Exportable
|
||||
# 获取 Thumbprint
|
||||
$thumbprint = $cert.Thumbprint
|
||||
# 绑定到 RDP
|
||||
$rdpCertPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp"
|
||||
Set-ItemProperty -Path $rdpCertPath -Name "SSLCertificateSHA1Hash" -Value "$thumbprint"
|
||||
`.trim()
|
||||
);
|
||||
formInst.setFieldValue("postCommand", initPresetScript(key, presetScriptParams));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -262,6 +289,10 @@ Set-ItemProperty -Path $rdpCertPath -Name "SSLCertificateSHA1Hash" -Value "$thum
|
||||
name={formName}
|
||||
onValuesChange={handleFormChange}
|
||||
>
|
||||
<Form.Item>
|
||||
<Alert type="info" message={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.local.guide") }}></span>} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="format" label={t("workflow_node.deploy.form.local_format.label")} rules={[formRule]}>
|
||||
<Select placeholder={t("workflow_node.deploy.form.local_format.placeholder")} onSelect={handleFormatSelect}>
|
||||
<Select.Option key={FORMAT_PEM} value={FORMAT_PEM}>
|
||||
@@ -350,7 +381,7 @@ Set-ItemProperty -Path $rdpCertPath -Name "SSLCertificateSHA1Hash" -Value "$thum
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item className="mb-0">
|
||||
<Form.Item className="mb-0" htmlFor="null">
|
||||
<label className="mb-1 block">
|
||||
<div className="flex w-full items-center justify-between gap-4">
|
||||
<div className="max-w-full grow truncate">
|
||||
@@ -359,13 +390,11 @@ Set-ItemProperty -Path $rdpCertPath -Name "SSLCertificateSHA1Hash" -Value "$thum
|
||||
<div className="text-right">
|
||||
<Dropdown
|
||||
menu={{
|
||||
items: [
|
||||
{
|
||||
key: "backup_files",
|
||||
label: t("workflow_node.deploy.form.local_preset_scripts.option.backup_files.label"),
|
||||
onClick: () => handlePresetPreScriptClick("backup_files"),
|
||||
},
|
||||
],
|
||||
items: ["sh_backup_files", "ps_backup_files"].map((key) => ({
|
||||
key,
|
||||
label: t(`workflow_node.deploy.form.local_preset_scripts.option.${key}.label`),
|
||||
onClick: () => handlePresetPreScriptClick(key),
|
||||
})),
|
||||
}}
|
||||
trigger={["click"]}
|
||||
>
|
||||
@@ -382,7 +411,7 @@ Set-ItemProperty -Path $rdpCertPath -Name "SSLCertificateSHA1Hash" -Value "$thum
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item className="mb-0">
|
||||
<Form.Item className="mb-0" htmlFor="null">
|
||||
<label className="mb-1 block">
|
||||
<div className="flex w-full items-center justify-between gap-4">
|
||||
<div className="max-w-full grow truncate">
|
||||
@@ -391,28 +420,11 @@ Set-ItemProperty -Path $rdpCertPath -Name "SSLCertificateSHA1Hash" -Value "$thum
|
||||
<div className="text-right">
|
||||
<Dropdown
|
||||
menu={{
|
||||
items: [
|
||||
{
|
||||
key: "reload_nginx",
|
||||
label: t("workflow_node.deploy.form.local_preset_scripts.option.reload_nginx.label"),
|
||||
onClick: () => handlePresetPostScriptClick("reload_nginx"),
|
||||
},
|
||||
{
|
||||
key: "binding_iis",
|
||||
label: t("workflow_node.deploy.form.local_preset_scripts.option.binding_iis.label"),
|
||||
onClick: () => handlePresetPostScriptClick("binding_iis"),
|
||||
},
|
||||
{
|
||||
key: "binding_netsh",
|
||||
label: t("workflow_node.deploy.form.local_preset_scripts.option.binding_netsh.label"),
|
||||
onClick: () => handlePresetPostScriptClick("binding_netsh"),
|
||||
},
|
||||
{
|
||||
key: "binding_rdp",
|
||||
label: t("workflow_node.deploy.form.local_preset_scripts.option.binding_rdp.label"),
|
||||
onClick: () => handlePresetPostScriptClick("binding_rdp"),
|
||||
},
|
||||
],
|
||||
items: ["sh_reload_nginx", "ps_binding_iis", "ps_binding_netsh", "ps_binding_rdp"].map((key) => ({
|
||||
key,
|
||||
label: t(`workflow_node.deploy.form.local_preset_scripts.option.${key}.label`),
|
||||
onClick: () => handlePresetPostScriptClick(key),
|
||||
})),
|
||||
}}
|
||||
trigger={["click"]}
|
||||
>
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, type FormInstance, Input, Switch } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
type DeployNodeConfigFormProxmoxVEConfigFieldValues = Nullish<{
|
||||
nodeName: string;
|
||||
autoRestart?: boolean;
|
||||
}>;
|
||||
|
||||
export type DeployNodeConfigFormProxmoxVEConfigProps = {
|
||||
form: FormInstance;
|
||||
formName: string;
|
||||
disabled?: boolean;
|
||||
initialValues?: DeployNodeConfigFormProxmoxVEConfigFieldValues;
|
||||
onValuesChange?: (values: DeployNodeConfigFormProxmoxVEConfigFieldValues) => void;
|
||||
};
|
||||
|
||||
const initFormModel = (): DeployNodeConfigFormProxmoxVEConfigFieldValues => {
|
||||
return {
|
||||
autoRestart: true,
|
||||
};
|
||||
};
|
||||
|
||||
const DeployNodeConfigFormProxmoxVEConfig = ({
|
||||
form: formInst,
|
||||
formName,
|
||||
disabled,
|
||||
initialValues,
|
||||
onValuesChange,
|
||||
}: DeployNodeConfigFormProxmoxVEConfigProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
nodeName: z
|
||||
.string({ message: t("workflow_node.deploy.form.proxmoxve_node_name.placeholder") })
|
||||
.nonempty(t("workflow_node.deploy.form.proxmoxve_node_name.placeholder")),
|
||||
autoRestart: z.boolean().nullish(),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
|
||||
onValuesChange?.(values);
|
||||
};
|
||||
|
||||
return (
|
||||
<Form
|
||||
form={formInst}
|
||||
disabled={disabled}
|
||||
initialValues={initialValues ?? initFormModel()}
|
||||
layout="vertical"
|
||||
name={formName}
|
||||
onValuesChange={handleFormChange}
|
||||
>
|
||||
<Form.Item name="nodeName" label={t("workflow_node.deploy.form.proxmoxve_node_name.label")} rules={[formRule]}>
|
||||
<Input placeholder={t("workflow_node.deploy.form.proxmoxve_node_name.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="autoRestart" label={t("workflow_node.deploy.form.proxmoxve_auto_restart.label")} rules={[formRule]}>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeConfigFormProxmoxVEConfig;
|
||||
@@ -7,6 +7,8 @@ import { z } from "zod";
|
||||
import Show from "@/components/Show";
|
||||
import { CERTIFICATE_FORMATS } from "@/domain/certificate";
|
||||
|
||||
import { initPresetScript } from "./DeployNodeConfigFormLocalConfig";
|
||||
|
||||
type DeployNodeConfigFormSSHConfigFieldValues = Nullish<{
|
||||
format: string;
|
||||
certPath: string;
|
||||
@@ -129,15 +131,14 @@ const DeployNodeConfigFormSSHConfig = ({ form: formInst, formName, disabled, ini
|
||||
|
||||
const handlePresetPreScriptClick = (key: string) => {
|
||||
switch (key) {
|
||||
case "backup_files":
|
||||
case "sh_backup_files":
|
||||
case "ps_backup_files":
|
||||
{
|
||||
formInst.setFieldValue(
|
||||
"preCommand",
|
||||
`# 请将以下路径替换为实际值
|
||||
cp "${formInst.getFieldValue("certPath") || "<your-cert-path>"}" "${formInst.getFieldValue("certPath") || "<your-cert-path>"}.bak" 2>/dev/null || :
|
||||
cp "${formInst.getFieldValue("keyPath") || "<your-key-path>"}" "${formInst.getFieldValue("keyPath") || "<your-key-path>"}.bak" 2>/dev/null || :
|
||||
`.trim()
|
||||
);
|
||||
const presetScriptParams = {
|
||||
certPath: formInst.getFieldValue("certPath"),
|
||||
keyPath: formInst.getFieldValue("keyPath"),
|
||||
};
|
||||
formInst.setFieldValue("preCommand", initPresetScript(key, presetScriptParams));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -145,9 +146,16 @@ cp "${formInst.getFieldValue("keyPath") || "<your-key-path>"}" "${formInst.getFi
|
||||
|
||||
const handlePresetPostScriptClick = (key: string) => {
|
||||
switch (key) {
|
||||
case "reload_nginx":
|
||||
case "sh_reload_nginx":
|
||||
case "ps_binding_iis":
|
||||
case "ps_binding_netsh":
|
||||
case "ps_binding_rdp":
|
||||
{
|
||||
formInst.setFieldValue("postCommand", "sudo service nginx reload");
|
||||
const presetScriptParams = {
|
||||
certPath: formInst.getFieldValue("certPath"),
|
||||
pfxPassword: formInst.getFieldValue("pfxPassword"),
|
||||
};
|
||||
formInst.setFieldValue("postCommand", initPresetScript(key, presetScriptParams));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -244,7 +252,7 @@ cp "${formInst.getFieldValue("keyPath") || "<your-key-path>"}" "${formInst.getFi
|
||||
<Select options={[{ value: t("workflow_node.deploy.form.ssh_shell_env.value") }]} value={t("workflow_node.deploy.form.ssh_shell_env.value")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item className="mb-0">
|
||||
<Form.Item className="mb-0" htmlFor="null">
|
||||
<label className="mb-1 block">
|
||||
<div className="flex w-full items-center justify-between gap-4">
|
||||
<div className="max-w-full grow truncate">
|
||||
@@ -253,13 +261,11 @@ cp "${formInst.getFieldValue("keyPath") || "<your-key-path>"}" "${formInst.getFi
|
||||
<div className="text-right">
|
||||
<Dropdown
|
||||
menu={{
|
||||
items: [
|
||||
{
|
||||
key: "backup_files",
|
||||
label: t("workflow_node.deploy.form.ssh_preset_scripts.option.backup_files.label"),
|
||||
onClick: () => handlePresetPreScriptClick("backup_files"),
|
||||
},
|
||||
],
|
||||
items: ["sh_backup_files", "ps_backup_files"].map((key) => ({
|
||||
key,
|
||||
label: t(`workflow_node.deploy.form.ssh_preset_scripts.option.${key}.label`),
|
||||
onClick: () => handlePresetPreScriptClick(key),
|
||||
})),
|
||||
}}
|
||||
trigger={["click"]}
|
||||
>
|
||||
@@ -276,7 +282,7 @@ cp "${formInst.getFieldValue("keyPath") || "<your-key-path>"}" "${formInst.getFi
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item className="mb-0">
|
||||
<Form.Item className="mb-0" htmlFor="null">
|
||||
<label className="mb-1 block">
|
||||
<div className="flex w-full items-center justify-between gap-4">
|
||||
<div className="max-w-full grow truncate">
|
||||
@@ -285,13 +291,11 @@ cp "${formInst.getFieldValue("keyPath") || "<your-key-path>"}" "${formInst.getFi
|
||||
<div className="text-right">
|
||||
<Dropdown
|
||||
menu={{
|
||||
items: [
|
||||
{
|
||||
key: "reload_nginx",
|
||||
label: t("workflow_node.deploy.form.ssh_preset_scripts.option.reload_nginx.label"),
|
||||
onClick: () => handlePresetPostScriptClick("reload_nginx"),
|
||||
},
|
||||
],
|
||||
items: ["sh_reload_nginx", "ps_binding_iis", "ps_binding_netsh", "ps_binding_rdp"].map((key) => ({
|
||||
key,
|
||||
label: t(`workflow_node.deploy.form.ssh_preset_scripts.option.${key}.label`),
|
||||
onClick: () => handlePresetPostScriptClick(key),
|
||||
})),
|
||||
}}
|
||||
trigger={["click"]}
|
||||
>
|
||||
|
||||
@@ -160,7 +160,7 @@ const ResourceIdsModalInput = memo(({ value, trigger, onChange }: { value?: stri
|
||||
{...formProps}
|
||||
layout="vertical"
|
||||
form={formInst}
|
||||
modalProps={{ destroyOnClose: true }}
|
||||
modalProps={{ destroyOnHidden: true }}
|
||||
title={t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.title")}
|
||||
trigger={trigger}
|
||||
validateTrigger="onSubmit"
|
||||
|
||||
@@ -180,7 +180,7 @@ const NotifyNodeConfigForm = forwardRef<NotifyNodeConfigFormInstance, NotifyNode
|
||||
<Input.TextArea autoSize={{ minRows: 3, maxRows: 5 }} placeholder={t("workflow_node.notify.form.message.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item className="mb-0">
|
||||
<Form.Item className="mb-0" htmlFor="null">
|
||||
<label className="mb-1 block">
|
||||
<div className="flex w-full items-center justify-between gap-4">
|
||||
<div className="max-w-full grow truncate line-through">{t("workflow_node.notify.form.channel.label")}</div>
|
||||
@@ -224,7 +224,7 @@ const NotifyNodeConfigForm = forwardRef<NotifyNodeConfigFormInstance, NotifyNode
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item className="mb-0">
|
||||
<Form.Item className="mb-0" htmlFor="null">
|
||||
<label className="mb-1 block">
|
||||
<div className="flex w-full items-center justify-between gap-4">
|
||||
<div className="max-w-full grow truncate">
|
||||
@@ -260,13 +260,14 @@ const NotifyNodeConfigForm = forwardRef<NotifyNodeConfigFormInstance, NotifyNode
|
||||
return !!provider?.usages?.includes(ACCESS_USAGES.NOTIFICATION);
|
||||
}}
|
||||
placeholder={t("workflow_node.notify.form.provider_access.placeholder")}
|
||||
showSearch
|
||||
onChange={handleProviderAccessSelect}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
|
||||
<Show when={!!nestedFormEl}>
|
||||
<Divider className="my-1">
|
||||
<Divider size="small">
|
||||
<Typography.Text className="text-xs font-normal" type="secondary">
|
||||
{t("workflow_node.notify.form.params_config.label")}
|
||||
</Typography.Text>
|
||||
|
||||
@@ -285,7 +285,7 @@ const SharedNodeConfigDrawer = ({
|
||||
<Drawer
|
||||
afterOpenChange={setOpen}
|
||||
closable={!pending}
|
||||
destroyOnClose
|
||||
destroyOnHidden
|
||||
extra={
|
||||
<SharedNodeMenu
|
||||
node={node}
|
||||
|
||||
@@ -31,6 +31,7 @@ export interface AccessModel extends BaseModel {
|
||||
| AccessConfigForGcore
|
||||
| AccessConfigForGname
|
||||
| AccessConfigForGoDaddy
|
||||
| AccessConfigForGoEdge
|
||||
| AccessConfigForGoogleTrustServices
|
||||
| AccessConfigForHuaweiCloud
|
||||
| AccessConfigForJDCloud
|
||||
@@ -42,6 +43,7 @@ export interface AccessModel extends BaseModel {
|
||||
| AccessConfigForNameSilo
|
||||
| AccessConfigForPorkbun
|
||||
| AccessConfigForPowerDNS
|
||||
| AccessConfigForProxmoxVE
|
||||
| AccessConfigForQiniu
|
||||
| AccessConfigForRainYun
|
||||
| AccessConfigForSafeLine
|
||||
@@ -125,6 +127,7 @@ export type AccessConfigForCdnfly = {
|
||||
apiUrl: string;
|
||||
apiKey: string;
|
||||
apiSecret: string;
|
||||
allowInsecureConnections?: boolean;
|
||||
};
|
||||
|
||||
export type AccessConfigForCloudflare = {
|
||||
@@ -194,6 +197,13 @@ export type AccessConfigForGoDaddy = {
|
||||
apiSecret: string;
|
||||
};
|
||||
|
||||
export type AccessConfigForGoEdge = {
|
||||
apiUrl: string;
|
||||
accessKeyId: string;
|
||||
accessKey: string;
|
||||
allowInsecureConnections?: boolean;
|
||||
};
|
||||
|
||||
export type AccessConfigForGoogleTrustServices = {
|
||||
eabKid: string;
|
||||
eabHmacKey: string;
|
||||
@@ -250,6 +260,14 @@ export type AccessConfigForPorkbun = {
|
||||
export type AccessConfigForPowerDNS = {
|
||||
apiUrl: string;
|
||||
apiKey: string;
|
||||
allowInsecureConnections?: boolean;
|
||||
};
|
||||
|
||||
export type AccessConfigForProxmoxVE = {
|
||||
apiUrl: string;
|
||||
apiToken: string;
|
||||
apiTokenSecret?: string;
|
||||
allowInsecureConnections?: boolean;
|
||||
};
|
||||
|
||||
export type AccessConfigForQiniu = {
|
||||
|
||||
@@ -30,6 +30,7 @@ export const ACCESS_PROVIDERS = Object.freeze({
|
||||
GCORE: "gcore",
|
||||
GNAME: "gname",
|
||||
GODADDY: "godaddy",
|
||||
GOEDGE: "goedge",
|
||||
GOOGLETRUSTSERVICES: "googletrustservices",
|
||||
HUAWEICLOUD: "huaweicloud",
|
||||
JDCLOUD: "jdcloud",
|
||||
@@ -45,6 +46,7 @@ export const ACCESS_PROVIDERS = Object.freeze({
|
||||
NS1: "ns1",
|
||||
PORKBUN: "porkbun",
|
||||
POWERDNS: "powerdns",
|
||||
PROXMOXVE: "proxmoxve",
|
||||
QINIU: "qiniu",
|
||||
RAINYUN: "rainyun",
|
||||
SAFELINE: "safeline",
|
||||
@@ -118,6 +120,8 @@ export const accessProvidersMap: Map<AccessProvider["type"] | string, AccessProv
|
||||
[ACCESS_PROVIDERS.CACHEFLY, "provider.cachefly", "/imgs/providers/cachefly.png", [ACCESS_USAGES.HOSTING]],
|
||||
[ACCESS_PROVIDERS.CDNFLY, "provider.cdnfly", "/imgs/providers/cdnfly.png", [ACCESS_USAGES.HOSTING]],
|
||||
[ACCESS_PROVIDERS.EDGIO, "provider.edgio", "/imgs/providers/edgio.svg", [ACCESS_USAGES.HOSTING]],
|
||||
[ACCESS_PROVIDERS.GOEDGE, "provider.goedge", "/imgs/providers/goedge.png", [ACCESS_USAGES.HOSTING]],
|
||||
[ACCESS_PROVIDERS.PROXMOXVE, "provider.proxmoxve", "/imgs/providers/proxmoxve.svg", [ACCESS_USAGES.HOSTING]],
|
||||
|
||||
[ACCESS_PROVIDERS.CLOUDFLARE, "provider.cloudflare", "/imgs/providers/cloudflare.svg", [ACCESS_USAGES.DNS]],
|
||||
[ACCESS_PROVIDERS.CLOUDNS, "provider.cloudns", "/imgs/providers/cloudns.png", [ACCESS_USAGES.DNS]],
|
||||
@@ -221,6 +225,7 @@ export const ACME_DNS01_PROVIDERS = Object.freeze({
|
||||
ACMEHTTPREQ: `${ACCESS_PROVIDERS.ACMEHTTPREQ}`,
|
||||
ALIYUN: `${ACCESS_PROVIDERS.ALIYUN}`, // 兼容旧值,等同于 `ALIYUN_DNS`
|
||||
ALIYUN_DNS: `${ACCESS_PROVIDERS.ALIYUN}-dns`,
|
||||
ALIYUN_ESA: `${ACCESS_PROVIDERS.ALIYUN}-esa`,
|
||||
AWS: `${ACCESS_PROVIDERS.AWS}`, // 兼容旧值,等同于 `AWS_ROUTE53`
|
||||
AWS_ROUTE53: `${ACCESS_PROVIDERS.AWS}-route53`,
|
||||
AZURE: `${ACCESS_PROVIDERS.AZURE}`, // 兼容旧值,等同于 `AZURE_DNS`
|
||||
@@ -273,6 +278,7 @@ export const acmeDns01ProvidersMap: Map<ACMEDns01Provider["type"] | string, ACME
|
||||
*/
|
||||
[
|
||||
[ACME_DNS01_PROVIDERS.ALIYUN_DNS, "provider.aliyun.dns"],
|
||||
[ACME_DNS01_PROVIDERS.ALIYUN_ESA, "provider.aliyun.esa"],
|
||||
[ACME_DNS01_PROVIDERS.TENCENTCLOUD_DNS, "provider.tencentcloud.dns"],
|
||||
[ACME_DNS01_PROVIDERS.TENCENTCLOUD_EO, "provider.tencentcloud.eo"],
|
||||
[ACME_DNS01_PROVIDERS.BAIDUCLOUD_DNS, "provider.baiducloud.dns"],
|
||||
@@ -328,6 +334,7 @@ export const DEPLOYMENT_PROVIDERS = Object.freeze({
|
||||
ALIYUN_CDN: `${ACCESS_PROVIDERS.ALIYUN}-cdn`,
|
||||
ALIYUN_CLB: `${ACCESS_PROVIDERS.ALIYUN}-clb`,
|
||||
ALIYUN_DCDN: `${ACCESS_PROVIDERS.ALIYUN}-dcdn`,
|
||||
ALIYUN_DDOS: `${ACCESS_PROVIDERS.ALIYUN}-ddospro`,
|
||||
ALIYUN_ESA: `${ACCESS_PROVIDERS.ALIYUN}-esa`,
|
||||
ALIYUN_FC: `${ACCESS_PROVIDERS.ALIYUN}-fc`,
|
||||
ALIYUN_LIVE: `${ACCESS_PROVIDERS.ALIYUN}-live`,
|
||||
@@ -352,6 +359,7 @@ export const DEPLOYMENT_PROVIDERS = Object.freeze({
|
||||
DOGECLOUD_CDN: `${ACCESS_PROVIDERS.DOGECLOUD}-cdn`,
|
||||
EDGIO_APPLICATIONS: `${ACCESS_PROVIDERS.EDGIO}-applications`,
|
||||
GCORE_CDN: `${ACCESS_PROVIDERS.GCORE}-cdn`,
|
||||
GOEDGE: `${ACCESS_PROVIDERS.GOEDGE}`,
|
||||
HUAWEICLOUD_CDN: `${ACCESS_PROVIDERS.HUAWEICLOUD}-cdn`,
|
||||
HUAWEICLOUD_ELB: `${ACCESS_PROVIDERS.HUAWEICLOUD}-elb`,
|
||||
HUAWEICLOUD_SCM: `${ACCESS_PROVIDERS.HUAWEICLOUD}-scm`,
|
||||
@@ -362,6 +370,7 @@ export const DEPLOYMENT_PROVIDERS = Object.freeze({
|
||||
JDCLOUD_VOD: `${ACCESS_PROVIDERS.JDCLOUD}-vod`,
|
||||
KUBERNETES_SECRET: `${ACCESS_PROVIDERS.KUBERNETES}-secret`,
|
||||
LOCAL: `${ACCESS_PROVIDERS.LOCAL}`,
|
||||
PROXMOXVE: `${ACCESS_PROVIDERS.PROXMOXVE}`,
|
||||
QINIU_CDN: `${ACCESS_PROVIDERS.QINIU}-cdn`,
|
||||
QINIU_KODO: `${ACCESS_PROVIDERS.QINIU}-kodo`,
|
||||
QINIU_PILI: `${ACCESS_PROVIDERS.QINIU}-pili`,
|
||||
@@ -406,6 +415,7 @@ export const DEPLOYMENT_CATEGORIES = Object.freeze({
|
||||
AV: "av",
|
||||
SERVERLESS: "serverless",
|
||||
WEBSITE: "website",
|
||||
NAS: "nas",
|
||||
OTHER: "other",
|
||||
} as const);
|
||||
|
||||
@@ -438,6 +448,7 @@ export const deploymentProvidersMap: Map<DeploymentProvider["type"] | string, De
|
||||
[DEPLOYMENT_PROVIDERS.ALIYUN_ALB, "provider.aliyun.alb", DEPLOYMENT_CATEGORIES.LOADBALANCE],
|
||||
[DEPLOYMENT_PROVIDERS.ALIYUN_NLB, "provider.aliyun.nlb", DEPLOYMENT_CATEGORIES.LOADBALANCE],
|
||||
[DEPLOYMENT_PROVIDERS.ALIYUN_WAF, "provider.aliyun.waf", DEPLOYMENT_CATEGORIES.FIREWALL],
|
||||
[DEPLOYMENT_PROVIDERS.ALIYUN_DDOS, "provider.aliyun.ddos", DEPLOYMENT_CATEGORIES.FIREWALL],
|
||||
[DEPLOYMENT_PROVIDERS.ALIYUN_LIVE, "provider.aliyun.live", DEPLOYMENT_CATEGORIES.AV],
|
||||
[DEPLOYMENT_PROVIDERS.ALIYUN_VOD, "provider.aliyun.vod", DEPLOYMENT_CATEGORIES.AV],
|
||||
[DEPLOYMENT_PROVIDERS.ALIYUN_FC, "provider.aliyun.fc", DEPLOYMENT_CATEGORIES.SERVERLESS],
|
||||
@@ -495,11 +506,13 @@ export const deploymentProvidersMap: Map<DeploymentProvider["type"] | string, De
|
||||
[DEPLOYMENT_PROVIDERS.CDNFLY, "provider.cdnfly", DEPLOYMENT_CATEGORIES.CDN],
|
||||
[DEPLOYMENT_PROVIDERS.EDGIO_APPLICATIONS, "provider.edgio.applications", DEPLOYMENT_CATEGORIES.WEBSITE],
|
||||
[DEPLOYMENT_PROVIDERS.GCORE_CDN, "provider.gcore.cdn", DEPLOYMENT_CATEGORIES.CDN],
|
||||
[DEPLOYMENT_PROVIDERS.GOEDGE, "provider.goedge", DEPLOYMENT_CATEGORIES.CDN],
|
||||
[DEPLOYMENT_PROVIDERS["1PANEL_SITE"], "provider.1panel.site", DEPLOYMENT_CATEGORIES.WEBSITE],
|
||||
[DEPLOYMENT_PROVIDERS["1PANEL_CONSOLE"], "provider.1panel.console", DEPLOYMENT_CATEGORIES.OTHER],
|
||||
[DEPLOYMENT_PROVIDERS.BAOTAPANEL_SITE, "provider.baotapanel.site", DEPLOYMENT_CATEGORIES.WEBSITE],
|
||||
[DEPLOYMENT_PROVIDERS.BAOTAPANEL_CONSOLE, "provider.baotapanel.console", DEPLOYMENT_CATEGORIES.OTHER],
|
||||
[DEPLOYMENT_PROVIDERS.SAFELINE, "provider.safeline", DEPLOYMENT_CATEGORIES.FIREWALL],
|
||||
[DEPLOYMENT_PROVIDERS.PROXMOXVE, "provider.proxmoxve", DEPLOYMENT_CATEGORIES.NAS],
|
||||
].map(([type, name, category, builtin]) => [
|
||||
type,
|
||||
{
|
||||
|
||||
@@ -1 +1 @@
|
||||
export const version = "v0.3.10";
|
||||
export const version = "v0.3.11";
|
||||
|
||||
@@ -29,18 +29,17 @@
|
||||
"access.form.provider.label": "Provider",
|
||||
"access.form.provider.placeholder": "Please select a provider",
|
||||
"access.form.provider.tooltip": "DNS provider: The provider that hosts your domain names and manages your DNS records.<br>Hosting provider: The provider that hosts your servers or cloud services for deploying certificates.<br><br><i>Cannot be edited after saving.</i>",
|
||||
"access.form.provider.search.placeholder": "Search provider ...",
|
||||
"access.form.certificate_authority.label": "Certificate authority",
|
||||
"access.form.certificate_authority.placeholder": "Please select a certificate authority",
|
||||
"access.form.notification_channel.label": "Notification channel",
|
||||
"access.form.notification_channel.placeholder": "Please select a notification channel",
|
||||
"access.form.1panel_api_url.label": "1Panel URL",
|
||||
"access.form.1panel_api_url.placeholder": "Please enter 1Panel URL",
|
||||
"access.form.1panel_api_url.tooltip": "For more information, see <a href=\"https://docs.1panel.pro/dev_manual/api_manual/\" target=\"_blank\">https://docs.1panel.pro/dev_manual/api_manual/</a>",
|
||||
"access.form.1panel_api_key.label": "1Panel API key",
|
||||
"access.form.1panel_api_key.placeholder": "Please enter 1Panel API key",
|
||||
"access.form.1panel_api_key.tooltip": "For more information, see <a href=\"https://docs.1panel.pro/dev_manual/api_manual/\" target=\"_blank\">https://docs.1panel.pro/dev_manual/api_manual/</a>",
|
||||
"access.form.1panel_allow_insecure_conns.label": "Insecure SSL/TLS connections",
|
||||
"access.form.1panel_allow_insecure_conns.tooltip": "Allowing insecure connections may lead to data leak or tampering. Use this option only when under trusted networks.",
|
||||
"access.form.1panel_allow_insecure_conns.switch.on": "Allow",
|
||||
"access.form.1panel_allow_insecure_conns.switch.off": "Disallow",
|
||||
"access.form.acmehttpreq_endpoint.label": "Endpoint",
|
||||
@@ -98,12 +97,10 @@
|
||||
"access.form.baishan_api_token.placeholder": "Please enter Baishan Cloud API token",
|
||||
"access.form.baotapanel_api_url.label": "aaPanel URL",
|
||||
"access.form.baotapanel_api_url.placeholder": "Please enter aaPanel URL",
|
||||
"access.form.baotapanel_api_url.tooltip": "For more information, see <a href=\"https://www.bt.cn/bbs/thread-20376-1-1.html\" target=\"_blank\">https://www.bt.cn/bbs/thread-20376-1-1.html</a>",
|
||||
"access.form.baotapanel_api_key.label": "aaPanel API key",
|
||||
"access.form.baotapanel_api_key.placeholder": "Please enter aaPanel API key",
|
||||
"access.form.baotapanel_api_key.tooltip": "For more information, see <a href=\"https://www.bt.cn/bbs/thread-20376-1-1.html\" target=\"_blank\">https://www.bt.cn/bbs/thread-20376-1-1.html</a>",
|
||||
"access.form.baotapanel_allow_insecure_conns.label": "Insecure SSL/TLS connections",
|
||||
"access.form.baotapanel_allow_insecure_conns.tooltip": "Allowing insecure connections may lead to data leak or tampering. Use this option only when under trusted networks.",
|
||||
"access.form.baotapanel_allow_insecure_conns.switch.on": "Allow",
|
||||
"access.form.baotapanel_allow_insecure_conns.switch.off": "Disallow",
|
||||
"access.form.byteplus_access_key.label": "BytePlus AccessKey",
|
||||
@@ -117,13 +114,15 @@
|
||||
"access.form.cachefly_api_token.tooltip": "For more information, see <a href=\"https://kb.cachefly.com/kb/guide/en/generating-tokens-and-keys-Oll9Irt5TI/Steps/2460228\" target=\"_blank\">https://kb.cachefly.com/kb/guide/en/generating-tokens-and-keys-Oll9Irt5TI/Steps/2460228</a>",
|
||||
"access.form.cdnfly_api_url.label": "Cdnfly API URL",
|
||||
"access.form.cdnfly_api_url.placeholder": "Please enter Cdnfly API URL",
|
||||
"access.form.cdnfly_api_url.tooltip": "For more information, see <a href=\"https://doc.cdnfly.cn/anzhuangshuoming.html\" target=\"_blank\">https://doc.cdnfly.cn/anzhuangshuoming.html</a>",
|
||||
"access.form.cdnfly_api_key.label": "Cdnfly user API key",
|
||||
"access.form.cdnfly_api_key.placeholder": "Please enter Cdnfly user API key",
|
||||
"access.form.cdnfly_api_key.tooltip": "For more information, see <a href=\"https://doc.cdnfly.cn/shiyongjieshao.html\" target=\"_blank\">https://doc.cdnfly.cn/shiyongjieshao.html</a>",
|
||||
"access.form.cdnfly_api_secret.label": "Cdnfly user API secret",
|
||||
"access.form.cdnfly_api_secret.placeholder": "Please enter Cdnfly user API secret",
|
||||
"access.form.cdnfly_api_secret.tooltip": "For more information, see <a href=\"https://doc.cdnfly.cn/shiyongjieshao.html\" target=\"_blank\">https://doc.cdnfly.cn/shiyongjieshao.html</a>",
|
||||
"access.form.cdnfly_allow_insecure_conns.label": "Insecure SSL/TLS connections",
|
||||
"access.form.cdnfly_allow_insecure_conns.switch.on": "Allow",
|
||||
"access.form.cdnfly_allow_insecure_conns.switch.off": "Disallow",
|
||||
"access.form.cloudflare_dns_api_token.label": "Cloudflare DNS API token",
|
||||
"access.form.cloudflare_dns_api_token.placeholder": "Please enter Cloudflare DNS API token",
|
||||
"access.form.cloudflare_dns_api_token.tooltip": "For more information, see <a href=\"https://developers.cloudflare.com/fundamentals/api/get-started/create-token/\" target=\"_blank\">https://developers.cloudflare.com/fundamentals/api/get-started/create-token/</a>",
|
||||
@@ -200,6 +199,17 @@
|
||||
"access.form.godaddy_api_secret.label": "GoDaddy API secret",
|
||||
"access.form.godaddy_api_secret.placeholder": "Please enter GoDaddy API secret",
|
||||
"access.form.godaddy_api_secret.tooltip": "For more information, see <a href=\"https://developer.godaddy.com/\" target=\"_blank\">https://developer.godaddy.com/</a>",
|
||||
"access.form.goedge_api_url.label": "GoEdge API URL",
|
||||
"access.form.goedge_api_url.placeholder": "Please enter GoEdge API URL",
|
||||
"access.form.goedge_access_key_id.label": "GoEdge user AccessKeyId",
|
||||
"access.form.goedge_access_key_id.placeholder": "Please enter GoEdge user AccessKeyId",
|
||||
"access.form.goedge_access_key_id.tooltip": "For more information, see <a href=\"https://goedge.cloud/docs/API/Auth.md\" target=\"_blank\">https://goedge.cloud/docs/API/Auth.md</a>",
|
||||
"access.form.goedge_access_key.label": "GoEdge user AccessKey",
|
||||
"access.form.goedge_access_key.placeholder": "Please enter GoEdge user AccessKey",
|
||||
"access.form.goedge_access_key.tooltip": "For more information, see <a href=\"https://goedge.cloud/docs/API/Auth.md\" target=\"_blank\">https://goedge.cloud/docs/API/Auth.md</a>",
|
||||
"access.form.goedge_allow_insecure_conns.label": "Insecure SSL/TLS connections",
|
||||
"access.form.goedge_allow_insecure_conns.switch.on": "Allow",
|
||||
"access.form.goedge_allow_insecure_conns.switch.off": "Disallow",
|
||||
"access.form.googletrustservices_eab_kid.label": "ACME EAB KID",
|
||||
"access.form.googletrustservices_eab_kid.placeholder": "Please enter ACME EAB KID",
|
||||
"access.form.googletrustservices_eab_kid.tooltip": "For more information, see <a href=\"https://cloud.google.com/certificate-manager/docs/public-ca-tutorial\" target=\"_blank\">https://cloud.google.com/certificate-manager/docs/public-ca-tutorial</a>",
|
||||
@@ -260,10 +270,23 @@
|
||||
"access.form.porkbun_secret_api_key.tooltip": "For more information, see <a href=\"https://porkbun.com/api/json/v3/documentation#Authentication\" target=\"_blank\">https://porkbun.com/api/json/v3/documentation</a>",
|
||||
"access.form.powerdns_api_url.label": "PowerDNS API URL",
|
||||
"access.form.powerdns_api_url.placeholder": "Please enter PowerDNS API URL",
|
||||
"access.form.powerdns_api_url.tooltip": "For more information, see <a href=\"https://doc.powerdns.com/authoritative/http-api/index.html#endpoints-and-objects-in-the-api\" target=\"_blank\">https://doc.powerdns.com/authoritative/http-api/index.html#endpoints-and-objects-in-the-api</a>",
|
||||
"access.form.powerdns_api_key.label": "PowerDNS API key",
|
||||
"access.form.powerdns_api_key.placeholder": "Please enter PowerDNS API key",
|
||||
"access.form.powerdns_api_key.tooltip": "For more information, see <a href=\"https://doc.powerdns.com/authoritative/http-api/index.html#enabling-the-api\" target=\"_blank\">https://doc.powerdns.com/authoritative/http-api/index.html#enabling-the-api</a>",
|
||||
"access.form.powerdns_allow_insecure_conns.label": "Insecure SSL/TLS connections",
|
||||
"access.form.powerdns_allow_insecure_conns.switch.on": "Allow",
|
||||
"access.form.powerdns_allow_insecure_conns.switch.off": "Disallow",
|
||||
"access.form.proxmoxve_api_url.label": "Proxmox VE URL",
|
||||
"access.form.proxmoxve_api_url.placeholder": "Please enter Proxmox VE URL",
|
||||
"access.form.proxmoxve_api_token.label": "Proxmox VE API token",
|
||||
"access.form.proxmoxve_api_token.placeholder": "Please enter Proxmox VE API token",
|
||||
"access.form.proxmoxve_api_token.tooltip": "For more information, see <a href=\"https://pve.proxmox.com/pve-docs/pve-admin-guide.html#pveum_tokens\" target=\"_blank\">https://pve.proxmox.com/pve-docs/pve-admin-guide.html#pveum_tokens</a>",
|
||||
"access.form.proxmoxve_api_token_secret.label": "Proxmox VE API token secret (Optional)",
|
||||
"access.form.proxmoxve_api_token_secret.placeholder": "Please enter Proxmox VE API token secret",
|
||||
"access.form.proxmoxve_api_token_secret.tooltip": "For more information, see <a href=\"https://pve.proxmox.com/pve-docs/pve-admin-guide.html#pveum_tokens\" target=\"_blank\">https://pve.proxmox.com/pve-docs/pve-admin-guide.html#pveum_tokens</a>",
|
||||
"access.form.proxmoxve_allow_insecure_conns.label": "Insecure SSL/TLS connections",
|
||||
"access.form.proxmoxve_allow_insecure_conns.switch.on": "Allow",
|
||||
"access.form.proxmoxve_allow_insecure_conns.switch.off": "Disallow",
|
||||
"access.form.qiniu_access_key.label": "Qiniu AccessKey",
|
||||
"access.form.qiniu_access_key.placeholder": "Please enter Qiniu AccessKey",
|
||||
"access.form.qiniu_access_key.tooltip": "For more information, see <a href=\"https://portal.qiniu.com/\" target=\"_blank\">https://portal.qiniu.com/</a>",
|
||||
@@ -275,12 +298,10 @@
|
||||
"access.form.rainyun_api_key.tooltip": "For more information, see <a href=\"https://app.rainyun.com/account/settings/api-key\" target=\"_blank\">https://app.rainyun.com/account/settings/api-key</a>",
|
||||
"access.form.safeline_api_url.label": "SafeLine URL",
|
||||
"access.form.safeline_api_url.placeholder": "Please enter SafeLine URL",
|
||||
"access.form.safeline_api_url.tooltip": "For more information, see <a href=\"https://docs.waf.chaitin.com/en/tutorials/install#use-web-ui\" target=\"_blank\">https://docs.waf.chaitin.com/en/tutorials/install</a>",
|
||||
"access.form.safeline_api_token.label": "SafeLine API token",
|
||||
"access.form.safeline_api_token.placeholder": "Please enter SafeLine API token",
|
||||
"access.form.safeline_api_token.tooltip": "For more information, see <a href=\"https://docs.waf.chaitin.com/en/reference/articles/openapi\" target=\"_blank\">https://docs.waf.chaitin.com/en/reference/articles/openapi</a>",
|
||||
"access.form.safeline_allow_insecure_conns.label": "Insecure SSL/TLS connections",
|
||||
"access.form.safeline_allow_insecure_conns.tooltip": "Allowing insecure connections may lead to data leak or tampering. Use this option only when under trusted networks.",
|
||||
"access.form.safeline_allow_insecure_conns.switch.on": "Allow",
|
||||
"access.form.safeline_allow_insecure_conns.switch.off": "Disallow",
|
||||
"access.form.ssh_host.label": "Server host",
|
||||
@@ -371,7 +392,6 @@
|
||||
"access.form.webhook_preset_data.option.serverchan.label": "ServerChan",
|
||||
"access.form.webhook_preset_data.option.common.label": "General template",
|
||||
"access.form.webhook_allow_insecure_conns.label": "Insecure SSL/TLS connections",
|
||||
"access.form.webhook_allow_insecure_conns.tooltip": "Allowing insecure connections may lead to data leak or tampering. Use this option only when under trusted networks.",
|
||||
"access.form.webhook_allow_insecure_conns.switch.on": "Allow",
|
||||
"access.form.webhook_allow_insecure_conns.switch.off": "Disallow",
|
||||
"access.form.wecombot_webhook_url.label": "WeCom bot Webhook URL",
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
"common.menu.theme": "Change theme",
|
||||
"common.menu.locale": "Change language",
|
||||
"common.menu.settings": "Settings",
|
||||
"common.menu.logout": "Log-out",
|
||||
"common.menu.document": "Document",
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"provider.aliyun.cdn": "Alibaba Cloud - CDN (Content Delivery Network)",
|
||||
"provider.aliyun.clb": "Alibaba Cloud - CLB (Classic Load Balancer)",
|
||||
"provider.aliyun.dcdn": "Alibaba Cloud - DCDN (Dynamic Route for Content Delivery Network)",
|
||||
"provider.aliyun.ddos": "Alibaba Cloud - Anti-DDoS Proxy",
|
||||
"provider.aliyun.dns": "Alibaba Cloud - DNS (Domain Name Service)",
|
||||
"provider.aliyun.esa": "Alibaba Cloud - ESA (Edge Security Acceleration)",
|
||||
"provider.aliyun.fc": "Alibaba Cloud - FC (Function Compute)",
|
||||
@@ -66,7 +67,6 @@
|
||||
"provider.gname": "GNAME",
|
||||
"provider.godaddy": "GoDaddy",
|
||||
"provider.goedge": "GoEdge",
|
||||
"provider.goedge.cdn": "GoEdge - CDN (Content Delivery Network)",
|
||||
"provider.googletrustservices": "Google Trust Services",
|
||||
"provider.huaweicloud": "Huawei Cloud",
|
||||
"provider.huaweicloud.cdn": "Huawei Cloud - CDN (Content Delivery Network)",
|
||||
@@ -93,6 +93,7 @@
|
||||
"provider.ns1": "NS1 (IBM NS1 Connect)",
|
||||
"provider.porkbun": "Porkbun",
|
||||
"provider.powerdns": "PowerDNS",
|
||||
"provider.proxmoxve": "Proxmox VE",
|
||||
"provider.qiniu": "Qiniu",
|
||||
"provider.qiniu.cdn": "Qiniu - CDN (Content Delivery Network)",
|
||||
"provider.qiniu.kodo": "Qiniu - Kodo",
|
||||
@@ -148,6 +149,7 @@
|
||||
"provider.category.av": "Audio/Video",
|
||||
"provider.category.serverless": "Serverless",
|
||||
"provider.category.website": "Website",
|
||||
"provider.category.nas": "NAS",
|
||||
"provider.category.other": "Other",
|
||||
|
||||
"provider.default_ca_provider.label": "(Default) Follow global settings"
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
"workflow_node.apply.form.provider_access.placeholder": "Please select an authorization of DNS provider",
|
||||
"workflow_node.apply.form.provider_access.tooltip": "Used to manage DNS records during ACME DNS-01 challenge.",
|
||||
"workflow_node.apply.form.provider_access.button": "Create",
|
||||
"workflow_node.apply.form.aliyun_esa_region.label": "Alibaba Cloud ESA region",
|
||||
"workflow_node.apply.form.aliyun_esa_region.placeholder": "Please enter Alibaba Cloud ESA region (e.g. cn-hangzhou)",
|
||||
"workflow_node.apply.form.aliyun_esa_region.tooltip": "For more information, see <a href=\"https://www.alibabacloud.com/help/en/edge-security-acceleration/esa/api-esa-2024-09-10-endpoint\" target=\"_blank\">https://www.alibabacloud.com/help/en/edge-security-acceleration/esa/api-esa-2024-09-10-endpoint</a>",
|
||||
"workflow_node.apply.form.aws_route53_region.label": "AWS Route53 Region",
|
||||
"workflow_node.apply.form.aws_route53_region.placeholder": "Please enter AWS Route53 region (e.g. us-east-1)",
|
||||
"workflow_node.apply.form.aws_route53_region.tooltip": "For more information, see <a href=\"https://docs.aws.amazon.com/en_us/general/latest/gr/rande.html#regional-endpoints\" target=\"_blank\">https://docs.aws.amazon.com/en_us/general/latest/gr/rande.html#regional-endpoints</a>",
|
||||
@@ -95,14 +98,13 @@
|
||||
"workflow_node.apply.form.skip_before_expiry_days.tooltip": "Be careful not to exceed the validity period limit of the issued certificate, otherwise the certificate may never be renewed.",
|
||||
|
||||
"workflow_node.deploy.label": "Deployment",
|
||||
"workflow_node.deploy.search.provider.placeholder": "Search deploy target ...",
|
||||
"workflow_node.deploy.form.provider.label": "Deploy target",
|
||||
"workflow_node.deploy.form.provider.placeholder": "Please select deploy target",
|
||||
"workflow_node.deploy.form.provider.search.placeholder": "Search deploy target ...",
|
||||
"workflow_node.deploy.form.provider_access.label": "Hosting provider authorization",
|
||||
"workflow_node.deploy.form.provider_access.placeholder": "Please select an authorization of Hosting provider",
|
||||
"workflow_node.deploy.form.provider_access.tooltip": "Used to invoke API during deployment.",
|
||||
"workflow_node.deploy.form.provider_access.button": "Create",
|
||||
"workflow_node.deploy.form.provider_access.guide_for_local": "Tips: If you are running Certimate in Docker, the \"Local\" refers to the container rather than the host.",
|
||||
"workflow_node.deploy.form.certificate.label": "Certificate",
|
||||
"workflow_node.deploy.form.certificate.placeholder": "Please select certificate",
|
||||
"workflow_node.deploy.form.certificate.tooltip": "The certificate to be deployed comes from the previous nodes of application or upload.",
|
||||
@@ -191,6 +193,12 @@
|
||||
"workflow_node.deploy.form.aliyun_dcdn_domain.label": "Alibaba Cloud DCDN domain",
|
||||
"workflow_node.deploy.form.aliyun_dcdn_domain.placeholder": "Please enter Alibaba Cloud DCDN domain name",
|
||||
"workflow_node.deploy.form.aliyun_dcdn_domain.tooltip": "For more information, see <a href=\"https://dcdn.console.aliyun.com\" target=\"_blank\">https://dcdn.console.aliyun.com</a>",
|
||||
"workflow_node.deploy.form.aliyun_ddos_region.label": "Alibaba Cloud Anti-DDoS region",
|
||||
"workflow_node.deploy.form.aliyun_ddos_region.placeholder": "Please enter Alibaba Cloud Anti-DDoS region (e.g. cn-hangzhou)",
|
||||
"workflow_node.deploy.form.aliyun_ddos_region.tooltip": "For more information, see <a href=\"https://www.alibabacloud.com/help/en/anti-ddos/anti-ddos-pro-and-premium/developer-reference/api-ddoscoo-2020-01-01-endpoint\" target=\"_blank\">https://www.alibabacloud.com/help/en/anti-ddos/anti-ddos-pro-and-premium/developer-reference/api-ddoscoo-2020-01-01-endpoint</a>",
|
||||
"workflow_node.deploy.form.aliyun_ddos_domain.label": "Alibaba Cloud Anti-DDoS domain",
|
||||
"workflow_node.deploy.form.aliyun_ddos_domain.placeholder": "Please enter Alibaba Cloud Anti-DDoS domain name",
|
||||
"workflow_node.deploy.form.aliyun_ddos_domain.tooltip": "For more information, see <a href=\"https://yundun.console.aliyun.com/?p=ddoscoo#/overview/layer4/ap-southeast-1\" target=\"_blank\">https://yundun.console.aliyun.com/?p=ddoscoo</a>",
|
||||
"workflow_node.deploy.form.aliyun_esa_region.label": "Alibaba Cloud ESA region",
|
||||
"workflow_node.deploy.form.aliyun_esa_region.placeholder": "Please enter Alibaba Cloud ESA region (e.g. cn-hangzhou)",
|
||||
"workflow_node.deploy.form.aliyun_esa_region.tooltip": "For more information, see <a href=\"https://www.alibabacloud.com/help/en/edge-security-acceleration/esa/api-esa-2024-09-10-endpoint\" target=\"_blank\">https://www.alibabacloud.com/help/en/edge-security-acceleration/esa/api-esa-2024-09-10-endpoint</a>",
|
||||
@@ -347,6 +355,14 @@
|
||||
"workflow_node.deploy.form.gcore_cdn_resource_id.label": "Gcore CDN resource ID",
|
||||
"workflow_node.deploy.form.gcore_cdn_resource_id.placeholder": "Please enter Gcore CDN resource ID",
|
||||
"workflow_node.deploy.form.gcore_cdn_resource_id.tooltip": "For more information, see <a href=\"https://cdn.gcore.com/resources/list\" target=\"_blank\">https://cdn.gcore.com/resources/list</a>",
|
||||
"workflow_node.deploy.form.gcore_cdn_certificate_id.label": "Gcore CDN certificate ID (Optional)",
|
||||
"workflow_node.deploy.form.gcore_cdn_certificate_id.placeholder": "Please enter Gcore CDN certificate ID",
|
||||
"workflow_node.deploy.form.gcore_cdn_certificate_id.tooltip": "For more information, see <a href=\"https://cdn.gcore.com/ssl\" target=\"_blank\">https://cdn.gcore.com/ssl</a>",
|
||||
"workflow_node.deploy.form.goedge_resource_type.label": "Resource type",
|
||||
"workflow_node.deploy.form.goedge_resource_type.placeholder": "Please select resource type",
|
||||
"workflow_node.deploy.form.goedge_resource_type.option.certificate.label": "Certificate",
|
||||
"workflow_node.deploy.form.goedge_certificate_id.label": "GoEdge certificate ID",
|
||||
"workflow_node.deploy.form.goedge_certificate_id.placeholder": "Please enter GoEdge certificate ID",
|
||||
"workflow_node.deploy.form.huaweicloud_cdn_region.label": "Huawei Cloud CDN region",
|
||||
"workflow_node.deploy.form.huaweicloud_cdn_region.placeholder": "Please enter Huawei Cloud CDN region (e.g. cn-north-1)",
|
||||
"workflow_node.deploy.form.huaweicloud_cdn_region.tooltip": "For more information, see <a href=\"https://console-intl.huaweicloud.com/apiexplorer/#/endpoint?locale=en-us\" target=\"_blank\">https://console-intl.huaweicloud.com/apiexplorer/#/endpoint</a>",
|
||||
@@ -424,10 +440,11 @@
|
||||
"workflow_node.deploy.form.k8s_secret_data_key_for_key.label": "Kubernetes Secret data key for private key",
|
||||
"workflow_node.deploy.form.k8s_secret_data_key_for_key.placeholder": "Please enter Kubernetes Secret data key for private key",
|
||||
"workflow_node.deploy.form.k8s_secret_data_key_for_key.tooltip": "For more information, see <a href=\"https://kubernetes.io/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/docs/concepts/configuration/secret/</a>",
|
||||
"workflow_node.deploy.form.local.guide": "Tips: If you are running Certimate in Docker, the \"Local\" refers to the container rather than the host.",
|
||||
"workflow_node.deploy.form.local_format.label": "File format",
|
||||
"workflow_node.deploy.form.local_format.placeholder": "Please select file format",
|
||||
"workflow_node.deploy.form.local_format.option.pem.label": "PEM (*.pem, *.crt, *.key)",
|
||||
"workflow_node.deploy.form.local_format.option.pfx.label": "PFX (*.pfx)",
|
||||
"workflow_node.deploy.form.local_format.option.pfx.label": "PFX (*.pfx, *.p12)",
|
||||
"workflow_node.deploy.form.local_format.option.jks.label": "JKS (*.jks)",
|
||||
"workflow_node.deploy.form.local_cert_path.label": "Certificate file saving path",
|
||||
"workflow_node.deploy.form.local_cert_path.placeholder": "Please enter saving path for certificate file",
|
||||
@@ -457,11 +474,15 @@
|
||||
"workflow_node.deploy.form.local_post_command.label": "Post-command (Optional)",
|
||||
"workflow_node.deploy.form.local_post_command.placeholder": "Please enter command to be executed after saving files",
|
||||
"workflow_node.deploy.form.local_preset_scripts.button": "Use preset scripts",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.backup_files.label": "POSIX Bash - Backup certificate files",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.reload_nginx.label": "POSIX Bash - Reload nginx",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.binding_iis.label": "PowerShell - Binding IIS",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.binding_netsh.label": "PowerShell - Binding netsh",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.binding_rdp.label": "PowerShell - Binding RDP",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.sh_backup_files.label": "POSIX Bash - Backup certificate files",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.ps_backup_files.label": "PowerShell - Backup certificate files",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.sh_reload_nginx.label": "POSIX Bash - Reload nginx",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.ps_binding_iis.label": "PowerShell - Binding IIS",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.ps_binding_netsh.label": "PowerShell - Binding netsh",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.ps_.label": "PowerShell - Binding RDP",
|
||||
"workflow_node.deploy.form.proxmoxve_node_name.label": "Proxmox VE cluster node name",
|
||||
"workflow_node.deploy.form.proxmoxve_node_name.placeholder": "Please enter Proxmox VE cluster node name",
|
||||
"workflow_node.deploy.form.proxmoxve_auto_restart.label": "Auto restart after deployment",
|
||||
"workflow_node.deploy.form.qiniu_cdn_domain.label": "Qiniu CDN domain",
|
||||
"workflow_node.deploy.form.qiniu_cdn_domain.placeholder": "Please enter Qiniu CDN domain name",
|
||||
"workflow_node.deploy.form.qiniu_cdn_domain.tooltip": "For more information, see <a href=\"https://portal.qiniu.com/cdn\" target=\"_blank\">https://portal.qiniu.com/cdn</a>",
|
||||
@@ -488,7 +509,7 @@
|
||||
"workflow_node.deploy.form.ssh_format.label": "File format",
|
||||
"workflow_node.deploy.form.ssh_format.placeholder": "Please select file format",
|
||||
"workflow_node.deploy.form.ssh_format.option.pem.label": "PEM (*.pem, *.crt, *.key)",
|
||||
"workflow_node.deploy.form.ssh_format.option.pfx.label": "PFX (*.pfx)",
|
||||
"workflow_node.deploy.form.ssh_format.option.pfx.label": "PFX (*.pfx, *.p12)",
|
||||
"workflow_node.deploy.form.ssh_format.option.jks.label": "JKS (*.jks)",
|
||||
"workflow_node.deploy.form.ssh_cert_path.label": "Certificate file uploading path",
|
||||
"workflow_node.deploy.form.ssh_cert_path.placeholder": "Please enter uploading path for certificate file",
|
||||
@@ -515,8 +536,12 @@
|
||||
"workflow_node.deploy.form.ssh_post_command.label": "Post-command (Optional)",
|
||||
"workflow_node.deploy.form.ssh_post_command.placeholder": "Please enter command to be executed after uploading files",
|
||||
"workflow_node.deploy.form.ssh_preset_scripts.button": "Use preset scripts",
|
||||
"workflow_node.deploy.form.ssh_preset_scripts.option.backup_files.label": "POSIX Bash - Backup certificate files",
|
||||
"workflow_node.deploy.form.ssh_preset_scripts.option.reload_nginx.label": "POSIX Bash - Reload nginx",
|
||||
"workflow_node.deploy.form.ssh_preset_scripts.option.sh_backup_files.label": "POSIX Bash - Backup certificate files",
|
||||
"workflow_node.deploy.form.ssh_preset_scripts.option.ps_backup_files.label": "PowerShell - Backup certificate files",
|
||||
"workflow_node.deploy.form.ssh_preset_scripts.option.sh_reload_nginx.label": "POSIX Bash - Reload nginx",
|
||||
"workflow_node.deploy.form.ssh_preset_scripts.option.ps_binding_iis.label": "PowerShell - Binding IIS",
|
||||
"workflow_node.deploy.form.ssh_preset_scripts.option.ps_binding_netsh.label": "PowerShell - Binding netsh",
|
||||
"workflow_node.deploy.form.ssh_preset_scripts.option.ps_binding_rdp.label": "PowerShell - Binding RDP",
|
||||
"workflow_node.deploy.form.ssh_use_scp.label": "Fallback to use SCP",
|
||||
"workflow_node.deploy.form.ssh_use_scp.tooltip": "If the remote server does not support SFTP, please enable this option to fallback to SCP.",
|
||||
"workflow_node.deploy.form.tencentcloud_cdn_domain.label": "Tencent Cloud CDN domain",
|
||||
|
||||
@@ -29,18 +29,17 @@
|
||||
"access.form.provider.label": "提供商",
|
||||
"access.form.provider.placeholder": "请选择提供商",
|
||||
"access.form.provider.tooltip": "提供商分为两种类型:<br>【DNS 提供商】你的 DNS 托管方,通常等同于域名注册商,用于在申请证书时管理您的域名解析记录。<br>【主机提供商】你的服务器或云服务的托管方,用于部署签发的证书。<br><br>该字段保存后不可修改。",
|
||||
"access.form.provider.search.placeholder": "搜索提供商……",
|
||||
"access.form.certificate_authority.label": "证书颁发机构",
|
||||
"access.form.certificate_authority.placeholder": "请选择证书颁发机构",
|
||||
"access.form.notification_channel.label": "通知渠道",
|
||||
"access.form.notification_channel.placeholder": "请选择通知渠道",
|
||||
"access.form.1panel_api_url.label": "1Panel URL",
|
||||
"access.form.1panel_api_url.placeholder": "请输入 1Panel URL",
|
||||
"access.form.1panel_api_url.tooltip": "这是什么?请参阅 <a href=\"https://1panel.cn/docs/dev_manual/api_manual/\" target=\"_blank\">https://1panel.cn/docs/dev_manual/api_manual/</a>",
|
||||
"access.form.1panel_api_key.label": "1Panel 接口密钥",
|
||||
"access.form.1panel_api_key.placeholder": "请输入 1Panel 接口密钥",
|
||||
"access.form.1panel_api_key.tooltip": "这是什么?请参阅 <a href=\"https://1panel.cn/docs/dev_manual/api_manual/\" target=\"_blank\">https://1panel.cn/docs/dev_manual/api_manual/</a>",
|
||||
"access.form.1panel_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误",
|
||||
"access.form.1panel_allow_insecure_conns.tooltip": "忽略 SSL/TLS 证书错误可能导致数据泄露或被篡改。建议仅在可信网络下启用。",
|
||||
"access.form.1panel_allow_insecure_conns.switch.on": "允许",
|
||||
"access.form.1panel_allow_insecure_conns.switch.off": "不允许",
|
||||
"access.form.acmehttpreq_endpoint.label": "服务端点",
|
||||
@@ -89,12 +88,10 @@
|
||||
"access.form.baishan_api_token.placeholder": "请输入白山云 API Token",
|
||||
"access.form.baotapanel_api_url.label": "宝塔面板 URL",
|
||||
"access.form.baotapanel_api_url.placeholder": "请输入宝塔面板 URL",
|
||||
"access.form.baotapanel_api_url.tooltip": "这是什么?请参阅 <a href=\"https://www.bt.cn/bbs/thread-20376-1-1.html\" target=\"_blank\">https://www.bt.cn/bbs/thread-20376-1-1.html</a>",
|
||||
"access.form.baotapanel_api_key.label": "宝塔面板接口密钥",
|
||||
"access.form.baotapanel_api_key.placeholder": "请输入宝塔面板接口密钥",
|
||||
"access.form.baotapanel_api_key.tooltip": "这是什么?请参阅 <a href=\"https://www.bt.cn/bbs/thread-113890-1-1.html\" target=\"_blank\">https://www.bt.cn/bbs/thread-113890-1-1.html</a>",
|
||||
"access.form.baotapanel_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误",
|
||||
"access.form.baotapanel_allow_insecure_conns.tooltip": "忽略 SSL/TLS 证书错误可能导致数据泄露或被篡改。建议仅在可信网络下启用。",
|
||||
"access.form.baotapanel_allow_insecure_conns.switch.on": "允许",
|
||||
"access.form.baotapanel_allow_insecure_conns.switch.off": "不允许",
|
||||
"access.form.bunny_api_key.label": "Bunny API Key",
|
||||
@@ -111,13 +108,15 @@
|
||||
"access.form.cachefly_api_token.tooltip": "这是什么?请参阅 <a href=\"https://kb.cachefly.com/kb/guide/en/generating-tokens-and-keys-Oll9Irt5TI/Steps/2460228\" target=\"_blank\">https://kb.cachefly.com/kb/guide/en/generating-tokens-and-keys-Oll9Irt5TI/Steps/2460228</a>",
|
||||
"access.form.cdnfly_api_url.label": "Cdnfly API URL",
|
||||
"access.form.cdnfly_api_url.placeholder": "请输入 Cdnfly API URL",
|
||||
"access.form.cdnfly_api_url.tooltip": "这是什么?请参阅 <a href=\"https://doc.cdnfly.cn/anzhuangshuoming.html\" target=\"_blank\">https://doc.cdnfly.cn/anzhuangshuoming.html</a>",
|
||||
"access.form.cdnfly_api_key.label": "Cdnfly 用户端 API Key",
|
||||
"access.form.cdnfly_api_key.placeholder": "请输入 Cdnfly 用户端 API Key",
|
||||
"access.form.cdnfly_api_key.tooltip": "这是什么?请参阅 <a href=\"https://doc.cdnfly.cn/shiyongjieshao.html\" target=\"_blank\">https://doc.cdnfly.cn/shiyongjieshao.html</a>",
|
||||
"access.form.cdnfly_api_secret.label": "Cdnfly 用户端 API Secret",
|
||||
"access.form.cdnfly_api_secret.placeholder": "请输入 Cdnfly 用户端 API Secret",
|
||||
"access.form.cdnfly_api_secret.tooltip": "这是什么?请参阅 <a href=\"https://doc.cdnfly.cn/shiyongjieshao.html\" target=\"_blank\">https://doc.cdnfly.cn/shiyongjieshao.html</a>",
|
||||
"access.form.cdnfly_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误",
|
||||
"access.form.cdnfly_allow_insecure_conns.switch.on": "允许",
|
||||
"access.form.cdnfly_allow_insecure_conns.switch.off": "不允许",
|
||||
"access.form.cloudflare_dns_api_token.label": "Cloudflare DNS API 令牌",
|
||||
"access.form.cloudflare_dns_api_token.placeholder": "请输入 Cloudflare DNS API 令牌",
|
||||
"access.form.cloudflare_dns_api_token.tooltip": "这是什么?请参阅 <a href=\"https://developers.cloudflare.com/fundamentals/api/get-started/create-token/\" target=\"_blank\">https://developers.cloudflare.com/fundamentals/api/get-started/create-token/</a>",
|
||||
@@ -194,6 +193,17 @@
|
||||
"access.form.godaddy_api_secret.label": "GoDaddy API Secret",
|
||||
"access.form.godaddy_api_secret.placeholder": "请输入 GoDaddy API Secret",
|
||||
"access.form.godaddy_api_secret.tooltip": "这是什么?请参阅 <a href=\"https://developer.godaddy.com/\" target=\"_blank\">https://developer.godaddy.com/</a>",
|
||||
"access.form.goedge_api_url.label": "GoEdge API URL",
|
||||
"access.form.goedge_api_url.placeholder": "请输入 GoEdge API URL",
|
||||
"access.form.goedge_access_key_id.label": "GoEdge 用户 AccessKeyId",
|
||||
"access.form.goedge_access_key_id.placeholder": "请输入 GoEdge 用户 AccessKeyId",
|
||||
"access.form.goedge_access_key_id.tooltip": "这是什么?请参阅 <a href=\"https://goedge.cloud/docs/API/Auth.md\" target=\"_blank\">https://goedge.cloud/docs/API/Auth.md</a>",
|
||||
"access.form.goedge_access_key.label": "GoEdge 用户 AccessKey",
|
||||
"access.form.goedge_access_key.placeholder": "请输入 GoEdge 用户 AccessKey",
|
||||
"access.form.goedge_access_key.tooltip": "这是什么?请参阅 <a href=\"https://goedge.cloud/docs/API/Auth.md\" target=\"_blank\">https://goedge.cloud/docs/API/Auth.md</a>",
|
||||
"access.form.goedge_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误",
|
||||
"access.form.goedge_allow_insecure_conns.switch.on": "允许",
|
||||
"access.form.goedge_allow_insecure_conns.switch.off": "不允许",
|
||||
"access.form.googletrustservices_eab_kid.label": "ACME EAB KID",
|
||||
"access.form.googletrustservices_eab_kid.placeholder": "请输入 ACME EAB KID",
|
||||
"access.form.googletrustservices_eab_kid.tooltip": "这是什么?请参阅 <a href=\"https://cloud.google.com/certificate-manager/docs/public-ca-tutorial\" target=\"_blank\">https://cloud.google.com/certificate-manager/docs/public-ca-tutorial</a>",
|
||||
@@ -254,10 +264,23 @@
|
||||
"access.form.porkbun_secret_api_key.tooltip": "这是什么?请参阅 <a href=\"https://porkbun.com/api/json/v3/documentation#Authentication\" target=\"_blank\">https://porkbun.com/api/json/v3/documentation</a>",
|
||||
"access.form.powerdns_api_url.label": "PowerDNS API URL",
|
||||
"access.form.powerdns_api_url.placeholder": "请输入 PowerDNS API URL",
|
||||
"access.form.powerdns_api_url.tooltip": "这是什么?请参阅 <a href=\"https://doc.powerdns.com/authoritative/http-api/index.html#endpoints-and-objects-in-the-api\" target=\"_blank\">https://doc.powerdns.com/authoritative/http-api/index.html#endpoints-and-objects-in-the-api</a>",
|
||||
"access.form.powerdns_api_key.label": "PowerDNS API Key",
|
||||
"access.form.powerdns_api_key.placeholder": "请输入 PowerDNS API Key",
|
||||
"access.form.powerdns_api_key.tooltip": "这是什么?请参阅 <a href=\"https://doc.powerdns.com/authoritative/http-api/index.html#enabling-the-api\" target=\"_blank\">https://doc.powerdns.com/authoritative/http-api/index.html#enabling-the-api</a>",
|
||||
"access.form.powerdns_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误",
|
||||
"access.form.powerdns_allow_insecure_conns.switch.on": "允许",
|
||||
"access.form.powerdns_allow_insecure_conns.switch.off": "不允许",
|
||||
"access.form.proxmoxve_api_url.label": "Proxmox VE URL",
|
||||
"access.form.proxmoxve_api_url.placeholder": "请输入 Proxmox VE URL",
|
||||
"access.form.proxmoxve_api_token.label": "Proxmox VE API Token",
|
||||
"access.form.proxmoxve_api_token.placeholder": "请输入 Proxmox VE API Token",
|
||||
"access.form.proxmoxve_api_token.tooltip": "这是什么?请参阅 <a href=\"https://pve.proxmox.com/pve-docs/pve-admin-guide.html#pveum_tokens\" target=\"_blank\">https://pve.proxmox.com/pve-docs/pve-admin-guide.html#pveum_tokens</a>",
|
||||
"access.form.proxmoxve_api_token_secret.label": "Proxmox VE API Token Secret(可选)",
|
||||
"access.form.proxmoxve_api_token_secret.placeholder": "请输入 Proxmox VE API Token Secret",
|
||||
"access.form.proxmoxve_api_token_secret.tooltip": "这是什么?请参阅 <a href=\"https://pve.proxmox.com/pve-docs/pve-admin-guide.html#pveum_tokens\" target=\"_blank\">https://pve.proxmox.com/pve-docs/pve-admin-guide.html#pveum_tokens</a>",
|
||||
"access.form.proxmoxve_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误",
|
||||
"access.form.proxmoxve_allow_insecure_conns.switch.on": "允许",
|
||||
"access.form.proxmoxve_allow_insecure_conns.switch.off": "不允许",
|
||||
"access.form.qiniu_access_key.label": "七牛云 AccessKey",
|
||||
"access.form.qiniu_access_key.placeholder": "请输入七牛云 AccessKey",
|
||||
"access.form.qiniu_access_key.tooltip": "这是什么?请参阅 <a href=\"https://portal.qiniu.com/\" target=\"_blank\">https://portal.qiniu.com/</a>",
|
||||
@@ -269,12 +292,10 @@
|
||||
"access.form.rainyun_api_key.tooltip": "这是什么?请参阅 <a href=\"https://app.rainyun.com/account/settings/api-key\" target=\"_blank\">https://app.rainyun.com/account/settings/api-key</a>",
|
||||
"access.form.safeline_api_url.label": "雷池 URL",
|
||||
"access.form.safeline_api_url.placeholder": "请输入雷池 URL",
|
||||
"access.form.safeline_api_url.tooltip": "这是什么?请参阅 <a href=\"https://docs.waf-ce.chaitin.cn/zh/%E4%B8%8A%E6%89%8B%E6%8C%87%E5%8D%97/%E5%AE%89%E8%A3%85%E9%9B%B7%E6%B1%A0#%E8%AE%BF%E9%97%AE%E9%9B%B7%E6%B1%A0%E6%8E%A7%E5%88%B6%E5%8F%B0\" target=\"_blank\">https://docs.waf-ce.chaitin.cn/zh/上手指南/安装雷池</a>",
|
||||
"access.form.safeline_api_token.label": "雷池 API Token",
|
||||
"access.form.safeline_api_token.placeholder": "请输入雷池 API Token",
|
||||
"access.form.safeline_api_token.tooltip": "这是什么?请参阅 <a href=\"https://docs.waf-ce.chaitin.cn/zh/%E6%9B%B4%E5%A4%9A%E6%8A%80%E6%9C%AF%E6%96%87%E6%A1%A3/OPENAPI\" target=\"_blank\">https://docs.waf-ce.chaitin.cn/zh/更多技术文档/OPENAPI</a>",
|
||||
"access.form.safeline_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误",
|
||||
"access.form.safeline_allow_insecure_conns.tooltip": "忽略 SSL/TLS 证书错误可能导致数据泄露或被篡改。建议仅在可信网络下启用。",
|
||||
"access.form.safeline_allow_insecure_conns.switch.on": "允许",
|
||||
"access.form.safeline_allow_insecure_conns.switch.off": "不允许",
|
||||
"access.form.ssh_host.label": "服务器地址",
|
||||
@@ -371,7 +392,6 @@
|
||||
"access.form.webhook_preset_data.option.serverchan.label": "Server 酱",
|
||||
"access.form.webhook_preset_data.option.common.label": "通用模板",
|
||||
"access.form.webhook_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误",
|
||||
"access.form.webhook_allow_insecure_conns.tooltip": "忽略 SSL/TLS 证书错误可能导致数据泄露或被篡改。建议仅在可信网络下启用。",
|
||||
"access.form.webhook_allow_insecure_conns.switch.on": "允许",
|
||||
"access.form.webhook_allow_insecure_conns.switch.off": "不允许",
|
||||
"access.form.wecombot_webhook_url.label": "企业微信群机器人 Webhook 地址",
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
"common.menu.theme": "切换主题",
|
||||
"common.menu.locale": "切换语言",
|
||||
"common.menu.settings": "系统设置",
|
||||
"common.menu.logout": "退出登录",
|
||||
"common.menu.document": "文档",
|
||||
|
||||
|
||||
@@ -11,9 +11,10 @@
|
||||
"provider.aliyun.cdn": "阿里云 - 内容分发网络 CDN",
|
||||
"provider.aliyun.clb": "阿里云 - 传统型负载均衡 CLB",
|
||||
"provider.aliyun.dcdn": "阿里云 - 全站加速 DCDN",
|
||||
"provider.aliyun.ddos": "阿里云 - DDoS 高防",
|
||||
"provider.aliyun.dns": "阿里云 - 云解析 DNS",
|
||||
"provider.aliyun.esa": "阿里云 - 边缘安全加速 ESA",
|
||||
"provider.aliyun.fc": "阿里云 - 函数计算 FC",
|
||||
"provider.aliyun.dns": "阿里云 - 云解析 DNS",
|
||||
"provider.aliyun.live": "阿里云 - 视频直播 Live",
|
||||
"provider.aliyun.nlb": "阿里云 - 网络型负载均衡 NLB",
|
||||
"provider.aliyun.oss": "阿里云 - 对象存储 OSS",
|
||||
@@ -66,7 +67,6 @@
|
||||
"provider.gname": "GNAME",
|
||||
"provider.godaddy": "GoDaddy",
|
||||
"provider.goedge": "GoEdge",
|
||||
"provider.goedge.cdn": "GoEdge - 内容分发网络 CDN",
|
||||
"provider.googletrustservices": "Google Trust Services",
|
||||
"provider.huaweicloud": "华为云",
|
||||
"provider.huaweicloud.cdn": "华为云 - 内容分发网络 CDN",
|
||||
@@ -93,6 +93,7 @@
|
||||
"provider.ns1": "NS1 (IBM NS1 Connect)",
|
||||
"provider.porkbun": "Porkbun",
|
||||
"provider.powerdns": "PowerDNS",
|
||||
"provider.proxmoxve": "Proxmox VE",
|
||||
"provider.qiniu": "七牛云",
|
||||
"provider.qiniu.cdn": "七牛云 - 内容分发网络 CDN",
|
||||
"provider.qiniu.kodo": "七牛云 - 对象存储 Kodo",
|
||||
@@ -148,6 +149,7 @@
|
||||
"provider.category.av": "音视频",
|
||||
"provider.category.serverless": "Serverless",
|
||||
"provider.category.website": "网站托管",
|
||||
"provider.category.nas": "NAS",
|
||||
"provider.category.other": "其他",
|
||||
|
||||
"provider.default_ca_provider.label": "(默认)不指定,跟随全局设置"
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
"workflow_node.apply.form.provider_access.placeholder": "请选择 DNS 提供商授权",
|
||||
"workflow_node.apply.form.provider_access.tooltip": "用于 ACME DNS-01 质询时操作域名解析记录,注意与部署阶段所需的主机提供商相区分。",
|
||||
"workflow_node.apply.form.provider_access.button": "新建",
|
||||
"workflow_node.apply.form.aliyun_esa_region.label": "阿里云 ESA 服务地域",
|
||||
"workflow_node.apply.form.aliyun_esa_region.placeholder": "请输入阿里云 ESA 服务地域(例如:cn-hangzhou)",
|
||||
"workflow_node.apply.form.aliyun_esa_region.tooltip": "这是什么?请参阅 <a href=\"https://help.aliyun.com/zh/edge-security-acceleration/esa/api-esa-2024-09-10-endpoint\" target=\"_blank\">https://help.aliyun.com/zh/edge-security-acceleration/esa/api-esa-2024-09-10-endpoint</a>",
|
||||
"workflow_node.apply.form.aws_route53_region.label": "AWS Route53 服务区域",
|
||||
"workflow_node.apply.form.aws_route53_region.placeholder": "请输入 AWS Route53 服务区域(例如:us-east-1)",
|
||||
"workflow_node.apply.form.aws_route53_region.tooltip": "这是什么?请参阅 <a href=\"https://docs.aws.amazon.com/zh_cn/general/latest/gr/rande.html#regional-endpoints\" target=\"_blank\">https://docs.aws.amazon.com/zh_cn/general/latest/gr/rande.html#regional-endpoints</a>",
|
||||
@@ -94,19 +97,18 @@
|
||||
"workflow_node.apply.form.skip_before_expiry_days.tooltip": "注意不要超过颁发的证书最大有效期,否则证书可能永远不会续期。",
|
||||
|
||||
"workflow_node.deploy.label": "部署证书",
|
||||
"workflow_node.deploy.search.provider.placeholder": "搜索部署目标……",
|
||||
"workflow_node.deploy.form.provider.label": "部署目标",
|
||||
"workflow_node.deploy.form.provider.placeholder": "请选择部署目标",
|
||||
"workflow_node.deploy.form.provider.search.placeholder": "搜索部署目标……",
|
||||
"workflow_node.deploy.form.provider_access.label": "主机提供商授权",
|
||||
"workflow_node.deploy.form.provider_access.placeholder": "请选择主机提供商授权",
|
||||
"workflow_node.deploy.form.provider_access.tooltip": "用于部署证书时调用相关 API,注意与申请阶段所需的 DNS 提供商相区分。",
|
||||
"workflow_node.deploy.form.provider_access.button": "新建",
|
||||
"workflow_node.deploy.form.provider_access.guide_for_local": "小贴士:如果你正在使用 Docker 运行 Certimate,“本地”指的是容器内而非宿主机。",
|
||||
"workflow_node.deploy.form.certificate.label": "待部署证书",
|
||||
"workflow_node.deploy.form.certificate.placeholder": "请选择待部署证书",
|
||||
"workflow_node.deploy.form.certificate.tooltip": "待部署证书来自之前的申请或上传节点。如果选项为空请先确保前序节点配置正确。",
|
||||
"workflow_node.deploy.form.params_config.label": "参数设置",
|
||||
"workflow_node.deploy.form.1panel_console_auto_restart.label": "部署后自动重启面板服务",
|
||||
"workflow_node.deploy.form.1panel_console_auto_restart.label": "部署后自动重启宝塔面板服务",
|
||||
"workflow_node.deploy.form.1panel_site_resource_type.label": "证书替换方式",
|
||||
"workflow_node.deploy.form.1panel_site_resource_type.placeholder": "请选择证书替换方式",
|
||||
"workflow_node.deploy.form.1panel_site_resource_type.option.website.label": "替换指定网站的证书",
|
||||
@@ -190,6 +192,12 @@
|
||||
"workflow_node.deploy.form.aliyun_dcdn_domain.label": "阿里云 DCDN 加速域名",
|
||||
"workflow_node.deploy.form.aliyun_dcdn_domain.placeholder": "请输入阿里云 DCDN 加速域名(支持泛域名)",
|
||||
"workflow_node.deploy.form.aliyun_dcdn_domain.tooltip": "这是什么?请参阅 <a href=\"https://dcdn.console.aliyun.com\" target=\"_blank\">https://dcdn.console.aliyun.com</a>",
|
||||
"workflow_node.deploy.form.aliyun_ddos_region.label": "阿里云 DDoS 高防服务地域",
|
||||
"workflow_node.deploy.form.aliyun_ddos_region.placeholder": "请输入阿里云 DDoS 高防服务地域(例如:cn-hangzhou)",
|
||||
"workflow_node.deploy.form.aliyun_ddos_region.tooltip": "这是什么?请参阅 <a href=\"https://help.aliyun.com/zh/anti-ddos/anti-ddos-pro-and-premium/developer-reference/api-ddoscoo-2020-01-01-endpoint\" target=\"_blank\">https://help.aliyun.com/zh/anti-ddos/anti-ddos-pro-and-premium/developer-reference/api-ddoscoo-2020-01-01-endpoint</a>",
|
||||
"workflow_node.deploy.form.aliyun_ddos_domain.label": "阿里云 DDoS 高防网站域名",
|
||||
"workflow_node.deploy.form.aliyun_ddos_domain.placeholder": "请输入阿里云 DDoS 高防网站域名(支持泛域名)",
|
||||
"workflow_node.deploy.form.aliyun_ddos_domain.tooltip": "这是什么?请参阅 <a href=\"https://yundun.console.aliyun.com/?p=ddoscoo#/overview/layer4/cn-hangzhou\" target=\"_blank\">https://yundun.console.aliyun.com/?p=ddoscoo</a>",
|
||||
"workflow_node.deploy.form.aliyun_esa_region.label": "阿里云 ESA 服务地域",
|
||||
"workflow_node.deploy.form.aliyun_esa_region.placeholder": "请输入阿里云 ESA 服务地域(例如:cn-hangzhou)",
|
||||
"workflow_node.deploy.form.aliyun_esa_region.tooltip": "这是什么?请参阅 <a href=\"https://help.aliyun.com/zh/edge-security-acceleration/esa/api-esa-2024-09-10-endpoint\" target=\"_blank\">https://help.aliyun.com/zh/edge-security-acceleration/esa/api-esa-2024-09-10-endpoint</a>",
|
||||
@@ -306,7 +314,7 @@
|
||||
"workflow_node.deploy.form.baishan_cdn_certificate_id.label": "白山云 CDN 原证书 ID(可选)",
|
||||
"workflow_node.deploy.form.baishan_cdn_certificate_id.placeholder": "请输入白山云 CDN 原证书 ID",
|
||||
"workflow_node.deploy.form.baishan_cdn_certificate_id.tooltip": "这是什么?请参阅 <a href=\"https://cdnx.console.baishan.com/#/cdn/cert\" target=\"_blank\">https://cdnx.console.baishan.com/#/cdn/cert</a><br><br>不填写时,将上传新证书;否则,将替换原证书。",
|
||||
"workflow_node.deploy.form.baotapanel_console_auto_restart.label": "部署后自动重启面板服务",
|
||||
"workflow_node.deploy.form.baotapanel_console_auto_restart.label": "部署后自动重启 1Panel 服务",
|
||||
"workflow_node.deploy.form.baotapanel_site_type.label": "宝塔面板网站类型",
|
||||
"workflow_node.deploy.form.baotapanel_site_type.placeholder": "请选择宝塔面板网站类型",
|
||||
"workflow_node.deploy.form.baotapanel_site_type.option.php.label": "PHP",
|
||||
@@ -346,6 +354,14 @@
|
||||
"workflow_node.deploy.form.gcore_cdn_resource_id.label": "Gcore CDN 资源 ID",
|
||||
"workflow_node.deploy.form.gcore_cdn_resource_id.placeholder": "请输入 Gcore CDN 资源 ID",
|
||||
"workflow_node.deploy.form.gcore_cdn_resource_id.tooltip": "这是什么?请参阅 <a href=\"https://cdn.gcore.com/resources/list\" target=\"_blank\">https://cdn.gcore.com/resources/list</a>",
|
||||
"workflow_node.deploy.form.gcore_cdn_certificate_id.label": "Gcore CDN 原证书 ID(可选)",
|
||||
"workflow_node.deploy.form.gcore_cdn_certificate_id.placeholder": "请输入 Gcore CDN 原证书 ID",
|
||||
"workflow_node.deploy.form.gcore_cdn_certificate_id.tooltip": "这是什么?请参阅 <a href=\"https://cdn.gcore.com/ssl\" target=\"_blank\">https://cdn.gcore.com/ssl</a><br><br>不填写时,将上传新证书;否则,将替换原证书。",
|
||||
"workflow_node.deploy.form.goedge_resource_type.label": "证书替换方式",
|
||||
"workflow_node.deploy.form.goedge_resource_type.placeholder": "请选择证书替换方式",
|
||||
"workflow_node.deploy.form.goedge_resource_type.option.certificate.label": "替换指定证书",
|
||||
"workflow_node.deploy.form.goedge_certificate_id.label": "GoEdge 证书 ID",
|
||||
"workflow_node.deploy.form.goedge_certificate_id.placeholder": "请输入 GoEdge 证书 ID",
|
||||
"workflow_node.deploy.form.huaweicloud_cdn_region.label": "华为云 CDN 服务区域",
|
||||
"workflow_node.deploy.form.huaweicloud_cdn_region.placeholder": "请输入华为云 CDN 服务区域(例如:cn-north-1)",
|
||||
"workflow_node.deploy.form.huaweicloud_cdn_region.tooltip": "这是什么?请参阅 <a href=\"https://console.huaweicloud.com/apiexplorer/#/endpoint\" target=\"_blank\">https://console.huaweicloud.com/apiexplorer/#/endpoint</a>",
|
||||
@@ -423,10 +439,11 @@
|
||||
"workflow_node.deploy.form.k8s_secret_data_key_for_key.label": "Kubernetes Secret 数据键(用于存放私钥的字段)",
|
||||
"workflow_node.deploy.form.k8s_secret_data_key_for_key.placeholder": "请输入 Kubernetes Secret 中用于存放私钥的数据键",
|
||||
"workflow_node.deploy.form.k8s_secret_data_key_for_key.tooltip": "这是什么?请参阅 <a href=\"https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/</a>",
|
||||
"workflow_node.deploy.form.local.guide": "小贴士:如果你正在使用 Docker 运行 Certimate,“本地”指的是容器内而非宿主机。",
|
||||
"workflow_node.deploy.form.local_format.label": "文件格式",
|
||||
"workflow_node.deploy.form.local_format.placeholder": "请选择文件格式",
|
||||
"workflow_node.deploy.form.local_format.option.pem.label": "PEM 格式(*.pem, *.crt, *.key)",
|
||||
"workflow_node.deploy.form.local_format.option.pfx.label": "PFX 格式(*.pfx)",
|
||||
"workflow_node.deploy.form.local_format.option.pfx.label": "PFX 格式(*.pfx, *.p12)",
|
||||
"workflow_node.deploy.form.local_format.option.jks.label": "JKS 格式(*.jks)",
|
||||
"workflow_node.deploy.form.local_cert_path.label": "证书文件保存路径",
|
||||
"workflow_node.deploy.form.local_cert_path.placeholder": "请输入证书文件保存路径",
|
||||
@@ -456,11 +473,15 @@
|
||||
"workflow_node.deploy.form.local_post_command.label": "后置命令(可选)",
|
||||
"workflow_node.deploy.form.local_post_command.placeholder": "请输入保存文件后执行的命令",
|
||||
"workflow_node.deploy.form.local_preset_scripts.button": "使用预设脚本",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.backup_files.label": "POSIX Bash - 备份原证书文件",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.reload_nginx.label": "POSIX Bash - 重启 nginx 进程",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.binding_iis.label": "PowerShell - 导入并绑定到 IIS(需管理员权限)",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.binding_netsh.label": "PowerShell - 导入并绑定到 netsh(需管理员权限)",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.binding_rdp.label": "PowerShell - 导入并绑定到 远程桌面连接(需管理员权限)",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.sh_backup_files.label": "POSIX Bash - 备份原证书文件",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.ps_backup_files.label": "PowerShell - 备份原证书文件",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.sh_reload_nginx.label": "POSIX Bash - 重启 nginx 进程",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.ps_binding_iis.label": "PowerShell - 导入并绑定到 IIS",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.ps_binding_netsh.label": "PowerShell - 导入并绑定到 netsh",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.ps_binding_rdp.label": "PowerShell - 导入并绑定到 RDP",
|
||||
"workflow_node.deploy.form.proxmoxve_node_name.label": "Proxmox VE 集群节点名称",
|
||||
"workflow_node.deploy.form.proxmoxve_node_name.placeholder": "请输入 Proxmox VE 集群节点名称",
|
||||
"workflow_node.deploy.form.proxmoxve_auto_restart.label": "部署后自动重启 Proxmox VE 服务",
|
||||
"workflow_node.deploy.form.qiniu_cdn_domain.label": "七牛云 CDN 加速域名",
|
||||
"workflow_node.deploy.form.qiniu_cdn_domain.placeholder": "请输入七牛云 CDN 加速域名(支持泛域名)",
|
||||
"workflow_node.deploy.form.qiniu_cdn_domain.tooltip": "这是什么?请参阅 <a href=\"https://portal.qiniu.com/cdn\" target=\"_blank\">https://portal.qiniu.com/cdn</a>",
|
||||
@@ -487,7 +508,7 @@
|
||||
"workflow_node.deploy.form.ssh_format.label": "文件格式",
|
||||
"workflow_node.deploy.form.ssh_format.placeholder": "请选择文件格式",
|
||||
"workflow_node.deploy.form.ssh_format.option.pem.label": "PEM 格式(*.pem, *.crt, *.key)",
|
||||
"workflow_node.deploy.form.ssh_format.option.pfx.label": "PFX 格式(*.pfx)",
|
||||
"workflow_node.deploy.form.ssh_format.option.pfx.label": "PFX 格式(*.pfx, *.p12)",
|
||||
"workflow_node.deploy.form.ssh_format.option.jks.label": "JKS 格式(*.jks)",
|
||||
"workflow_node.deploy.form.ssh_cert_path.label": "证书文件上传路径",
|
||||
"workflow_node.deploy.form.ssh_cert_path.placeholder": "请输入证书文件上传路径",
|
||||
@@ -514,8 +535,12 @@
|
||||
"workflow_node.deploy.form.ssh_post_command.label": "后置命令(可选)",
|
||||
"workflow_node.deploy.form.ssh_post_command.placeholder": "请输入保存文件后执行的命令",
|
||||
"workflow_node.deploy.form.ssh_preset_scripts.button": "使用预设脚本",
|
||||
"workflow_node.deploy.form.ssh_preset_scripts.option.backup_files.label": "POSIX Bash - 备份原证书文件",
|
||||
"workflow_node.deploy.form.ssh_preset_scripts.option.reload_nginx.label": "POSIX Bash - 重启 nginx 进程",
|
||||
"workflow_node.deploy.form.ssh_preset_scripts.option.sh_backup_files.label": "POSIX Bash - 备份原证书文件",
|
||||
"workflow_node.deploy.form.ssh_preset_scripts.option.ps_backup_files.label": "PowerShell - 备份原证书文件",
|
||||
"workflow_node.deploy.form.ssh_preset_scripts.option.sh_reload_nginx.label": "POSIX Bash - 重启 nginx 进程",
|
||||
"workflow_node.deploy.form.ssh_preset_scripts.option.ps_binding_iis.label": "PowerShell - 导入并绑定到 IIS",
|
||||
"workflow_node.deploy.form.ssh_preset_scripts.option.ps_binding_netsh.label": "PowerShell - 导入并绑定到 netsh",
|
||||
"workflow_node.deploy.form.ssh_preset_scripts.option.ps_binding_rdp.label": "PowerShell - 导入并绑定到 RDP",
|
||||
"workflow_node.deploy.form.ssh_use_scp.label": "回退使用 SCP",
|
||||
"workflow_node.deploy.form.ssh_use_scp.tooltip": "如果你的远程服务器不支持 SFTP,请开启此选项回退为 SCP。",
|
||||
"workflow_node.deploy.form.tencentcloud_cdn_domain.label": "腾讯云 CDN 加速域名",
|
||||
|
||||
@@ -31,10 +31,6 @@ const ConsoleLayout = () => {
|
||||
navigate("/login");
|
||||
};
|
||||
|
||||
const handleSettingsClick = () => {
|
||||
navigate("/settings/account");
|
||||
};
|
||||
|
||||
const auth = getAuthStore();
|
||||
if (!auth.isValid || !auth.isSuperuser) {
|
||||
return <Navigate to="/login" />;
|
||||
@@ -66,9 +62,6 @@ const ConsoleLayout = () => {
|
||||
<Tooltip title={t("common.menu.locale")} mouseEnterDelay={2}>
|
||||
<LocaleToggleButton size="large" />
|
||||
</Tooltip>
|
||||
<Tooltip title={t("common.menu.settings")} mouseEnterDelay={2}>
|
||||
<Button icon={<SettingOutlinedIcon />} size="large" onClick={handleSettingsClick} />
|
||||
</Tooltip>
|
||||
<Tooltip title={t("common.menu.logout")} mouseEnterDelay={2}>
|
||||
<Button danger icon={<LogoutOutlinedIcon />} size="large" onClick={handleLogoutClick} />
|
||||
</Tooltip>
|
||||
@@ -94,11 +87,13 @@ const SiderMenu = memo(({ onSelect }: { onSelect?: (key: string) => void }) => {
|
||||
const MENU_KEY_WORKFLOWS = "/workflows";
|
||||
const MENU_KEY_CERTIFICATES = "/certificates";
|
||||
const MENU_KEY_ACCESSES = "/accesses";
|
||||
const MENU_KEY_SETTINGS = "/settings";
|
||||
const menuItems: Required<MenuProps>["items"] = [
|
||||
[MENU_KEY_HOME, <HomeOutlinedIcon />, t("dashboard.page.title")],
|
||||
[MENU_KEY_WORKFLOWS, <NodeIndexOutlinedIcon />, t("workflow.page.title")],
|
||||
[MENU_KEY_CERTIFICATES, <SafetyOutlinedIcon />, t("certificate.page.title")],
|
||||
[MENU_KEY_ACCESSES, <CloudServerOutlinedIcon />, t("access.page.title")],
|
||||
[MENU_KEY_SETTINGS, <SettingOutlinedIcon />, t("settings.page.title")],
|
||||
].map(([key, icon, label]) => {
|
||||
return {
|
||||
key: key as string,
|
||||
@@ -167,7 +162,7 @@ const SiderMenuDrawer = memo(({ trigger }: { trigger: React.ReactNode }) => {
|
||||
|
||||
<Drawer
|
||||
closable={false}
|
||||
destroyOnClose
|
||||
destroyOnHidden
|
||||
open={siderOpen}
|
||||
placement="left"
|
||||
styles={{
|
||||
|
||||
@@ -95,7 +95,7 @@ const CertificateList = () => {
|
||||
return (
|
||||
<div style={{ padding: 0 }}>
|
||||
<Menu items={items} selectable={false} />
|
||||
<Divider style={{ margin: 0 }} />
|
||||
<Divider className="my-0" />
|
||||
<Space className="w-full justify-end" style={{ padding: themeToken.paddingSM }}>
|
||||
<Button size="small" disabled={!filters.state} onClick={handleResetClick}>
|
||||
{t("common.button.reset")}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user