zhengkunwang 2023-11-20 10:44:10 +08:00 committed by GitHub
parent 8f05668bcc
commit 6c7e9d0a52
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 640 additions and 141 deletions

View file

@ -86,6 +86,27 @@ func (b *BaseApi) RenewWebsiteSSL(c *gin.Context) {
helper.SuccessWithData(c, nil)
}
// @Tags Website SSL
// @Summary Apply ssl
// @Description 申请证书
// @Accept json
// @Param request body request.WebsiteSSLApply true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /websites/ssl/obtain [post]
// @x-panel-log {"bodyKeys":["ID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ID","isList":false,"db":"website_ssls","output_column":"primary_domain","output_value":"domain"}],"formatZH":"申请证书 [domain]","formatEN":"apply ssl [domain]"}
func (b *BaseApi) ApplyWebsiteSSL(c *gin.Context) {
var req request.WebsiteSSLApply
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteSSLService.ObtainSSL(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithOutData(c)
}
// @Tags Website SSL
// @Summary Resolve website ssl
// @Description 解析网站 ssl

View file

@ -15,6 +15,7 @@ type WebsiteSSLCreate struct {
DnsAccountID uint `json:"dnsAccountId"`
AutoRenew bool `json:"autoRenew"`
KeyType string `json:"keyType"`
Apply bool `json:"apply"`
}
type WebsiteDNSReq struct {
@ -26,6 +27,10 @@ type WebsiteSSLRenew struct {
SSLID uint `json:"SSLId" validate:"required"`
}
type WebsiteSSLApply struct {
ID uint `json:"ID" validate:"required"`
}
type WebsiteAcmeAccountCreate struct {
Email string `json:"email" validate:"required"`
Type string `json:"type" validate:"required,oneof=letsencrypt zerossl buypass google"`

View file

@ -17,6 +17,9 @@ type WebsiteSSL struct {
AutoRenew bool `gorm:"type:varchar(64);not null" json:"autoRenew"`
ExpireDate time.Time `json:"expireDate"`
StartDate time.Time `json:"startDate"`
Status string `gorm:"not null;default:ready" json:"status"`
Message string `json:"message"`
KeyType string `gorm:"not null;default:2048" json:"keyType"`
AcmeAccount WebsiteAcmeAccount `json:"acmeAccount" gorm:"-:migration"`
Websites []Website `json:"websites" gorm:"-:migration"`

View file

@ -11,11 +11,15 @@ import (
"github.com/1Panel-dev/1Panel/backend/buserr"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/common"
"github.com/1Panel-dev/1Panel/backend/utils/files"
"github.com/1Panel-dev/1Panel/backend/utils/ssl"
"github.com/go-acme/lego/v4/certcrypto"
"github.com/jinzhu/gorm"
"path"
"strconv"
"strings"
"time"
)
type WebsiteSSLService struct {
@ -32,6 +36,7 @@ type IWebsiteSSLService interface {
Delete(id uint) error
Update(update request.WebsiteSSLUpdate) error
Upload(req request.WebsiteSSLUpload) error
ObtainSSL(apply request.WebsiteSSLApply) error
}
func NewIWebsiteSSLService() IWebsiteSSLService {
@ -95,74 +100,39 @@ func (w WebsiteSSLService) Create(create request.WebsiteSSLCreate) (request.Webs
if err != nil {
return res, err
}
client, err := ssl.NewAcmeClient(acmeAccount)
if err != nil {
return res, err
websiteSSL := model.WebsiteSSL{
Status: constant.SSLInit,
Provider: create.Provider,
AcmeAccountID: acmeAccount.ID,
PrimaryDomain: create.PrimaryDomain,
ExpireDate: time.Now(),
KeyType: create.KeyType,
}
var websiteSSL model.WebsiteSSL
var domains []string
if create.OtherDomains != "" {
otherDomainArray := strings.Split(create.OtherDomains, "\n")
for _, domain := range otherDomainArray {
if !common.IsValidDomain(domain) {
err = buserr.WithName("ErrDomainFormat", domain)
return res, err
}
domains = append(domains, domain)
}
}
websiteSSL.Domains = strings.Join(domains, ",")
switch create.Provider {
case constant.DNSAccount:
if create.Provider == constant.DNSAccount || create.Provider == constant.Http {
websiteSSL.AutoRenew = create.AutoRenew
}
if create.Provider == constant.DNSAccount {
dnsAccount, err := websiteDnsRepo.GetFirst(commonRepo.WithByID(create.DnsAccountID))
if err != nil {
return res, err
}
if err := client.UseDns(ssl.DnsType(dnsAccount.Type), dnsAccount.Authorization); err != nil {
return res, err
}
websiteSSL.AutoRenew = create.AutoRenew
case constant.Http:
appInstall, err := getAppInstallByKey(constant.AppOpenresty)
if err != nil {
return request.WebsiteSSLCreate{}, err
}
if err := client.UseHTTP(path.Join(appInstall.GetPath(), "root")); err != nil {
return res, err
}
websiteSSL.AutoRenew = create.AutoRenew
case constant.DnsManual:
if err := client.UseManualDns(); err != nil {
return res, err
}
websiteSSL.DnsAccountID = dnsAccount.ID
}
domains := []string{create.PrimaryDomain}
otherDomainArray := strings.Split(create.OtherDomains, "\n")
if create.OtherDomains != "" {
domains = append(otherDomainArray, domains...)
}
block, _ := pem.Decode([]byte(acmeAccount.PrivateKey))
privateKey, err := x509.ParseECPrivateKey(block.Bytes)
if err != nil {
return res, err
}
resource, err := client.ObtainSSL(domains, privateKey)
if err != nil {
return res, err
}
if create.Provider == constant.DNSAccount {
websiteSSL.DnsAccountID = create.DnsAccountID
}
websiteSSL.AcmeAccountID = acmeAccount.ID
websiteSSL.Provider = create.Provider
websiteSSL.Domains = strings.Join(otherDomainArray, ",")
websiteSSL.PrimaryDomain = create.PrimaryDomain
websiteSSL.PrivateKey = string(resource.PrivateKey)
websiteSSL.Pem = string(resource.Certificate)
websiteSSL.CertURL = resource.CertURL
certBlock, _ := pem.Decode(resource.Certificate)
cert, err := x509.ParseCertificate(certBlock.Bytes)
if err != nil {
return request.WebsiteSSLCreate{}, err
}
websiteSSL.ExpireDate = cert.NotAfter
websiteSSL.StartDate = cert.NotBefore
websiteSSL.Type = cert.Issuer.CommonName
websiteSSL.Organization = cert.Issuer.Organization[0]
if err := websiteSSLRepo.Create(context.TODO(), &websiteSSL); err != nil {
return res, err
}
@ -170,6 +140,99 @@ func (w WebsiteSSLService) Create(create request.WebsiteSSLCreate) (request.Webs
return create, nil
}
func (w WebsiteSSLService) ObtainSSL(apply request.WebsiteSSLApply) error {
websiteSSL, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(apply.ID))
if err != nil {
return err
}
acmeAccount, err := websiteAcmeRepo.GetFirst(commonRepo.WithByID(websiteSSL.AcmeAccountID))
if err != nil {
return err
}
client, err := ssl.NewAcmeClient(acmeAccount)
if err != nil {
return err
}
switch websiteSSL.Provider {
case constant.DNSAccount:
dnsAccount, err := websiteDnsRepo.GetFirst(commonRepo.WithByID(websiteSSL.DnsAccountID))
if err != nil {
return err
}
if err := client.UseDns(ssl.DnsType(dnsAccount.Type), dnsAccount.Authorization); err != nil {
return err
}
case constant.Http:
appInstall, err := getAppInstallByKey(constant.AppOpenresty)
if err != nil {
if gorm.IsRecordNotFoundError(err) {
return buserr.New("ErrOpenrestyNotFound")
}
return err
}
if err := client.UseHTTP(path.Join(appInstall.GetPath(), "root")); err != nil {
return err
}
case constant.DnsManual:
if err := client.UseManualDns(); err != nil {
return err
}
}
domains := []string{websiteSSL.PrimaryDomain}
domains = append(domains, domains...)
privateKey, err := certcrypto.GeneratePrivateKey(ssl.KeyType(websiteSSL.KeyType))
if err != nil {
return err
}
websiteSSL.Status = constant.SSLApply
err = websiteSSLRepo.Save(websiteSSL)
if err != nil {
return err
}
go func() {
resource, err := client.ObtainSSL(domains, privateKey)
if err != nil {
handleError(websiteSSL, err)
return
}
websiteSSL.PrivateKey = string(resource.PrivateKey)
websiteSSL.Pem = string(resource.Certificate)
websiteSSL.CertURL = resource.CertURL
certBlock, _ := pem.Decode(resource.Certificate)
cert, err := x509.ParseCertificate(certBlock.Bytes)
if err != nil {
handleError(websiteSSL, err)
return
}
websiteSSL.ExpireDate = cert.NotAfter
websiteSSL.StartDate = cert.NotBefore
websiteSSL.Type = cert.Issuer.CommonName
websiteSSL.Organization = cert.Issuer.Organization[0]
websiteSSL.Status = constant.SSLReady
err = websiteSSLRepo.Save(websiteSSL)
if err != nil {
return
}
}()
return nil
}
func handleError(websiteSSL model.WebsiteSSL, err error) {
if websiteSSL.Status == constant.SSLInit || websiteSSL.Status == constant.SSLError {
websiteSSL.Status = constant.Error
} else {
websiteSSL.Status = constant.SSLApplyError
}
websiteSSL.Message = err.Error()
_ = websiteSSLRepo.Save(websiteSSL)
}
func (w WebsiteSSLService) Renew(sslId uint) error {
websiteSSL, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(sslId))
if err != nil {

View file

@ -3,7 +3,6 @@ package constant
const (
StatusRunning = "Running"
StatusDone = "Done"
StatusStoped = "Stoped"
StatusWaiting = "Waiting"
StatusSuccess = "Success"
StatusFailed = "Failed"

View file

@ -45,4 +45,10 @@ const (
ConfigPHP = "php"
ConfigFPM = "fpm"
SSLInit = "init"
SSLError = "error"
SSLReady = "ready"
SSLApply = "applying"
SSLApplyError = "applyError"
)

View file

@ -92,6 +92,8 @@ ErrSSLCertificateNotFound: 'The certificate file does not exist'
ErrSSLKeyFormat: 'Private key file verification error'
ErrSSLCertificateFormat: 'Certificate file format error, please use pem format'
ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid or EabHmacKey cannot be empty'
ErrOpenrestyNotFound: 'Http mode requires Openresty to be installed first'
#mysql
ErrUserIsExist: "The current user already exists. Please enter a new user"

View file

@ -92,6 +92,7 @@ ErrSSLCertificateNotFound: '證書文件不存在'
ErrSSLKeyFormat: '私鑰文件校驗錯誤'
ErrSSLCertificateFormat: '證書文件格式錯誤,請使用 pem 格式'
ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid 或 EabHmacKey 不能為空'
ErrOpenrestyNotFound: 'Http 模式需要先安裝 Openresty'
#mysql
ErrUserIsExist: "當前用戶已存在,請重新輸入"

View file

@ -92,6 +92,7 @@ ErrSSLCertificateNotFound: '证书文件不存在'
ErrSSLKeyFormat: '私钥文件校验失败'
ErrSSLCertificateFormat: '证书文件格式错误,请使用 pem 格式'
ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid 或 EabHmacKey 不能为空'
ErrOpenrestyNotFound: 'Http 模式需要首先安装 Openresty'
#mysql
ErrUserIsExist: "当前用户已存在,请重新输入"

View file

@ -54,6 +54,7 @@ func Init() {
migrations.AddAppSyncStatus,
migrations.UpdateAcmeAccount,
migrations.UpdateWebsiteSSL,
})
if err := m.Migrate(); err != nil {
global.LOG.Error(err)

View file

@ -15,3 +15,13 @@ var UpdateAcmeAccount = &gormigrate.Migration{
return nil
},
}
var UpdateWebsiteSSL = &gormigrate.Migration{
ID: "20231119-update-website-ssl",
Migrate: func(tx *gorm.DB) error {
if err := tx.AutoMigrate(&model.WebsiteSSL{}); err != nil {
return err
}
return nil
},
}

View file

@ -24,5 +24,6 @@ func (a *WebsiteSSLRouter) InitWebsiteSSLRouter(Router *gin.RouterGroup) {
groupRouter.GET("/:id", baseApi.GetWebsiteSSLById)
groupRouter.POST("/update", baseApi.UpdateWebsiteSSL)
groupRouter.POST("/upload", baseApi.UploadWebsiteSSL)
groupRouter.POST("/obtain", baseApi.ApplyWebsiteSSL)
}
}

View file

@ -1,5 +1,5 @@
// Code generated by swaggo/swag. DO NOT EDIT.
// Package docs GENERATED BY SWAG; DO NOT EDIT
// This file was generated by swaggo/swag
package docs
import "github.com/swaggo/swag"
@ -12349,6 +12349,57 @@ const docTemplate = `{
}
}
},
"/websites/ssl/obtain": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "申请证书",
"consumes": [
"application/json"
],
"tags": [
"Website SSL"
],
"summary": "Apply ssl",
"parameters": [
{
"description": "request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/request.WebsiteSSLApply"
}
}
],
"responses": {
"200": {
"description": "OK"
}
},
"x-panel-log": {
"BeforeFunctions": [
{
"db": "website_ssls",
"input_column": "id",
"input_value": "ID",
"isList": false,
"output_column": "primary_domain",
"output_value": "domain"
}
],
"bodyKeys": [
"ID"
],
"formatEN": "apply ssl [domain]",
"formatZH": "申请证书 [domain]",
"paramKeys": []
}
}
},
"/websites/ssl/renew": {
"post": {
"security": [
@ -16736,6 +16787,9 @@ const docTemplate = `{
"id": {
"type": "integer"
},
"keyType": {
"type": "string"
},
"type": {
"type": "string"
},
@ -16800,6 +16854,12 @@ const docTemplate = `{
"id": {
"type": "integer"
},
"keyType": {
"type": "string"
},
"message": {
"type": "string"
},
"organization": {
"type": "string"
},
@ -16818,6 +16878,9 @@ const docTemplate = `{
"startDate": {
"type": "string"
},
"status": {
"type": "string"
},
"type": {
"type": "string"
},
@ -18113,6 +18176,7 @@ const docTemplate = `{
"type": "object",
"required": [
"email",
"keyType",
"type"
],
"properties": {
@ -18125,6 +18189,17 @@ const docTemplate = `{
"email": {
"type": "string"
},
"keyType": {
"type": "string",
"enum": [
"P256",
"P384",
"2048",
"3072",
"4096",
"8192"
]
},
"type": {
"type": "string",
"enum": [
@ -18597,6 +18672,17 @@ const docTemplate = `{
}
}
},
"request.WebsiteSSLApply": {
"type": "object",
"required": [
"ID"
],
"properties": {
"ID": {
"type": "integer"
}
}
},
"request.WebsiteSSLCreate": {
"type": "object",
"required": [
@ -18608,12 +18694,18 @@ const docTemplate = `{
"acmeAccountId": {
"type": "integer"
},
"apply": {
"type": "boolean"
},
"autoRenew": {
"type": "boolean"
},
"dnsAccountId": {
"type": "integer"
},
"keyType": {
"type": "string"
},
"otherDomains": {
"type": "string"
},
@ -19231,6 +19323,9 @@ const docTemplate = `{
"id": {
"type": "integer"
},
"keyType": {
"type": "string"
},
"type": {
"type": "string"
},

View file

@ -12342,6 +12342,57 @@
}
}
},
"/websites/ssl/obtain": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "申请证书",
"consumes": [
"application/json"
],
"tags": [
"Website SSL"
],
"summary": "Apply ssl",
"parameters": [
{
"description": "request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/request.WebsiteSSLApply"
}
}
],
"responses": {
"200": {
"description": "OK"
}
},
"x-panel-log": {
"BeforeFunctions": [
{
"db": "website_ssls",
"input_column": "id",
"input_value": "ID",
"isList": false,
"output_column": "primary_domain",
"output_value": "domain"
}
],
"bodyKeys": [
"ID"
],
"formatEN": "apply ssl [domain]",
"formatZH": "申请证书 [domain]",
"paramKeys": []
}
}
},
"/websites/ssl/renew": {
"post": {
"security": [
@ -16729,6 +16780,9 @@
"id": {
"type": "integer"
},
"keyType": {
"type": "string"
},
"type": {
"type": "string"
},
@ -16793,6 +16847,12 @@
"id": {
"type": "integer"
},
"keyType": {
"type": "string"
},
"message": {
"type": "string"
},
"organization": {
"type": "string"
},
@ -16811,6 +16871,9 @@
"startDate": {
"type": "string"
},
"status": {
"type": "string"
},
"type": {
"type": "string"
},
@ -18106,6 +18169,7 @@
"type": "object",
"required": [
"email",
"keyType",
"type"
],
"properties": {
@ -18118,6 +18182,17 @@
"email": {
"type": "string"
},
"keyType": {
"type": "string",
"enum": [
"P256",
"P384",
"2048",
"3072",
"4096",
"8192"
]
},
"type": {
"type": "string",
"enum": [
@ -18590,6 +18665,17 @@
}
}
},
"request.WebsiteSSLApply": {
"type": "object",
"required": [
"ID"
],
"properties": {
"ID": {
"type": "integer"
}
}
},
"request.WebsiteSSLCreate": {
"type": "object",
"required": [
@ -18601,12 +18687,18 @@
"acmeAccountId": {
"type": "integer"
},
"apply": {
"type": "boolean"
},
"autoRenew": {
"type": "boolean"
},
"dnsAccountId": {
"type": "integer"
},
"keyType": {
"type": "string"
},
"otherDomains": {
"type": "string"
},
@ -19224,6 +19316,9 @@
"id": {
"type": "integer"
},
"keyType": {
"type": "string"
},
"type": {
"type": "string"
},

View file

@ -2661,6 +2661,8 @@ definitions:
type: string
id:
type: integer
keyType:
type: string
type:
type: string
updatedAt:
@ -2703,6 +2705,10 @@ definitions:
type: string
id:
type: integer
keyType:
type: string
message:
type: string
organization:
type: string
pem:
@ -2715,6 +2721,8 @@ definitions:
type: string
startDate:
type: string
status:
type: string
type:
type: string
updatedAt:
@ -3586,6 +3594,15 @@ definitions:
type: string
email:
type: string
keyType:
enum:
- P256
- P384
- "2048"
- "3072"
- "4096"
- "8192"
type: string
type:
enum:
- letsencrypt
@ -3595,6 +3612,7 @@ definitions:
type: string
required:
- email
- keyType
- type
type: object
request.WebsiteCommonReq:
@ -3907,14 +3925,25 @@ definitions:
required:
- id
type: object
request.WebsiteSSLApply:
properties:
ID:
type: integer
required:
- ID
type: object
request.WebsiteSSLCreate:
properties:
acmeAccountId:
type: integer
apply:
type: boolean
autoRenew:
type: boolean
dnsAccountId:
type: integer
keyType:
type: string
otherDomains:
type: string
primaryDomain:
@ -4328,6 +4357,8 @@ definitions:
type: string
id:
type: integer
keyType:
type: string
type:
type: string
updatedAt:
@ -12291,6 +12322,39 @@ paths:
formatEN: Delete ssl [domain]
formatZH: 删除 ssl [domain]
paramKeys: []
/websites/ssl/obtain:
post:
consumes:
- application/json
description: 申请证书
parameters:
- description: request
in: body
name: request
required: true
schema:
$ref: '#/definitions/request.WebsiteSSLApply'
responses:
"200":
description: OK
security:
- ApiKeyAuth: []
summary: Apply ssl
tags:
- Website SSL
x-panel-log:
BeforeFunctions:
- db: website_ssls
input_column: id
input_value: ID
isList: false
output_column: primary_domain
output_value: domain
bodyKeys:
- ID
formatEN: apply ssl [domain]
formatZH: 申请证书 [domain]
paramKeys: []
/websites/ssl/renew:
post:
consumes:

View file

@ -164,6 +164,8 @@ export namespace Website {
websites?: Website.Website[];
autoRenew: boolean;
acmeAccountId?: number;
status: string;
domains?: string;
}
export interface SSLCreate {
@ -446,4 +448,8 @@ export namespace Website {
certificatePath: string;
type: string;
}
export interface SSLObtain {
ID: number;
}
}

View file

@ -120,6 +120,10 @@ export const ApplySSL = (req: Website.SSLApply) => {
return http.post<Website.SSLApply>(`/websites/ssl/apply`, req);
};
export const ObtainSSL = (req: Website.SSLObtain) => {
return http.post<any>(`/websites/ssl/obtain`, req);
};
export const RenewSSL = (req: Website.SSLRenew) => {
return http.post<any>(`/websites/ssl/renew`, req, TimeoutEnum.T_10M);
};

View file

@ -48,6 +48,7 @@ const loadingStatus = [
'creating',
'starting',
'removing',
'applying',
];
const loadingIcon = (status: string): boolean => {

View file

@ -236,6 +236,10 @@ const message = {
recreating: 'Recreating',
creating: 'Creating',
systemrestart: 'Interrupt',
init: 'Waiting for application',
ready: 'normal',
applying: 'Applying',
applyerror: 'Failure',
},
units: {
second: 'Second',
@ -1753,6 +1757,10 @@ const message = {
createAcme: 'Create Account',
acmeHelper: 'Acme account is used to apply for free certificates',
upload: 'Upload Certificate',
applyType: 'Application method',
apply: 'Apply',
applyStart: 'Certificate application starts',
getDnsResolve: 'Getting DNS resolution value, please wait...',
},
firewall: {
create: 'Create rule',

View file

@ -235,6 +235,10 @@ const message = {
recreating: '重建中',
creating: '創建中',
systemrestart: '中斷',
init: '等待申請',
ready: '正常',
applying: '申請中',
applyerror: '失敗',
},
units: {
second: '秒',
@ -1664,6 +1668,10 @@ const message = {
createAcme: '創建賬戶',
acmeHelper: 'Acme 賬戶用於申請免費證書',
upload: '上傳證書',
applyType: '申請方式',
apply: '申請',
applyStart: '證書申請開始',
getDnsResolve: '正在取得 DNS 解析值,請稍後 ...',
},
firewall: {
create: '創建規則',

View file

@ -235,6 +235,10 @@ const message = {
recreating: '重建中',
creating: '创建中',
systemrestart: '中断',
init: '等待申请',
ready: '正常',
applying: '申请中',
applyerror: '失败',
},
units: {
second: '秒',
@ -1664,6 +1668,10 @@ const message = {
createAcme: '创建账户',
acmeHelper: 'Acme 账户用于申请免费证书',
upload: '上传证书',
applyType: '申请方式',
apply: '申请',
applyStart: '证书申请开始',
getDnsResolve: '正在获取 DNS 解析值,请稍后 ...',
},
firewall: {
create: '创建规则',

View file

@ -0,0 +1,93 @@
<template>
<el-dialog
v-model="open"
:title="$t('ssl.apply')"
:destroy-on-close="true"
:close-on-click-modal="false"
width="50%"
:before-close="handleClose"
>
<div v-if="loading">
<el-alert type="info" :closable="false" center>{{ $t('ssl.getDnsResolve') }}</el-alert>
</div>
<div v-if="dnsResolve.length > 0">
<span>{{ $t('ssl.dnsResolveHelper') }}</span>
<el-table :data="dnsResolve" border :table-layout="'auto'">
<el-table-column prop="domain" :label="$t('website.domain')" />
<el-table-column prop="resolve" :label="$t('ssl.resolveDomain')" />
<el-table-column prop="value" :label="$t('ssl.value')" />
<el-table-column :label="$t('commons.table.type')">TXT</el-table-column>
</el-table>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleClose" :disabled="loading">{{ $t('commons.button.cancel') }}</el-button>
<el-button type="primary" @click="submit()" :disabled="loading">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { Website } from '@/api/interface/website';
import { GetDnsResolve, ObtainSSL } from '@/api/modules/website';
import i18n from '@/lang';
import { MsgSuccess } from '@/utils/message';
import { ref } from 'vue';
interface RenewProps {
ssl: Website.SSL;
}
const open = ref(false);
const loading = ref(false);
const dnsResolve = ref<Website.DNSResolve[]>([]);
const sslID = ref(0);
const em = defineEmits(['close']);
const handleClose = () => {
open.value = false;
em('close', false);
};
const acceptParams = async (props: RenewProps) => {
open.value = true;
dnsResolve.value = [];
sslID.value = props.ssl.id;
getDnsResolve(props.ssl);
};
const getDnsResolve = async (row: Website.SSL) => {
loading.value = true;
let domains = [row.primaryDomain];
if (row.domains != '') {
let otherDomains = row.domains.split(',');
domains = domains.concat(otherDomains);
}
try {
const res = await GetDnsResolve({ acmeAccountId: row.acmeAccountId, domains: domains });
if (res.data) {
dnsResolve.value = res.data;
}
} finally {
loading.value = false;
}
};
const submit = () => {
ObtainSSL({ ID: sslID.value })
.then(() => {
MsgSuccess(i18n.global.t('ssl.applyStart'));
handleClose();
})
.finally(() => {});
};
defineExpose({
acceptParams,
});
</script>

View file

@ -57,15 +57,6 @@
></el-option>
</el-select>
</el-form-item>
<el-form-item v-if="ssl.provider === 'dnsManual' && dnsResolve.length > 0">
<span>{{ $t('ssl.dnsResolveHelper') }}</span>
<el-table :data="dnsResolve" border :table-layout="'auto'">
<el-table-column prop="domain" :label="$t('website.domain')" />
<el-table-column prop="resolve" :label="$t('ssl.resolveDomain')" />
<el-table-column prop="value" :label="$t('ssl.value')" />
<el-table-column :label="$t('commons.table.type')">TXT</el-table-column>
</el-table>
</el-form-item>
<el-form-item :label="''" prop="autoRenew" v-if="ssl.provider !== 'dnsManual'">
<el-checkbox v-model="ssl.autoRenew" :label="$t('ssl.autoRenew')" />
</el-form-item>
@ -86,7 +77,7 @@
<script lang="ts" setup>
import DrawerHeader from '@/components/drawer-header/index.vue';
import { Website } from '@/api/interface/website';
import { CreateSSL, GetDnsResolve, SearchAcmeAccount, SearchDnsAccount } from '@/api/modules/website';
import { CreateSSL, SearchAcmeAccount, SearchDnsAccount } from '@/api/modules/website';
import { Rules } from '@/global/form-rules';
import i18n from '@/lang';
import { FormInstance } from 'element-plus';
@ -140,7 +131,6 @@ const initData = () => ({
const ssl = ref(initData());
const dnsResolve = ref<Website.DNSResolve[]>([]);
const hasResolve = ref(false);
const em = defineEmits(['close']);
const handleClose = () => {
@ -182,44 +172,21 @@ const changeProvider = () => {
dnsResolve.value = [];
};
const getDnsResolve = async (acmeAccountId: number, domains: string[]) => {
hasResolve.value = false;
loading.value = true;
try {
const res = await GetDnsResolve({ acmeAccountId: acmeAccountId, domains: domains });
if (res.data) {
dnsResolve.value = res.data;
hasResolve.value = true;
}
} finally {
loading.value = false;
}
};
const submit = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
await formEl.validate((valid) => {
if (!valid) {
return;
}
if (ssl.value.provider != 'dnsManual' || hasResolve.value) {
loading.value = true;
CreateSSL(ssl.value)
.then(() => {
handleClose();
MsgSuccess(i18n.global.t('commons.msg.createSuccess'));
})
.finally(() => {
loading.value = false;
});
} else {
let domains = [ssl.value.primaryDomain];
if (ssl.value.otherDomains != '') {
let otherDomains = ssl.value.otherDomains.split('\n');
domains = domains.concat(otherDomains);
}
getDnsResolve(ssl.value.acmeAccountId, domains);
}
loading.value = true;
CreateSSL(ssl.value)
.then(() => {
handleClose();
MsgSuccess(i18n.global.t('commons.msg.createSuccess'));
})
.finally(() => {
loading.value = false;
});
});
};

View file

@ -19,7 +19,7 @@
<el-descriptions-item :label="$t('website.otherDomains')">
{{ ssl.domains }}
</el-descriptions-item>
<el-descriptions-item :label="$t('ssl.provider')">
<el-descriptions-item :label="$t('ssl.applyType')">
{{ getProvider(ssl.provider) }}
</el-descriptions-item>
<el-descriptions-item

View file

@ -25,7 +25,7 @@
</template>
<template #main>
<br />
<ComplexTable :data="data" :pagination-config="paginationConfig" @search="search()">
<ComplexTable :data="data" :pagination-config="paginationConfig" @search="search()" v-loading="loading">
<el-table-column
:label="$t('website.domain')"
fix
@ -38,7 +38,13 @@
show-overflow-tooltip
prop="domains"
></el-table-column>
<el-table-column :label="$t('ssl.provider')" fix show-overflow-tooltip prop="provider">
<el-table-column
:label="$t('ssl.applyType')"
fix
show-overflow-tooltip
prop="provider"
width="100px"
>
<template #default="{ row }">{{ getProvider(row.provider) }}</template>
</el-table-column>
<el-table-column
@ -47,13 +53,41 @@
show-overflow-tooltip
prop="acmeAccount.email"
></el-table-column>
<el-table-column
:label="$t('commons.table.status')"
fix
show-overflow-tooltip
prop="status"
width="100px"
>
<template #default="{ row }">
<el-popover
v-if="
row.status === 'error' ||
row.status === 'applyError' ||
row.status === 'systemRestart'
"
placement="bottom"
:width="400"
trigger="hover"
:content="row.message"
>
<template #reference>
<Status :key="row.status" :status="row.status"></Status>
</template>
</el-popover>
<div v-else>
<Status :key="row.status" :status="row.status"></Status>
</div>
</template>
</el-table-column>
<el-table-column
:label="$t('website.brand')"
fix
show-overflow-tooltip
prop="organization"
></el-table-column>
<el-table-column :label="$t('ssl.autoRenew')" fix>
<el-table-column :label="$t('ssl.autoRenew')" fix width="100px">
<template #default="{ row }">
<el-switch
:disabled="row.provider === 'dnsManual' || row.provider === 'manual'"
@ -80,22 +114,20 @@
<DnsAccount ref="dnsAccountRef"></DnsAccount>
<AcmeAccount ref="acmeAccountRef"></AcmeAccount>
<Create ref="sslCreateRef" @close="search()"></Create>
<Renew ref="renewRef" @close="search()"></Renew>
<Detail ref="detailRef"></Detail>
<SSLUpload ref="sslUploadRef" @close="search()"></SSLUpload>
<Apply ref="applyRef" @search="search" />
<OpDialog ref="opRef" @search="search" />
</LayoutContent>
<OpDialog ref="opRef" @search="search" />
</div>
</template>
<script lang="ts" setup>
import { onMounted, reactive, ref, computed } from 'vue';
import OpDialog from '@/components/del-dialog/index.vue';
import { DeleteSSL, SearchSSL, UpdateSSL } from '@/api/modules/website';
import { DeleteSSL, ObtainSSL, SearchSSL, UpdateSSL } from '@/api/modules/website';
import DnsAccount from './dns-account/index.vue';
import AcmeAccount from './acme-account/index.vue';
import Renew from './renew/index.vue';
import Create from './create/index.vue';
import Detail from './detail/index.vue';
import { dateFormat, getProvider } from '@/utils/util';
@ -104,6 +136,7 @@ import { Website } from '@/api/interface/website';
import { MsgSuccess } from '@/utils/message';
import { GlobalStore } from '@/store';
import SSLUpload from './upload/index.vue';
import Apply from './apply/index.vue';
const globalStore = GlobalStore();
const paginationConfig = reactive({
@ -121,6 +154,7 @@ const data = ref();
const loading = ref(false);
const opRef = ref();
const sslUploadRef = ref();
const applyRef = ref();
const routerButton = [
{
@ -132,17 +166,24 @@ const routerButton = [
const buttons = [
{
label: i18n.global.t('ssl.detail'),
disabled: function (row: Website.SSL) {
return row.status === 'init' || row.status === 'error';
},
click: function (row: Website.SSL) {
openDetail(row.id);
},
},
{
label: i18n.global.t('website.renewSSL'),
label: i18n.global.t('ssl.apply'),
disabled: function (row: Website.SSL) {
return row.provider === 'manual';
return row.status === 'applying';
},
click: function (row: Website.SSL) {
openRenewSSL(row.id, row.websites);
if (row.provider === 'dnsManual') {
applyRef.value.acceptParams({ ssl: row });
} else {
applySSL(row);
}
},
},
{
@ -203,6 +244,22 @@ const openDetail = (id: number) => {
detailRef.value.acceptParams(id);
};
const applySSL = (row: Website.SSL) => {
if (row.status === 'init' || row.status === 'error') {
loading.value = true;
ObtainSSL({ ID: row.id })
.then(() => {
MsgSuccess(i18n.global.t('ssl.applyStart'));
search();
})
.finally(() => {
loading.value = false;
});
} else {
openRenewSSL(row.id, row.websites);
}
};
const deleteSSL = async (row: any) => {
opRef.value.acceptParams({
title: i18n.global.t('commons.button.delete'),

1
go.mod
View file

@ -25,6 +25,7 @@ require (
github.com/google/uuid v1.3.1
github.com/gorilla/websocket v1.5.0
github.com/jinzhu/copier v0.3.5
github.com/jinzhu/gorm v1.9.2
github.com/joho/godotenv v1.5.1
github.com/klauspost/compress v1.16.5
github.com/mholt/archiver/v4 v4.0.0-alpha.8

27
go.sum
View file

@ -67,7 +67,6 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdko
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
github.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs=
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@ -78,7 +77,6 @@ github.com/aliyun/aliyun-oss-go-sdk v2.2.5+incompatible/go.mod h1:T/Aws4fEfogEE9
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc=
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/aws/aws-sdk-go v1.44.99 h1:ITZ9q/fmH+Ksaz2TbyMU2d19vOOWs/hAlt8NbXAieHw=
github.com/aws/aws-sdk-go v1.44.99/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
@ -110,7 +108,6 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
@ -134,7 +131,6 @@ github.com/compose-spec/compose-go v1.20.0 h1:h4ZKOst1EF/DwZp7dWkb+wbTVE4nEyT9Lc
github.com/compose-spec/compose-go v1.20.0/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM=
github.com/connesc/cipherio v0.2.1 h1:FGtpTPMbKNNWByNrr9aEBtaJtXjqOzkIXNYJp6OEycw=
github.com/connesc/cipherio v0.2.1/go.mod h1:ukY0MWJDFnJEbXMQtOcn2VmTpRfzcTz4OoVrWGGJZcA=
github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU=
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
@ -149,16 +145,13 @@ github.com/containerd/nydus-snapshotter v0.8.2 h1:7SOrMU2YmLzfbsr5J7liMZJlNi5WT6
github.com/containerd/stargz-snapshotter v0.14.3 h1:OTUVZoPSPs8mGgmQUE1dqw3WX/3nrsmsurW7UPLWl1U=
github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k=
github.com/containerd/ttrpc v1.2.2 h1:9vqZr0pxwOF5koz6N0N3kJ0zDHokrcPxIR/ZR2YFtOs=
github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s=
github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9FqcttATPO/4=
github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -190,7 +183,6 @@ github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c/go.mod h1:CADgU4DSXK
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
@ -215,6 +207,7 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
@ -259,7 +252,6 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
@ -339,7 +331,6 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@ -425,7 +416,6 @@ github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg=
github.com/h2non/filetype v1.1.1 h1:xvOwnXKAckvtLWsN398qS9QhlxlnVXBjXBydK2/UFB4=
@ -472,6 +462,7 @@ github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg=
github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo=
github.com/jinzhu/gorm v1.9.2 h1:lCvgEaqe/HVE+tjAR2mt4HbbHAZsQOv3XAZiEZV37iw=
github.com/jinzhu/gorm v1.9.2/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo=
github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
@ -487,7 +478,6 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@ -500,7 +490,6 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
@ -533,8 +522,8 @@ github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgx
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
github.com/lib/pq v0.0.0-20150723085316-0dad96c0b94f h1:I1iYfgQavGa2tgdgKn+2Qg1yQhHEETvh/mNSxG3x5c0=
github.com/lib/pq v0.0.0-20150723085316-0dad96c0b94f/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
@ -569,7 +558,6 @@ github.com/minio/minio-go/v7 v7.0.36 h1:KPzAl8C6jcRFEUsGUHR6deRivvKATPNZThzi7D9y
github.com/minio/minio-go/v7 v7.0.36/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw=
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
@ -604,11 +592,8 @@ github.com/mozillazg/go-httpheader v0.2.1 h1:geV7TrjbL8KXSyvghnFm+NyTux/hxwueTSr
github.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60=
github.com/mozillazg/go-pinyin v0.20.0 h1:BtR3DsxpApHfKReaPO1fCqF4pThRwH9uwvXzm+GnMFQ=
github.com/mozillazg/go-pinyin v0.20.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc=
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 h1:o6uBwrhM5C8Ll3MAAxrQxRHEu7FkapwTuI2WmL1rw4g=
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8=
@ -699,7 +684,6 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
@ -709,7 +693,6 @@ github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/secure-systems-lab/go-securesystemslib v0.4.0 h1:b23VGrQhTA8cN2CbBw7/FulN9fTtqYUdS5+Oxzt+DUE=
github.com/secure-systems-lab/go-securesystemslib v0.4.0/go.mod h1:FGBZgq2tXWICsxWQW1msNf49F0Pf2Op5Htayx335Qbs=
github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI=
@ -751,7 +734,6 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
github.com/spf13/viper v0.0.0-20150530192845-be5ff3e4840c/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
github.com/spf13/viper v1.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU=
github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As=
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -780,7 +762,6 @@ github.com/swaggo/gin-swagger v1.5.3/go.mod h1:3XJKSfHjDMB5dBo/0rrTXidPmgLeqsX89
github.com/swaggo/swag v1.8.1/go.mod h1:ugemnJsPZm/kRwFUnzBlbHRd0JY9zE1M4F+uy2pAaPQ=
github.com/swaggo/swag v1.16.1 h1:fTNRhKstPKxcnoKsytm4sahr8FaYzUcT7i1/3nd/fBg=
github.com/swaggo/swag v1.16.1/go.mod h1:9/LMvHycG3NFHfR6LwvikHv5iFvmPADQ359cKikGxto=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.194/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.194/go.mod h1:yrBKWhChnDqNz1xuXdSbWXG56XawEq0G5j1lg4VwBD4=
github.com/tencentyun/cos-go-sdk-v5 v0.7.41 h1:iU0Li/Np78H4SBna0ECQoF3mpgi6ImLXU+doGzPFXGc=
@ -829,7 +810,6 @@ github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@ -1257,7 +1237,6 @@ k8s.io/api v0.22.4 h1:UvyHW0ezB2oIgHAxlYoo6UJQObYXU7awuNarwoHEOjw=
k8s.io/api v0.22.4/go.mod h1:Rgs+9gIGYC5laXQSZZ9JqT5NevNgoGiOdVWi1BAB3qk=
k8s.io/apimachinery v0.22.4 h1:9uwcvPpukBw/Ri0EUmWz+49cnFtaoiyEhQTK+xOe7Ck=
k8s.io/apimachinery v0.22.4/go.mod h1:yU6oA6Gnax9RrxGzVvPFFJ+mpnW6PBSqp0sx0I0HHW0=
k8s.io/apiserver v0.22.4/go.mod h1:38WmcUZiiy41A7Aty8/VorWRa8vDGqoUzDf2XYlku0E=
k8s.io/client-go v0.22.4 h1:aAQ1Wk+I3bjCNk35YWUqbaueqrIonkfDPJSPDDe8Kfg=
k8s.io/client-go v0.22.4/go.mod h1:Yzw4e5e7h1LNHA4uqnMVrpEpUs1hJOiuBsJKIlRCHDA=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=