diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index f5304bb1..52494864 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -7,7 +7,7 @@ assignees: "" --- **描述问题** -简要描述问题是什么 +简要描述问题是什么,1 个 ISSUE 只描述一个问题。 **复现步骤** 复现该问题的步骤: diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index eccd8712..9eb598c9 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -7,7 +7,7 @@ assignees: "" --- **功能描述** -简要描述你希望添加的功能和相关问题。 +简要描述你希望添加的功能和相关问题,1 个 ISSUE 只描述一个功能。 **动机** 为什么这个功能对项目有帮助? diff --git a/.github/workflows/push_image.yml b/.github/workflows/push_image.yml index b64c8bbf..22802cbf 100644 --- a/.github/workflows/push_image.yml +++ b/.github/workflows/push_image.yml @@ -52,7 +52,7 @@ jobs: uses: docker/build-push-action@v6 with: context: . - file: ./Dockerfile_build + file: ./Dockerfile platforms: linux/amd64,linux/arm64 push: true tags: ${{ steps.meta.outputs.tags }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d1b51411..8ec32deb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,18 +14,18 @@ jobs: with: fetch-depth: 0 - # - name: Set up Node.js - # uses: actions/setup-node@v4 - # with: - # node-version: 20.11.0 + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 20.11.0 - name: Set up Go uses: actions/setup-go@v5 with: go-version: ">=1.22.5" - # - name: Build Admin dashboard UI - # run: npm --prefix=./ui ci && npm --prefix=./ui run build + - name: Build Admin dashboard UI + run: npm --prefix=./ui ci && npm --prefix=./ui run build - name: Run GoReleaser uses: goreleaser/goreleaser-action@v3 diff --git a/.gitignore b/.gitignore index 7fd3ecd1..bfb74e99 100644 --- a/.gitignore +++ b/.gitignore @@ -9,13 +9,12 @@ *.njsproj *.sln *.sw? - __debug_bin* vendor pb_data build main - +ui/dist ./dist ./certimate /docker/data diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..173dca23 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,29 @@ +FROM node:20-alpine3.19 AS front-builder + +WORKDIR /app + +COPY . /app/ + +RUN \ + cd /app/ui && \ + npm install && \ + npm run build + +FROM golang:1.22-alpine AS builder + +WORKDIR /app + +COPY ../. /app/ + +RUN rm -rf /app/ui/dist +COPY --from=front-builder /app/ui/dist /app/ui/dist + +RUN go build -o certimate + +FROM alpine:latest + +WORKDIR /app + +COPY --from=builder /app/certimate . + +ENTRYPOINT ["./certimate", "serve", "--http", "0.0.0.0:8090"] diff --git a/Dockerfile_build b/Dockerfile_build deleted file mode 100644 index efd3d962..00000000 --- a/Dockerfile_build +++ /dev/null @@ -1,16 +0,0 @@ -FROM golang:1.22-alpine as builder - -WORKDIR /app - -COPY ../. /app/ - -RUN go build -o certimate - - -FROM alpine:latest - -WORKDIR /app - -COPY --from=builder /app/certimate . - -ENTRYPOINT ["./certimate", "serve", "--http", "0.0.0.0:8090"] diff --git a/README.md b/README.md index bacb09f0..cb3b0b29 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,8 @@ go run main.go serve | CloudFlare | √ | | 可签发在 CloudFlare 注册的域名;CloudFlare 服务自带 SSL 证书 | | GoDaddy | √ | | 可签发在 GoDaddy 注册的域名 | | Namesilo | √ | | 可签发在 Namesilo 注册的域名 | +| PowerDNS | √ | | 可签发通过PowerDNS管理的域名 | +| HTTP request | √ | | 可签发通过HTTP Request修改dns的域名 | | 本地部署 | | √ | 可部署到本地服务器 | | SSH | | √ | 可部署到 SSH 服务器 | | Webhook | | √ | 可部署时回调到 Webhook | diff --git a/README_EN.md b/README_EN.md index 85625fed..d048cecb 100644 --- a/README_EN.md +++ b/README_EN.md @@ -81,6 +81,9 @@ password:1234567890 | 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 by PowerDNS | +| HTTP request | √ | | Supports domains dns managed by HTTP Request | + | Local Deploy | | √ | Supports deployment to local servers | | SSH | | √ | Supports deployment to SSH servers | | Webhook | | √ | Supports callback to Webhook | diff --git a/go.mod b/go.mod index 7604d1e9..6a8a5f15 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module certimate +module github.com/usual2970/certimate go 1.22.0 diff --git a/internal/applicant/aliyun.go b/internal/applicant/aliyun.go index 0b0dc61d..40adf960 100644 --- a/internal/applicant/aliyun.go +++ b/internal/applicant/aliyun.go @@ -7,7 +7,7 @@ import ( "github.com/go-acme/lego/v4/providers/dns/alidns" - "certimate/internal/domain" + "github.com/usual2970/certimate/internal/domain" ) type aliyun struct { diff --git a/internal/applicant/applicant.go b/internal/applicant/applicant.go index 60209b90..b70f216e 100644 --- a/internal/applicant/applicant.go +++ b/internal/applicant/applicant.go @@ -9,6 +9,9 @@ import ( "fmt" "strings" + "github.com/usual2970/certimate/internal/domain" + "github.com/usual2970/certimate/internal/utils/app" + "github.com/go-acme/lego/v4/certcrypto" "github.com/go-acme/lego/v4/certificate" "github.com/go-acme/lego/v4/challenge" @@ -16,9 +19,6 @@ import ( "github.com/go-acme/lego/v4/lego" "github.com/go-acme/lego/v4/registration" "github.com/pocketbase/pocketbase/models" - - "certimate/internal/domain" - "certimate/internal/utils/app" ) const ( @@ -29,6 +29,8 @@ const ( configTypeCloudflare = "cloudflare" configTypeNamesilo = "namesilo" configTypeGodaddy = "godaddy" + configTypePdns = "pdns" + configTypeHttpreq = "httpreq" ) const defaultSSLProvider = "letsencrypt" @@ -136,6 +138,10 @@ func Get(record *models.Record) (Applicant, error) { return NewNamesilo(option), nil case configTypeGodaddy: return NewGodaddy(option), nil + case configTypePdns: + return NewPdns(option), nil + case configTypeHttpreq: + return NewHttpreq(option), nil default: return nil, errors.New("unknown config type") } diff --git a/internal/applicant/aws.go b/internal/applicant/aws.go index 9a491d06..be18d747 100644 --- a/internal/applicant/aws.go +++ b/internal/applicant/aws.go @@ -7,7 +7,7 @@ import ( "github.com/go-acme/lego/v4/providers/dns/route53" - "certimate/internal/domain" + "github.com/usual2970/certimate/internal/domain" ) type aws struct { diff --git a/internal/applicant/cloudflare.go b/internal/applicant/cloudflare.go index 75d083fd..f1c40ebe 100644 --- a/internal/applicant/cloudflare.go +++ b/internal/applicant/cloudflare.go @@ -7,7 +7,7 @@ import ( cf "github.com/go-acme/lego/v4/providers/dns/cloudflare" - "certimate/internal/domain" + "github.com/usual2970/certimate/internal/domain" ) type cloudflare struct { diff --git a/internal/applicant/godaddy.go b/internal/applicant/godaddy.go index adcfe13b..7ae40a72 100644 --- a/internal/applicant/godaddy.go +++ b/internal/applicant/godaddy.go @@ -7,7 +7,7 @@ import ( godaddyProvider "github.com/go-acme/lego/v4/providers/dns/godaddy" - "certimate/internal/domain" + "github.com/usual2970/certimate/internal/domain" ) type godaddy struct { diff --git a/internal/applicant/httpreq.go b/internal/applicant/httpreq.go new file mode 100644 index 00000000..7972b7ae --- /dev/null +++ b/internal/applicant/httpreq.go @@ -0,0 +1,38 @@ +package applicant + +import ( + "encoding/json" + "fmt" + "os" + + "github.com/go-acme/lego/v4/providers/dns/httpreq" + + "github.com/usual2970/certimate/internal/domain" +) + +type httpReq struct { + option *ApplyOption +} + +func NewHttpreq(option *ApplyOption) Applicant { + return &httpReq{ + option: option, + } +} + +func (a *httpReq) Apply() (*Certificate, error) { + access := &domain.HttpreqAccess{} + json.Unmarshal([]byte(a.option.Access), access) + + os.Setenv("HTTPREQ_ENDPOINT", access.Endpoint) + os.Setenv("HTTPREQ_MODE", access.Mode) + os.Setenv("HTTPREQ_USERNAME", access.Username) + os.Setenv("HTTPREQ_PASSWORD", access.Password) + os.Setenv("HTTPREQ_PROPAGATION_TIMEOUT", fmt.Sprintf("%d", a.option.Timeout)) + dnsProvider, err := httpreq.NewDNSProvider() + if err != nil { + return nil, err + } + + return apply(a.option, dnsProvider) +} diff --git a/internal/applicant/huaweicloud.go b/internal/applicant/huaweicloud.go index 294e95a6..94f72c7f 100644 --- a/internal/applicant/huaweicloud.go +++ b/internal/applicant/huaweicloud.go @@ -7,7 +7,7 @@ import ( huaweicloudProvider "github.com/go-acme/lego/v4/providers/dns/huaweicloud" - "certimate/internal/domain" + "github.com/usual2970/certimate/internal/domain" ) type huaweicloud struct { diff --git a/internal/applicant/namesilo.go b/internal/applicant/namesilo.go index 0f2aa155..55fd3b3c 100644 --- a/internal/applicant/namesilo.go +++ b/internal/applicant/namesilo.go @@ -7,7 +7,7 @@ import ( namesiloProvider "github.com/go-acme/lego/v4/providers/dns/namesilo" - "certimate/internal/domain" + "github.com/usual2970/certimate/internal/domain" ) type namesilo struct { diff --git a/internal/applicant/pdns.go b/internal/applicant/pdns.go new file mode 100644 index 00000000..2c84c85e --- /dev/null +++ b/internal/applicant/pdns.go @@ -0,0 +1,36 @@ +package applicant + +import ( + "encoding/json" + "fmt" + "os" + + "github.com/go-acme/lego/v4/providers/dns/pdns" + + "github.com/usual2970/certimate/internal/domain" +) + +type powerdns struct { + option *ApplyOption +} + +func NewPdns(option *ApplyOption) Applicant { + return &powerdns{ + option: option, + } +} + +func (a *powerdns) Apply() (*Certificate, error) { + access := &domain.PdnsAccess{} + json.Unmarshal([]byte(a.option.Access), access) + + os.Setenv("PDNS_API_URL", access.ApiUrl) + os.Setenv("PDNS_API_KEY", access.ApiKey) + os.Setenv("PDNS_PROPAGATION_TIMEOUT", fmt.Sprintf("%d", a.option.Timeout)) + dnsProvider, err := pdns.NewDNSProvider() + if err != nil { + return nil, err + } + + return apply(a.option, dnsProvider) +} diff --git a/internal/applicant/tencent.go b/internal/applicant/tencent.go index 705f63ad..4733e22e 100644 --- a/internal/applicant/tencent.go +++ b/internal/applicant/tencent.go @@ -7,7 +7,7 @@ import ( "github.com/go-acme/lego/v4/providers/dns/tencentcloud" - "certimate/internal/domain" + "github.com/usual2970/certimate/internal/domain" ) type tencent struct { diff --git a/internal/deployer/aliyun_cdn.go b/internal/deployer/aliyun_cdn.go index 467ab96f..97ac0d83 100644 --- a/internal/deployer/aliyun_cdn.go +++ b/internal/deployer/aliyun_cdn.go @@ -10,8 +10,8 @@ import ( util "github.com/alibabacloud-go/tea-utils/v2/service" "github.com/alibabacloud-go/tea/tea" - "certimate/internal/domain" - "certimate/internal/utils/rand" + "github.com/usual2970/certimate/internal/domain" + "github.com/usual2970/certimate/internal/utils/rand" ) type AliyunCDNDeployer struct { diff --git a/internal/deployer/aliyun_esa.go b/internal/deployer/aliyun_esa.go index 0403e04b..79bc54ea 100644 --- a/internal/deployer/aliyun_esa.go +++ b/internal/deployer/aliyun_esa.go @@ -1,7 +1,7 @@ /* * @Author: Bin * @Date: 2024-09-17 - * @FilePath: /certimate/internal/deployer/aliyun_esa.go + * @FilePath: /github.com/usual2970/certimate/internal/deployer/aliyun_esa.go */ package deployer @@ -15,8 +15,8 @@ import ( util "github.com/alibabacloud-go/tea-utils/v2/service" "github.com/alibabacloud-go/tea/tea" - "certimate/internal/domain" - "certimate/internal/utils/rand" + "github.com/usual2970/certimate/internal/domain" + "github.com/usual2970/certimate/internal/utils/rand" ) type AliyunESADeployer struct { diff --git a/internal/deployer/aliyun_oss.go b/internal/deployer/aliyun_oss.go index e8d259d5..9626e3bc 100644 --- a/internal/deployer/aliyun_oss.go +++ b/internal/deployer/aliyun_oss.go @@ -7,7 +7,7 @@ import ( "github.com/aliyun/aliyun-oss-go-sdk/oss" - "certimate/internal/domain" + "github.com/usual2970/certimate/internal/domain" ) type AliyunOSSDeployer struct { diff --git a/internal/deployer/deployer.go b/internal/deployer/deployer.go index b60b5d51..18794028 100644 --- a/internal/deployer/deployer.go +++ b/internal/deployer/deployer.go @@ -9,9 +9,9 @@ import ( "github.com/pocketbase/pocketbase/models" - "certimate/internal/applicant" - "certimate/internal/domain" - "certimate/internal/utils/app" + "github.com/usual2970/certimate/internal/applicant" + "github.com/usual2970/certimate/internal/domain" + "github.com/usual2970/certimate/internal/utils/app" ) const ( diff --git a/internal/deployer/huaweicloud_cdn.go b/internal/deployer/huaweicloud_cdn.go index 65963578..f7db488d 100644 --- a/internal/deployer/huaweicloud_cdn.go +++ b/internal/deployer/huaweicloud_cdn.go @@ -11,8 +11,8 @@ import ( cdnModel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v2/model" cdnRegion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v2/region" - "certimate/internal/domain" - uploaderImpl "certimate/internal/pkg/core/uploader/impl" + "github.com/usual2970/certimate/internal/domain" + uploaderImpl "github.com/usual2970/certimate/internal/pkg/core/uploader/impl" ) type HuaweiCloudCDNDeployer struct { diff --git a/internal/deployer/k8s_secret.go b/internal/deployer/k8s_secret.go index 97d16fcf..3729114f 100644 --- a/internal/deployer/k8s_secret.go +++ b/internal/deployer/k8s_secret.go @@ -9,7 +9,7 @@ import ( "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/clientcmd" - "certimate/internal/domain" + "github.com/usual2970/certimate/internal/domain" ) type K8sSecretDeployer struct { diff --git a/internal/deployer/local.go b/internal/deployer/local.go index c9f9ecd6..784660b6 100644 --- a/internal/deployer/local.go +++ b/internal/deployer/local.go @@ -9,7 +9,7 @@ import ( "path/filepath" "runtime" - "certimate/internal/domain" + "github.com/usual2970/certimate/internal/domain" ) type LocalDeployer struct { diff --git a/internal/deployer/qiniu_cdn.go b/internal/deployer/qiniu_cdn.go index f6ff80c6..f6e6b167 100644 --- a/internal/deployer/qiniu_cdn.go +++ b/internal/deployer/qiniu_cdn.go @@ -10,8 +10,8 @@ import ( "github.com/qiniu/go-sdk/v7/auth" - "certimate/internal/domain" - xhttp "certimate/internal/utils/http" + "github.com/usual2970/certimate/internal/domain" + xhttp "github.com/usual2970/certimate/internal/utils/http" ) const qiniuGateway = "http://api.qiniu.com" diff --git a/internal/deployer/qiniu_cdn_test.go b/internal/deployer/qiniu_cdn_test.go index 7e625dfb..396f6546 100644 --- a/internal/deployer/qiniu_cdn_test.go +++ b/internal/deployer/qiniu_cdn_test.go @@ -5,7 +5,7 @@ import ( "github.com/qiniu/go-sdk/v7/auth" - "certimate/internal/applicant" + "github.com/usual2970/certimate/internal/applicant" ) func Test_qiuniu_uploadCert(t *testing.T) { diff --git a/internal/deployer/ssh.go b/internal/deployer/ssh.go index e2885236..551e8634 100644 --- a/internal/deployer/ssh.go +++ b/internal/deployer/ssh.go @@ -11,7 +11,7 @@ import ( "github.com/pkg/sftp" sshPkg "golang.org/x/crypto/ssh" - "certimate/internal/domain" + "github.com/usual2970/certimate/internal/domain" ) type SSHDeployer struct { diff --git a/internal/deployer/tencent_cdn.go b/internal/deployer/tencent_cdn.go index e97898eb..aa315466 100644 --- a/internal/deployer/tencent_cdn.go +++ b/internal/deployer/tencent_cdn.go @@ -12,8 +12,8 @@ import ( "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" ssl "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205" - "certimate/internal/domain" - "certimate/internal/utils/rand" + "github.com/usual2970/certimate/internal/domain" + "github.com/usual2970/certimate/internal/utils/rand" ) type TencentCDNDeployer struct { diff --git a/internal/deployer/webhook.go b/internal/deployer/webhook.go index 97927254..522705d4 100644 --- a/internal/deployer/webhook.go +++ b/internal/deployer/webhook.go @@ -7,8 +7,8 @@ import ( "fmt" "net/http" - "certimate/internal/domain" - xhttp "certimate/internal/utils/http" + "github.com/usual2970/certimate/internal/domain" + xhttp "github.com/usual2970/certimate/internal/utils/http" ) type WebhookDeployer struct { diff --git a/internal/domain/access.go b/internal/domain/access.go index ebd9191a..889d37fa 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -41,6 +41,18 @@ type GodaddyAccess struct { ApiSecret string `json:"apiSecret"` } +type PdnsAccess struct { + ApiUrl string `json:"apiUrl"` + ApiKey string `json:"apiKey"` +} + +type HttpreqAccess struct { + Endpoint string `json:"endpoint"` + Mode string `json:"mode"` + Username string `json:"username"` + Password string `json:"password"` +} + type LocalAccess struct{} type SSHAccess struct { diff --git a/internal/domains/deploy.go b/internal/domains/deploy.go index 0f6776c6..23b3a1dd 100644 --- a/internal/domains/deploy.go +++ b/internal/domains/deploy.go @@ -7,9 +7,9 @@ import ( "github.com/pocketbase/pocketbase/models" - "certimate/internal/applicant" - "certimate/internal/deployer" - "certimate/internal/utils/app" + "github.com/usual2970/certimate/internal/applicant" + "github.com/usual2970/certimate/internal/deployer" + "github.com/usual2970/certimate/internal/utils/app" ) type Phase string diff --git a/internal/domains/domains.go b/internal/domains/domains.go index 03fc24f1..dd65dff8 100644 --- a/internal/domains/domains.go +++ b/internal/domains/domains.go @@ -6,7 +6,7 @@ import ( "github.com/pocketbase/pocketbase/models" - "certimate/internal/utils/app" + "github.com/usual2970/certimate/internal/utils/app" ) func create(ctx context.Context, record *models.Record) error { diff --git a/internal/domains/event.go b/internal/domains/event.go index 5ad38ad1..7acb31e9 100644 --- a/internal/domains/event.go +++ b/internal/domains/event.go @@ -3,7 +3,7 @@ package domains import ( "github.com/pocketbase/pocketbase/core" - "certimate/internal/utils/app" + "github.com/usual2970/certimate/internal/utils/app" ) const tableName = "domains" diff --git a/internal/domains/history.go b/internal/domains/history.go index 616c7c8c..47ed5afa 100644 --- a/internal/domains/history.go +++ b/internal/domains/history.go @@ -5,9 +5,9 @@ import ( "github.com/pocketbase/pocketbase/models" - "certimate/internal/applicant" - "certimate/internal/utils/app" - "certimate/internal/utils/xtime" + "github.com/usual2970/certimate/internal/applicant" + "github.com/usual2970/certimate/internal/utils/app" + "github.com/usual2970/certimate/internal/utils/xtime" ) type historyItem struct { diff --git a/internal/domains/init.go b/internal/domains/init.go index 69de4018..6ca683a0 100644 --- a/internal/domains/init.go +++ b/internal/domains/init.go @@ -3,8 +3,8 @@ package domains import ( "context" - "certimate/internal/notify" - "certimate/internal/utils/app" + "github.com/usual2970/certimate/internal/notify" + "github.com/usual2970/certimate/internal/utils/app" ) func InitSchedule() { diff --git a/internal/notify/expire.go b/internal/notify/expire.go index 985d7491..d4942272 100644 --- a/internal/notify/expire.go +++ b/internal/notify/expire.go @@ -8,8 +8,8 @@ import ( "github.com/pocketbase/dbx" "github.com/pocketbase/pocketbase/models" - "certimate/internal/utils/app" - "certimate/internal/utils/xtime" + "github.com/usual2970/certimate/internal/utils/app" + "github.com/usual2970/certimate/internal/utils/xtime" ) type msg struct { diff --git a/internal/notify/notify.go b/internal/notify/notify.go index 90e661f1..e5265b51 100644 --- a/internal/notify/notify.go +++ b/internal/notify/notify.go @@ -5,8 +5,8 @@ import ( "fmt" "strconv" - "certimate/internal/domain" - "certimate/internal/utils/app" + "github.com/usual2970/certimate/internal/domain" + "github.com/usual2970/certimate/internal/utils/app" notifyPackage "github.com/nikoksr/notify" "github.com/nikoksr/notify/service/dingding" diff --git a/internal/notify/service.go b/internal/notify/service.go index 3e733514..22b77160 100644 --- a/internal/notify/service.go +++ b/internal/notify/service.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "certimate/internal/domain" + "github.com/usual2970/certimate/internal/domain" ) const ( diff --git a/internal/repository/setting.go b/internal/repository/setting.go index 2bf29d0c..c173151f 100644 --- a/internal/repository/setting.go +++ b/internal/repository/setting.go @@ -3,8 +3,8 @@ package repository import ( "context" - "certimate/internal/domain" - "certimate/internal/utils/app" + "github.com/usual2970/certimate/internal/domain" + "github.com/usual2970/certimate/internal/utils/app" ) type SettingRepository struct{} diff --git a/internal/rest/notify.go b/internal/rest/notify.go index 3430119b..eb8aae48 100644 --- a/internal/rest/notify.go +++ b/internal/rest/notify.go @@ -3,8 +3,8 @@ package rest import ( "context" - "certimate/internal/domain" - "certimate/internal/utils/resp" + "github.com/usual2970/certimate/internal/domain" + "github.com/usual2970/certimate/internal/utils/resp" "github.com/labstack/echo/v5" ) diff --git a/internal/routes/routes.go b/internal/routes/routes.go index 2c670446..d469bb3c 100644 --- a/internal/routes/routes.go +++ b/internal/routes/routes.go @@ -1,9 +1,9 @@ package routes import ( - "certimate/internal/notify" - "certimate/internal/repository" - "certimate/internal/rest" + "github.com/usual2970/certimate/internal/notify" + "github.com/usual2970/certimate/internal/repository" + "github.com/usual2970/certimate/internal/rest" "github.com/labstack/echo/v5" "github.com/pocketbase/pocketbase/apis" diff --git a/internal/utils/resp/resp.go b/internal/utils/resp/resp.go index 0153a14c..b4d8240f 100644 --- a/internal/utils/resp/resp.go +++ b/internal/utils/resp/resp.go @@ -3,7 +3,7 @@ package resp import ( "net/http" - "certimate/internal/domain" + "github.com/usual2970/certimate/internal/domain" "github.com/labstack/echo/v5" ) diff --git a/main.go b/main.go index 37482041..7a0bf641 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "github.com/usual2970/certimate/ui" "log" "os" "strings" @@ -10,11 +11,11 @@ import ( "github.com/pocketbase/pocketbase/core" "github.com/pocketbase/pocketbase/plugins/migratecmd" - "certimate/internal/domains" - "certimate/internal/routes" - "certimate/internal/utils/app" - _ "certimate/migrations" - "certimate/ui" + _ "github.com/usual2970/certimate/migrations" + + "github.com/usual2970/certimate/internal/domains" + "github.com/usual2970/certimate/internal/routes" + "github.com/usual2970/certimate/internal/utils/app" _ "time/tzdata" ) diff --git a/migrations/1726569833_updated_domains.go b/migrations/1726569833_updated_domains.go index d624ca51..262b0c42 100644 --- a/migrations/1726569833_updated_domains.go +++ b/migrations/1726569833_updated_domains.go @@ -11,7 +11,7 @@ import ( func init() { m.Register(func(db dbx.Builder) error { - dao := daos.New(db); + dao := daos.New(db) collection, err := dao.FindCollectionByNameOrId("z3p974ainxjqlvs") if err != nil { @@ -47,7 +47,7 @@ func init() { return dao.SaveCollection(collection) }, func(db dbx.Builder) error { - dao := daos.New(db); + dao := daos.New(db) collection, err := dao.FindCollectionByNameOrId("z3p974ainxjqlvs") if err != nil { diff --git a/migrations/1728610007_updated_access.go b/migrations/1728610007_updated_access.go index 1c02c53a..48f3a74a 100644 --- a/migrations/1728610007_updated_access.go +++ b/migrations/1728610007_updated_access.go @@ -11,7 +11,7 @@ import ( func init() { m.Register(func(db dbx.Builder) error { - dao := daos.New(db); + dao := daos.New(db) collection, err := dao.FindCollectionByNameOrId("4yzbv8urny5ja1e") if err != nil { @@ -50,7 +50,7 @@ func init() { return dao.SaveCollection(collection) }, func(db dbx.Builder) error { - dao := daos.New(db); + dao := daos.New(db) collection, err := dao.FindCollectionByNameOrId("4yzbv8urny5ja1e") if err != nil { diff --git a/migrations/1729160433_updated_access.go b/migrations/1729160433_updated_access.go index 22290d79..05e14cc0 100644 --- a/migrations/1729160433_updated_access.go +++ b/migrations/1729160433_updated_access.go @@ -11,7 +11,7 @@ import ( func init() { m.Register(func(db dbx.Builder) error { - dao := daos.New(db); + dao := daos.New(db) collection, err := dao.FindCollectionByNameOrId("4yzbv8urny5ja1e") if err != nil { @@ -51,7 +51,7 @@ func init() { return dao.SaveCollection(collection) }, func(db dbx.Builder) error { - dao := daos.New(db); + dao := daos.New(db) collection, err := dao.FindCollectionByNameOrId("4yzbv8urny5ja1e") if err != nil { diff --git a/migrations/1729241998_updated_access.go b/migrations/1729241998_updated_access.go index 65ac594e..cfa43c23 100644 --- a/migrations/1729241998_updated_access.go +++ b/migrations/1729241998_updated_access.go @@ -11,7 +11,7 @@ import ( func init() { m.Register(func(db dbx.Builder) error { - dao := daos.New(db); + dao := daos.New(db) collection, err := dao.FindCollectionByNameOrId("4yzbv8urny5ja1e") if err != nil { @@ -52,7 +52,7 @@ func init() { return dao.SaveCollection(collection) }, func(db dbx.Builder) error { - dao := daos.New(db); + dao := daos.New(db) collection, err := dao.FindCollectionByNameOrId("4yzbv8urny5ja1e") if err != nil { diff --git a/migrations/1729339341_updated_access.go b/migrations/1729339341_updated_access.go new file mode 100644 index 00000000..51561a76 --- /dev/null +++ b/migrations/1729339341_updated_access.go @@ -0,0 +1,98 @@ +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/ui/dist/assets/index-YqBWA4KK.css b/ui/dist/assets/index-YqBWA4KK.css deleted file mode 100644 index d169c0a5..00000000 --- a/ui/dist/assets/index-YqBWA4KK.css +++ /dev/null @@ -1 +0,0 @@ -*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}:root{--background: 0 0% 100%;--foreground: 20 14.3% 4.1%;--card: 0 0% 100%;--card-foreground: 20 14.3% 4.1%;--popover: 0 0% 100%;--popover-foreground: 20 14.3% 4.1%;--primary: 24.6 95% 53.1%;--primary-foreground: 60 9.1% 97.8%;--secondary: 60 4.8% 95.9%;--secondary-foreground: 24 9.8% 10%;--muted: 60 4.8% 95.9%;--muted-foreground: 25 5.3% 44.7%;--accent: 60 4.8% 95.9%;--accent-foreground: 24 9.8% 10%;--destructive: 0 84.2% 60.2%;--destructive-foreground: 60 9.1% 97.8%;--border: 20 5.9% 90%;--input: 20 5.9% 90%;--ring: 24.6 95% 53.1%;--radius: .5rem;--chart-1: 12 76% 61%;--chart-2: 173 58% 39%;--chart-3: 197 37% 24%;--chart-4: 43 74% 66%;--chart-5: 27 87% 67%}.dark{--background: 20 14.3% 4.1%;--foreground: 60 9.1% 97.8%;--card: 20 14.3% 4.1%;--card-foreground: 60 9.1% 97.8%;--popover: 20 14.3% 4.1%;--popover-foreground: 60 9.1% 97.8%;--primary: 20.5 90.2% 48.2%;--primary-foreground: 60 9.1% 97.8%;--secondary: 12 6.5% 15.1%;--secondary-foreground: 60 9.1% 97.8%;--muted: 12 6.5% 15.1%;--muted-foreground: 24 5.4% 63.9%;--accent: 12 6.5% 15.1%;--accent-foreground: 60 9.1% 97.8%;--destructive: 0 72.2% 50.6%;--destructive-foreground: 60 9.1% 97.8%;--border: 12 6.5% 15.1%;--input: 12 6.5% 15.1%;--ring: 20.5 90.2% 48.2%;--chart-1: 220 70% 50%;--chart-2: 160 60% 45%;--chart-3: 30 80% 55%;--chart-4: 280 65% 60%;--chart-5: 340 75% 55%}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.container{width:100%;margin-right:auto;margin-left:auto;padding-right:2rem;padding-left:2rem}@media (min-width: 1400px){.container{max-width:1400px}}@media (min-width: 1920px){.container{max-width:1920px}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{top:0;right:0;bottom:0;left:0}.inset-x-0{left:0;right:0}.inset-y-0{top:0;bottom:0}.bottom-0{bottom:0}.left-0{left:0}.left-2{left:.5rem}.left-\[50\%\]{left:50%}.right-0{right:0}.right-2{right:.5rem}.right-4{right:1rem}.top-0{top:0}.top-2{top:.5rem}.top-4{top:1rem}.top-\[1px\]{top:1px}.top-\[50\%\]{top:50%}.top-\[60\%\]{top:60%}.top-full{top:100%}.z-10{z-index:10}.z-50{z-index:50}.z-\[100\]{z-index:100}.z-\[1\]{z-index:1}.-mx-1{margin-left:-.25rem;margin-right:-.25rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-\[-0\.65rem\]{margin-left:-.65rem;margin-right:-.65rem}.mx-auto{margin-left:auto;margin-right:auto}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-4{margin-top:1rem;margin-bottom:1rem}.mb-1{margin-bottom:.25rem}.mb-10{margin-bottom:2.5rem}.mb-3{margin-bottom:.75rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-auto{margin-left:auto}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-10{margin-top:2.5rem}.mt-2{margin-top:.5rem}.mt-20{margin-top:5rem}.mt-24{margin-top:6rem}.mt-3{margin-top:.75rem}.mt-32{margin-top:8rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-7{margin-top:1.75rem}.mt-auto{margin-top:auto}.block{display:block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.aspect-square{aspect-ratio:1 / 1}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-11{height:2.75rem}.h-12{height:3rem}.h-14{height:3.5rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-\[1\.2rem\]{height:1.2rem}.h-\[1px\]{height:1px}.h-\[36px\]{height:36px}.h-\[75vh\]{height:75vh}.h-\[80dvh\]{height:80dvh}.h-\[80vh\]{height:80vh}.h-\[var\(--radix-navigation-menu-viewport-height\)\]{height:var(--radix-navigation-menu-viewport-height)}.h-\[var\(--radix-select-trigger-height\)\]{height:var(--radix-select-trigger-height)}.h-auto{height:auto}.h-full{height:100%}.h-px{height:1px}.max-h-96{max-height:24rem}.max-h-\[80vh\]{max-height:80vh}.max-h-screen{max-height:100vh}.min-h-\[180px\]{min-height:180px}.min-h-\[80px\]{min-height:80px}.min-h-screen{min-height:100vh}.w-10{width:2.5rem}.w-11{width:2.75rem}.w-16{width:4rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-24{width:6rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-3\/4{width:75%}.w-32{width:8rem}.w-36{width:9rem}.w-4{width:1rem}.w-40{width:10rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-56{width:14rem}.w-6{width:1.5rem}.w-60{width:15rem}.w-64{width:16rem}.w-8{width:2rem}.w-9{width:2.25rem}.w-\[1\.2rem\]{width:1.2rem}.w-\[100px\]{width:100px}.w-\[1px\]{width:1px}.w-\[36px\]{width:36px}.w-full{width:100%}.w-max{width:-moz-max-content;width:max-content}.min-w-\[8rem\]{min-width:8rem}.min-w-\[var\(--radix-select-trigger-width\)\]{min-width:var(--radix-select-trigger-width)}.max-w-\[35em\]{max-width:35em}.max-w-\[40em\]{max-width:40em}.max-w-\[60px\]{max-width:60px}.max-w-lg{max-width:32rem}.max-w-max{max-width:-moz-max-content;max-width:max-content}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.caption-bottom{caption-side:bottom}.translate-x-\[-50\%\]{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-\[-50\%\]{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-0{--tw-rotate: 0deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-45{--tw-rotate: 45deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-90{--tw-rotate: 90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-0{--tw-scale-x: 0;--tw-scale-y: 0;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-100{--tw-scale-x: 1;--tw-scale-y: 1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.list-none{list-style-type:none}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-baseline{align-items:baseline}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-5{gap:1.25rem}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.25rem * var(--tw-space-x-reverse));margin-left:calc(.25rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.5rem * var(--tw-space-x-reverse));margin-left:calc(.5rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.75rem * var(--tw-space-x-reverse));margin-left:calc(.75rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(1rem * var(--tw-space-x-reverse));margin-left:calc(1rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-5>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(1.25rem * var(--tw-space-x-reverse));margin-left:calc(1.25rem * calc(1 - var(--tw-space-x-reverse)))}.space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(0px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px * var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem * var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(2rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem * var(--tw-space-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-y-hidden{overflow-y:hidden}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.text-nowrap{text-wrap:nowrap}.break-words{overflow-wrap:break-word}.rounded{border-radius:.25rem}.rounded-\[inherit\]{border-radius:inherit}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-sm{border-radius:calc(var(--radius) - 4px)}.rounded-xl{border-radius:.75rem}.rounded-t-\[10px\]{border-top-left-radius:10px;border-top-right-radius:10px}.rounded-tl-sm{border-top-left-radius:calc(var(--radius) - 4px)}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-destructive{border-color:hsl(var(--destructive))}.border-destructive\/50{border-color:hsl(var(--destructive) / .5)}.border-input{border-color:hsl(var(--input))}.border-primary{border-color:hsl(var(--primary))}.border-transparent{border-color:transparent}.border-l-transparent{border-left-color:transparent}.border-t-transparent{border-top-color:transparent}.bg-background{background-color:hsl(var(--background))}.bg-black\/80{background-color:#000c}.bg-border{background-color:hsl(var(--border))}.bg-card{background-color:hsl(var(--card))}.bg-destructive{background-color:hsl(var(--destructive))}.bg-gray-950{--tw-bg-opacity: 1;background-color:rgb(3 7 18 / var(--tw-bg-opacity))}.bg-green-600{--tw-bg-opacity: 1;background-color:rgb(22 163 74 / var(--tw-bg-opacity))}.bg-muted{background-color:hsl(var(--muted))}.bg-muted\/40{background-color:hsl(var(--muted) / .4)}.bg-muted\/50{background-color:hsl(var(--muted) / .5)}.bg-orange-100{--tw-bg-opacity: 1;background-color:rgb(255 237 213 / var(--tw-bg-opacity))}.bg-popover{background-color:hsl(var(--popover))}.bg-primary{background-color:hsl(var(--primary))}.bg-secondary{background-color:hsl(var(--secondary))}.bg-transparent{background-color:transparent}.fill-current{fill:currentColor}.p-0{padding:0}.p-1{padding:.25rem}.p-10{padding:2.5rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-\[1px\]{padding:1px}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-8{padding-left:2rem;padding-right:2rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.pb-4{padding-bottom:1rem}.pl-2\.5{padding-left:.625rem}.pl-8{padding-left:2rem}.pr-2{padding-right:.5rem}.pr-2\.5{padding-right:.625rem}.pr-8{padding-right:2rem}.pt-0{padding-top:0}.pt-1{padding-top:.25rem}.pt-2{padding-top:.5rem}.pt-5{padding-top:1.25rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-middle{vertical-align:middle}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.leading-none{line-height:1}.tracking-tight{letter-spacing:-.025em}.tracking-widest{letter-spacing:.1em}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity))}.text-blue-500{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity))}.text-card-foreground{color:hsl(var(--card-foreground))}.text-current{color:currentColor}.text-destructive{color:hsl(var(--destructive))}.text-destructive-foreground{color:hsl(var(--destructive-foreground))}.text-foreground{color:hsl(var(--foreground))}.text-foreground\/50{color:hsl(var(--foreground) / .5)}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity))}.text-green-400{--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity))}.text-green-600{--tw-text-opacity: 1;color:rgb(22 163 74 / var(--tw-text-opacity))}.text-green-700{--tw-text-opacity: 1;color:rgb(21 128 61 / var(--tw-text-opacity))}.text-muted-foreground{color:hsl(var(--muted-foreground))}.text-popover-foreground{color:hsl(var(--popover-foreground))}.text-primary{color:hsl(var(--primary))}.text-primary-foreground{color:hsl(var(--primary-foreground))}.text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity))}.text-secondary-foreground{color:hsl(var(--secondary-foreground))}.text-stone-100{--tw-text-opacity: 1;color:rgb(245 245 244 / var(--tw-text-opacity))}.text-stone-600{--tw-text-opacity: 1;color:rgb(87 83 78 / var(--tw-text-opacity))}.text-stone-700{--tw-text-opacity: 1;color:rgb(68 64 60 / var(--tw-text-opacity))}.text-yellow-400{--tw-text-opacity: 1;color:rgb(250 204 21 / var(--tw-text-opacity))}.underline{text-decoration-line:underline}.underline-offset-4{text-underline-offset:4px}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-90{opacity:.9}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.outline{outline-style:solid}.ring-0{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-offset-background{--tw-ring-offset-color: hsl(var(--background))}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}@keyframes enter{0%{opacity:var(--tw-enter-opacity, 1);transform:translate3d(var(--tw-enter-translate-x, 0),var(--tw-enter-translate-y, 0),0) scale3d(var(--tw-enter-scale, 1),var(--tw-enter-scale, 1),var(--tw-enter-scale, 1)) rotate(var(--tw-enter-rotate, 0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity, 1);transform:translate3d(var(--tw-exit-translate-x, 0),var(--tw-exit-translate-y, 0),0) scale3d(var(--tw-exit-scale, 1),var(--tw-exit-scale, 1),var(--tw-exit-scale, 1)) rotate(var(--tw-exit-rotate, 0))}}.animate-in{animation-name:enter;animation-duration:.15s;--tw-enter-opacity: initial;--tw-enter-scale: initial;--tw-enter-rotate: initial;--tw-enter-translate-x: initial;--tw-enter-translate-y: initial}.fade-in-0{--tw-enter-opacity: 0}.zoom-in-95{--tw-enter-scale: .95}.duration-200{animation-duration:.2s}.ease-in-out{animation-timing-function:cubic-bezier(.4,0,.2,1)}.file\:border-0::file-selector-button{border-width:0px}.file\:bg-transparent::file-selector-button{background-color:transparent}.file\:text-sm::file-selector-button{font-size:.875rem;line-height:1.25rem}.file\:font-medium::file-selector-button{font-weight:500}.placeholder\:text-muted-foreground::-moz-placeholder{color:hsl(var(--muted-foreground))}.placeholder\:text-muted-foreground::placeholder{color:hsl(var(--muted-foreground))}.hover\:bg-accent:hover{background-color:hsl(var(--accent))}.hover\:bg-destructive\/80:hover{background-color:hsl(var(--destructive) / .8)}.hover\:bg-destructive\/90:hover{background-color:hsl(var(--destructive) / .9)}.hover\:bg-muted\/50:hover{background-color:hsl(var(--muted) / .5)}.hover\:bg-primary\/80:hover{background-color:hsl(var(--primary) / .8)}.hover\:bg-primary\/90:hover{background-color:hsl(var(--primary) / .9)}.hover\:bg-secondary:hover{background-color:hsl(var(--secondary))}.hover\:bg-secondary\/80:hover{background-color:hsl(var(--secondary) / .8)}.hover\:text-accent-foreground:hover{color:hsl(var(--accent-foreground))}.hover\:text-foreground:hover{color:hsl(var(--foreground))}.hover\:text-primary:hover{color:hsl(var(--primary))}.hover\:text-stone-900:hover{--tw-text-opacity: 1;color:rgb(28 25 23 / var(--tw-text-opacity))}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-100:hover{opacity:1}.focus\:bg-accent:focus{background-color:hsl(var(--accent))}.focus\:text-accent-foreground:focus{color:hsl(var(--accent-foreground))}.focus\:opacity-100:focus{opacity:1}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-ring:focus{--tw-ring-color: hsl(var(--ring))}.focus\:ring-offset-2:focus{--tw-ring-offset-width: 2px}.focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-visible\:ring-ring:focus-visible{--tw-ring-color: hsl(var(--ring))}.focus-visible\:ring-offset-2:focus-visible{--tw-ring-offset-width: 2px}.focus-visible\:ring-offset-background:focus-visible{--tw-ring-offset-color: hsl(var(--background))}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.group:hover .group-hover\:opacity-100{opacity:1}.group.destructive .group-\[\.destructive\]\:border-muted\/40{border-color:hsl(var(--muted) / .4)}.group.destructive .group-\[\.destructive\]\:text-red-300{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity))}.group.destructive .group-\[\.destructive\]\:hover\:border-destructive\/30:hover{border-color:hsl(var(--destructive) / .3)}.group.destructive .group-\[\.destructive\]\:hover\:bg-destructive:hover{background-color:hsl(var(--destructive))}.group.destructive .group-\[\.destructive\]\:hover\:text-destructive-foreground:hover{color:hsl(var(--destructive-foreground))}.group.destructive .group-\[\.destructive\]\:hover\:text-red-50:hover{--tw-text-opacity: 1;color:rgb(254 242 242 / var(--tw-text-opacity))}.group.destructive .group-\[\.destructive\]\:focus\:ring-destructive:focus{--tw-ring-color: hsl(var(--destructive))}.group.destructive .group-\[\.destructive\]\:focus\:ring-red-400:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(248 113 113 / var(--tw-ring-opacity))}.group.destructive .group-\[\.destructive\]\:focus\:ring-offset-red-600:focus{--tw-ring-offset-color: #dc2626}.peer:disabled~.peer-disabled\:cursor-not-allowed{cursor:not-allowed}.peer:disabled~.peer-disabled\:opacity-70{opacity:.7}.data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.data-\[side\=bottom\]\:translate-y-1[data-side=bottom]{--tw-translate-y: .25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[side\=left\]\:-translate-x-1[data-side=left]{--tw-translate-x: -.25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[side\=right\]\:translate-x-1[data-side=right]{--tw-translate-x: .25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[side\=top\]\:-translate-y-1[data-side=top]{--tw-translate-y: -.25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[state\=checked\]\:translate-x-5[data-state=checked]{--tw-translate-x: 1.25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[state\=unchecked\]\:translate-x-0[data-state=unchecked],.data-\[swipe\=cancel\]\:translate-x-0[data-swipe=cancel]{--tw-translate-x: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[swipe\=end\]\:translate-x-\[var\(--radix-toast-swipe-end-x\)\][data-swipe=end]{--tw-translate-x: var(--radix-toast-swipe-end-x);transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[swipe\=move\]\:translate-x-\[var\(--radix-toast-swipe-move-x\)\][data-swipe=move]{--tw-translate-x: var(--radix-toast-swipe-move-x);transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes accordion-up{0%{height:var(--radix-accordion-content-height)}to{height:0}}.data-\[state\=closed\]\:animate-accordion-up[data-state=closed]{animation:accordion-up .2s ease-out}@keyframes collapsible-up{0%{height:var(--radix-collapsible-content-height)}to{height:0}}.data-\[state\=closed\]\:animate-collapsible-up[data-state=closed]{animation:collapsible-up .2s ease-out}@keyframes accordion-down{0%{height:0}to{height:var(--radix-accordion-content-height)}}.data-\[state\=open\]\:animate-accordion-down[data-state=open]{animation:accordion-down .2s ease-out}@keyframes collapsible-down{0%{height:0}to{height:var(--radix-collapsible-content-height)}}.data-\[state\=open\]\:animate-collapsible-down[data-state=open]{animation:collapsible-down .2s ease-out}.data-\[active\]\:bg-accent\/50[data-active]{background-color:hsl(var(--accent) / .5)}.data-\[state\=active\]\:bg-background[data-state=active]{background-color:hsl(var(--background))}.data-\[state\=checked\]\:bg-primary[data-state=checked]{background-color:hsl(var(--primary))}.data-\[state\=open\]\:bg-accent[data-state=open]{background-color:hsl(var(--accent))}.data-\[state\=open\]\:bg-accent\/50[data-state=open]{background-color:hsl(var(--accent) / .5)}.data-\[state\=open\]\:bg-secondary[data-state=open]{background-color:hsl(var(--secondary))}.data-\[state\=selected\]\:bg-muted[data-state=selected]{background-color:hsl(var(--muted))}.data-\[state\=unchecked\]\:bg-input[data-state=unchecked]{background-color:hsl(var(--input))}.data-\[state\=active\]\:text-foreground[data-state=active]{color:hsl(var(--foreground))}.data-\[state\=open\]\:text-muted-foreground[data-state=open]{color:hsl(var(--muted-foreground))}.data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}.data-\[state\=active\]\:shadow-sm[data-state=active]{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.data-\[swipe\=move\]\:transition-none[data-swipe=move]{transition-property:none}.data-\[state\=closed\]\:duration-300[data-state=closed]{transition-duration:.3s}.data-\[state\=open\]\:duration-500[data-state=open]{transition-duration:.5s}.data-\[motion\^\=from-\]\:animate-in[data-motion^=from-],.data-\[state\=open\]\:animate-in[data-state=open],.data-\[state\=visible\]\:animate-in[data-state=visible]{animation-name:enter;animation-duration:.15s;--tw-enter-opacity: initial;--tw-enter-scale: initial;--tw-enter-rotate: initial;--tw-enter-translate-x: initial;--tw-enter-translate-y: initial}.data-\[motion\^\=to-\]\:animate-out[data-motion^=to-],.data-\[state\=closed\]\:animate-out[data-state=closed],.data-\[state\=hidden\]\:animate-out[data-state=hidden],.data-\[swipe\=end\]\:animate-out[data-swipe=end]{animation-name:exit;animation-duration:.15s;--tw-exit-opacity: initial;--tw-exit-scale: initial;--tw-exit-rotate: initial;--tw-exit-translate-x: initial;--tw-exit-translate-y: initial}.data-\[motion\^\=from-\]\:fade-in[data-motion^=from-]{--tw-enter-opacity: 0}.data-\[motion\^\=to-\]\:fade-out[data-motion^=to-],.data-\[state\=closed\]\:fade-out-0[data-state=closed]{--tw-exit-opacity: 0}.data-\[state\=closed\]\:fade-out-80[data-state=closed]{--tw-exit-opacity: .8}.data-\[state\=hidden\]\:fade-out[data-state=hidden]{--tw-exit-opacity: 0}.data-\[state\=open\]\:fade-in-0[data-state=open],.data-\[state\=visible\]\:fade-in[data-state=visible]{--tw-enter-opacity: 0}.data-\[state\=closed\]\:zoom-out-95[data-state=closed]{--tw-exit-scale: .95}.data-\[state\=open\]\:zoom-in-90[data-state=open]{--tw-enter-scale: .9}.data-\[state\=open\]\:zoom-in-95[data-state=open]{--tw-enter-scale: .95}.data-\[motion\=from-end\]\:slide-in-from-right-52[data-motion=from-end]{--tw-enter-translate-x: 13rem}.data-\[motion\=from-start\]\:slide-in-from-left-52[data-motion=from-start]{--tw-enter-translate-x: -13rem}.data-\[motion\=to-end\]\:slide-out-to-right-52[data-motion=to-end]{--tw-exit-translate-x: 13rem}.data-\[motion\=to-start\]\:slide-out-to-left-52[data-motion=to-start]{--tw-exit-translate-x: -13rem}.data-\[side\=bottom\]\:slide-in-from-top-2[data-side=bottom]{--tw-enter-translate-y: -.5rem}.data-\[side\=left\]\:slide-in-from-right-2[data-side=left]{--tw-enter-translate-x: .5rem}.data-\[side\=right\]\:slide-in-from-left-2[data-side=right]{--tw-enter-translate-x: -.5rem}.data-\[side\=top\]\:slide-in-from-bottom-2[data-side=top]{--tw-enter-translate-y: .5rem}.data-\[state\=closed\]\:slide-out-to-bottom[data-state=closed]{--tw-exit-translate-y: 100%}.data-\[state\=closed\]\:slide-out-to-left[data-state=closed]{--tw-exit-translate-x: -100%}.data-\[state\=closed\]\:slide-out-to-left-1\/2[data-state=closed]{--tw-exit-translate-x: -50%}.data-\[state\=closed\]\:slide-out-to-right[data-state=closed],.data-\[state\=closed\]\:slide-out-to-right-full[data-state=closed]{--tw-exit-translate-x: 100%}.data-\[state\=closed\]\:slide-out-to-top[data-state=closed]{--tw-exit-translate-y: -100%}.data-\[state\=closed\]\:slide-out-to-top-\[48\%\][data-state=closed]{--tw-exit-translate-y: -48%}.data-\[state\=open\]\:slide-in-from-bottom[data-state=open]{--tw-enter-translate-y: 100%}.data-\[state\=open\]\:slide-in-from-left[data-state=open]{--tw-enter-translate-x: -100%}.data-\[state\=open\]\:slide-in-from-left-1\/2[data-state=open]{--tw-enter-translate-x: -50%}.data-\[state\=open\]\:slide-in-from-right[data-state=open]{--tw-enter-translate-x: 100%}.data-\[state\=open\]\:slide-in-from-top[data-state=open]{--tw-enter-translate-y: -100%}.data-\[state\=open\]\:slide-in-from-top-\[48\%\][data-state=open]{--tw-enter-translate-y: -48%}.data-\[state\=open\]\:slide-in-from-top-full[data-state=open]{--tw-enter-translate-y: -100%}.data-\[state\=closed\]\:duration-300[data-state=closed]{animation-duration:.3s}.data-\[state\=open\]\:duration-500[data-state=open]{animation-duration:.5s}.group[data-state=open] .group-data-\[state\=open\]\:rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.dark\:-rotate-90:is(.dark *){--tw-rotate: -90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.dark\:rotate-0:is(.dark *){--tw-rotate: 0deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.dark\:scale-0:is(.dark *){--tw-scale-x: 0;--tw-scale-y: 0;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.dark\:scale-100:is(.dark *){--tw-scale-x: 1;--tw-scale-y: 1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.dark\:border-destructive:is(.dark *){border-color:hsl(var(--destructive))}.dark\:border-stone-200:is(.dark *){--tw-border-opacity: 1;border-color:rgb(231 229 228 / var(--tw-border-opacity))}.dark\:border-stone-400:is(.dark *){--tw-border-opacity: 1;border-color:rgb(168 162 158 / var(--tw-border-opacity))}.dark\:border-stone-500:is(.dark *){--tw-border-opacity: 1;border-color:rgb(120 113 108 / var(--tw-border-opacity))}.dark\:border-stone-700:is(.dark *){--tw-border-opacity: 1;border-color:rgb(68 64 60 / var(--tw-border-opacity))}.dark\:bg-stone-950:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(12 10 9 / var(--tw-bg-opacity))}.dark\:text-gray-200:is(.dark *){--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity))}.dark\:text-stone-200:is(.dark *){--tw-text-opacity: 1;color:rgb(231 229 228 / var(--tw-text-opacity))}.dark\:text-white:is(.dark *){--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.dark\:hover\:text-stone-200:hover:is(.dark *){--tw-text-opacity: 1;color:rgb(231 229 228 / var(--tw-text-opacity))}@media (min-width: 640px){.sm\:bottom-0{bottom:0}.sm\:right-0{right:0}.sm\:top-auto{top:auto}.sm\:ml-2{margin-left:.5rem}.sm\:mt-0{margin-top:0}.sm\:flex{display:flex}.sm\:w-24{width:6rem}.sm\:w-32{width:8rem}.sm\:w-36{width:9rem}.sm\:w-40{width:10rem}.sm\:w-48{width:12rem}.sm\:w-56{width:14rem}.sm\:w-60{width:15rem}.sm\:w-64{width:16rem}.sm\:max-w-5xl{max-width:64rem}.sm\:max-w-\[600px\]{max-width:600px}.sm\:max-w-sm{max-width:24rem}.sm\:flex-row{flex-direction:row}.sm\:flex-col{flex-direction:column}.sm\:justify-end{justify-content:flex-end}.sm\:justify-center{justify-content:center}.sm\:gap-2\.5{gap:.625rem}.sm\:space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.5rem * var(--tw-space-x-reverse));margin-left:calc(.5rem * calc(1 - var(--tw-space-x-reverse)))}.sm\:rounded-lg{border-radius:var(--radius)}.sm\:p-2{padding:.5rem}.sm\:pt-0{padding-top:0}.sm\:text-left{text-align:left}.data-\[state\=open\]\:sm\:slide-in-from-bottom-full[data-state=open]{--tw-enter-translate-y: 100%}}@media (min-width: 768px){.md\:absolute{position:absolute}.md\:mt-0{margin-top:0}.md\:mt-5{margin-top:1.25rem}.md\:block{display:block}.md\:hidden{display:none}.md\:w-\[200px\]{width:200px}.md\:w-\[250px\]{width:250px}.md\:w-\[350px\]{width:350px}.md\:w-\[35em\]{width:35em}.md\:w-\[45em\]{width:45em}.md\:w-\[var\(--radix-navigation-menu-viewport-width\)\]{width:var(--radix-navigation-menu-viewport-width)}.md\:w-auto{width:auto}.md\:max-w-\[35em\]{max-width:35em}.md\:max-w-\[420px\]{max-width:420px}.md\:grid-cols-\[180px_1fr\]{grid-template-columns:180px 1fr}.md\:flex-row{flex-direction:row}.md\:flex-col{flex-direction:column}.md\:space-x-10>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(2.5rem * var(--tw-space-x-reverse));margin-left:calc(2.5rem * calc(1 - var(--tw-space-x-reverse)))}.md\:space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.md\:p-3{padding:.75rem}}@media (min-width: 1024px){.lg\:h-\[60px\]{height:60px}.lg\:grid-cols-\[200px_1fr\]{grid-template-columns:200px 1fr}.lg\:gap-6{gap:1.5rem}.lg\:p-6{padding:1.5rem}.lg\:px-4{padding-left:1rem;padding-right:1rem}.lg\:px-6{padding-left:1.5rem;padding-right:1.5rem}}@media (min-width: 1536px){@media (min-width: 768px){.\32xl\:md\:grid-cols-\[280px_1fr\]{grid-template-columns:280px 1fr}}}.\[\&\:has\(\[role\=checkbox\]\)\]\:pr-0:has([role=checkbox]){padding-right:0}.\[\&\>span\]\:line-clamp-1>span{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1}.\[\&\>svg\+div\]\:translate-y-\[-3px\]>svg+div{--tw-translate-y: -3px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.\[\&\>svg\]\:absolute>svg{position:absolute}.\[\&\>svg\]\:left-4>svg{left:1rem}.\[\&\>svg\]\:top-4>svg{top:1rem}.\[\&\>svg\]\:size-3\.5>svg{width:.875rem;height:.875rem}.\[\&\>svg\]\:text-destructive>svg{color:hsl(var(--destructive))}.\[\&\>svg\]\:text-foreground>svg{color:hsl(var(--foreground))}.\[\&\>svg\~\*\]\:pl-7>svg~*{padding-left:1.75rem}.\[\&\>tr\]\:last\:border-b-0:last-child>tr{border-bottom-width:0px}.\[\&\[data-state\=open\]\>svg\]\:rotate-180[data-state=open]>svg{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.\[\&_p\]\:leading-relaxed p{line-height:1.625}.\[\&_tr\:last-child\]\:border-0 tr:last-child{border-width:0px}.\[\&_tr\]\:border-b tr{border-bottom-width:1px} diff --git a/ui/dist/imgs/providers/aliyun.svg b/ui/dist/imgs/providers/aliyun.svg deleted file mode 100644 index 7d0b70e0..00000000 --- a/ui/dist/imgs/providers/aliyun.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ui/dist/imgs/providers/aws.svg b/ui/dist/imgs/providers/aws.svg deleted file mode 100644 index 9f211f19..00000000 --- a/ui/dist/imgs/providers/aws.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ui/dist/imgs/providers/cloudflare.svg b/ui/dist/imgs/providers/cloudflare.svg deleted file mode 100644 index b6f07b50..00000000 --- a/ui/dist/imgs/providers/cloudflare.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ui/dist/imgs/providers/godaddy.svg b/ui/dist/imgs/providers/godaddy.svg deleted file mode 100644 index a859a7ae..00000000 --- a/ui/dist/imgs/providers/godaddy.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ui/dist/imgs/providers/huaweicloud.svg b/ui/dist/imgs/providers/huaweicloud.svg deleted file mode 100644 index 552e59e7..00000000 --- a/ui/dist/imgs/providers/huaweicloud.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ui/dist/imgs/providers/k8s.svg b/ui/dist/imgs/providers/k8s.svg deleted file mode 100644 index b7f555f7..00000000 --- a/ui/dist/imgs/providers/k8s.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ui/dist/imgs/providers/letsencrypt.svg b/ui/dist/imgs/providers/letsencrypt.svg deleted file mode 100644 index 3a6c2312..00000000 --- a/ui/dist/imgs/providers/letsencrypt.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ui/dist/imgs/providers/local.svg b/ui/dist/imgs/providers/local.svg deleted file mode 100644 index 2f59af07..00000000 --- a/ui/dist/imgs/providers/local.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ui/dist/imgs/providers/namesilo.svg b/ui/dist/imgs/providers/namesilo.svg deleted file mode 100644 index e0cc8da4..00000000 --- a/ui/dist/imgs/providers/namesilo.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ui/dist/imgs/providers/qiniu.svg b/ui/dist/imgs/providers/qiniu.svg deleted file mode 100644 index d3b98877..00000000 --- a/ui/dist/imgs/providers/qiniu.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ui/dist/imgs/providers/ssh.svg b/ui/dist/imgs/providers/ssh.svg deleted file mode 100644 index 8dea9e89..00000000 --- a/ui/dist/imgs/providers/ssh.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ui/dist/imgs/providers/tencent.svg b/ui/dist/imgs/providers/tencent.svg deleted file mode 100644 index 76e54dbb..00000000 --- a/ui/dist/imgs/providers/tencent.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ui/dist/imgs/providers/webhook.svg b/ui/dist/imgs/providers/webhook.svg deleted file mode 100644 index 2ca5bff3..00000000 --- a/ui/dist/imgs/providers/webhook.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ui/dist/imgs/providers/zerossl.svg b/ui/dist/imgs/providers/zerossl.svg deleted file mode 100644 index 8563aece..00000000 --- a/ui/dist/imgs/providers/zerossl.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ui/dist/vite.svg b/ui/dist/vite.svg deleted file mode 100644 index 2d1e68d6..00000000 --- a/ui/dist/vite.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ui/public/imgs/providers/httpreq.svg b/ui/public/imgs/providers/httpreq.svg new file mode 100644 index 00000000..621de609 --- /dev/null +++ b/ui/public/imgs/providers/httpreq.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ui/public/imgs/providers/pdns.svg b/ui/public/imgs/providers/pdns.svg new file mode 100644 index 00000000..39a111e7 --- /dev/null +++ b/ui/public/imgs/providers/pdns.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ui/src/components/certimate/AccessEdit.tsx b/ui/src/components/certimate/AccessEdit.tsx index c49bad72..6d589cee 100644 --- a/ui/src/components/certimate/AccessEdit.tsx +++ b/ui/src/components/certimate/AccessEdit.tsx @@ -14,6 +14,8 @@ import AccessAwsForm from "./AccessAwsForm"; import AccessCloudflareForm from "./AccessCloudflareForm"; import AccessNamesiloForm from "./AccessNamesiloForm"; import AccessGodaddyForm from "./AccessGodaddyForm"; +import AccessPdnsForm from "./AccessPdnsForm"; +import AccessHttpreqForm from "./AccessHttpreqForm"; import AccessLocalForm from "./AccessLocalForm"; import AccessSSHForm from "./AccessSSHForm"; import AccessWebhookForm from "./AccessWebhookForm"; @@ -125,6 +127,28 @@ const AccessEdit = ({ trigger, op, data, className }: AccessEditProps) => { /> ); break; + case "pdns": + form = ( + { + setOpen(false); + }} + /> + ); + break; + case "httpreq": + form = ( + { + setOpen(false); + }} + /> + ); + break; case "local": form = ( void; +}; + +const AccessHttpreqForm = ({ data, op, onAfterReq }: AccessHttpreqFormProps) => { + const { addAccess, updateAccess } = useConfig(); + const { t } = useTranslation(); + const formSchema = z.object({ + id: z.string().optional(), + name: z + .string() + .min(1, "access.authorization.form.name.placeholder") + .max(64, t("common.errmsg.string_max", { max: 64 })), + configType: accessFormType, + endpoint: z.string().url("common.errmsg.url_invalid"), + mode: z + .enum(["RAW", ""]), + username: z + .string() + .min(1, "access.authorization.form.access_key_secret.placeholder") + .max(128, t("common.errmsg.string_max", { max: 128 })), + password: z + .string() + .min(1, "access.authorization.form.access_key_secret.placeholder") + .max(128, t("common.errmsg.string_max", { max: 128 })), + }); + + let config: HttpreqConfig = { + endpoint: "", + mode: "", + username: "", + password: "", + }; + if (data) config = data.config as HttpreqConfig; + + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + id: data?.id, + name: data?.name || "", + configType: "httpreq", + endpoint: config.endpoint, + mode: config.mode === "RAW" ? "RAW" : "", + username: config.username, + password: config.password, + }, + }); + + const onSubmit = async (data: z.infer) => { + const req: Access = { + id: data.id as string, + name: data.name, + configType: data.configType, + usage: getUsageByConfigType(data.configType), + config: { + endpoint: data.endpoint, + mode: data.mode, + username: data.username, + password: data.password, + }, + }; + + try { + req.id = op == "copy" ? "" : req.id; + const rs = await save(req); + + onAfterReq(); + + req.id = rs.id; + req.created = rs.created; + req.updated = rs.updated; + if (data.id && op == "edit") { + updateAccess(req); + return; + } + + addAccess(req); + } catch (e) { + const err = e as ClientResponseError; + + Object.entries(err.response.data as PbErrorData).forEach(([key, value]) => { + form.setError(key as keyof z.infer, { + type: "manual", + message: value.message, + }); + }); + + return; + } + }; + const i18n_prefix = "access.authorization.form.httpreq"; + return ( + <> +
+
+ { + e.stopPropagation(); + form.handleSubmit(onSubmit)(e); + }} + className="space-y-8" + > + ( + + {t("access.authorization.form.name.label")} + + + + + + + )} + /> + + ( + + {t("access.authorization.form.config.label")} + + + + + + + )} + /> + + ( + + {t("access.authorization.form.config.label")} + + + + + + + )} + /> + + ( + + {t(i18n_prefix + "_endpoint.label")} + + + + + + + )} + /> + + ( + + {t(i18n_prefix + "_mode.label")} + + + + + + + )} + /> + + ( + + {t("access.authorization.form.username.label")} + + + + + + + )} + /> + + ( + + {t("access.authorization.form.password.label")} + + + + + + + )} + /> + + + +
+ +
+ + +
+ + ); +}; + +export default AccessHttpreqForm; + diff --git a/ui/src/components/certimate/AccessPdnsForm.tsx b/ui/src/components/certimate/AccessPdnsForm.tsx new file mode 100644 index 00000000..a3c0813f --- /dev/null +++ b/ui/src/components/certimate/AccessPdnsForm.tsx @@ -0,0 +1,195 @@ +import { useForm } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import z from "zod"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { ClientResponseError } from "pocketbase"; + +import { Button } from "@/components/ui/button"; +import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; +import { Input } from "@/components/ui/input"; +import { PbErrorData } from "@/domain/base"; +import { Access, PdnsConfig, accessFormType, getUsageByConfigType } from "@/domain/access"; +import { save } from "@/repository/access"; +import { useConfig } from "@/providers/config"; + +type AccessPdnsFormProps = { + op: "add" | "edit" | "copy"; + data?: Access; + onAfterReq: () => void; +}; + +const AccessPdnsForm = ({ data, op, onAfterReq }: AccessPdnsFormProps) => { + const { addAccess, updateAccess } = useConfig(); + const { t } = useTranslation(); + const formSchema = z.object({ + id: z.string().optional(), + name: z + .string() + .min(1, "access.authorization.form.name.placeholder") + .max(64, t("common.errmsg.string_max", { max: 64 })), + configType: accessFormType, + apiUrl: z.string().url("common.errmsg.url_invalid"), + apiKey: z + .string() + .min(1, "access.authorization.form.access_key_secret.placeholder") + .max(64, t("common.errmsg.string_max", { max: 64 })), + }); + + let config: PdnsConfig = { + apiUrl: "", + apiKey: "", + }; + if (data) config = data.config as PdnsConfig; + + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + id: data?.id, + name: data?.name || "", + configType: "pdns", + apiUrl: config.apiUrl, + apiKey: config.apiKey, + }, + }); + + const onSubmit = async (data: z.infer) => { + const req: Access = { + id: data.id as string, + name: data.name, + configType: data.configType, + usage: getUsageByConfigType(data.configType), + config: { + apiUrl: data.apiUrl, + apiKey: data.apiKey, + }, + }; + + try { + req.id = op == "copy" ? "" : req.id; + const rs = await save(req); + + onAfterReq(); + + req.id = rs.id; + req.created = rs.created; + req.updated = rs.updated; + if (data.id && op == "edit") { + updateAccess(req); + return; + } + + addAccess(req); + } catch (e) { + const err = e as ClientResponseError; + + Object.entries(err.response.data as PbErrorData).forEach(([key, value]) => { + form.setError(key as keyof z.infer, { + type: "manual", + message: value.message, + }); + }); + + return; + } + }; + + return ( + <> +
+
+ { + e.stopPropagation(); + form.handleSubmit(onSubmit)(e); + }} + className="space-y-8" + > + ( + + {t("access.authorization.form.name.label")} + + + + + + + )} + /> + + ( + + {t("access.authorization.form.config.label")} + + + + + + + )} + /> + + ( + + {t("access.authorization.form.config.label")} + + + + + + + )} + /> + + ( + + {t("access.authorization.form.pdns_api_url.label")} + + + + + + + )} + /> + + ( + + {t("access.authorization.form.pdns_api_key.label")} + + + + + + + )} + /> + + + +
+ +
+ + +
+ + ); +}; + +export default AccessPdnsForm; + diff --git a/ui/src/components/certimate/DeployList.tsx b/ui/src/components/certimate/DeployList.tsx index b3a1b62e..6c3caf71 100644 --- a/ui/src/components/certimate/DeployList.tsx +++ b/ui/src/components/certimate/DeployList.tsx @@ -326,7 +326,7 @@ const DeployEditDialog = ({ trigger, deployConfig, onSave }: DeployEditDialogPro {trigger} - {t("history.page.title")} + {t("domain.deployment.tab")} @@ -889,3 +889,4 @@ const DeployToKubernetes = () => { ); }; + diff --git a/ui/src/domain/access.ts b/ui/src/domain/access.ts index 9462fad1..988374b8 100644 --- a/ui/src/domain/access.ts +++ b/ui/src/domain/access.ts @@ -9,6 +9,8 @@ export const accessTypeMap: Map = new Map([ ["cloudflare", ["common.provider.cloudflare", "/imgs/providers/cloudflare.svg"]], ["namesilo", ["common.provider.namesilo", "/imgs/providers/namesilo.svg"]], ["godaddy", ["common.provider.godaddy", "/imgs/providers/godaddy.svg"]], + ["pdns", ["common.provider.pdns", "/imgs/providers/pdns.svg"]], + ["httpreq", ["common.provider.httpreq", "/imgs/providers/httpreq.svg"]], ["local", ["common.provider.local", "/imgs/providers/local.svg"]], ["ssh", ["common.provider.ssh", "/imgs/providers/ssh.svg"]], ["webhook", ["common.provider.webhook", "/imgs/providers/webhook.svg"]], @@ -29,6 +31,8 @@ export const accessFormType = z.union( z.literal("cloudflare"), z.literal("namesilo"), z.literal("godaddy"), + z.literal("pdns"), + z.literal("httpreq"), z.literal("local"), z.literal("ssh"), z.literal("webhook"), @@ -54,6 +58,8 @@ export type Access = { | CloudflareConfig | NamesiloConfig | GodaddyConfig + | PdnsConfig + | HttpreqConfig | LocalConfig | SSHConfig | WebhookConfig @@ -104,6 +110,18 @@ export type GodaddyConfig = { apiSecret: string; }; +export type PdnsConfig = { + apiUrl: string; + apiKey: string; +}; + +export type HttpreqConfig = { + endpoint: string; + mode: string; + username: string; + password: string; +}; + export type LocalConfig = Record; export type SSHConfig = { @@ -142,6 +160,8 @@ export const getUsageByConfigType = (configType: string): AccessUsage => { case "cloudflare": case "namesilo": case "godaddy": + case "pdns": + case "httpreq": return "apply"; default: diff --git a/ui/src/i18n/locales/en/nls.access.json b/ui/src/i18n/locales/en/nls.access.json index de48aa2a..15ae27ca 100644 --- a/ui/src/i18n/locales/en/nls.access.json +++ b/ui/src/i18n/locales/en/nls.access.json @@ -38,6 +38,14 @@ "access.authorization.form.godaddy_api_key.placeholder": "Please enter GO_DADDY_API_KEY", "access.authorization.form.godaddy_api_secret.label": "GO_DADDY_API_SECRET", "access.authorization.form.godaddy_api_secret.placeholder": "Please enter GO_DADDY_API_SECRET", + "access.authorization.form.pdns_api_url.label": "PDNS_API_URL", + "access.authorization.form.pdns_api_url.placeholder": "Please enter PDNS_API_URL", + "access.authorization.form.pdns_api_key.label": "PDNS_API_KEY", + "access.authorization.form.pdns_api_key.placeholder": "Please enter PDNS_API_KEY", + "access.authorization.form.httpreq_endpoint.label": "HTTPREQ_ENDPOINT", + "access.authorization.form.httpreq_endpoint.placeholder": "Please enter HTTPREQ_ENDPOINT", + "access.authorization.form.httpreq_mode.label": "HTTPREQ_MODE", + "access.authorization.form.httpreq_mode.placeholder": "Please enter HTTPREQ_MODE(RAW or '')", "access.authorization.form.namesilo_api_key.label": "NAMESILO_API_KEY", "access.authorization.form.namesilo_api_key.placeholder": "Please enter NAMESILO_API_KEY", "access.authorization.form.username.label": "Username", diff --git a/ui/src/i18n/locales/en/nls.common.json b/ui/src/i18n/locales/en/nls.common.json index 8fa0aab0..358639e0 100644 --- a/ui/src/i18n/locales/en/nls.common.json +++ b/ui/src/i18n/locales/en/nls.common.json @@ -66,6 +66,8 @@ "common.provider.cloudflare": "Cloudflare", "common.provider.namesilo": "Namesilo", "common.provider.godaddy": "GoDaddy", + "common.provider.pdns": "PowerDNS", + "common.provider.httpreq": "Http Request", "common.provider.local": "Local Deployment", "common.provider.ssh": "SSH Deployment", "common.provider.webhook": "Webhook", diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index df0b2fa2..70e2074f 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -39,6 +39,14 @@ "access.authorization.form.godaddy_api_secret.label": "GO_DADDY_API_SECRET", "access.authorization.form.godaddy_api_secret.placeholder": "请输入 GO_DADDY_API_SECRET", "access.authorization.form.namesilo_api_key.label": "NAMESILO_API_KEY", + "access.authorization.form.pdns_api_url.label": "PDNS_API_URL", + "access.authorization.form.pdns_api_url.placeholder": "请输入 PDNS_API_URL", + "access.authorization.form.pdns_api_key.label": "PDNS_API_KEY", + "access.authorization.form.pdns_api_key.placeholder": "请输入 PDNS_API_KEY", + "access.authorization.form.httpreq_endpoint.label": "HTTP 请求端点", + "access.authorization.form.httpreq_endpoint.placeholder": "请输入 请求端点", + "access.authorization.form.httpreq_mode.label": "模式", + "access.authorization.form.httpreq_mode.placeholder": "请输入模式( RAW or '')", "access.authorization.form.namesilo_api_key.placeholder": "请输入 NAMESILO_API_KEY", "access.authorization.form.username.label": "用户名", "access.authorization.form.username.placeholder": "请输入用户名", diff --git a/ui/src/i18n/locales/zh/nls.common.json b/ui/src/i18n/locales/zh/nls.common.json index 2568b23e..f6179636 100644 --- a/ui/src/i18n/locales/zh/nls.common.json +++ b/ui/src/i18n/locales/zh/nls.common.json @@ -66,6 +66,8 @@ "common.provider.cloudflare": "Cloudflare", "common.provider.namesilo": "Namesilo", "common.provider.godaddy": "GoDaddy", + "common.provider.pdns": "PowerDNS", + "common.provider.httpreq": "Http Request", "common.provider.local": "本地部署", "common.provider.ssh": "SSH 部署", "common.provider.webhook": "Webhook", @@ -75,3 +77,4 @@ "common.provider.telegram": "Telegram", "common.provider.lark": "飞书" } +