diff --git a/README.md b/README.md index 2e36d3a2..63d7898b 100644 --- a/README.md +++ b/README.md @@ -74,8 +74,8 @@ make local.run | 服务商 | 支持申请证书 | 支持部署证书 | 备注 | | :--------: | :----------: | :----------: | ------------------------------------------------------------ | | 阿里云 | √ | √ | 可签发在阿里云注册的域名;可部署到阿里云 OSS、CDN | -| 腾讯云 | √ | √ | 可签发在腾讯云注册的域名;可部署到腾讯云 CDN、COS | -| 华为云 | √ | √ | 可签发在华为云注册的域名;可部署到华为云 CDN | +| 腾讯云 | √ | √ | 可签发在腾讯云注册的域名;可部署到腾讯云 COS、CDN、CLB | +| 华为云 | √ | √ | 可签发在华为云注册的域名;可部署到华为云 CDN、ELB | | 七牛云 | | √ | 可部署到七牛云 CDN | | AWS | √ | | 可签发在 AWS Route53 托管的域名 | | CloudFlare | √ | | 可签发在 CloudFlare 注册的域名;CloudFlare 服务自带 SSL 证书 | diff --git a/README_EN.md b/README_EN.md index f6356c86..5bb30b38 100644 --- a/README_EN.md +++ b/README_EN.md @@ -70,22 +70,22 @@ password:1234567890 ## List of Supported Providers -| Provider | Registration | Deployment | Remarks | -| :-----------: | :----------: | :--------: | ------------------------------------------------------------------------------------------- | -| Alibaba Cloud | √ | √ | Supports domains registered on Alibaba Cloud; supports deployment to Alibaba Cloud OSS, CDN | -| Tencent Cloud | √ | √ | Supports domains registered on Tencent Cloud; supports deployment to Tencent Cloud CDN, COS | -| Huawei Cloud | √ | √ | Supports domains registered on Huawei Cloud; supports deployment to Huawei Cloud CDN | -| Qiniu Cloud | | √ | Supports deployment to Qiniu Cloud CDN | -| AWS | √ | | Supports domains managed on AWS Route53 | -| CloudFlare | √ | | Supports domains registered on CloudFlare; CloudFlare services come with SSL certificates | -| GoDaddy | √ | | Supports domains registered on GoDaddy | -| Namesilo | √ | | Supports domains registered on Namesilo | -| PowerDNS | √ | | Supports domains managed on PowerDNS | -| HTTP Request | √ | | Supports domains which allow managing DNS by HTTP request | -| Local Deploy | | √ | Supports deployment to local servers | -| SSH | | √ | Supports deployment to SSH servers | -| Webhook | | √ | Supports callback to Webhook | -| Kubernetes | | √ | Supports deployment to Kubernetes Secret | +| Provider | Registration | Deployment | Remarks | +| :-----------: | :----------: | :--------: | ------------------------------------------------------------------------------------------------ | +| Alibaba Cloud | √ | √ | Supports domains registered on Alibaba Cloud; supports deployment to Alibaba Cloud OSS, CDN | +| Tencent Cloud | √ | √ | Supports domains registered on Tencent Cloud; supports deployment to Tencent Cloud COS, CDN, CLB | +| Huawei Cloud | √ | √ | Supports domains registered on Huawei Cloud; supports deployment to Huawei Cloud CDN, ELB | +| Qiniu Cloud | | √ | Supports deployment to Qiniu Cloud CDN | +| AWS | √ | | Supports domains managed on AWS Route53 | +| CloudFlare | √ | | Supports domains registered on CloudFlare; CloudFlare services come with SSL certificates | +| GoDaddy | √ | | Supports domains registered on GoDaddy | +| Namesilo | √ | | Supports domains registered on Namesilo | +| PowerDNS | √ | | Supports domains managed on PowerDNS | +| HTTP Request | √ | | Supports domains which allow managing DNS by HTTP request | +| Local Deploy | | √ | Supports deployment to local servers | +| SSH | | √ | Supports deployment to SSH servers | +| Webhook | | √ | Supports callback to Webhook | +| Kubernetes | | √ | Supports deployment to Kubernetes Secret | ## Screenshots diff --git a/go.mod b/go.mod index 0147a2cf..dff90fd5 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1017 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1017 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.992 - golang.org/x/crypto v0.27.0 + golang.org/x/crypto v0.28.0 k8s.io/apimachinery v0.31.1 k8s.io/client-go v0.31.1 ) @@ -149,19 +149,19 @@ require ( gocloud.dev v0.37.0 // indirect golang.org/x/image v0.18.0 // indirect golang.org/x/mod v0.21.0 // indirect - golang.org/x/net v0.29.0 // indirect + golang.org/x/net v0.30.0 // indirect golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/term v0.24.0 // indirect - golang.org/x/text v0.18.0 // indirect - golang.org/x/time v0.6.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/term v0.25.0 // indirect + golang.org/x/text v0.19.0 // indirect + golang.org/x/time v0.7.0 // indirect golang.org/x/tools v0.25.0 // indirect golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 // indirect - google.golang.org/api v0.197.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/grpc v1.66.1 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/api v0.202.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect + google.golang.org/grpc v1.67.1 // indirect + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect modernc.org/gc/v3 v3.0.0-20240722195230-4a140ff9c08e // indirect diff --git a/go.sum b/go.sum index 0513ac00..f666c84a 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,13 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.115.1 h1:Jo0SM9cQnSkYfp44+v+NQXHpcHqlnRJk2qxh6yvxxxQ= -cloud.google.com/go v0.115.1/go.mod h1:DuujITeaufu3gL68/lOFIirVNJwQeyf5UXyi+Wbgknc= -cloud.google.com/go/auth v0.9.3 h1:VOEUIAADkkLtyfr3BLa3R8Ed/j6w1jTBmARx+wb5w5U= -cloud.google.com/go/auth v0.9.3/go.mod h1:7z6VY+7h3KUdRov5F1i8NDP5ZzWKYmEPO842BgCsmTk= +cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= +cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= +cloud.google.com/go/auth v0.9.8 h1:+CSJ0Gw9iVeSENVCKJoLHhdUykDgXSc4Qn+gu2BRtR8= +cloud.google.com/go/auth v0.9.8/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY= cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc= cloud.google.com/go/compute v1.25.0 h1:H1/4SqSUhjPFE7L5ddzHOfY2bCAvjwNRZPNl6Ni5oYU= -cloud.google.com/go/compute/metadata v0.5.1 h1:NM6oZeZNlYjiwYje+sYFjEpP0Q0zCan1bmQW/KmIrGs= -cloud.google.com/go/compute/metadata v0.5.1/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= +cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo= +cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= cloud.google.com/go/iam v1.1.11 h1:0mQ8UKSfdHLut6pH9FM3bI55KWR46ketn0PuXleDyxw= cloud.google.com/go/iam v1.1.11/go.mod h1:biXoiLWYIKntto2joP+62sd9uW5EpkZmKIvfNcTWlnQ= cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs= @@ -510,8 +510,8 @@ golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1m golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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= @@ -560,8 +560,8 @@ golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= 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.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= @@ -601,8 +601,8 @@ golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -614,8 +614,8 @@ golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= 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.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -629,11 +629,11 @@ golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 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.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= -golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= +golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -661,28 +661,28 @@ gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJ gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= -google.golang.org/api v0.197.0 h1:x6CwqQLsFiA5JKAiGyGBjc2bNtHtLddhJCE2IKuhhcQ= -google.golang.org/api v0.197.0/go.mod h1:AuOuo20GoQ331nq7DquGHlU6d+2wN2fZ8O0ta60nRNw= +google.golang.org/api v0.202.0 h1:y1iuVHMqokQbimW79ZqPZWo4CiyFu6HcCYHwSNyzlfo= +google.golang.org/api v0.202.0/go.mod h1:3Jjeq7M/SFblTNCp7ES2xhq+WvGL0KeXI0joHQBfwTQ= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 h1:BulPr26Jqjnd4eYDVe+YvyR7Yc2vJGkO5/0UxD0/jZU= -google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:hL97c3SYopEHblzpxRL4lSs523++l8DYxGM1FQiYmb4= +google.golang.org/genproto v0.0.0-20241015192408-796eee8c2d53 h1:Df6WuGvthPzc+JiQ/G+m+sNX24kc0aTBqoDN/0yyykE= +google.golang.org/genproto v0.0.0-20241015192408-796eee8c2d53/go.mod h1:fheguH3Am2dGp1LfXkrvwqC/KlFq8F0nLq3LryOMrrE= google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed h1:3RgNmBoI9MZhsj3QxC+AP/qQhNwpCLOvYDYYsFrhFt0= google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed/go.mod h1:OCdP9MfskevB/rbYvHTsXTtKC+3bHWajPdoKgjcYkfo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.66.1 h1:hO5qAXR19+/Z44hmvIM4dQFMSYX9XcWsByfoxutBpAM= -google.golang.org/grpc v1.66.1/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -692,8 +692,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/applicant/applicant.go b/internal/applicant/applicant.go index cdaab89e..17e97cb5 100644 --- a/internal/applicant/applicant.go +++ b/internal/applicant/applicant.go @@ -12,6 +12,8 @@ import ( "strings" "github.com/usual2970/certimate/internal/domain" + "github.com/usual2970/certimate/internal/pkg/utils/x509" + "github.com/usual2970/certimate/internal/repository" "github.com/usual2970/certimate/internal/utils/app" "github.com/go-acme/lego/v4/certcrypto" @@ -39,16 +41,19 @@ const defaultSSLProvider = "letsencrypt" const ( sslProviderLetsencrypt = "letsencrypt" sslProviderZeroSSL = "zerossl" + sslProviderGts = "gts" ) const ( zerosslUrl = "https://acme.zerossl.com/v2/DV90" letsencryptUrl = "https://acme-v02.api.letsencrypt.org/directory" + gtsUrl = "https://dv.acme-v02.api.pki.goog/directory" ) var sslProviderUrls = map[string]string{ sslProviderLetsencrypt: letsencryptUrl, sslProviderZeroSSL: zerosslUrl, + sslProviderGts: gtsUrl, } const defaultEmail = "536464346@qq.com" @@ -75,9 +80,37 @@ type ApplyOption struct { } type ApplyUser struct { + Ca string Email string Registration *registration.Resource - key crypto.PrivateKey + key string +} + +func newApplyUser(ca, email string) (*ApplyUser, error) { + repo := getAcmeAccountRepository() + rs := &ApplyUser{ + Ca: ca, + Email: email, + } + resp, err := repo.GetByCAAndEmail(ca, email) + if err != nil { + privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + return nil, err + } + keyStr, err := x509.PrivateKeyToPEM(privateKey) + if err != nil { + return nil, err + } + rs.key = keyStr + + return rs, nil + } + + rs.Registration = resp.Resource + rs.key = resp.Key + + return rs, nil } func (u *ApplyUser) GetEmail() string { @@ -89,6 +122,15 @@ func (u ApplyUser) GetRegistration() *registration.Resource { } func (u *ApplyUser) GetPrivateKey() crypto.PrivateKey { + rs, _ := x509.ParsePrivateKeyFromPEM(u.key) + return rs +} + +func (u *ApplyUser) hasRegistration() bool { + return u.Registration != nil +} + +func (u *ApplyUser) getPrivateKeyString() string { return u.key } @@ -157,10 +199,13 @@ type SSLProviderConfig struct { } type SSLProviderConfigContent struct { - Zerossl struct { - EabHmacKey string `json:"eabHmacKey"` - EabKid string `json:"eabKid"` - } + Zerossl SSLProviderEab `json:"zerossl"` + Gts SSLProviderEab `json:"gts"` +} + +type SSLProviderEab struct { + EabHmacKey string `json:"eabHmacKey"` + EabKid string `json:"eabKid"` } func apply(option *ApplyOption, provider challenge.Provider) (*Certificate, error) { @@ -176,21 +221,16 @@ func apply(option *ApplyOption, provider challenge.Provider) (*Certificate, erro } } - privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - return nil, err - } - // Some unified lego environment variables are configured here. // link: https://github.com/go-acme/lego/issues/1867 os.Setenv("LEGO_DISABLE_CNAME_SUPPORT", strconv.FormatBool(option.DisableFollowCNAME)) - myUser := ApplyUser{ - Email: option.Email, - key: privateKey, + myUser, err := newApplyUser(sslProvider.Provider, option.Email) + if err != nil { + return nil, err } - config := lego.NewConfig(&myUser) + config := lego.NewConfig(myUser) // This CA URL is configured for a local dev instance of Boulder running in Docker in a VM. config.CADirURL = sslProviderUrls[sslProvider.Provider] @@ -211,11 +251,13 @@ func apply(option *ApplyOption, provider challenge.Provider) (*Certificate, erro client.Challenge.SetDNS01Provider(provider, challengeOptions...) // New users will need to register - reg, err := getReg(client, sslProvider) - if err != nil { - return nil, fmt.Errorf("failed to register: %w", err) + if !myUser.hasRegistration() { + reg, err := getReg(client, sslProvider, myUser) + if err != nil { + return nil, fmt.Errorf("failed to register: %w", err) + } + myUser.Registration = reg } - myUser.Registration = reg domains := strings.Split(option.Domain, ";") request := certificate.ObtainRequest{ @@ -237,7 +279,16 @@ func apply(option *ApplyOption, provider challenge.Provider) (*Certificate, erro }, nil } -func getReg(client *lego.Client, sslProvider *SSLProviderConfig) (*registration.Resource, error) { +type AcmeAccountRepository interface { + GetByCAAndEmail(ca, email string) (*domain.AcmeAccount, error) + Save(ca, email, key string, resource *registration.Resource) error +} + +func getAcmeAccountRepository() AcmeAccountRepository { + return repository.NewAcmeAccountRepository() +} + +func getReg(client *lego.Client, sslProvider *SSLProviderConfig, user *ApplyUser) (*registration.Resource, error) { var reg *registration.Resource var err error switch sslProvider.Provider { @@ -247,6 +298,12 @@ func getReg(client *lego.Client, sslProvider *SSLProviderConfig) (*registration. Kid: sslProvider.Config.Zerossl.EabKid, HmacEncoded: sslProvider.Config.Zerossl.EabHmacKey, }) + case sslProviderGts: + reg, err = client.Registration.RegisterWithExternalAccountBinding(registration.RegisterEABOptions{ + TermsOfServiceAgreed: true, + Kid: sslProvider.Config.Gts.EabKid, + HmacEncoded: sslProvider.Config.Gts.EabHmacKey, + }) case sslProviderLetsencrypt: reg, err = client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true}) @@ -259,6 +316,18 @@ func getReg(client *lego.Client, sslProvider *SSLProviderConfig) (*registration. return nil, err } + repo := getAcmeAccountRepository() + + resp, err := repo.GetByCAAndEmail(sslProvider.Provider, user.GetEmail()) + if err == nil { + user.key = resp.Key + return resp.Resource, nil + } + + if err := repo.Save(sslProvider.Provider, user.GetEmail(), user.getPrivateKeyString(), reg); err != nil { + return nil, fmt.Errorf("failed to save registration: %w", err) + } + return reg, nil } diff --git a/internal/deployer/deployer.go b/internal/deployer/deployer.go index 8ae0014a..512fd748 100644 --- a/internal/deployer/deployer.go +++ b/internal/deployer/deployer.go @@ -19,6 +19,7 @@ const ( targetAliyunCDN = "aliyun-cdn" targetAliyunESA = "aliyun-dcdn" targetTencentCDN = "tencent-cdn" + targetTencentCLB = "tencent-clb" targetTencentCOS = "tencent-cos" targetHuaweiCloudCDN = "huaweicloud-cdn" targetHuaweiCloudELB = "huaweicloud-elb" @@ -107,6 +108,8 @@ func getWithDeployConfig(record *models.Record, cert *applicant.Certificate, dep return NewAliyunESADeployer(option) case targetTencentCDN: return NewTencentCDNDeployer(option) + case targetTencentCLB: + return NewTencentCLBDeployer(option) case targetTencentCOS: return NewTencentCOSDeployer(option) case targetHuaweiCloudCDN: diff --git a/internal/deployer/k8s_secret.go b/internal/deployer/k8s_secret.go index 3729114f..89789269 100644 --- a/internal/deployer/k8s_secret.go +++ b/internal/deployer/k8s_secret.go @@ -4,12 +4,15 @@ import ( "context" "encoding/json" "fmt" + "strings" + corev1 "k8s.io/api/core/v1" k8sMetaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/clientcmd" "github.com/usual2970/certimate/internal/domain" + "github.com/usual2970/certimate/internal/pkg/utils/x509" ) type K8sSecretDeployer struct { @@ -43,7 +46,7 @@ func (d *K8sSecretDeployer) Deploy(ctx context.Context) error { return err } - d.infos = append(d.infos, toStr("kubeClient 创建成功", nil)) + d.infos = append(d.infos, toStr("kubeClient create success.", nil)) namespace := getDeployString(d.option.DeployConfig, "namespace") if namespace == "" { @@ -65,36 +68,61 @@ func (d *K8sSecretDeployer) Deploy(ctx context.Context) error { namespace = "tls.key" } - // 获取 Secret 实例 - secret, err := client.CoreV1().Secrets(namespace).Get(context.TODO(), secretName, k8sMetaV1.GetOptions{}) + certificate, err := x509.ParseCertificateFromPEM(d.option.Certificate.Certificate) if err != nil { - return fmt.Errorf("failed to get k8s secret: %w", err) + return fmt.Errorf("failed to parse certificate: %w", err) } - // 更新 Secret Data - secret.Data[secretDataKeyForCrt] = []byte(d.option.Certificate.Certificate) - secret.Data[secretDataKeyForKey] = []byte(d.option.Certificate.PrivateKey) - _, err = client.CoreV1().Secrets(namespace).Update(context.TODO(), secret, k8sMetaV1.UpdateOptions{}) + secretPayload := corev1.Secret{ + TypeMeta: k8sMetaV1.TypeMeta{ + Kind: "Secret", + APIVersion: "v1", + }, + ObjectMeta: k8sMetaV1.ObjectMeta{ + Name: secretName, + Annotations: map[string]string{ + "certimate/domains": d.option.Domain, + "certimate/alt-names": strings.Join(certificate.DNSNames, ","), + "certimate/common-name": certificate.Subject.CommonName, + "certimate/issuer-organization": strings.Join(certificate.Issuer.Organization, ","), + }, + }, + Type: corev1.SecretType("kubernetes.io/tls"), + } + + secretPayload.Data = make(map[string][]byte) + secretPayload.Data[secretDataKeyForCrt] = []byte(d.option.Certificate.Certificate) + secretPayload.Data[secretDataKeyForKey] = []byte(d.option.Certificate.PrivateKey) + + // 获取 Secret 实例 + _, err = client.CoreV1().Secrets(namespace).Get(context.TODO(), secretName, k8sMetaV1.GetOptions{}) + if err != nil { + _, err = client.CoreV1().Secrets(namespace).Create(context.TODO(), &secretPayload, k8sMetaV1.CreateOptions{}) + if err != nil { + return fmt.Errorf("failed to create k8s secret: %w", err) + } else { + d.infos = append(d.infos, toStr("Certificate has been created in K8s Secret", nil)) + return nil + } + } + + // 更新 Secret 实例 + _, err = client.CoreV1().Secrets(namespace).Update(ctx, &secretPayload, k8sMetaV1.UpdateOptions{}) if err != nil { return fmt.Errorf("failed to update k8s secret: %w", err) } - d.infos = append(d.infos, toStr("证书已更新到 K8s Secret", nil)) + d.infos = append(d.infos, toStr("Certificate has been updated to K8s Secret", nil)) return nil } func (d *K8sSecretDeployer) createClient(access *domain.KubernetesAccess) (*kubernetes.Clientset, error) { - kubeConfig, err := clientcmd.Load([]byte(access.KubeConfig)) + kubeConfig, err := clientcmd.NewClientConfigFromBytes([]byte(access.KubeConfig)) if err != nil { return nil, err } - - clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( - &clientcmd.ClientConfigLoadingRules{ExplicitPath: ""}, - &clientcmd.ConfigOverrides{CurrentContext: kubeConfig.CurrentContext}, - ) - config, err := clientConfig.ClientConfig() + config, err := kubeConfig.ClientConfig() if err != nil { return nil, err } diff --git a/internal/deployer/tencent_clb.go b/internal/deployer/tencent_clb.go new file mode 100644 index 00000000..ba97e840 --- /dev/null +++ b/internal/deployer/tencent_clb.go @@ -0,0 +1,117 @@ +package deployer + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" + "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" + ssl "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205" + + "github.com/usual2970/certimate/internal/domain" + "github.com/usual2970/certimate/internal/utils/rand" +) + +type TencentCLBDeployer struct { + option *DeployerOption + credential *common.Credential + infos []string +} + +func NewTencentCLBDeployer(option *DeployerOption) (Deployer, error) { + access := &domain.TencentAccess{} + if err := json.Unmarshal([]byte(option.Access), access); err != nil { + return nil, fmt.Errorf("failed to unmarshal tencent access: %w", err) + } + + credential := common.NewCredential( + access.SecretId, + access.SecretKey, + ) + + return &TencentCLBDeployer{ + option: option, + credential: credential, + infos: make([]string, 0), + }, nil +} + +func (d *TencentCLBDeployer) GetID() string { + return fmt.Sprintf("%s-%s", d.option.AccessRecord.GetString("name"), d.option.AccessRecord.Id) +} + +func (d *TencentCLBDeployer) GetInfo() []string { + return d.infos +} + +func (d *TencentCLBDeployer) Deploy(ctx context.Context) error { + // 上传证书 + certId, err := d.uploadCert() + if err != nil { + return fmt.Errorf("failed to upload certificate: %w", err) + } + d.infos = append(d.infos, toStr("上传证书", certId)) + + if err := d.deploy(certId); err != nil { + return fmt.Errorf("failed to deploy: %w", err) + } + + return nil +} + +func (d *TencentCLBDeployer) uploadCert() (string, error) { + cpf := profile.NewClientProfile() + cpf.HttpProfile.Endpoint = "ssl.tencentcloudapi.com" + + client, _ := ssl.NewClient(d.credential, "", cpf) + + request := ssl.NewUploadCertificateRequest() + + request.CertificatePublicKey = common.StringPtr(d.option.Certificate.Certificate) + request.CertificatePrivateKey = common.StringPtr(d.option.Certificate.PrivateKey) + request.Alias = common.StringPtr(d.option.Domain + "_" + rand.RandStr(6)) + request.Repeatable = common.BoolPtr(false) + + response, err := client.UploadCertificate(request) + if err != nil { + return "", fmt.Errorf("failed to upload certificate: %w", err) + } + + return *response.Response.CertificateId, nil +} + +func (d *TencentCLBDeployer) deploy(certId string) error { + cpf := profile.NewClientProfile() + cpf.HttpProfile.Endpoint = "ssl.tencentcloudapi.com" + // 实例化要请求产品的client对象,clientProfile是可选的 + client, _ := ssl.NewClient(d.credential, getDeployString(d.option.DeployConfig, "region"), cpf) + + // 实例化一个请求对象,每个接口都会对应一个request对象 + request := ssl.NewDeployCertificateInstanceRequest() + + request.CertificateId = common.StringPtr(certId) + request.ResourceType = common.StringPtr("clb") + request.Status = common.Int64Ptr(1) + + clbId := getDeployString(d.option.DeployConfig, "clbId") + lsnId := getDeployString(d.option.DeployConfig, "lsnId") + domain := getDeployString(d.option.DeployConfig, "domain") + + if(domain == ""){ + // 未开启SNI,只需要精确到监听器 + request.InstanceIdList = common.StringPtrs([]string{fmt.Sprintf("%s|%s", clbId, lsnId)}) + }else{ + // 开启SNI,需要精确到域名,支持泛域名 + request.InstanceIdList = common.StringPtrs([]string{fmt.Sprintf("%s|%s|%s", clbId, lsnId, domain)}) + } + + + // 返回的resp是一个DeployCertificateInstanceResponse的实例,与请求对象对应 + resp, err := client.DeployCertificateInstance(request) + if err != nil { + return fmt.Errorf("failed to deploy certificate: %w", err) + } + d.infos = append(d.infos, toStr("部署证书", resp.Response)) + return nil +} \ No newline at end of file diff --git a/internal/deployer/tencent-cos.go b/internal/deployer/tencent_cos.go similarity index 100% rename from internal/deployer/tencent-cos.go rename to internal/deployer/tencent_cos.go diff --git a/internal/domain/acme_accounts.go b/internal/domain/acme_accounts.go new file mode 100644 index 00000000..05e25e42 --- /dev/null +++ b/internal/domain/acme_accounts.go @@ -0,0 +1,17 @@ +package domain + +import ( + "time" + + "github.com/go-acme/lego/v4/registration" +) + +type AcmeAccount struct { + Id string + Ca string + Email string + Resource *registration.Resource + Key string + Created time.Time + Updated time.Time +} diff --git a/internal/pkg/utils/x509/x509.go b/internal/pkg/utils/x509/x509.go index 5bc3f287..0239df69 100644 --- a/internal/pkg/utils/x509/x509.go +++ b/internal/pkg/utils/x509/x509.go @@ -1,6 +1,7 @@ package x509 import ( + "crypto/ecdsa" "crypto/x509" "encoding/pem" "fmt" @@ -46,3 +47,35 @@ func EqualCertificate(a, b *x509.Certificate) bool { a.Issuer.SerialNumber == b.Issuer.SerialNumber && a.Subject.SerialNumber == b.Subject.SerialNumber } + +// 将 ECDSA 私钥转换为 PEM 格式的字符串。 +func PrivateKeyToPEM(privateKey *ecdsa.PrivateKey) (string, error) { + data, err := x509.MarshalECPrivateKey(privateKey) + if err != nil { + return "", fmt.Errorf("failed to marshal EC private key: %w", err) + } + + block := &pem.Block{ + Type: "EC PRIVATE KEY", + Bytes: data, + } + + return string(pem.EncodeToMemory(block)), nil +} + +// 从 PEM 编码的私钥字符串解析并返回一个 ECDSA 私钥对象。 +func ParsePrivateKeyFromPEM(privateKeyPem string) (*ecdsa.PrivateKey, error) { + pemData := []byte(privateKeyPem) + + block, _ := pem.Decode(pemData) + if block == nil { + return nil, fmt.Errorf("failed to decode PEM block") + } + + privateKey, err := x509.ParseECPrivateKey(block.Bytes) + if err != nil { + return nil, fmt.Errorf("failed to parse private key: %w", err) + } + + return privateKey, nil +} diff --git a/internal/repository/acme_account.go b/internal/repository/acme_account.go new file mode 100644 index 00000000..9f7e6d21 --- /dev/null +++ b/internal/repository/acme_account.go @@ -0,0 +1,71 @@ +package repository + +import ( + "fmt" + + "github.com/go-acme/lego/v4/registration" + "github.com/pocketbase/dbx" + "github.com/pocketbase/pocketbase/models" + "github.com/usual2970/certimate/internal/domain" + "github.com/usual2970/certimate/internal/utils/app" + "golang.org/x/sync/singleflight" +) + +type AcmeAccountRepository struct{} + +func NewAcmeAccountRepository() *AcmeAccountRepository { + return &AcmeAccountRepository{} +} + +var g singleflight.Group + +func (r *AcmeAccountRepository) GetByCAAndEmail(ca, email string) (*domain.AcmeAccount, error) { + resp, err, _ := g.Do(fmt.Sprintf("acme_account_%s_%s", ca, email), func() (interface{}, error) { + resp, err := app.GetApp().Dao().FindFirstRecordByFilter("acme_accounts", "ca={:ca} && email={:email}", dbx.Params{"ca": ca, "email": email}) + if err != nil { + return nil, err + } + return resp, nil + }) + if err != nil { + return nil, err + } + + if resp == nil { + return nil, fmt.Errorf("acme account not found") + } + + record, ok := resp.(*models.Record) + if !ok { + return nil, fmt.Errorf("acme account not found") + } + + resource := ®istration.Resource{} + if err := record.UnmarshalJSONField("resource", resource); err != nil { + return nil, err + } + + return &domain.AcmeAccount{ + Id: record.GetString("id"), + Ca: record.GetString("ca"), + Email: record.GetString("email"), + Key: record.GetString("key"), + Resource: resource, + Created: record.GetTime("created"), + Updated: record.GetTime("updated"), + }, nil +} + +func (r *AcmeAccountRepository) Save(ca, email, key string, resource *registration.Resource) error { + collection, err := app.GetApp().Dao().FindCollectionByNameOrId("acme_accounts") + if err != nil { + return err + } + + record := models.NewRecord(collection) + record.Set("ca", ca) + record.Set("email", email) + record.Set("key", key) + record.Set("resource", resource) + return app.GetApp().Dao().Save(record) +} diff --git a/migrations/1726569833_updated_domains.go b/migrations/1726569833_updated_domains.go deleted file mode 100644 index 262b0c42..00000000 --- a/migrations/1726569833_updated_domains.go +++ /dev/null @@ -1,85 +0,0 @@ -package migrations - -import ( - "encoding/json" - - "github.com/pocketbase/dbx" - "github.com/pocketbase/pocketbase/daos" - m "github.com/pocketbase/pocketbase/migrations" - "github.com/pocketbase/pocketbase/models/schema" -) - -func init() { - m.Register(func(db dbx.Builder) error { - dao := daos.New(db) - - collection, err := dao.FindCollectionByNameOrId("z3p974ainxjqlvs") - if err != nil { - return err - } - - // update - edit_targetType := &schema.SchemaField{} - if err := json.Unmarshal([]byte(`{ - "system": false, - "id": "srybpixz", - "name": "targetType", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "aliyun-oss", - "aliyun-cdn", - "aliyun-dcdn", - "ssh", - "webhook", - "tencent-cdn", - "qiniu-cdn" - ] - } - }`), edit_targetType); err != nil { - return err - } - collection.Schema.AddField(edit_targetType) - - return dao.SaveCollection(collection) - }, func(db dbx.Builder) error { - dao := daos.New(db) - - collection, err := dao.FindCollectionByNameOrId("z3p974ainxjqlvs") - if err != nil { - return err - } - - // update - edit_targetType := &schema.SchemaField{} - if err := json.Unmarshal([]byte(`{ - "system": false, - "id": "srybpixz", - "name": "targetType", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "aliyun-oss", - "aliyun-cdn", - "ssh", - "webhook", - "tencent-cdn", - "qiniu-cdn" - ] - } - }`), edit_targetType); err != nil { - return err - } - collection.Schema.AddField(edit_targetType) - - return dao.SaveCollection(collection) - }) -} diff --git a/migrations/1726670437_collections_snapshot.go b/migrations/1726670437_collections_snapshot.go deleted file mode 100644 index 07b1e6d3..00000000 --- a/migrations/1726670437_collections_snapshot.go +++ /dev/null @@ -1,694 +0,0 @@ -package migrations - -import ( - "encoding/json" - - "github.com/pocketbase/dbx" - "github.com/pocketbase/pocketbase/daos" - m "github.com/pocketbase/pocketbase/migrations" - "github.com/pocketbase/pocketbase/models" -) - -func init() { - m.Register(func(db dbx.Builder) error { - jsonData := `[ - { - "id": "z3p974ainxjqlvs", - "created": "2024-07-29 10:02:48.334Z", - "updated": "2024-09-18 14:23:22.359Z", - "name": "domains", - "type": "base", - "system": false, - "schema": [ - { - "system": false, - "id": "iuaerpl2", - "name": "domain", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "ukkhuw85", - "name": "email", - "type": "email", - "required": false, - "presentable": false, - "unique": false, - "options": { - "exceptDomains": null, - "onlyDomains": null - } - }, - { - "system": false, - "id": "v98eebqq", - "name": "crontab", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "alc8e9ow", - "name": "access", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "4yzbv8urny5ja1e", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - }, - { - "system": false, - "id": "topsc9bj", - "name": "certUrl", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "vixgq072", - "name": "certStableUrl", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "g3a3sza5", - "name": "privateKey", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "gr6iouny", - "name": "certificate", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "tk6vnrmn", - "name": "issuerCertificate", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "sjo6ibse", - "name": "csr", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "x03n1bkj", - "name": "expiredAt", - "type": "date", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": "", - "max": "" - } - }, - { - "system": false, - "id": "srybpixz", - "name": "targetType", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "aliyun-oss", - "aliyun-cdn", - "aliyun-dcdn", - "ssh", - "webhook", - "tencent-cdn", - "qiniu-cdn" - ] - } - }, - { - "system": false, - "id": "xy7yk0mb", - "name": "targetAccess", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "4yzbv8urny5ja1e", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - }, - { - "system": false, - "id": "6jqeyggw", - "name": "enabled", - "type": "bool", - "required": false, - "presentable": false, - "unique": false, - "options": {} - }, - { - "system": false, - "id": "hdsjcchf", - "name": "deployed", - "type": "bool", - "required": false, - "presentable": false, - "unique": false, - "options": {} - }, - { - "system": false, - "id": "aiya3rev", - "name": "rightnow", - "type": "bool", - "required": false, - "presentable": false, - "unique": false, - "options": {} - }, - { - "system": false, - "id": "ixznmhzc", - "name": "lastDeployedAt", - "type": "date", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": "", - "max": "" - } - }, - { - "system": false, - "id": "ghtlkn5j", - "name": "lastDeployment", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "0a1o4e6sstp694f", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - }, - { - "system": false, - "id": "zfnyj9he", - "name": "variables", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "1bspzuku", - "name": "group", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "teolp9pl72dxlxq", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - }, - { - "system": false, - "id": "g65gfh7a", - "name": "nameservers", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - } - ], - "indexes": [ - "CREATE UNIQUE INDEX ` + "`" + `idx_4ABO6EQ` + "`" + ` ON ` + "`" + `domains` + "`" + ` (` + "`" + `domain` + "`" + `)" - ], - "listRule": null, - "viewRule": null, - "createRule": null, - "updateRule": null, - "deleteRule": null, - "options": {} - }, - { - "id": "4yzbv8urny5ja1e", - "created": "2024-07-29 10:04:39.685Z", - "updated": "2024-09-17 00:53:25.859Z", - "name": "access", - "type": "base", - "system": false, - "schema": [ - { - "system": false, - "id": "geeur58v", - "name": "name", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "iql7jpwx", - "name": "config", - "type": "json", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSize": 2000000 - } - }, - { - "system": false, - "id": "hwy7m03o", - "name": "configType", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "aliyun", - "tencent", - "ssh", - "webhook", - "cloudflare", - "qiniu", - "namesilo", - "godaddy" - ] - } - }, - { - "system": false, - "id": "lr33hiwg", - "name": "deleted", - "type": "date", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": "", - "max": "" - } - }, - { - "system": false, - "id": "hsxcnlvd", - "name": "usage", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "apply", - "deploy", - "all" - ] - } - }, - { - "system": false, - "id": "c8egzzwj", - "name": "group", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "teolp9pl72dxlxq", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - } - ], - "indexes": [ - "CREATE UNIQUE INDEX ` + "`" + `idx_wkoST0j` + "`" + ` ON ` + "`" + `access` + "`" + ` (` + "`" + `name` + "`" + `)" - ], - "listRule": null, - "viewRule": null, - "createRule": null, - "updateRule": null, - "deleteRule": null, - "options": {} - }, - { - "id": "0a1o4e6sstp694f", - "created": "2024-07-30 06:30:27.801Z", - "updated": "2024-09-17 00:53:25.859Z", - "name": "deployments", - "type": "base", - "system": false, - "schema": [ - { - "system": false, - "id": "farvlzk7", - "name": "domain", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "z3p974ainxjqlvs", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - }, - { - "system": false, - "id": "jx5f69i3", - "name": "log", - "type": "json", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSize": 2000000 - } - }, - { - "system": false, - "id": "qbxdtg9q", - "name": "phase", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "check", - "apply", - "deploy" - ] - } - }, - { - "system": false, - "id": "rglrp1hz", - "name": "phaseSuccess", - "type": "bool", - "required": false, - "presentable": false, - "unique": false, - "options": {} - }, - { - "system": false, - "id": "lt1g1blu", - "name": "deployedAt", - "type": "date", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": "", - "max": "" - } - } - ], - "indexes": [], - "listRule": null, - "viewRule": null, - "createRule": null, - "updateRule": null, - "deleteRule": null, - "options": {} - }, - { - "id": "_pb_users_auth_", - "created": "2024-09-12 13:09:54.234Z", - "updated": "2024-09-17 00:53:25.859Z", - "name": "users", - "type": "auth", - "system": false, - "schema": [ - { - "system": false, - "id": "users_name", - "name": "name", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "users_avatar", - "name": "avatar", - "type": "file", - "required": false, - "presentable": false, - "unique": false, - "options": { - "mimeTypes": [ - "image/jpeg", - "image/png", - "image/svg+xml", - "image/gif", - "image/webp" - ], - "thumbs": null, - "maxSelect": 1, - "maxSize": 5242880, - "protected": false - } - } - ], - "indexes": [], - "listRule": "id = @request.auth.id", - "viewRule": "id = @request.auth.id", - "createRule": "", - "updateRule": "id = @request.auth.id", - "deleteRule": "id = @request.auth.id", - "options": { - "allowEmailAuth": true, - "allowOAuth2Auth": true, - "allowUsernameAuth": true, - "exceptEmailDomains": null, - "manageRule": null, - "minPasswordLength": 8, - "onlyEmailDomains": null, - "onlyVerified": false, - "requireEmail": false - } - }, - { - "id": "dy6ccjb60spfy6p", - "created": "2024-09-12 23:12:21.677Z", - "updated": "2024-09-17 00:53:25.860Z", - "name": "settings", - "type": "base", - "system": false, - "schema": [ - { - "system": false, - "id": "1tcmdsdf", - "name": "name", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "f9wyhypi", - "name": "content", - "type": "json", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSize": 2000000 - } - } - ], - "indexes": [ - "CREATE UNIQUE INDEX ` + "`" + `idx_RO7X9Vw` + "`" + ` ON ` + "`" + `settings` + "`" + ` (` + "`" + `name` + "`" + `)" - ], - "listRule": null, - "viewRule": null, - "createRule": null, - "updateRule": null, - "deleteRule": null, - "options": {} - }, - { - "id": "teolp9pl72dxlxq", - "created": "2024-09-13 12:51:05.611Z", - "updated": "2024-09-17 00:53:25.860Z", - "name": "access_groups", - "type": "base", - "system": false, - "schema": [ - { - "system": false, - "id": "7sajiv6i", - "name": "name", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "xp8admif", - "name": "access", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "4yzbv8urny5ja1e", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": null, - "displayFields": null - } - } - ], - "indexes": [ - "CREATE UNIQUE INDEX ` + "`" + `idx_RgRXp0R` + "`" + ` ON ` + "`" + `access_groups` + "`" + ` (` + "`" + `name` + "`" + `)" - ], - "listRule": null, - "viewRule": null, - "createRule": null, - "updateRule": null, - "deleteRule": null, - "options": {} - } - ]` - - collections := []*models.Collection{} - if err := json.Unmarshal([]byte(jsonData), &collections); err != nil { - return err - } - - return daos.New(db).ImportCollections(collections, true, nil) - }, func(db dbx.Builder) error { - return nil - }) -} diff --git a/migrations/1727006428_collections_snapshot.go b/migrations/1727006428_collections_snapshot.go deleted file mode 100644 index abd631d3..00000000 --- a/migrations/1727006428_collections_snapshot.go +++ /dev/null @@ -1,704 +0,0 @@ -package migrations - -import ( - "encoding/json" - - "github.com/pocketbase/dbx" - "github.com/pocketbase/pocketbase/daos" - m "github.com/pocketbase/pocketbase/migrations" - "github.com/pocketbase/pocketbase/models" -) - -func init() { - m.Register(func(db dbx.Builder) error { - jsonData := `[ - { - "id": "z3p974ainxjqlvs", - "created": "2024-07-29 10:02:48.334Z", - "updated": "2024-09-19 00:27:35.936Z", - "name": "domains", - "type": "base", - "system": false, - "schema": [ - { - "system": false, - "id": "iuaerpl2", - "name": "domain", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "ukkhuw85", - "name": "email", - "type": "email", - "required": false, - "presentable": false, - "unique": false, - "options": { - "exceptDomains": null, - "onlyDomains": null - } - }, - { - "system": false, - "id": "v98eebqq", - "name": "crontab", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "alc8e9ow", - "name": "access", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "4yzbv8urny5ja1e", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - }, - { - "system": false, - "id": "topsc9bj", - "name": "certUrl", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "vixgq072", - "name": "certStableUrl", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "g3a3sza5", - "name": "privateKey", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "gr6iouny", - "name": "certificate", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "tk6vnrmn", - "name": "issuerCertificate", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "sjo6ibse", - "name": "csr", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "x03n1bkj", - "name": "expiredAt", - "type": "date", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": "", - "max": "" - } - }, - { - "system": false, - "id": "srybpixz", - "name": "targetType", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "aliyun-oss", - "aliyun-cdn", - "aliyun-dcdn", - "ssh", - "webhook", - "tencent-cdn", - "qiniu-cdn" - ] - } - }, - { - "system": false, - "id": "xy7yk0mb", - "name": "targetAccess", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "4yzbv8urny5ja1e", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - }, - { - "system": false, - "id": "6jqeyggw", - "name": "enabled", - "type": "bool", - "required": false, - "presentable": false, - "unique": false, - "options": {} - }, - { - "system": false, - "id": "hdsjcchf", - "name": "deployed", - "type": "bool", - "required": false, - "presentable": false, - "unique": false, - "options": {} - }, - { - "system": false, - "id": "aiya3rev", - "name": "rightnow", - "type": "bool", - "required": false, - "presentable": false, - "unique": false, - "options": {} - }, - { - "system": false, - "id": "ixznmhzc", - "name": "lastDeployedAt", - "type": "date", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": "", - "max": "" - } - }, - { - "system": false, - "id": "ghtlkn5j", - "name": "lastDeployment", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "0a1o4e6sstp694f", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - }, - { - "system": false, - "id": "zfnyj9he", - "name": "variables", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "1bspzuku", - "name": "group", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "teolp9pl72dxlxq", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - }, - { - "system": false, - "id": "g65gfh7a", - "name": "nameservers", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - } - ], - "indexes": [ - "CREATE UNIQUE INDEX ` + "`" + `idx_4ABO6EQ` + "`" + ` ON ` + "`" + `domains` + "`" + ` (` + "`" + `domain` + "`" + `)" - ], - "listRule": null, - "viewRule": null, - "createRule": null, - "updateRule": null, - "deleteRule": null, - "options": {} - }, - { - "id": "4yzbv8urny5ja1e", - "created": "2024-07-29 10:04:39.685Z", - "updated": "2024-09-19 00:27:35.936Z", - "name": "access", - "type": "base", - "system": false, - "schema": [ - { - "system": false, - "id": "geeur58v", - "name": "name", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "iql7jpwx", - "name": "config", - "type": "json", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSize": 2000000 - } - }, - { - "system": false, - "id": "hwy7m03o", - "name": "configType", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "aliyun", - "tencent", - "ssh", - "webhook", - "cloudflare", - "qiniu", - "namesilo", - "godaddy" - ] - } - }, - { - "system": false, - "id": "lr33hiwg", - "name": "deleted", - "type": "date", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": "", - "max": "" - } - }, - { - "system": false, - "id": "hsxcnlvd", - "name": "usage", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "apply", - "deploy", - "all" - ] - } - }, - { - "system": false, - "id": "c8egzzwj", - "name": "group", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "teolp9pl72dxlxq", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - } - ], - "indexes": [ - "CREATE UNIQUE INDEX ` + "`" + `idx_wkoST0j` + "`" + ` ON ` + "`" + `access` + "`" + ` (` + "`" + `name` + "`" + `)" - ], - "listRule": null, - "viewRule": null, - "createRule": null, - "updateRule": null, - "deleteRule": null, - "options": {} - }, - { - "id": "0a1o4e6sstp694f", - "created": "2024-07-30 06:30:27.801Z", - "updated": "2024-09-22 11:46:35.167Z", - "name": "deployments", - "type": "base", - "system": false, - "schema": [ - { - "system": false, - "id": "farvlzk7", - "name": "domain", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "z3p974ainxjqlvs", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - }, - { - "system": false, - "id": "jx5f69i3", - "name": "log", - "type": "json", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSize": 2000000 - } - }, - { - "system": false, - "id": "qbxdtg9q", - "name": "phase", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "check", - "apply", - "deploy" - ] - } - }, - { - "system": false, - "id": "rglrp1hz", - "name": "phaseSuccess", - "type": "bool", - "required": false, - "presentable": false, - "unique": false, - "options": {} - }, - { - "system": false, - "id": "lt1g1blu", - "name": "deployedAt", - "type": "date", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": "", - "max": "" - } - }, - { - "system": false, - "id": "wledpzgb", - "name": "wholeSuccess", - "type": "bool", - "required": false, - "presentable": false, - "unique": false, - "options": {} - } - ], - "indexes": [], - "listRule": null, - "viewRule": null, - "createRule": null, - "updateRule": null, - "deleteRule": null, - "options": {} - }, - { - "id": "_pb_users_auth_", - "created": "2024-09-12 13:09:54.234Z", - "updated": "2024-09-19 00:27:35.937Z", - "name": "users", - "type": "auth", - "system": false, - "schema": [ - { - "system": false, - "id": "users_name", - "name": "name", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "users_avatar", - "name": "avatar", - "type": "file", - "required": false, - "presentable": false, - "unique": false, - "options": { - "mimeTypes": [ - "image/jpeg", - "image/png", - "image/svg+xml", - "image/gif", - "image/webp" - ], - "thumbs": null, - "maxSelect": 1, - "maxSize": 5242880, - "protected": false - } - } - ], - "indexes": [], - "listRule": "id = @request.auth.id", - "viewRule": "id = @request.auth.id", - "createRule": "", - "updateRule": "id = @request.auth.id", - "deleteRule": "id = @request.auth.id", - "options": { - "allowEmailAuth": true, - "allowOAuth2Auth": true, - "allowUsernameAuth": true, - "exceptEmailDomains": null, - "manageRule": null, - "minPasswordLength": 8, - "onlyEmailDomains": null, - "onlyVerified": false, - "requireEmail": false - } - }, - { - "id": "dy6ccjb60spfy6p", - "created": "2024-09-12 23:12:21.677Z", - "updated": "2024-09-19 00:27:35.937Z", - "name": "settings", - "type": "base", - "system": false, - "schema": [ - { - "system": false, - "id": "1tcmdsdf", - "name": "name", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "f9wyhypi", - "name": "content", - "type": "json", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSize": 2000000 - } - } - ], - "indexes": [ - "CREATE UNIQUE INDEX ` + "`" + `idx_RO7X9Vw` + "`" + ` ON ` + "`" + `settings` + "`" + ` (` + "`" + `name` + "`" + `)" - ], - "listRule": null, - "viewRule": null, - "createRule": null, - "updateRule": null, - "deleteRule": null, - "options": {} - }, - { - "id": "teolp9pl72dxlxq", - "created": "2024-09-13 12:51:05.611Z", - "updated": "2024-09-19 00:27:35.937Z", - "name": "access_groups", - "type": "base", - "system": false, - "schema": [ - { - "system": false, - "id": "7sajiv6i", - "name": "name", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "xp8admif", - "name": "access", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "4yzbv8urny5ja1e", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": null, - "displayFields": null - } - } - ], - "indexes": [ - "CREATE UNIQUE INDEX ` + "`" + `idx_RgRXp0R` + "`" + ` ON ` + "`" + `access_groups` + "`" + ` (` + "`" + `name` + "`" + `)" - ], - "listRule": null, - "viewRule": null, - "createRule": null, - "updateRule": null, - "deleteRule": null, - "options": {} - } - ]` - - collections := []*models.Collection{} - if err := json.Unmarshal([]byte(jsonData), &collections); err != nil { - return err - } - - return daos.New(db).ImportCollections(collections, true, nil) - }, func(db dbx.Builder) error { - return nil - }) -} diff --git a/migrations/1727188693_collections_snapshot.go b/migrations/1727188693_collections_snapshot.go deleted file mode 100644 index b6838203..00000000 --- a/migrations/1727188693_collections_snapshot.go +++ /dev/null @@ -1,704 +0,0 @@ -package migrations - -import ( - "encoding/json" - - "github.com/pocketbase/dbx" - "github.com/pocketbase/pocketbase/daos" - m "github.com/pocketbase/pocketbase/migrations" - "github.com/pocketbase/pocketbase/models" -) - -func init() { - m.Register(func(db dbx.Builder) error { - jsonData := `[ - { - "id": "z3p974ainxjqlvs", - "created": "2024-07-29 10:02:48.334Z", - "updated": "2024-09-22 12:08:14.644Z", - "name": "domains", - "type": "base", - "system": false, - "schema": [ - { - "system": false, - "id": "iuaerpl2", - "name": "domain", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "ukkhuw85", - "name": "email", - "type": "email", - "required": false, - "presentable": false, - "unique": false, - "options": { - "exceptDomains": null, - "onlyDomains": null - } - }, - { - "system": false, - "id": "v98eebqq", - "name": "crontab", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "alc8e9ow", - "name": "access", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "4yzbv8urny5ja1e", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - }, - { - "system": false, - "id": "topsc9bj", - "name": "certUrl", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "vixgq072", - "name": "certStableUrl", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "g3a3sza5", - "name": "privateKey", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "gr6iouny", - "name": "certificate", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "tk6vnrmn", - "name": "issuerCertificate", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "sjo6ibse", - "name": "csr", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "x03n1bkj", - "name": "expiredAt", - "type": "date", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": "", - "max": "" - } - }, - { - "system": false, - "id": "srybpixz", - "name": "targetType", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "aliyun-oss", - "aliyun-cdn", - "aliyun-dcdn", - "ssh", - "webhook", - "tencent-cdn", - "qiniu-cdn" - ] - } - }, - { - "system": false, - "id": "xy7yk0mb", - "name": "targetAccess", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "4yzbv8urny5ja1e", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - }, - { - "system": false, - "id": "6jqeyggw", - "name": "enabled", - "type": "bool", - "required": false, - "presentable": false, - "unique": false, - "options": {} - }, - { - "system": false, - "id": "hdsjcchf", - "name": "deployed", - "type": "bool", - "required": false, - "presentable": false, - "unique": false, - "options": {} - }, - { - "system": false, - "id": "aiya3rev", - "name": "rightnow", - "type": "bool", - "required": false, - "presentable": false, - "unique": false, - "options": {} - }, - { - "system": false, - "id": "ixznmhzc", - "name": "lastDeployedAt", - "type": "date", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": "", - "max": "" - } - }, - { - "system": false, - "id": "ghtlkn5j", - "name": "lastDeployment", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "0a1o4e6sstp694f", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - }, - { - "system": false, - "id": "zfnyj9he", - "name": "variables", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "1bspzuku", - "name": "group", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "teolp9pl72dxlxq", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - }, - { - "system": false, - "id": "g65gfh7a", - "name": "nameservers", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - } - ], - "indexes": [ - "CREATE UNIQUE INDEX ` + "`" + `idx_4ABO6EQ` + "`" + ` ON ` + "`" + `domains` + "`" + ` (` + "`" + `domain` + "`" + `)" - ], - "listRule": null, - "viewRule": null, - "createRule": null, - "updateRule": null, - "deleteRule": null, - "options": {} - }, - { - "id": "4yzbv8urny5ja1e", - "created": "2024-07-29 10:04:39.685Z", - "updated": "2024-09-22 12:08:14.644Z", - "name": "access", - "type": "base", - "system": false, - "schema": [ - { - "system": false, - "id": "geeur58v", - "name": "name", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "iql7jpwx", - "name": "config", - "type": "json", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSize": 2000000 - } - }, - { - "system": false, - "id": "hwy7m03o", - "name": "configType", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "aliyun", - "tencent", - "ssh", - "webhook", - "cloudflare", - "qiniu", - "namesilo", - "godaddy" - ] - } - }, - { - "system": false, - "id": "lr33hiwg", - "name": "deleted", - "type": "date", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": "", - "max": "" - } - }, - { - "system": false, - "id": "hsxcnlvd", - "name": "usage", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "apply", - "deploy", - "all" - ] - } - }, - { - "system": false, - "id": "c8egzzwj", - "name": "group", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "teolp9pl72dxlxq", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - } - ], - "indexes": [ - "CREATE UNIQUE INDEX ` + "`" + `idx_wkoST0j` + "`" + ` ON ` + "`" + `access` + "`" + ` (` + "`" + `name` + "`" + `)" - ], - "listRule": null, - "viewRule": null, - "createRule": null, - "updateRule": null, - "deleteRule": null, - "options": {} - }, - { - "id": "0a1o4e6sstp694f", - "created": "2024-07-30 06:30:27.801Z", - "updated": "2024-09-22 12:08:14.644Z", - "name": "deployments", - "type": "base", - "system": false, - "schema": [ - { - "system": false, - "id": "farvlzk7", - "name": "domain", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "z3p974ainxjqlvs", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - }, - { - "system": false, - "id": "jx5f69i3", - "name": "log", - "type": "json", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSize": 2000000 - } - }, - { - "system": false, - "id": "qbxdtg9q", - "name": "phase", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "check", - "apply", - "deploy" - ] - } - }, - { - "system": false, - "id": "rglrp1hz", - "name": "phaseSuccess", - "type": "bool", - "required": false, - "presentable": false, - "unique": false, - "options": {} - }, - { - "system": false, - "id": "lt1g1blu", - "name": "deployedAt", - "type": "date", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": "", - "max": "" - } - }, - { - "system": false, - "id": "wledpzgb", - "name": "wholeSuccess", - "type": "bool", - "required": false, - "presentable": false, - "unique": false, - "options": {} - } - ], - "indexes": [], - "listRule": null, - "viewRule": null, - "createRule": null, - "updateRule": null, - "deleteRule": null, - "options": {} - }, - { - "id": "_pb_users_auth_", - "created": "2024-09-12 13:09:54.234Z", - "updated": "2024-09-22 12:08:14.644Z", - "name": "users", - "type": "auth", - "system": false, - "schema": [ - { - "system": false, - "id": "users_name", - "name": "name", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "users_avatar", - "name": "avatar", - "type": "file", - "required": false, - "presentable": false, - "unique": false, - "options": { - "mimeTypes": [ - "image/jpeg", - "image/png", - "image/svg+xml", - "image/gif", - "image/webp" - ], - "thumbs": null, - "maxSelect": 1, - "maxSize": 5242880, - "protected": false - } - } - ], - "indexes": [], - "listRule": "id = @request.auth.id", - "viewRule": "id = @request.auth.id", - "createRule": "", - "updateRule": "id = @request.auth.id", - "deleteRule": "id = @request.auth.id", - "options": { - "allowEmailAuth": true, - "allowOAuth2Auth": true, - "allowUsernameAuth": true, - "exceptEmailDomains": null, - "manageRule": null, - "minPasswordLength": 8, - "onlyEmailDomains": null, - "onlyVerified": false, - "requireEmail": false - } - }, - { - "id": "dy6ccjb60spfy6p", - "created": "2024-09-12 23:12:21.677Z", - "updated": "2024-09-22 12:08:14.644Z", - "name": "settings", - "type": "base", - "system": false, - "schema": [ - { - "system": false, - "id": "1tcmdsdf", - "name": "name", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "f9wyhypi", - "name": "content", - "type": "json", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSize": 2000000 - } - } - ], - "indexes": [ - "CREATE UNIQUE INDEX ` + "`" + `idx_RO7X9Vw` + "`" + ` ON ` + "`" + `settings` + "`" + ` (` + "`" + `name` + "`" + `)" - ], - "listRule": null, - "viewRule": null, - "createRule": null, - "updateRule": null, - "deleteRule": null, - "options": {} - }, - { - "id": "teolp9pl72dxlxq", - "created": "2024-09-13 12:51:05.611Z", - "updated": "2024-09-22 12:08:14.645Z", - "name": "access_groups", - "type": "base", - "system": false, - "schema": [ - { - "system": false, - "id": "7sajiv6i", - "name": "name", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "xp8admif", - "name": "access", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "4yzbv8urny5ja1e", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": null, - "displayFields": null - } - } - ], - "indexes": [ - "CREATE UNIQUE INDEX ` + "`" + `idx_RgRXp0R` + "`" + ` ON ` + "`" + `access_groups` + "`" + ` (` + "`" + `name` + "`" + `)" - ], - "listRule": null, - "viewRule": null, - "createRule": null, - "updateRule": null, - "deleteRule": null, - "options": {} - } - ]` - - collections := []*models.Collection{} - if err := json.Unmarshal([]byte(jsonData), &collections); err != nil { - return err - } - - return daos.New(db).ImportCollections(collections, true, nil) - }, func(db dbx.Builder) error { - return nil - }) -} diff --git a/migrations/1727341442_collections_snapshot.go b/migrations/1727341442_collections_snapshot.go deleted file mode 100644 index f3982d16..00000000 --- a/migrations/1727341442_collections_snapshot.go +++ /dev/null @@ -1,706 +0,0 @@ -package migrations - -import ( - "encoding/json" - - "github.com/pocketbase/dbx" - "github.com/pocketbase/pocketbase/daos" - m "github.com/pocketbase/pocketbase/migrations" - "github.com/pocketbase/pocketbase/models" -) - -func init() { - m.Register(func(db dbx.Builder) error { - jsonData := `[ - { - "id": "z3p974ainxjqlvs", - "created": "2024-07-29 10:02:48.334Z", - "updated": "2024-09-26 08:20:28.305Z", - "name": "domains", - "type": "base", - "system": false, - "schema": [ - { - "system": false, - "id": "iuaerpl2", - "name": "domain", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "ukkhuw85", - "name": "email", - "type": "email", - "required": false, - "presentable": false, - "unique": false, - "options": { - "exceptDomains": null, - "onlyDomains": null - } - }, - { - "system": false, - "id": "v98eebqq", - "name": "crontab", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "alc8e9ow", - "name": "access", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "4yzbv8urny5ja1e", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - }, - { - "system": false, - "id": "topsc9bj", - "name": "certUrl", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "vixgq072", - "name": "certStableUrl", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "g3a3sza5", - "name": "privateKey", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "gr6iouny", - "name": "certificate", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "tk6vnrmn", - "name": "issuerCertificate", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "sjo6ibse", - "name": "csr", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "x03n1bkj", - "name": "expiredAt", - "type": "date", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": "", - "max": "" - } - }, - { - "system": false, - "id": "srybpixz", - "name": "targetType", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "aliyun-oss", - "aliyun-cdn", - "aliyun-dcdn", - "ssh", - "webhook", - "tencent-cdn", - "qiniu-cdn", - "local" - ] - } - }, - { - "system": false, - "id": "xy7yk0mb", - "name": "targetAccess", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "4yzbv8urny5ja1e", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - }, - { - "system": false, - "id": "6jqeyggw", - "name": "enabled", - "type": "bool", - "required": false, - "presentable": false, - "unique": false, - "options": {} - }, - { - "system": false, - "id": "hdsjcchf", - "name": "deployed", - "type": "bool", - "required": false, - "presentable": false, - "unique": false, - "options": {} - }, - { - "system": false, - "id": "aiya3rev", - "name": "rightnow", - "type": "bool", - "required": false, - "presentable": false, - "unique": false, - "options": {} - }, - { - "system": false, - "id": "ixznmhzc", - "name": "lastDeployedAt", - "type": "date", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": "", - "max": "" - } - }, - { - "system": false, - "id": "ghtlkn5j", - "name": "lastDeployment", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "0a1o4e6sstp694f", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - }, - { - "system": false, - "id": "zfnyj9he", - "name": "variables", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "1bspzuku", - "name": "group", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "teolp9pl72dxlxq", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - }, - { - "system": false, - "id": "g65gfh7a", - "name": "nameservers", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - } - ], - "indexes": [ - "CREATE UNIQUE INDEX ` + "`" + `idx_4ABO6EQ` + "`" + ` ON ` + "`" + `domains` + "`" + ` (` + "`" + `domain` + "`" + `)" - ], - "listRule": null, - "viewRule": null, - "createRule": null, - "updateRule": null, - "deleteRule": null, - "options": {} - }, - { - "id": "4yzbv8urny5ja1e", - "created": "2024-07-29 10:04:39.685Z", - "updated": "2024-09-26 08:36:59.632Z", - "name": "access", - "type": "base", - "system": false, - "schema": [ - { - "system": false, - "id": "geeur58v", - "name": "name", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "iql7jpwx", - "name": "config", - "type": "json", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSize": 2000000 - } - }, - { - "system": false, - "id": "hwy7m03o", - "name": "configType", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "aliyun", - "tencent", - "ssh", - "webhook", - "cloudflare", - "qiniu", - "namesilo", - "godaddy", - "local" - ] - } - }, - { - "system": false, - "id": "lr33hiwg", - "name": "deleted", - "type": "date", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": "", - "max": "" - } - }, - { - "system": false, - "id": "hsxcnlvd", - "name": "usage", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "apply", - "deploy", - "all" - ] - } - }, - { - "system": false, - "id": "c8egzzwj", - "name": "group", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "teolp9pl72dxlxq", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - } - ], - "indexes": [ - "CREATE UNIQUE INDEX ` + "`" + `idx_wkoST0j` + "`" + ` ON ` + "`" + `access` + "`" + ` (` + "`" + `name` + "`" + `)" - ], - "listRule": null, - "viewRule": null, - "createRule": null, - "updateRule": null, - "deleteRule": null, - "options": {} - }, - { - "id": "0a1o4e6sstp694f", - "created": "2024-07-30 06:30:27.801Z", - "updated": "2024-09-24 14:44:48.041Z", - "name": "deployments", - "type": "base", - "system": false, - "schema": [ - { - "system": false, - "id": "farvlzk7", - "name": "domain", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "z3p974ainxjqlvs", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": 1, - "displayFields": null - } - }, - { - "system": false, - "id": "jx5f69i3", - "name": "log", - "type": "json", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSize": 2000000 - } - }, - { - "system": false, - "id": "qbxdtg9q", - "name": "phase", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "check", - "apply", - "deploy" - ] - } - }, - { - "system": false, - "id": "rglrp1hz", - "name": "phaseSuccess", - "type": "bool", - "required": false, - "presentable": false, - "unique": false, - "options": {} - }, - { - "system": false, - "id": "lt1g1blu", - "name": "deployedAt", - "type": "date", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": "", - "max": "" - } - }, - { - "system": false, - "id": "wledpzgb", - "name": "wholeSuccess", - "type": "bool", - "required": false, - "presentable": false, - "unique": false, - "options": {} - } - ], - "indexes": [], - "listRule": null, - "viewRule": null, - "createRule": null, - "updateRule": null, - "deleteRule": null, - "options": {} - }, - { - "id": "_pb_users_auth_", - "created": "2024-09-12 13:09:54.234Z", - "updated": "2024-09-24 14:44:48.041Z", - "name": "users", - "type": "auth", - "system": false, - "schema": [ - { - "system": false, - "id": "users_name", - "name": "name", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "users_avatar", - "name": "avatar", - "type": "file", - "required": false, - "presentable": false, - "unique": false, - "options": { - "mimeTypes": [ - "image/jpeg", - "image/png", - "image/svg+xml", - "image/gif", - "image/webp" - ], - "thumbs": null, - "maxSelect": 1, - "maxSize": 5242880, - "protected": false - } - } - ], - "indexes": [], - "listRule": "id = @request.auth.id", - "viewRule": "id = @request.auth.id", - "createRule": "", - "updateRule": "id = @request.auth.id", - "deleteRule": "id = @request.auth.id", - "options": { - "allowEmailAuth": true, - "allowOAuth2Auth": true, - "allowUsernameAuth": true, - "exceptEmailDomains": null, - "manageRule": null, - "minPasswordLength": 8, - "onlyEmailDomains": null, - "onlyVerified": false, - "requireEmail": false - } - }, - { - "id": "dy6ccjb60spfy6p", - "created": "2024-09-12 23:12:21.677Z", - "updated": "2024-09-24 14:44:48.041Z", - "name": "settings", - "type": "base", - "system": false, - "schema": [ - { - "system": false, - "id": "1tcmdsdf", - "name": "name", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "f9wyhypi", - "name": "content", - "type": "json", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSize": 2000000 - } - } - ], - "indexes": [ - "CREATE UNIQUE INDEX ` + "`" + `idx_RO7X9Vw` + "`" + ` ON ` + "`" + `settings` + "`" + ` (` + "`" + `name` + "`" + `)" - ], - "listRule": null, - "viewRule": null, - "createRule": null, - "updateRule": null, - "deleteRule": null, - "options": {} - }, - { - "id": "teolp9pl72dxlxq", - "created": "2024-09-13 12:51:05.611Z", - "updated": "2024-09-24 14:44:48.041Z", - "name": "access_groups", - "type": "base", - "system": false, - "schema": [ - { - "system": false, - "id": "7sajiv6i", - "name": "name", - "type": "text", - "required": false, - "presentable": false, - "unique": false, - "options": { - "min": null, - "max": null, - "pattern": "" - } - }, - { - "system": false, - "id": "xp8admif", - "name": "access", - "type": "relation", - "required": false, - "presentable": false, - "unique": false, - "options": { - "collectionId": "4yzbv8urny5ja1e", - "cascadeDelete": false, - "minSelect": null, - "maxSelect": null, - "displayFields": null - } - } - ], - "indexes": [ - "CREATE UNIQUE INDEX ` + "`" + `idx_RgRXp0R` + "`" + ` ON ` + "`" + `access_groups` + "`" + ` (` + "`" + `name` + "`" + `)" - ], - "listRule": null, - "viewRule": null, - "createRule": null, - "updateRule": null, - "deleteRule": null, - "options": {} - } - ]` - - collections := []*models.Collection{} - if err := json.Unmarshal([]byte(jsonData), &collections); err != nil { - return err - } - - return daos.New(db).ImportCollections(collections, true, nil) - }, func(db dbx.Builder) error { - return nil - }) -} diff --git a/migrations/1728610007_updated_access.go b/migrations/1728610007_updated_access.go deleted file mode 100644 index 48f3a74a..00000000 --- a/migrations/1728610007_updated_access.go +++ /dev/null @@ -1,92 +0,0 @@ -package migrations - -import ( - "encoding/json" - - "github.com/pocketbase/dbx" - "github.com/pocketbase/pocketbase/daos" - m "github.com/pocketbase/pocketbase/migrations" - "github.com/pocketbase/pocketbase/models/schema" -) - -func init() { - m.Register(func(db dbx.Builder) error { - dao := daos.New(db) - - collection, err := dao.FindCollectionByNameOrId("4yzbv8urny5ja1e") - if err != nil { - return err - } - - // update - edit_configType := &schema.SchemaField{} - if err := json.Unmarshal([]byte(`{ - "system": false, - "id": "hwy7m03o", - "name": "configType", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "aliyun", - "tencent", - "huaweicloud", - "qiniu", - "cloudflare", - "namesilo", - "godaddy", - "local", - "ssh", - "webhook" - ] - } - }`), edit_configType); err != nil { - return err - } - collection.Schema.AddField(edit_configType) - - return dao.SaveCollection(collection) - }, func(db dbx.Builder) error { - dao := daos.New(db) - - collection, err := dao.FindCollectionByNameOrId("4yzbv8urny5ja1e") - if err != nil { - return err - } - - // update - edit_configType := &schema.SchemaField{} - if err := json.Unmarshal([]byte(`{ - "system": false, - "id": "hwy7m03o", - "name": "configType", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "aliyun", - "tencent", - "huaweicloud", - "ssh", - "webhook", - "cloudflare", - "qiniu", - "namesilo", - "godaddy", - "local" - ] - } - }`), edit_configType); err != nil { - return err - } - collection.Schema.AddField(edit_configType) - - return dao.SaveCollection(collection) - }) -} diff --git a/migrations/1729160433_updated_access.go b/migrations/1729160433_updated_access.go deleted file mode 100644 index 05e14cc0..00000000 --- a/migrations/1729160433_updated_access.go +++ /dev/null @@ -1,93 +0,0 @@ -package migrations - -import ( - "encoding/json" - - "github.com/pocketbase/dbx" - "github.com/pocketbase/pocketbase/daos" - m "github.com/pocketbase/pocketbase/migrations" - "github.com/pocketbase/pocketbase/models/schema" -) - -func init() { - m.Register(func(db dbx.Builder) error { - dao := daos.New(db) - - collection, err := dao.FindCollectionByNameOrId("4yzbv8urny5ja1e") - if err != nil { - return err - } - - // update - edit_configType := &schema.SchemaField{} - if err := json.Unmarshal([]byte(`{ - "system": false, - "id": "hwy7m03o", - "name": "configType", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "aliyun", - "tencent", - "huaweicloud", - "qiniu", - "aws", - "cloudflare", - "namesilo", - "godaddy", - "local", - "ssh", - "webhook" - ] - } - }`), edit_configType); err != nil { - return err - } - collection.Schema.AddField(edit_configType) - - return dao.SaveCollection(collection) - }, func(db dbx.Builder) error { - dao := daos.New(db) - - collection, err := dao.FindCollectionByNameOrId("4yzbv8urny5ja1e") - if err != nil { - return err - } - - // update - edit_configType := &schema.SchemaField{} - if err := json.Unmarshal([]byte(`{ - "system": false, - "id": "hwy7m03o", - "name": "configType", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "aliyun", - "tencent", - "huaweicloud", - "qiniu", - "cloudflare", - "namesilo", - "godaddy", - "local", - "ssh", - "webhook" - ] - } - }`), edit_configType); err != nil { - return err - } - collection.Schema.AddField(edit_configType) - - return dao.SaveCollection(collection) - }) -} diff --git a/migrations/1729241998_updated_access.go b/migrations/1729241998_updated_access.go deleted file mode 100644 index cfa43c23..00000000 --- a/migrations/1729241998_updated_access.go +++ /dev/null @@ -1,95 +0,0 @@ -package migrations - -import ( - "encoding/json" - - "github.com/pocketbase/dbx" - "github.com/pocketbase/pocketbase/daos" - m "github.com/pocketbase/pocketbase/migrations" - "github.com/pocketbase/pocketbase/models/schema" -) - -func init() { - m.Register(func(db dbx.Builder) error { - dao := daos.New(db) - - collection, err := dao.FindCollectionByNameOrId("4yzbv8urny5ja1e") - if err != nil { - return err - } - - // update - edit_configType := &schema.SchemaField{} - if err := json.Unmarshal([]byte(`{ - "system": false, - "id": "hwy7m03o", - "name": "configType", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "aliyun", - "tencent", - "huaweicloud", - "qiniu", - "aws", - "cloudflare", - "namesilo", - "godaddy", - "local", - "ssh", - "webhook", - "k8s" - ] - } - }`), edit_configType); err != nil { - return err - } - collection.Schema.AddField(edit_configType) - - return dao.SaveCollection(collection) - }, func(db dbx.Builder) error { - dao := daos.New(db) - - collection, err := dao.FindCollectionByNameOrId("4yzbv8urny5ja1e") - if err != nil { - return err - } - - // update - edit_configType := &schema.SchemaField{} - if err := json.Unmarshal([]byte(`{ - "system": false, - "id": "hwy7m03o", - "name": "configType", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "aliyun", - "tencent", - "huaweicloud", - "qiniu", - "aws", - "cloudflare", - "namesilo", - "godaddy", - "local", - "ssh", - "webhook" - ] - } - }`), edit_configType); err != nil { - return err - } - collection.Schema.AddField(edit_configType) - - return dao.SaveCollection(collection) - }) -} diff --git a/migrations/1729339341_updated_access.go b/migrations/1729339341_updated_access.go deleted file mode 100644 index 51561a76..00000000 --- a/migrations/1729339341_updated_access.go +++ /dev/null @@ -1,98 +0,0 @@ -package migrations - -import ( - "encoding/json" - - "github.com/pocketbase/dbx" - "github.com/pocketbase/pocketbase/daos" - m "github.com/pocketbase/pocketbase/migrations" - "github.com/pocketbase/pocketbase/models/schema" -) - -func init() { - m.Register(func(db dbx.Builder) error { - dao := daos.New(db) - - collection, err := dao.FindCollectionByNameOrId("4yzbv8urny5ja1e") - if err != nil { - return err - } - - // update - edit_configType := &schema.SchemaField{} - if err := json.Unmarshal([]byte(`{ - "system": false, - "id": "hwy7m03o", - "name": "configType", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "aliyun", - "tencent", - "huaweicloud", - "qiniu", - "aws", - "cloudflare", - "namesilo", - "godaddy", - "pdns", - "httpreq", - "local", - "ssh", - "webhook", - "k8s" - ] - } - }`), edit_configType); err != nil { - return err - } - collection.Schema.AddField(edit_configType) - - return dao.SaveCollection(collection) - }, func(db dbx.Builder) error { - dao := daos.New(db) - - collection, err := dao.FindCollectionByNameOrId("4yzbv8urny5ja1e") - if err != nil { - return err - } - - // update - edit_configType := &schema.SchemaField{} - if err := json.Unmarshal([]byte(`{ - "system": false, - "id": "hwy7m03o", - "name": "configType", - "type": "select", - "required": false, - "presentable": false, - "unique": false, - "options": { - "maxSelect": 1, - "values": [ - "aliyun", - "tencent", - "huaweicloud", - "qiniu", - "aws", - "cloudflare", - "namesilo", - "godaddy", - "local", - "ssh", - "webhook", - "k8s" - ] - } - }`), edit_configType); err != nil { - return err - } - collection.Schema.AddField(edit_configType) - - return dao.SaveCollection(collection) - }) -} diff --git a/migrations/1728778480_collections_snapshot.go b/migrations/1729671262_collections_snapshot.go similarity index 89% rename from migrations/1728778480_collections_snapshot.go rename to migrations/1729671262_collections_snapshot.go index 7134989e..f72fdbe0 100644 --- a/migrations/1728778480_collections_snapshot.go +++ b/migrations/1729671262_collections_snapshot.go @@ -15,7 +15,7 @@ func init() { { "id": "z3p974ainxjqlvs", "created": "2024-07-29 10:02:48.334Z", - "updated": "2024-10-08 06:50:56.637Z", + "updated": "2024-10-13 02:40:36.312Z", "name": "domains", "type": "base", "system": false, @@ -353,7 +353,7 @@ func init() { { "id": "4yzbv8urny5ja1e", "created": "2024-07-29 10:04:39.685Z", - "updated": "2024-10-11 13:55:13.777Z", + "updated": "2024-10-20 04:36:58.692Z", "name": "access", "type": "base", "system": false, @@ -399,12 +399,16 @@ func init() { "tencent", "huaweicloud", "qiniu", + "aws", "cloudflare", "namesilo", "godaddy", + "pdns", + "httpreq", "local", "ssh", - "webhook" + "webhook", + "k8s" ] } }, @@ -468,7 +472,7 @@ func init() { { "id": "0a1o4e6sstp694f", "created": "2024-07-30 06:30:27.801Z", - "updated": "2024-09-26 12:29:38.334Z", + "updated": "2024-10-17 15:21:58.176Z", "name": "deployments", "type": "base", "system": false, @@ -563,7 +567,7 @@ func init() { { "id": "_pb_users_auth_", "created": "2024-09-12 13:09:54.234Z", - "updated": "2024-09-26 12:29:38.334Z", + "updated": "2024-10-13 02:40:36.312Z", "name": "users", "type": "auth", "system": false, @@ -626,7 +630,7 @@ func init() { { "id": "dy6ccjb60spfy6p", "created": "2024-09-12 23:12:21.677Z", - "updated": "2024-09-26 12:29:38.334Z", + "updated": "2024-10-13 02:40:36.312Z", "name": "settings", "type": "base", "system": false, @@ -671,7 +675,7 @@ func init() { { "id": "teolp9pl72dxlxq", "created": "2024-09-13 12:51:05.611Z", - "updated": "2024-09-26 12:29:38.334Z", + "updated": "2024-10-13 02:40:36.312Z", "name": "access_groups", "type": "base", "system": false, @@ -716,6 +720,76 @@ func init() { "updateRule": null, "deleteRule": null, "options": {} + }, + { + "id": "012d7abbod1hwvr", + "created": "2024-10-23 06:37:13.155Z", + "updated": "2024-10-23 07:34:58.636Z", + "name": "acme_accounts", + "type": "base", + "system": false, + "schema": [ + { + "system": false, + "id": "fmjfn0yw", + "name": "ca", + "type": "text", + "required": false, + "presentable": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + }, + { + "system": false, + "id": "qqwijqzt", + "name": "email", + "type": "email", + "required": false, + "presentable": false, + "unique": false, + "options": { + "exceptDomains": null, + "onlyDomains": null + } + }, + { + "system": false, + "id": "genxqtii", + "name": "key", + "type": "text", + "required": false, + "presentable": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + }, + { + "system": false, + "id": "1aoia909", + "name": "resource", + "type": "json", + "required": false, + "presentable": false, + "unique": false, + "options": { + "maxSize": 2000000 + } + } + ], + "indexes": [], + "listRule": null, + "viewRule": null, + "createRule": null, + "updateRule": null, + "deleteRule": null, + "options": {} } ]` diff --git a/ui/public/imgs/providers/google.svg b/ui/public/imgs/providers/google.svg new file mode 100644 index 00000000..d5f4dbeb --- /dev/null +++ b/ui/public/imgs/providers/google.svg @@ -0,0 +1,28 @@ + + + + + Google-color + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ui/src/components/certimate/DeployEditDialog.tsx b/ui/src/components/certimate/DeployEditDialog.tsx index 974dc590..35a7345c 100644 --- a/ui/src/components/certimate/DeployEditDialog.tsx +++ b/ui/src/components/certimate/DeployEditDialog.tsx @@ -12,6 +12,7 @@ import { Context as DeployEditContext } from "./DeployEdit"; import DeployToAliyunOSS from "./DeployToAliyunOSS"; import DeployToAliyunCDN from "./DeployToAliyunCDN"; import DeployToTencentCDN from "./DeployToTencentCDN"; +import DeployToTencentCLB from "./DeployToTencentCLB"; import DeployToTencentCOS from "./DeployToTencentCOS"; import DeployToHuaweiCloudCDN from "./DeployToHuaweiCloudCDN"; import DeployToHuaweiCloudELB from "./DeployToHuaweiCloudELB"; @@ -120,6 +121,9 @@ const DeployEditDialog = ({ trigger, deployConfig, onSave }: DeployEditDialogPro case "tencent-cdn": childComponent = ; break; + case "tencent-clb": + childComponent = ; + break; case "tencent-cos": childComponent = ; break; diff --git a/ui/src/components/certimate/DeployToQiniuCDN.tsx b/ui/src/components/certimate/DeployToQiniuCDN.tsx index e4749206..508939cd 100644 --- a/ui/src/components/certimate/DeployToQiniuCDN.tsx +++ b/ui/src/components/certimate/DeployToQiniuCDN.tsx @@ -49,7 +49,7 @@ const DeployToQiniuCDN = () => { return (
- + { return (
- + { + const { deploy: data, setDeploy, error, setError } = useDeployEditContext(); + + const { t } = useTranslation(); + + useEffect(() => { + setError({}); + }, []); + + useEffect(() => { + const resp = domainSchema.safeParse(data.config?.domain); + if (!resp.success) { + setError({ + ...error, + domain: JSON.parse(resp.error.message)[0].message, + }); + } else { + setError({ + ...error, + domain: "", + }); + } + }, [data]); + + useEffect(() => { + const clbIdresp = clbIdSchema.safeParse(data.config?.clbId); + if (!clbIdresp.success) { + setError({ + ...error, + clbId: JSON.parse(clbIdresp.error.message)[0].message, + }); + } else { + setError({ + ...error, + clbId: "", + }); + } + }, [data]); + + useEffect(() => { + const lsnIdresp = lsnIdSchema.safeParse(data.config?.lsnId); + if (!lsnIdresp.success) { + setError({ + ...error, + lsnId: JSON.parse(lsnIdresp.error.message)[0].message, + }); + } else { + setError({ + ...error, + lsnId: "", + }); + } + }, [data]); + + useEffect(() => { + const regionResp = regionSchema.safeParse(data.config?.region); + if (!regionResp.success) { + setError({ + ...error, + region: JSON.parse(regionResp.error.message)[0].message, + }); + } else { + setError({ + ...error, + region: "", + }); + } + }, []); + + useEffect(() => { + if (!data.id) { + setDeploy({ + ...data, + config: { + lsnId: "", + clbId: "", + domain: "", + region: "", + }, + }); + } + }, []); + + const regionSchema = z.string().regex(/^ap-[a-z]+$/, { + message: t("domain.deployment.form.tencent_clb_region.placeholder"), + }); + + const domainSchema = z.string().regex(/^$|^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, { + message: t("common.errmsg.domain_invalid"), + }); + + const clbIdSchema = z.string().regex(/^lb-[a-zA-Z0-9]{8}$/, { + message: t("domain.deployment.form.tencent_clb_id.placeholder"), + }); + + const lsnIdSchema = z.string().regex(/^lbl-.{8}$/, { + message: t("domain.deployment.form.tencent_clb_listener.placeholder"), + }); + + return ( +
+
+ + { + const temp = e.target.value; + + const resp = regionSchema.safeParse(temp); + if (!resp.success) { + setError({ + ...error, + region: JSON.parse(resp.error.message)[0].message, + }); + } else { + setError({ + ...error, + region: "", + }); + } + + const newData = produce(data, (draft) => { + if (!draft.config) { + draft.config = {}; + } + draft.config.region = temp; + }); + setDeploy(newData); + }} + /> +
{error?.region}
+
+ +
+ + { + const temp = e.target.value; + + const resp = clbIdSchema.safeParse(temp); + if (!resp.success) { + setError({ + ...error, + clbId: JSON.parse(resp.error.message)[0].message, + }); + } else { + setError({ + ...error, + clbId: "", + }); + } + + const newData = produce(data, (draft) => { + if (!draft.config) { + draft.config = {}; + } + draft.config.clbId = temp; + }); + setDeploy(newData); + }} + /> +
{error?.clbId}
+
+ +
+ + { + const temp = e.target.value; + + const resp = lsnIdSchema.safeParse(temp); + if (!resp.success) { + setError({ + ...error, + lsnId: JSON.parse(resp.error.message)[0].message, + }); + } else { + setError({ + ...error, + lsnId: "", + }); + } + + const newData = produce(data, (draft) => { + if (!draft.config) { + draft.config = {}; + } + draft.config.lsnId = temp; + }); + setDeploy(newData); + }} + /> +
{error?.lsnId}
+
+ +
+ + { + const temp = e.target.value; + + const resp = domainSchema.safeParse(temp); + if (!resp.success) { + setError({ + ...error, + domain: JSON.parse(resp.error.message)[0].message, + }); + } else { + setError({ + ...error, + domain: "", + }); + } + + const newData = produce(data, (draft) => { + if (!draft.config) { + draft.config = {}; + } + draft.config.domain = temp; + }); + setDeploy(newData); + }} + /> +
{error?.domain}
+
+
+ ); +}; + +export default DeployToTencentCLB; diff --git a/ui/src/components/certimate/DeployToTencentCOS.tsx b/ui/src/components/certimate/DeployToTencentCOS.tsx index 7b1f370e..7fcb5e2a 100644 --- a/ui/src/components/certimate/DeployToTencentCOS.tsx +++ b/ui/src/components/certimate/DeployToTencentCOS.tsx @@ -32,7 +32,7 @@ const DeployToTencentCOS = () => { }, [data]); useEffect(() => { - const bucketResp = bucketSchema.safeParse(data.config?.domain); + const bucketResp = bucketSchema.safeParse(data.config?.bucket); if (!bucketResp.success) { setError({ ...error, @@ -46,6 +46,21 @@ const DeployToTencentCOS = () => { } }, []); + useEffect(() => { + const regionResp = regionSchema.safeParse(data.config?.region); + if (!regionResp.success) { + setError({ + ...error, + region: JSON.parse(regionResp.error.message)[0].message, + }); + } else { + setError({ + ...error, + region: "", + }); + } + }, []); + useEffect(() => { if (!data.id) { setDeploy({ @@ -63,8 +78,12 @@ const DeployToTencentCOS = () => { message: t("common.errmsg.domain_invalid"), }); - const bucketSchema = z.string().min(1, { - message: t("domain.deployment.form.tencent_cos_region.placeholder"), + const regionSchema = z.string().regex(/^ap-[a-z]+$/, { + message: t("domain.deployment.form.cos_region.placeholder"), + }); + + const bucketSchema = z.string().regex(/^.+-\d+$/, { + message: t("domain.deployment.form.cos_bucket.placeholder"), }); return ( @@ -78,6 +97,19 @@ const DeployToTencentCOS = () => { onChange={(e) => { const temp = e.target.value; + const resp = bucketSchema.safeParse(temp); + if (!resp.success) { + setError({ + ...error, + region: JSON.parse(resp.error.message)[0].message, + }); + } else { + setError({ + ...error, + region: "", + }); + } + const newData = produce(data, (draft) => { if (!draft.config) { draft.config = {}; @@ -87,7 +119,7 @@ const DeployToTencentCOS = () => { setDeploy(newData); }} /> -
{error?.endpoint}
+
{error?.region}
@@ -127,7 +159,7 @@ const DeployToTencentCOS = () => {
{ diff --git a/ui/src/domain/domain.ts b/ui/src/domain/domain.ts index f8bfc691..97bb4ce1 100644 --- a/ui/src/domain/domain.ts +++ b/ui/src/domain/domain.ts @@ -76,6 +76,7 @@ export const deployTargetsMap: Map = new Map ["aliyun-cdn", "common.provider.aliyun.cdn", "/imgs/providers/aliyun.svg"], ["aliyun-dcdn", "common.provider.aliyun.dcdn", "/imgs/providers/aliyun.svg"], ["tencent-cdn", "common.provider.tencent.cdn", "/imgs/providers/tencent.svg"], + ["tencent-clb", "common.provider.tencent.clb", "/imgs/providers/tencent.svg"], ["tencent-cos", "common.provider.tencent.cos", "/imgs/providers/tencent.svg"], ["huaweicloud-cdn", "common.provider.huaweicloud.cdn", "/imgs/providers/huaweicloud.svg"], ["huaweicloud-elb", "common.provider.huaweicloud.elb", "/imgs/providers/huaweicloud.svg"], diff --git a/ui/src/domain/settings.ts b/ui/src/domain/settings.ts index 8ee2dad0..62f00670 100644 --- a/ui/src/domain/settings.ts +++ b/ui/src/domain/settings.ts @@ -1,7 +1,7 @@ -export type Setting = { +export type Setting = { id?: string; name?: string; - content?: EmailsSetting | NotifyTemplates | NotifyChannels | SSLProviderSetting; + content?: T; }; export type EmailsSetting = { @@ -53,7 +53,7 @@ export const defaultNotifyTemplate: NotifyTemplate = { content: "有 {COUNT} 张证书即将过期,域名分别为 {DOMAINS},请保持关注!", }; -export type SSLProvider = "letsencrypt" | "zerossl"; +export type SSLProvider = "letsencrypt" | "zerossl" | "gts"; export type SSLProviderSetting = { provider: SSLProvider; diff --git a/ui/src/i18n/locales/en/nls.common.json b/ui/src/i18n/locales/en/nls.common.json index cf22bdd1..872ef19b 100644 --- a/ui/src/i18n/locales/en/nls.common.json +++ b/ui/src/i18n/locales/en/nls.common.json @@ -56,14 +56,15 @@ "common.provider.aliyun.oss": "Alibaba Cloud - OSS", "common.provider.aliyun.cdn": "Alibaba Cloud - CDN", "common.provider.aliyun.dcdn": "Alibaba Cloud - DCDN", - "common.provider.tencent": "Tencent", - "common.provider.tencent.cdn": "Tencent - CDN", - "common.provider.tencent.cos": "Tencent - COS", + "common.provider.tencent": "Tencent Cloud", + "common.provider.tencent.cdn": "Tencent Cloud - CDN", + "common.provider.tencent.clb": "Tencent Cloud - CLB", + "common.provider.tencent.cos": "Tencent Cloud - COS", "common.provider.huaweicloud": "Huawei Cloud", "common.provider.huaweicloud.cdn": "Huawei Cloud - CDN", "common.provider.huaweicloud.elb": "Huawei Cloud - ELB", - "common.provider.qiniu": "Qiniu", - "common.provider.qiniu.cdn": "Qiniu - CDN", + "common.provider.qiniu": "Qiniu Cloud", + "common.provider.qiniu.cdn": "Qiniu Cloud - CDN", "common.provider.aws": "AWS", "common.provider.cloudflare": "Cloudflare", "common.provider.namesilo": "Namesilo", diff --git a/ui/src/i18n/locales/en/nls.domain.json b/ui/src/i18n/locales/en/nls.domain.json index 3a5d5ba2..80f1a4d7 100644 --- a/ui/src/i18n/locales/en/nls.domain.json +++ b/ui/src/i18n/locales/en/nls.domain.json @@ -55,6 +55,7 @@ "domain.deployment.form.access.placeholder": "Please select provider authorization configuration", "domain.deployment.form.access.list": "Provider Authorization Configurations", "domain.deployment.form.domain.label": "Deploy to domain (Single domain only, not wildcard domain)", + "domain.deployment.form.domain.label.wildsupported": "Deploy to domain (Wildcard domain is also supported)", "domain.deployment.form.domain.placeholder": "Please enter domain to be deployed", "domain.deployment.form.aliyun_oss_endpoint.label": "Endpoint", "domain.deployment.form.aliyun_oss_endpoint.placeholder": "Please enter endpoint", @@ -64,6 +65,14 @@ "domain.deployment.form.tencent_cos_region.placeholder": "Please enter region (e.g. ap-guangzhou)", "domain.deployment.form.tencent_cos_bucket.label": "Bucket", "domain.deployment.form.tencent_cos_bucket.placeholder": "Please enter bucket", + "domain.deployment.form.tencent_clb_region.label": "Region", + "domain.deployment.form.tencent_clb_region.placeholder": "Please enter region (e.g. ap-guangzhou)", + "domain.deployment.form.tencent_clb_id.label": "CLB ID", + "domain.deployment.form.tencent_clb_id.placeholder": "Please enter CLB ID (e.g. lb-xxxxxxxx)", + "domain.deployment.form.tencent_clb_listener.label": "Listener ID", + "domain.deployment.form.tencent_clb_listener.placeholder": "Please enter listener ID (e.g. lbl-xxxxxxxx). The specific listener should have set the corresponding domain HTTPS forwarding, and the original certificate domain should be consistent with the certificate to be deployed.", + "domain.deployment.form.tencent_clb_domain.label": "Deploy to domain (Wildcard domain is also supported)", + "domain.deployment.form.tencent_clb_domain.placeholder": "Please enter domain to be deployed. If SNI is not enabled, you can leave it blank.", "domain.deployment.form.huaweicloud_elb_region.label": "Region", "domain.deployment.form.huaweicloud_elb_region.placeholder": "Please enter region (e.g. cn-north-1)", "domain.deployment.form.huaweicloud_elb_resource_type.label": "Resource Type", diff --git a/ui/src/i18n/locales/zh/nls.common.json b/ui/src/i18n/locales/zh/nls.common.json index 8a2431a4..818807ce 100644 --- a/ui/src/i18n/locales/zh/nls.common.json +++ b/ui/src/i18n/locales/zh/nls.common.json @@ -51,14 +51,14 @@ "common.errmsg.host_invalid": "请输入正确的域名或 IP 地址", "common.errmsg.ip_invalid": "请输入正确的 IP 地址", "common.errmsg.url_invalid": "请输入正确的 URL", - "common.provider.aliyun": "阿里云", "common.provider.aliyun.oss": "阿里云 - OSS", "common.provider.aliyun.cdn": "阿里云 - CDN", "common.provider.aliyun.dcdn": "阿里云 - DCDN", "common.provider.tencent": "腾讯云", - "common.provider.tencent.cdn": "腾讯云 - CDN", "common.provider.tencent.cos": "腾讯云 - COS", + "common.provider.tencent.cdn": "腾讯云 - CDN", + "common.provider.tencent.clb": "腾讯云 - CLB", "common.provider.huaweicloud": "华为云", "common.provider.huaweicloud.cdn": "华为云 - CDN", "common.provider.huaweicloud.elb": "华为云 - ELB", diff --git a/ui/src/i18n/locales/zh/nls.domain.json b/ui/src/i18n/locales/zh/nls.domain.json index 78d77319..ae7f4d0f 100644 --- a/ui/src/i18n/locales/zh/nls.domain.json +++ b/ui/src/i18n/locales/zh/nls.domain.json @@ -55,6 +55,7 @@ "domain.deployment.form.access.placeholder": "请选择授权配置", "domain.deployment.form.access.list": "服务商授权配置列表", "domain.deployment.form.domain.label": "部署到域名(仅支持单个域名;不支持泛域名)", + "domain.deployment.form.domain.label.wildsupported": "部署到域名(支持泛域名)", "domain.deployment.form.domain.placeholder": "请输入部署到的域名", "domain.deployment.form.aliyun_oss_endpoint.label": "Endpoint", "domain.deployment.form.aliyun_oss_endpoint.placeholder": "请输入 Endpoint", @@ -64,6 +65,14 @@ "domain.deployment.form.tencent_cos_region.placeholder": "请输入地域(如 ap-guangzhou)", "domain.deployment.form.tencent_cos_bucket.label": "存储桶", "domain.deployment.form.tencent_cos_bucket.placeholder": "请输入存储桶名", + "domain.deployment.form.tencent_clb_region.label": "地域", + "domain.deployment.form.tencent_clb_region.placeholder": "请输入地域(如 ap-guangzhou)", + "domain.deployment.form.tencent_clb_id.label": "负载均衡器 ID", + "domain.deployment.form.tencent_clb_id.placeholder": "请输入负载均衡器实例 ID(如 lb-xxxxxxxx)", + "domain.deployment.form.tencent_clb_listener.label": "监听器 ID(对应监听器应已设置对应域名 HTTPS 转发, 且原证书对应域名应与待部署证书的一致)", + "domain.deployment.form.tencent_clb_listener.placeholder": "请输入监听器 ID(如 lb-xxxxxxxx)", + "domain.deployment.form.tencent_clb_domain.label": "部署到域名(支持泛域名)", + "domain.deployment.form.tencent_clb_domain.placeholder": "请输入部署到的域名, 如未开启 SNI, 可置空忽略此项", "domain.deployment.form.huaweicloud_elb_region.label": "地域", "domain.deployment.form.huaweicloud_elb_region.placeholder": "请输入地域(如 cn-north-1)", "domain.deployment.form.huaweicloud_elb_resource_type.label": "资源类型替换方式", diff --git a/ui/src/pages/history/History.tsx b/ui/src/pages/history/History.tsx index 36acf2b0..24de0c7b 100644 --- a/ui/src/pages/history/History.tsx +++ b/ui/src/pages/history/History.tsx @@ -150,6 +150,10 @@ const History = () => {
[{item.time}]
{item.message}
+ {item.info && + item.info.map((info: string) => { + return
{info}
; + })} {item.error &&
{item.error}
}
); diff --git a/ui/src/pages/setting/SSLProvider.tsx b/ui/src/pages/setting/SSLProvider.tsx index f5c1b28e..f4c07632 100644 --- a/ui/src/pages/setting/SSLProvider.tsx +++ b/ui/src/pages/setting/SSLProvider.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useContext, useEffect, useState, createContext } from "react"; import { useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { z } from "zod"; @@ -14,93 +14,71 @@ import { getErrMessage } from "@/lib/error"; import { cn } from "@/lib/utils"; import { SSLProvider as SSLProviderType, SSLProviderSetting, Setting } from "@/domain/settings"; import { getSetting, update } from "@/repository/settings"; +import { produce } from "immer"; + +type SSLProviderContext = { + setting: Setting; + onSubmit: (data: Setting) => void; + setConfig: (config: Setting) => void; +}; + +const Context = createContext({} as SSLProviderContext); + +export const useSSLProviderContext = () => { + return useContext(Context); +}; const SSLProvider = () => { const { t } = useTranslation(); - const formSchema = z.object({ - provider: z.enum(["letsencrypt", "zerossl"], { - message: t("settings.ca.provider.errmsg.empty"), - }), - eabKid: z.string().optional(), - eabHmacKey: z.string().optional(), - }); - - const form = useForm>({ - resolver: zodResolver(formSchema), - defaultValues: { + const [config, setConfig] = useState>({ + id: "", + content: { provider: "letsencrypt", + config: {}, }, }); - const [provider, setProvider] = useState("letsencrypt"); - - const [config, setConfig] = useState(); - const { toast } = useToast(); useEffect(() => { const fetchData = async () => { - const setting = await getSetting("ssl-provider"); + const setting = await getSetting("ssl-provider"); if (setting) { setConfig(setting); - const content = setting.content as SSLProviderSetting; - - form.setValue("provider", content.provider); - form.setValue("eabKid", content.config[content.provider].eabKid); - form.setValue("eabHmacKey", content.config[content.provider].eabHmacKey); - setProvider(content.provider); - } else { - form.setValue("provider", "letsencrypt"); - setProvider("letsencrypt"); } }; fetchData(); }, []); + const setProvider = (val: SSLProviderType) => { + const newData = produce(config, (draft) => { + if (draft.content) { + draft.content.provider = val; + } else { + draft.content = { + provider: val, + config: {}, + }; + } + }); + setConfig(newData); + }; + const getOptionCls = (val: string) => { - if (provider === val) { - return "border-primary"; + if (config.content?.provider === val) { + return "border-primary dark:border-primary"; } return ""; }; - const onSubmit = async (values: z.infer) => { - if (values.provider === "zerossl") { - if (!values.eabKid) { - form.setError("eabKid", { - message: t("settings.ca.eab_kid_hmac_key.errmsg.empty"), - }); - } - if (!values.eabHmacKey) { - form.setError("eabHmacKey", { - message: t("settings.ca.eab_kid_hmac_key.errmsg.empty"), - }); - } - if (!values.eabKid || !values.eabHmacKey) { - return; - } - } - - const setting: Setting = { - id: config?.id, - name: "ssl-provider", - content: { - provider: values.provider, - config: { - letsencrypt: {}, - zerossl: { - eabKid: values.eabKid ?? "", - eabHmacKey: values.eabHmacKey ?? "", - }, - }, - }, - }; - + const onSubmit = async (data: Setting) => { try { - await update(setting); + console.log(data); + const resp = await update({ ...data }); + setConfig(resp); toast({ title: t("common.update.succeeded.message"), description: t("common.update.succeeded.message"), @@ -117,89 +95,352 @@ const SSLProvider = () => { return ( <> -
-
- - ( - - {t("common.text.ca")} - - { - setProvider(val); - form.setValue("provider", val as SSLProviderType); - }} - value={provider} - > -
- - -
-
- - -
-
-
- - ( - - )} - /> - - ( - - )} - /> - - -
- )} - /> - -
- + +
+ + { + setProvider(val as SSLProviderType); + }} + value={config.content?.provider} + > +
+ +
- - -
+
+ + +
+ +
+ + +
+ + + +
+ ); }; +const SSLProviderForm = ({ kind }: { kind: string }) => { + const getForm = () => { + switch (kind) { + case "zerossl": + return ; + case "gts": + return ; + default: + return ; + } + }; + + return ( + <> +
{getForm()}
+ + ); +}; + +const getConfigStr = (content: SSLProviderSetting, kind: string, key: string) => { + if (!content.config) { + return ""; + } + if (!content.config[kind]) { + return ""; + } + return content.config[kind][key] ?? ""; +}; + +const SSLProviderLetsEncryptForm = () => { + const { t } = useTranslation(); + + const { setting, onSubmit } = useSSLProviderContext(); + + const formSchema = z.object({ + kind: z.literal("letsencrypt"), + }); + + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + kind: "letsencrypt", + }, + }); + + const onLocalSubmit = async (data: z.infer) => { + const newData = produce(setting, (draft) => { + if (!draft.content) { + draft.content = { + provider: data.kind, + config: { + letsencrypt: {}, + }, + }; + } + }); + onSubmit(newData); + }; + + return ( +
+ + ( + + )} + /> + + + +
+ +
+ + + ); +}; +const SSLProviderZeroSSLForm = () => { + const { t } = useTranslation(); + + const { setting, onSubmit } = useSSLProviderContext(); + + const formSchema = z.object({ + kind: z.literal("zerossl"), + eabKid: z.string().min(1, { message: t("settings.ca.eab_kid_hmac_key.errmsg.empty") }), + eabHmacKey: z.string().min(1, { message: t("settings.ca.eab_kid_hmac_key.errmsg.empty") }), + }); + + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + kind: "zerossl", + eabKid: "", + eabHmacKey: "", + }, + }); + + useEffect(() => { + if (setting.content) { + const content = setting.content; + + form.reset({ + eabKid: getConfigStr(content, "zerossl", "eabKid"), + eabHmacKey: getConfigStr(content, "zerossl", "eabHmacKey"), + }); + } + }, [setting]); + + const onLocalSubmit = async (data: z.infer) => { + const newData = produce(setting, (draft) => { + if (!draft.content) { + draft.content = { + provider: "zerossl", + config: { + zerossl: {}, + }, + }; + } + + draft.content.config.zerossl = { + eabKid: data.eabKid, + eabHmacKey: data.eabHmacKey, + }; + }); + onSubmit(newData); + }; + + return ( +
+ + ( + + )} + /> + ( + + EAB_KID + + + + + + + )} + /> + + ( + + EAB_HMAC_KEY + + + + + + + )} + /> + + + +
+ +
+ + + ); +}; + +const SSLProviderGtsForm = () => { + const { t } = useTranslation(); + + const { setting, onSubmit } = useSSLProviderContext(); + + const formSchema = z.object({ + kind: z.literal("gts"), + eabKid: z.string().min(1, { message: t("settings.ca.eab_kid_hmac_key.errmsg.empty") }), + eabHmacKey: z.string().min(1, { message: t("settings.ca.eab_kid_hmac_key.errmsg.empty") }), + }); + + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + kind: "gts", + eabKid: "", + eabHmacKey: "", + }, + }); + + useEffect(() => { + if (setting.content) { + const content = setting.content; + + form.reset({ + eabKid: getConfigStr(content, "gts", "eabKid"), + eabHmacKey: getConfigStr(content, "gts", "eabHmacKey"), + }); + } + }, [setting]); + + const onLocalSubmit = async (data: z.infer) => { + const newData = produce(setting, (draft) => { + if (!draft.content) { + draft.content = { + provider: "gts", + config: { + zerossl: {}, + }, + }; + } + + draft.content.config.gts = { + eabKid: data.eabKid, + eabHmacKey: data.eabHmacKey, + }; + }); + onSubmit(newData); + }; + + return ( +
+ + ( + + )} + /> + ( + + EAB_KID + + + + + + + )} + /> + + ( + + EAB_HMAC_KEY + + + + + + + )} + /> + + + +
+ +
+ + + ); +}; + export default SSLProvider; + diff --git a/ui/src/providers/config/index.tsx b/ui/src/providers/config/index.tsx index 0b98c129..d484859c 100644 --- a/ui/src/providers/config/index.tsx +++ b/ui/src/providers/config/index.tsx @@ -2,7 +2,7 @@ import { createContext, ReactNode, useCallback, useContext, useEffect, useReduce import { Access } from "@/domain/access"; import { AccessGroup } from "@/domain/access_groups"; -import { Setting } from "@/domain/settings"; +import { EmailsSetting, Setting } from "@/domain/settings"; import { list } from "@/repository/access"; import { list as getAccessGroups } from "@/repository/access_group"; import { getEmails } from "@/repository/settings"; @@ -10,13 +10,13 @@ import { configReducer } from "./reducer"; export type ConfigData = { accesses: Access[]; - emails: Setting; + emails: Setting; accessGroups: AccessGroup[]; }; export type ConfigContext = { config: ConfigData; - setEmails: (email: Setting) => void; + setEmails: (email: Setting) => void; addAccess: (access: Access) => void; updateAccess: (access: Access) => void; deleteAccess: (id: string) => void; @@ -68,7 +68,7 @@ export const ConfigProvider = ({ children }: ConfigProviderProps) => { dispatchConfig({ type: "SET_ACCESS_GROUPS", payload: accessGroups }); }, []); - const setEmails = useCallback((emails: Setting) => { + const setEmails = useCallback((emails: Setting) => { dispatchConfig({ type: "SET_EMAILS", payload: emails }); }, []); diff --git a/ui/src/providers/config/reducer.ts b/ui/src/providers/config/reducer.ts index 0367f009..fd45386c 100644 --- a/ui/src/providers/config/reducer.ts +++ b/ui/src/providers/config/reducer.ts @@ -8,7 +8,7 @@ type Action = | { type: "DELETE_ACCESS"; payload: string } | { type: "UPDATE_ACCESS"; payload: Access } | { type: "SET_ACCESSES"; payload: Access[] } - | { type: "SET_EMAILS"; payload: Setting } + | { type: "SET_EMAILS"; payload: Setting } | { type: "ADD_EMAIL"; payload: string } | { type: "SET_ACCESS_GROUPS"; payload: AccessGroup[] }; diff --git a/ui/src/providers/notify/index.tsx b/ui/src/providers/notify/index.tsx index a0e9c195..47f55676 100644 --- a/ui/src/providers/notify/index.tsx +++ b/ui/src/providers/notify/index.tsx @@ -1,13 +1,13 @@ import { ReactNode, useContext, createContext, useEffect, useReducer, useCallback } from "react"; -import { NotifyChannel, Setting } from "@/domain/settings"; +import { NotifyChannel, NotifyChannels, Setting } from "@/domain/settings"; import { getSetting } from "@/repository/settings"; import { notifyReducer } from "./reducer"; export type NotifyContext = { - config: Setting; + config: Setting; setChannel: (data: { channel: string; data: NotifyChannel }) => void; - setChannels: (data: Setting) => void; + setChannels: (data: Setting) => void; }; const Context = createContext({} as NotifyContext); @@ -23,7 +23,7 @@ export const NotifyProvider = ({ children }: NotifyProviderProps) => { useEffect(() => { const featchData = async () => { - const chanels = await getSetting("notifyChannels"); + const chanels = await getSetting("notifyChannels"); dispatchNotify({ type: "SET_CHANNELS", payload: chanels, @@ -39,7 +39,7 @@ export const NotifyProvider = ({ children }: NotifyProviderProps) => { }); }, []); - const setChannels = useCallback((setting: Setting) => { + const setChannels = useCallback((setting: Setting) => { dispatchNotify({ type: "SET_CHANNELS", payload: setting, diff --git a/ui/src/providers/notify/reducer.tsx b/ui/src/providers/notify/reducer.tsx index d5a36efc..8bdaecc9 100644 --- a/ui/src/providers/notify/reducer.tsx +++ b/ui/src/providers/notify/reducer.tsx @@ -1,4 +1,4 @@ -import { NotifyChannel, Setting } from "@/domain/settings"; +import { NotifyChannel, NotifyChannels, Setting } from "@/domain/settings"; type Action = | { @@ -10,10 +10,10 @@ type Action = } | { type: "SET_CHANNELS"; - payload: Setting; + payload: Setting; }; -export const notifyReducer = (state: Setting, action: Action) => { +export const notifyReducer = (state: Setting, action: Action) => { switch (action.type) { case "SET_CHANNEL": { const channel = action.payload.channel; diff --git a/ui/src/repository/settings.ts b/ui/src/repository/settings.ts index 0734cafd..5894c50c 100644 --- a/ui/src/repository/settings.ts +++ b/ui/src/repository/settings.ts @@ -1,9 +1,9 @@ -import { Setting } from "@/domain/settings"; +import { EmailsSetting, Setting } from "@/domain/settings"; import { getPb } from "./api"; export const getEmails = async () => { try { - const resp = await getPb().collection("settings").getFirstListItem("name='emails'"); + const resp = await getPb().collection("settings").getFirstListItem>("name='emails'"); return resp; } catch (e) { return { @@ -12,21 +12,21 @@ export const getEmails = async () => { } }; -export const getSetting = async (name: string) => { +export const getSetting = async (name: string) => { try { - const resp = await getPb().collection("settings").getFirstListItem(`name='${name}'`); + const resp = await getPb().collection("settings").getFirstListItem>(`name='${name}'`); return resp; } catch (e) { - const rs: Setting = { + const rs: Setting = { name: name, }; return rs; } }; -export const update = async (setting: Setting) => { +export const update = async (setting: Setting) => { const pb = getPb(); - let resp: Setting; + let resp: Setting; if (setting.id) { resp = await pb.collection("settings").update(setting.id, setting); } else {