mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-19 00:09:16 +08:00
feat: 增加证书申请
This commit is contained in:
parent
ac864ff4e7
commit
681a0c9106
@ -12,6 +12,7 @@ services:
|
|||||||
- ./conf/nginx.conf:/etc/nginx/nginx.conf
|
- ./conf/nginx.conf:/etc/nginx/nginx.conf
|
||||||
- ./log:/var/log/nginx
|
- ./log:/var/log/nginx
|
||||||
- ./conf/conf.d:/etc/nginx/conf.d/
|
- ./conf/conf.d:/etc/nginx/conf.d/
|
||||||
|
- ./ssl:/etc/nginx/ssl
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
1panel:
|
1panel:
|
||||||
|
@ -24,43 +24,59 @@ func (b *BaseApi) PageWebsiteSSL(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (b *BaseApi) CreateWebsiteSSL(c *gin.Context) {
|
func (b *BaseApi) CreateWebsiteSSL(c *gin.Context) {
|
||||||
// var req dto.WebsiteSSLCreate
|
var req dto.WebsiteSSLCreate
|
||||||
// if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
// helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
// return
|
return
|
||||||
// }
|
}
|
||||||
// if _, err := WebsiteSSLService.Create(req); err != nil {
|
res, err := websiteSSLService.Create(req)
|
||||||
// helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
if err != nil {
|
||||||
// return
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
// }
|
return
|
||||||
// helper.SuccessWithData(c, nil)
|
}
|
||||||
//}
|
helper.SuccessWithData(c, res)
|
||||||
//
|
}
|
||||||
//func (b *BaseApi) UpdateWebsiteSSL(c *gin.Context) {
|
|
||||||
// var req dto.WebsiteSSLUpdate
|
func (b *BaseApi) ApplyWebsiteSSL(c *gin.Context) {
|
||||||
// if err := c.ShouldBindJSON(&req); err != nil {
|
var req dto.WebsiteSSLApply
|
||||||
// helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
// return
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
// }
|
return
|
||||||
// if _, err := WebsiteSSLService.Update(req); err != nil {
|
}
|
||||||
// helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
res, err := websiteSSLService.Apply(req)
|
||||||
// return
|
if err != nil {
|
||||||
// }
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
// helper.SuccessWithData(c, nil)
|
return
|
||||||
//}
|
}
|
||||||
//
|
helper.SuccessWithData(c, res)
|
||||||
//func (b *BaseApi) DeleteWebsiteSSL(c *gin.Context) {
|
}
|
||||||
//
|
|
||||||
// id, err := helper.GetParamID(c)
|
func (b *BaseApi) GetDNSResolve(c *gin.Context) {
|
||||||
// if err != nil {
|
var req dto.WebsiteDNSReq
|
||||||
// helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
// return
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
// }
|
return
|
||||||
//
|
}
|
||||||
// if err := WebsiteSSLService.Delete(id); err != nil {
|
res, err := websiteSSLService.GetDNSResolve(req)
|
||||||
// helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
if err != nil {
|
||||||
// return
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
// }
|
return
|
||||||
// helper.SuccessWithData(c, nil)
|
}
|
||||||
//}
|
helper.SuccessWithData(c, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BaseApi) DeleteWebsiteSSL(c *gin.Context) {
|
||||||
|
|
||||||
|
id, err := helper.GetParamID(c)
|
||||||
|
if err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := websiteSSLService.Delete(id); err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
helper.SuccessWithData(c, nil)
|
||||||
|
}
|
||||||
|
@ -21,6 +21,7 @@ type NginxScope string
|
|||||||
const (
|
const (
|
||||||
Index NginxScope = "index"
|
Index NginxScope = "index"
|
||||||
LimitConn NginxScope = "limit-conn"
|
LimitConn NginxScope = "limit-conn"
|
||||||
|
SSL NginxScope = "ssl"
|
||||||
)
|
)
|
||||||
|
|
||||||
type NginxOp string
|
type NginxOp string
|
||||||
@ -34,6 +35,7 @@ const (
|
|||||||
var ScopeKeyMap = map[NginxScope][]string{
|
var ScopeKeyMap = map[NginxScope][]string{
|
||||||
Index: {"index"},
|
Index: {"index"},
|
||||||
LimitConn: {"limit_conn", "limit_rate", "limit_conn_zone"},
|
LimitConn: {"limit_conn", "limit_rate", "limit_conn_zone"},
|
||||||
|
SSL: {"ssl_certificate", "ssl_certificate_key"},
|
||||||
}
|
}
|
||||||
|
|
||||||
var RepeatKeys = map[string]struct {
|
var RepeatKeys = map[string]struct {
|
||||||
|
@ -28,6 +28,10 @@ type WebSiteCreate struct {
|
|||||||
WebSiteGroupID uint `json:"webSiteGroupID" validate:"required"`
|
WebSiteGroupID uint `json:"webSiteGroupID" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type WebsiteDTO struct {
|
||||||
|
model.WebSite
|
||||||
|
}
|
||||||
|
|
||||||
type WebSiteUpdate struct {
|
type WebSiteUpdate struct {
|
||||||
ID uint `json:"id" validate:"required"`
|
ID uint `json:"id" validate:"required"`
|
||||||
PrimaryDomain string `json:"primaryDomain" validate:"required"`
|
PrimaryDomain string `json:"primaryDomain" validate:"required"`
|
||||||
|
@ -6,8 +6,34 @@ type WebsiteSSLDTO struct {
|
|||||||
model.WebSiteSSL
|
model.WebSiteSSL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SSLProvider string
|
||||||
|
|
||||||
|
const (
|
||||||
|
DNSAccount = "dnsAccount"
|
||||||
|
DnsCommon = "dnsCommon"
|
||||||
|
Http = "http"
|
||||||
|
)
|
||||||
|
|
||||||
type WebsiteSSLCreate struct {
|
type WebsiteSSLCreate struct {
|
||||||
Name string `json:"name" validate:"required"`
|
Domains []string `json:"domains" validate:"required"`
|
||||||
Type string `json:"type" validate:"required"`
|
Provider SSLProvider `json:"provider" validate:"required"`
|
||||||
Authorization map[string]string `json:"authorization" validate:"required"`
|
WebsiteID uint `json:"websiteId" validate:"required"`
|
||||||
|
AcmeAccountID uint `json:"acmeAccountId"`
|
||||||
|
DnsAccountID uint `json:"dnsAccountId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type WebsiteSSLApply struct {
|
||||||
|
WebsiteID uint `json:"websiteId" validate:"required"`
|
||||||
|
SSLID uint `json:"SSLId" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type WebsiteDNSReq struct {
|
||||||
|
Domains []string `json:"domains" validate:"required"`
|
||||||
|
AcmeAccountID uint `json:"acmeAccountId" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type WebsiteDNSRes struct {
|
||||||
|
Key string `json:"resolve"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
Type string `json:"type"`
|
||||||
}
|
}
|
||||||
|
@ -4,17 +4,18 @@ import "time"
|
|||||||
|
|
||||||
type WebSite struct {
|
type WebSite struct {
|
||||||
BaseModel
|
BaseModel
|
||||||
PrimaryDomain string `gorm:"type:varchar(128);not null" json:"primaryDomain"`
|
PrimaryDomain string `gorm:"type:varchar(128);not null" json:"primaryDomain"`
|
||||||
Type string `gorm:"type:varchar(64);not null" json:"type"`
|
Type string `gorm:"type:varchar(64);not null" json:"type"`
|
||||||
Alias string `gorm:"type:varchar(128);not null" json:"alias"`
|
Alias string `gorm:"type:varchar(128);not null" json:"alias"`
|
||||||
Remark string `gorm:"type:longtext;" json:"remark"`
|
Remark string `gorm:"type:longtext;" json:"remark"`
|
||||||
Status string `gorm:"type:varchar(64);not null" json:"status"`
|
Status string `gorm:"type:varchar(64);not null" json:"status"`
|
||||||
ExpireDate time.Time `json:"expireDate"`
|
ExpireDate time.Time `json:"expireDate"`
|
||||||
AppInstallID uint `gorm:"type:integer" json:"appInstallId"`
|
AppInstallID uint `gorm:"type:integer" json:"appInstallId"`
|
||||||
WebSiteGroupID uint `gorm:"type:integer" json:"webSiteGroupId"`
|
WebSiteGroupID uint `gorm:"type:integer" json:"webSiteGroupId"`
|
||||||
WebSiteSSLID uint `gorm:"type:integer" json:"webSiteSSLId"`
|
WebSiteSSLID uint `gorm:"type:integer" json:"webSiteSSLId"`
|
||||||
WebsiteDnsAccountID uint `gorm:"type:integer" json:"websiteDnsAccountId"`
|
WebsiteDnsAccountID uint `gorm:"type:integer" json:"websiteDnsAccountId"`
|
||||||
WebsiteAcmeAccountID uint `gorm:"type:integer" json:"websiteAcmeAccountId"`
|
WebsiteAcmeAccountID uint `gorm:"type:integer" json:"websiteAcmeAccountId"`
|
||||||
|
Domains []WebSiteDomain `json:"domains"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w WebSite) TableName() string {
|
func (w WebSite) TableName() string {
|
||||||
|
@ -4,14 +4,16 @@ import "time"
|
|||||||
|
|
||||||
type WebSiteSSL struct {
|
type WebSiteSSL struct {
|
||||||
BaseModel
|
BaseModel
|
||||||
PrivateKey string `gorm:"type:longtext;not null" json:"privateKey"`
|
Alias string `gorm:"type:varchar(64);not null" json:"alias"`
|
||||||
Pem string `gorm:"type:longtext;not null" json:"pem"`
|
PrivateKey string `gorm:"type:longtext;not null" json:"privateKey"`
|
||||||
Domain string `gorm:"type:varchar(256);not null" json:"domain"`
|
Pem string `gorm:"type:longtext;not null" json:"pem"`
|
||||||
CertURL string `gorm:"type:varchar(256);not null" json:"certURL"`
|
Domain string `gorm:"type:varchar(256);not null" json:"domain"`
|
||||||
Type string `gorm:"type:varchar(64);not null" json:"type"`
|
CertURL string `gorm:"type:varchar(256);not null" json:"certURL"`
|
||||||
IssuerName string `gorm:"type:varchar(64);not null" json:"issuerName"`
|
Type string `gorm:"type:varchar(64);not null" json:"type"`
|
||||||
ExpireDate time.Time `json:"expireDate"`
|
IssuerName string `gorm:"type:varchar(64);not null" json:"issuerName"`
|
||||||
StartDate time.Time `json:"startDate"`
|
DnsAccountID uint `gorm:"type:integer;not null" json:"dnsAccountId"`
|
||||||
|
ExpireDate time.Time `json:"expireDate"`
|
||||||
|
StartDate time.Time `json:"startDate"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w WebSiteSSL) TableName() string {
|
func (w WebSiteSSL) TableName() string {
|
||||||
|
@ -28,7 +28,7 @@ func (w WebSiteRepo) Page(page, size int, opts ...DBOption) (int64, []model.WebS
|
|||||||
func (w WebSiteRepo) GetFirst(opts ...DBOption) (model.WebSite, error) {
|
func (w WebSiteRepo) GetFirst(opts ...DBOption) (model.WebSite, error) {
|
||||||
var website model.WebSite
|
var website model.WebSite
|
||||||
db := getDb(opts...).Model(&model.WebSite{})
|
db := getDb(opts...).Model(&model.WebSite{})
|
||||||
if err := db.First(&website).Error; err != nil {
|
if err := db.Preload("Domains").First(&website).Error; err != nil {
|
||||||
return website, err
|
return website, err
|
||||||
}
|
}
|
||||||
return website, nil
|
return website, nil
|
||||||
|
@ -14,6 +14,15 @@ func (w WebsiteAcmeAccountRepo) Page(page, size int, opts ...DBOption) (int64, [
|
|||||||
return count, accounts, err
|
return count, accounts, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w WebsiteAcmeAccountRepo) GetFirst(opts ...DBOption) (model.WebsiteAcmeAccount, error) {
|
||||||
|
var account model.WebsiteAcmeAccount
|
||||||
|
db := getDb(opts...).Model(&model.WebsiteAcmeAccount{})
|
||||||
|
if err := db.First(&account).Error; err != nil {
|
||||||
|
return account, err
|
||||||
|
}
|
||||||
|
return account, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (w WebsiteAcmeAccountRepo) Create(account model.WebsiteAcmeAccount) error {
|
func (w WebsiteAcmeAccountRepo) Create(account model.WebsiteAcmeAccount) error {
|
||||||
return getDb().Create(&account).Error
|
return getDb().Create(&account).Error
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,15 @@ func (w WebsiteDnsAccountRepo) Page(page, size int, opts ...DBOption) (int64, []
|
|||||||
return count, accounts, err
|
return count, accounts, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w WebsiteDnsAccountRepo) GetFirst(opts ...DBOption) (model.WebsiteDnsAccount, error) {
|
||||||
|
var account model.WebsiteDnsAccount
|
||||||
|
db := getDb(opts...).Model(&model.WebsiteDnsAccount{})
|
||||||
|
if err := db.First(&account).Error; err != nil {
|
||||||
|
return account, err
|
||||||
|
}
|
||||||
|
return account, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (w WebsiteDnsAccountRepo) Create(account model.WebsiteDnsAccount) error {
|
func (w WebsiteDnsAccountRepo) Create(account model.WebsiteDnsAccount) error {
|
||||||
return getDb().Create(&account).Error
|
return getDb().Create(&account).Error
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,20 @@
|
|||||||
package repo
|
package repo
|
||||||
|
|
||||||
import "github.com/1Panel-dev/1Panel/backend/app/model"
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
type WebsiteSSLRepo struct {
|
type WebsiteSSLRepo struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w WebsiteSSLRepo) ByAlias(alias string) DBOption {
|
||||||
|
return func(db *gorm.DB) *gorm.DB {
|
||||||
|
return db.Where("alias = ?", alias)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (w WebsiteSSLRepo) Page(page, size int, opts ...DBOption) (int64, []model.WebSiteSSL, error) {
|
func (w WebsiteSSLRepo) Page(page, size int, opts ...DBOption) (int64, []model.WebSiteSSL, error) {
|
||||||
var sslList []model.WebSiteSSL
|
var sslList []model.WebSiteSSL
|
||||||
db := getDb(opts...).Model(&model.WebSiteSSL{})
|
db := getDb(opts...).Model(&model.WebSiteSSL{})
|
||||||
@ -14,8 +24,17 @@ func (w WebsiteSSLRepo) Page(page, size int, opts ...DBOption) (int64, []model.W
|
|||||||
return count, sslList, err
|
return count, sslList, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w WebsiteSSLRepo) Create(ssl model.WebSiteSSL) error {
|
func (w WebsiteSSLRepo) GetFirst(opts ...DBOption) (model.WebSiteSSL, error) {
|
||||||
return getDb().Create(&ssl).Error
|
var website model.WebSiteSSL
|
||||||
|
db := getDb(opts...).Model(&model.WebSiteSSL{})
|
||||||
|
if err := db.First(&website).Error; err != nil {
|
||||||
|
return website, err
|
||||||
|
}
|
||||||
|
return website, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WebsiteSSLRepo) Create(ctx context.Context, ssl *model.WebSiteSSL) error {
|
||||||
|
return getTx(ctx).Create(ssl).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w WebsiteSSLRepo) Save(ssl model.WebSiteSSL) error {
|
func (w WebsiteSSLRepo) Save(ssl model.WebSiteSSL) error {
|
||||||
|
@ -99,12 +99,14 @@ func (w WebsiteService) UpdateWebsite(req dto.WebSiteUpdate) error {
|
|||||||
return websiteRepo.Save(context.TODO(), &website)
|
return websiteRepo.Save(context.TODO(), &website)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w WebsiteService) GetWebsite(id uint) (model.WebSite, error) {
|
func (w WebsiteService) GetWebsite(id uint) (dto.WebsiteDTO, error) {
|
||||||
|
var res dto.WebsiteDTO
|
||||||
website, err := websiteRepo.GetFirst(commonRepo.WithByID(id))
|
website, err := websiteRepo.GetFirst(commonRepo.WithByID(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return website, err
|
return res, err
|
||||||
}
|
}
|
||||||
return website, nil
|
res.WebSite = website
|
||||||
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w WebsiteService) DeleteWebSite(req dto.WebSiteDel) error {
|
func (w WebsiteService) DeleteWebSite(req dto.WebSiteDel) error {
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/x509"
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/utils/ssl"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type WebSiteSSLService struct {
|
type WebSiteSSLService struct {
|
||||||
@ -18,44 +24,115 @@ func (w WebSiteSSLService) Page(search dto.PageInfo) (int64, []dto.WebsiteSSLDTO
|
|||||||
return total, sslDTOs, err
|
return total, sslDTOs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (w WebSiteSSLService) Create(create dto.WebsiteSSLCreate) (dto.WebsiteSSLCreate, error) {
|
func (w WebSiteSSLService) Create(create dto.WebsiteSSLCreate) (dto.WebsiteSSLCreate, error) {
|
||||||
//
|
|
||||||
// authorization, err := json.Marshal(create.Authorization)
|
var res dto.WebsiteSSLCreate
|
||||||
// if err != nil {
|
acmeAccount, err := websiteAcmeRepo.GetFirst(commonRepo.WithByID(create.AcmeAccountID))
|
||||||
// return dto.WebsiteSSLCreate{}, err
|
if err != nil {
|
||||||
// }
|
return res, err
|
||||||
//
|
}
|
||||||
// if err := websiteSSLRepo.Create(model.WebsiteDnsAccount{
|
dnsAccount, err := websiteDnsRepo.GetFirst(commonRepo.WithByID(create.DnsAccountID))
|
||||||
// Name: create.Name,
|
if err != nil {
|
||||||
// Type: create.Type,
|
return res, err
|
||||||
// Authorization: string(authorization),
|
}
|
||||||
// }); err != nil {
|
client, err := ssl.NewPrivateKeyClient(acmeAccount.Email, acmeAccount.PrivateKey)
|
||||||
// return dto.WebsiteSSLCreate{}, err
|
if err != nil {
|
||||||
// }
|
return res, err
|
||||||
//
|
}
|
||||||
// return create, nil
|
if create.Provider == dto.Http {
|
||||||
//}
|
|
||||||
//
|
} else {
|
||||||
//func (w WebSiteSSLService) Update(update dto.WebsiteDnsAccountUpdate) (dto.WebsiteDnsAccountUpdate, error) {
|
if err := client.UseDns(ssl.DnsType(dnsAccount.Type), dnsAccount.Authorization); err != nil {
|
||||||
//
|
return res, err
|
||||||
// authorization, err := json.Marshal(update.Authorization)
|
}
|
||||||
// if err != nil {
|
}
|
||||||
// return dto.WebsiteDnsAccountUpdate{}, err
|
|
||||||
// }
|
resource, err := client.GetSSL(create.Domains)
|
||||||
//
|
if err != nil {
|
||||||
// if err := websiteSSLRepo.Save(model.WebsiteDnsAccount{
|
return res, err
|
||||||
// BaseModel: model.BaseModel{
|
}
|
||||||
// ID: update.ID,
|
|
||||||
// },
|
var websiteSSL model.WebSiteSSL
|
||||||
// Name: update.Name,
|
|
||||||
// Type: update.Type,
|
//TODO 判断同一个账号下的证书
|
||||||
// Authorization: string(authorization),
|
websiteSSL.Alias = create.Domains[0]
|
||||||
// }); err != nil {
|
websiteSSL.Domain = strings.Join(create.Domains, ",")
|
||||||
// return dto.WebsiteDnsAccountUpdate{}, err
|
websiteSSL.PrivateKey = string(resource.PrivateKey)
|
||||||
// }
|
websiteSSL.Pem = string(resource.Certificate)
|
||||||
//
|
websiteSSL.CertURL = resource.CertURL
|
||||||
// return update, nil
|
|
||||||
//}
|
cert, err := x509.ParseCertificate([]byte(websiteSSL.Pem))
|
||||||
|
if err != nil {
|
||||||
|
return dto.WebsiteSSLCreate{}, err
|
||||||
|
}
|
||||||
|
websiteSSL.ExpireDate = cert.NotAfter
|
||||||
|
websiteSSL.StartDate = cert.NotBefore
|
||||||
|
websiteSSL.Type = cert.Issuer.CommonName
|
||||||
|
websiteSSL.IssuerName = cert.Issuer.Organization[0]
|
||||||
|
|
||||||
|
if err := createPemFile(websiteSSL); err != nil {
|
||||||
|
return dto.WebsiteSSLCreate{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := websiteSSLRepo.Create(context.TODO(), &websiteSSL); err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return create, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WebSiteSSLService) Apply(apply dto.WebsiteSSLApply) (dto.WebsiteSSLApply, error) {
|
||||||
|
websiteSSL, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(apply.SSLID))
|
||||||
|
if err != nil {
|
||||||
|
return dto.WebsiteSSLApply{}, err
|
||||||
|
}
|
||||||
|
website, err := websiteRepo.GetFirst(commonRepo.WithByID(apply.WebsiteID))
|
||||||
|
if err != nil {
|
||||||
|
return dto.WebsiteSSLApply{}, err
|
||||||
|
}
|
||||||
|
if err := createPemFile(websiteSSL); err != nil {
|
||||||
|
return dto.WebsiteSSLApply{}, err
|
||||||
|
}
|
||||||
|
nginxParams := getNginxParamsFromStaticFile(dto.SSL)
|
||||||
|
for i, param := range nginxParams {
|
||||||
|
if param.Name == "ssl_certificate" {
|
||||||
|
nginxParams[i].Params = []string{path.Join("/etc/nginx/ssl", websiteSSL.Alias, "fullchain.pem")}
|
||||||
|
}
|
||||||
|
if param.Name == "ssl_certificate_key" {
|
||||||
|
nginxParams[i].Params = []string{path.Join("/etc/nginx/ssl", websiteSSL.Alias, "privkey.pem")}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := updateNginxConfig(website, nginxParams, dto.SSL); err != nil {
|
||||||
|
return dto.WebsiteSSLApply{}, err
|
||||||
|
}
|
||||||
|
website.WebSiteSSLID = websiteSSL.ID
|
||||||
|
if err := websiteRepo.Save(context.TODO(), &website); err != nil {
|
||||||
|
return dto.WebsiteSSLApply{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return apply, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WebSiteSSLService) GetDNSResolve(req dto.WebsiteDNSReq) (dto.WebsiteDNSRes, error) {
|
||||||
|
acmeAccount, err := websiteAcmeRepo.GetFirst(commonRepo.WithByID(req.AcmeAccountID))
|
||||||
|
if err != nil {
|
||||||
|
return dto.WebsiteDNSRes{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := ssl.NewPrivateKeyClient(acmeAccount.Email, acmeAccount.PrivateKey)
|
||||||
|
if err != nil {
|
||||||
|
return dto.WebsiteDNSRes{}, err
|
||||||
|
}
|
||||||
|
re, err := client.UseManualDns(req.Domains)
|
||||||
|
if err != nil {
|
||||||
|
return dto.WebsiteDNSRes{}, err
|
||||||
|
}
|
||||||
|
var res dto.WebsiteDNSRes
|
||||||
|
res.Key = re.Key
|
||||||
|
res.Value = re.Value
|
||||||
|
res.Type = "TXT"
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (w WebSiteSSLService) Delete(id uint) error {
|
func (w WebSiteSSLService) Delete(id uint) error {
|
||||||
return websiteSSLRepo.DeleteBy(commonRepo.WithByID(id))
|
return websiteSSLRepo.DeleteBy(commonRepo.WithByID(id))
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@ -258,16 +259,38 @@ func updateNginxConfig(website model.WebSite, params []dto.NginxParam, scope dto
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateConfig(config *components.Config, scope dto.NginxScope) {
|
func updateConfig(config *components.Config, scope dto.NginxScope) {
|
||||||
if scope == dto.LimitConn {
|
newConfig := &components.Config{}
|
||||||
limit := parser.NewStringParser(string(nginx_conf.Limit)).Parse()
|
switch scope {
|
||||||
for _, dir := range limit.GetDirectives() {
|
case dto.LimitConn:
|
||||||
newDir := components.Directive{
|
newConfig = parser.NewStringParser(string(nginx_conf.Limit)).Parse()
|
||||||
Name: dir.GetName(),
|
|
||||||
Parameters: dir.GetParameters(),
|
|
||||||
}
|
|
||||||
config.UpdateDirectiveBySecondKey(dir.GetName(), dir.GetParameters()[0], newDir)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if reflect.DeepEqual(newConfig, &components.Config{}) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, dir := range newConfig.GetDirectives() {
|
||||||
|
newDir := components.Directive{
|
||||||
|
Name: dir.GetName(),
|
||||||
|
Parameters: dir.GetParameters(),
|
||||||
|
}
|
||||||
|
config.UpdateDirectiveBySecondKey(dir.GetName(), dir.GetParameters()[0], newDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNginxParamsFromStaticFile(scope dto.NginxScope) []dto.NginxParam {
|
||||||
|
var nginxParams []dto.NginxParam
|
||||||
|
newConfig := &components.Config{}
|
||||||
|
switch scope {
|
||||||
|
case dto.SSL:
|
||||||
|
newConfig = parser.NewStringParser(string(nginx_conf.SSL)).Parse()
|
||||||
|
}
|
||||||
|
for _, dir := range newConfig.GetDirectives() {
|
||||||
|
nginxParams = append(nginxParams, dto.NginxParam{
|
||||||
|
Name: dir.GetName(),
|
||||||
|
Params: dir.GetParameters(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return nginxParams
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteNginxConfig(website model.WebSite, keys []string) error {
|
func deleteNginxConfig(website model.WebSite, keys []string) error {
|
||||||
@ -285,6 +308,48 @@ func deleteNginxConfig(website model.WebSite, keys []string) error {
|
|||||||
return nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxConfig.ContainerName)
|
return nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxConfig.ContainerName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createPemFile(websiteSSL model.WebSiteSSL) error {
|
||||||
|
nginxApp, err := appRepo.GetFirst(appRepo.WithKey("nginx"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
nginxInstall, err := appInstallRepo.GetFirst(appInstallRepo.WithAppId(nginxApp.ID))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
configDir := path.Join(constant.AppInstallDir, "nginx", nginxInstall.Name, "ssl", websiteSSL.Alias)
|
||||||
|
fileOp := files.NewFileOp()
|
||||||
|
|
||||||
|
if !fileOp.Stat(configDir) {
|
||||||
|
if err := fileOp.CreateDir(configDir, 0775); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fullChainFile := path.Join(configDir, "fullchain.pem")
|
||||||
|
privatePemFile := path.Join(configDir, "privkey.pem")
|
||||||
|
|
||||||
|
if !fileOp.Stat(fullChainFile) {
|
||||||
|
if err := fileOp.CreateFile(fullChainFile); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !fileOp.Stat(privatePemFile) {
|
||||||
|
if err := fileOp.CreateFile(privatePemFile); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := fileOp.WriteFile(fullChainFile, strings.NewReader(websiteSSL.Pem), 0644); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := fileOp.WriteFile(privatePemFile, strings.NewReader(websiteSSL.PrivateKey), 0644); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func getParamArray(key string, param interface{}) []string {
|
func getParamArray(key string, param interface{}) []string {
|
||||||
var res []string
|
var res []string
|
||||||
switch param.(type) {
|
switch param.(type) {
|
||||||
|
@ -83,6 +83,7 @@ func Routers() *gin.Engine {
|
|||||||
systemRouter.InitWebsiteGroupRouter(PrivateGroup)
|
systemRouter.InitWebsiteGroupRouter(PrivateGroup)
|
||||||
systemRouter.InitWebsiteDnsAccountRouter(PrivateGroup)
|
systemRouter.InitWebsiteDnsAccountRouter(PrivateGroup)
|
||||||
systemRouter.InitDatabaseRouter(PrivateGroup)
|
systemRouter.InitDatabaseRouter(PrivateGroup)
|
||||||
|
systemRouter.InitWebsiteSSLRouter(PrivateGroup)
|
||||||
systemRouter.InitWebsiteAcmeAccountRouter(PrivateGroup)
|
systemRouter.InitWebsiteAcmeAccountRouter(PrivateGroup)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ type RouterGroup struct {
|
|||||||
WebsiteGroupRouter
|
WebsiteGroupRouter
|
||||||
WebsiteDnsAccountRouter
|
WebsiteDnsAccountRouter
|
||||||
WebsiteAcmeAccountRouter
|
WebsiteAcmeAccountRouter
|
||||||
|
WebsiteSSLRouter
|
||||||
DatabaseRouter
|
DatabaseRouter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,8 +15,8 @@ func (a *WebsiteDnsAccountRouter) InitWebsiteDnsAccountRouter(Router *gin.Router
|
|||||||
|
|
||||||
baseApi := v1.ApiGroupApp.BaseApi
|
baseApi := v1.ApiGroupApp.BaseApi
|
||||||
{
|
{
|
||||||
groupRouter.POST("", baseApi.PageWebsiteDnsAccount)
|
groupRouter.POST("/search", baseApi.PageWebsiteDnsAccount)
|
||||||
groupRouter.POST("/create", baseApi.CreateWebsiteDnsAccount)
|
groupRouter.POST("", baseApi.CreateWebsiteDnsAccount)
|
||||||
groupRouter.POST("/update", baseApi.UpdateWebsiteDnsAccount)
|
groupRouter.POST("/update", baseApi.UpdateWebsiteDnsAccount)
|
||||||
groupRouter.DELETE("/:id", baseApi.DeleteWebsiteDnsAccount)
|
groupRouter.DELETE("/:id", baseApi.DeleteWebsiteDnsAccount)
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,10 @@ func (a *WebsiteSSLRouter) InitWebsiteSSLRouter(Router *gin.RouterGroup) {
|
|||||||
|
|
||||||
baseApi := v1.ApiGroupApp.BaseApi
|
baseApi := v1.ApiGroupApp.BaseApi
|
||||||
{
|
{
|
||||||
groupRouter.POST("", baseApi.PageWebsiteSSL)
|
groupRouter.POST("/search", baseApi.PageWebsiteSSL)
|
||||||
|
groupRouter.POST("", baseApi.CreateWebsiteSSL)
|
||||||
|
groupRouter.POST("/apply", baseApi.ApplyWebsiteSSL)
|
||||||
|
groupRouter.POST("/resolve", baseApi.GetDNSResolve)
|
||||||
|
groupRouter.POST("/:id", baseApi.DeleteWebsiteSSL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,27 +1,27 @@
|
|||||||
-----BEGIN privateKey-----
|
-----BEGIN privateKey-----
|
||||||
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
|
||||||
-----END privateKey-----
|
-----END privateKey-----
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/go-acme/lego/v4/challenge"
|
"github.com/go-acme/lego/v4/challenge"
|
||||||
"github.com/go-acme/lego/v4/challenge/dns01"
|
"github.com/go-acme/lego/v4/challenge/dns01"
|
||||||
"github.com/go-acme/lego/v4/lego"
|
"github.com/go-acme/lego/v4/lego"
|
||||||
|
"github.com/go-acme/lego/v4/providers/dns/alidns"
|
||||||
"github.com/go-acme/lego/v4/providers/dns/dnspod"
|
"github.com/go-acme/lego/v4/providers/dns/dnspod"
|
||||||
"github.com/go-acme/lego/v4/registration"
|
"github.com/go-acme/lego/v4/registration"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -58,7 +59,8 @@ func NewAcmeClient(email, privateKey string) (*AcmeClient, error) {
|
|||||||
type DnsType string
|
type DnsType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DnsPod DnsType = "dnsPod"
|
DnsPod DnsType = "DnsPod"
|
||||||
|
AliYun DnsType = "AliYun"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DNSParam struct {
|
type DNSParam struct {
|
||||||
@ -87,9 +89,37 @@ func (c *AcmeClient) UseDns(dnsType DnsType, params string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if dnsType == AliYun {
|
||||||
|
alidnsConfig := alidns.NewDefaultConfig()
|
||||||
|
alidnsConfig.SecretKey = param.SecretKey
|
||||||
|
alidnsConfig.APIKey = param.AccessKey
|
||||||
|
p, err = alidns.NewDNSProviderConfig(alidnsConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return c.Client.Challenge.SetDNS01Provider(p, dns01.AddDNSTimeout(6*time.Minute))
|
return c.Client.Challenge.SetDNS01Provider(p, dns01.AddDNSTimeout(6*time.Minute))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *AcmeClient) UseManualDns(domains []string) (*Resolve, error) {
|
||||||
|
p := &manualDnsProvider{}
|
||||||
|
if err := c.Client.Challenge.SetDNS01Provider(p, dns01.AddDNSTimeout(6*time.Minute)); err != nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
request := certificate.ObtainRequest{
|
||||||
|
Domains: domains,
|
||||||
|
Bundle: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := c.Client.Certificate.Obtain(request)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return p.Resolve, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *AcmeClient) UseHTTP() {
|
func (c *AcmeClient) UseHTTP() {
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -108,3 +138,29 @@ func (c *AcmeClient) GetSSL(domains []string) (certificate.Resource, error) {
|
|||||||
|
|
||||||
return *certificates, nil
|
return *certificates, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Resolve struct {
|
||||||
|
Key string
|
||||||
|
Value string
|
||||||
|
}
|
||||||
|
|
||||||
|
type manualDnsProvider struct {
|
||||||
|
Resolve *Resolve
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *manualDnsProvider) Present(domain, token, keyAuth string) error {
|
||||||
|
fqdn, value := dns01.GetRecord(domain, keyAuth)
|
||||||
|
p.Resolve = &Resolve{
|
||||||
|
Key: fqdn,
|
||||||
|
Value: value,
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *manualDnsProvider) CleanUp(domain, token, keyAuth string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *AcmeClient) GetDNSResolve() {
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -14,6 +14,19 @@ export namespace WebSite {
|
|||||||
appinstall?: NewAppInstall;
|
appinstall?: NewAppInstall;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface WebSiteDTO extends CommonModel {
|
||||||
|
primaryDomain: string;
|
||||||
|
type: string;
|
||||||
|
alias: string;
|
||||||
|
remark: string;
|
||||||
|
domains: WebSite.Domain[];
|
||||||
|
appType: string;
|
||||||
|
appInstallId?: number;
|
||||||
|
webSiteGroupId: number;
|
||||||
|
otherDomains: string;
|
||||||
|
appinstall?: NewAppInstall;
|
||||||
|
}
|
||||||
|
|
||||||
export interface NewAppInstall {
|
export interface NewAppInstall {
|
||||||
name: string;
|
name: string;
|
||||||
appDetailId: number;
|
appDetailId: number;
|
||||||
@ -115,6 +128,19 @@ export namespace WebSite {
|
|||||||
startDate: string;
|
startDate: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SSLCreate {
|
||||||
|
domains: string[];
|
||||||
|
provider: string;
|
||||||
|
websiteId: number;
|
||||||
|
acmeAccountId: number;
|
||||||
|
dnsAccountId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SSLApply {
|
||||||
|
websiteId: number;
|
||||||
|
SSLId: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface AcmeAccount extends CommonModel {
|
export interface AcmeAccount extends CommonModel {
|
||||||
email: string;
|
email: string;
|
||||||
url: string;
|
url: string;
|
||||||
@ -123,4 +149,15 @@ export namespace WebSite {
|
|||||||
export interface AcmeAccountCreate {
|
export interface AcmeAccountCreate {
|
||||||
email: string;
|
email: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DNSResolveReq {
|
||||||
|
domains: string[];
|
||||||
|
acmeAccountId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DNSResolve {
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ export const UpdateWebsite = (req: WebSite.WebSiteUpdateReq) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const GetWebsite = (id: number) => {
|
export const GetWebsite = (id: number) => {
|
||||||
return http.get<WebSite.WebSite>(`/websites/${id}`);
|
return http.get<WebSite.WebSiteDTO>(`/websites/${id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DeleteWebsite = (req: WebSite.WebSiteDel) => {
|
export const DeleteWebsite = (req: WebSite.WebSiteDel) => {
|
||||||
@ -59,11 +59,11 @@ export const UpdateNginxConfig = (req: WebSite.NginxConfigReq) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const SearchDnsAccount = (req: ReqPage) => {
|
export const SearchDnsAccount = (req: ReqPage) => {
|
||||||
return http.post<ResPage<WebSite.DnsAccount>>(`/websites/dns`, req);
|
return http.post<ResPage<WebSite.DnsAccount>>(`/websites/dns/search`, req);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CreateDnsAccount = (req: WebSite.DnsAccountCreate) => {
|
export const CreateDnsAccount = (req: WebSite.DnsAccountCreate) => {
|
||||||
return http.post<any>(`/websites/dns/create`, req);
|
return http.post<any>(`/websites/dns`, req);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const UpdateDnsAccount = (req: WebSite.DnsAccountUpdate) => {
|
export const UpdateDnsAccount = (req: WebSite.DnsAccountUpdate) => {
|
||||||
@ -74,10 +74,6 @@ export const DeleteDnsAccount = (id: number) => {
|
|||||||
return http.delete<any>(`/websites/dns/${id}`);
|
return http.delete<any>(`/websites/dns/${id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SearchSSL = (req: ReqPage) => {
|
|
||||||
return http.post<ResPage<WebSite.SSL>>(`/websites/ssl`, req);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const SearchAcmeAccount = (req: ReqPage) => {
|
export const SearchAcmeAccount = (req: ReqPage) => {
|
||||||
return http.post<ResPage<WebSite.AcmeAccount>>(`/websites/acme/search`, req);
|
return http.post<ResPage<WebSite.AcmeAccount>>(`/websites/acme/search`, req);
|
||||||
};
|
};
|
||||||
@ -89,3 +85,23 @@ export const CreateAcmeAccount = (req: WebSite.AcmeAccountCreate) => {
|
|||||||
export const DeleteAcmeAccount = (id: number) => {
|
export const DeleteAcmeAccount = (id: number) => {
|
||||||
return http.delete<any>(`/websites/acme/${id}`);
|
return http.delete<any>(`/websites/acme/${id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const SearchSSL = (req: ReqPage) => {
|
||||||
|
return http.post<ResPage<WebSite.SSL>>(`/websites/ssl/search`, req);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CreateSSL = (req: WebSite.SSLCreate) => {
|
||||||
|
return http.post<WebSite.SSLCreate>(`/websites/ssl`, req);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DeleteSSL = (id: number) => {
|
||||||
|
return http.delete<any>(`/websites/ssl/${id}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ApplySSL = (req: WebSite.SSLApply) => {
|
||||||
|
return http.post<WebSite.SSLApply>(`/websites/ssl/apply`, req);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const GetDnsResolve = (req: WebSite.DNSResolveReq) => {
|
||||||
|
return http.post<WebSite.DNSResolve>(`/websites/ssl/resolve`, req);
|
||||||
|
};
|
||||||
|
@ -31,7 +31,7 @@ export const useDeleteData = <P = any, R = any>(
|
|||||||
if (!res) return reject(false);
|
if (!res) return reject(false);
|
||||||
ElMessage({
|
ElMessage({
|
||||||
type: 'success',
|
type: 'success',
|
||||||
message: i18n.global.t('commons.msg.deleteSuccess'),
|
message: i18n.global.t('commons.msg.operationSuccess'),
|
||||||
});
|
});
|
||||||
resolve(true);
|
resolve(true);
|
||||||
})
|
})
|
||||||
|
@ -692,7 +692,7 @@ export default {
|
|||||||
perip: '单IP限制',
|
perip: '单IP限制',
|
||||||
peripHelper: '限制单个IP访问最大并发数',
|
peripHelper: '限制单个IP访问最大并发数',
|
||||||
rate: '流量限制',
|
rate: '流量限制',
|
||||||
rateHelper: '限制每个请求的流量上限(单位:KB)',
|
rateHelper: '限制每个请求的流量上(单位:KB)',
|
||||||
limtHelper: '启用流量控制',
|
limtHelper: '启用流量控制',
|
||||||
other: '其他',
|
other: '其他',
|
||||||
currentSSL: '当前证书',
|
currentSSL: '当前证书',
|
||||||
@ -707,5 +707,12 @@ export default {
|
|||||||
accountManage: '账户管理',
|
accountManage: '账户管理',
|
||||||
email: '邮箱',
|
email: '邮箱',
|
||||||
addAccount: '新增账户',
|
addAccount: '新增账户',
|
||||||
|
acmeAccount: 'Acme 账户',
|
||||||
|
provider: '验证方式',
|
||||||
|
dnsCommon: '手动解析',
|
||||||
|
expireDate: '到期时间',
|
||||||
|
brand: '品牌',
|
||||||
|
deploySSL: '部署',
|
||||||
|
deploySSLHelper: '确定部署证书?',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -16,15 +16,15 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import LayoutContent from '@/layout/layout-content.vue';
|
import LayoutContent from '@/layout/layout-content.vue';
|
||||||
import { computed, onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import Basic from './basic/index.vue';
|
import Basic from './basic/index.vue';
|
||||||
import SSL from './ssl/index.vue';
|
import SSL from './ssl/index.vue';
|
||||||
import router from '@/routers';
|
import router from '@/routers';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
type: Number,
|
type: String,
|
||||||
default: 0,
|
default: '0',
|
||||||
},
|
},
|
||||||
tab: {
|
tab: {
|
||||||
type: String,
|
type: String,
|
||||||
@ -32,10 +32,7 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const id = computed(() => {
|
let id = ref(0);
|
||||||
return props.id;
|
|
||||||
});
|
|
||||||
|
|
||||||
let index = ref('basic');
|
let index = ref('basic');
|
||||||
|
|
||||||
const changeTab = (index: string) => {
|
const changeTab = (index: string) => {
|
||||||
@ -43,6 +40,7 @@ const changeTab = (index: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
id.value = Number(props.id);
|
||||||
if (props.tab !== index.value) {
|
if (props.tab !== index.value) {
|
||||||
index.value = props.tab;
|
index.value = props.tab;
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ const types = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: i18n.global.t('website.aliyun'),
|
label: i18n.global.t('website.aliyun'),
|
||||||
value: 'Aliyun',
|
value: 'AliYun',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'CloudFlare',
|
label: 'CloudFlare',
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<Account :id="id" v-if="index == '1'"></Account>
|
<Account :id="id" v-if="index == '1'"></Account>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane :label="$t('website.applySSL')">
|
<el-tab-pane :label="$t('website.applySSL')">
|
||||||
<SSL v-if="index == '2'"></SSL>
|
<SSL :id="id" v-if="index == '2'"></SSL>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</template>
|
</template>
|
||||||
|
@ -0,0 +1,190 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog v-model="open" :title="$t('commons.button.create')" width="30%" :before-close="handleClose">
|
||||||
|
<el-form
|
||||||
|
ref="sslForm"
|
||||||
|
label-position="right"
|
||||||
|
:model="ssl"
|
||||||
|
label-width="150px"
|
||||||
|
:rules="rules"
|
||||||
|
v-loading="loading"
|
||||||
|
>
|
||||||
|
<el-form-item :label="$t('website.acmeAccount')" prop="acmeAccountId">
|
||||||
|
<el-select v-model="ssl.acmeAccountId">
|
||||||
|
<el-option
|
||||||
|
v-for="(acme, index) in acmeAccounts"
|
||||||
|
:key="index"
|
||||||
|
:label="acme.email"
|
||||||
|
:value="acme.id"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('website.provider')" prop="provider">
|
||||||
|
<el-radio-group v-model="ssl.provider">
|
||||||
|
<el-radio label="dnsAccount">{{ $t('website.dnsAccount') }}</el-radio>
|
||||||
|
<el-radio label="dnsCommon">{{ $t('website.dnsCommon') }}</el-radio>
|
||||||
|
<el-radio label="http">HTTP</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('website.dnsAccount')" prop="dnsAccountId" v-if="ssl.provider === 'dnsAccount'">
|
||||||
|
<el-select v-model="ssl.dnsAccountId">
|
||||||
|
<el-option
|
||||||
|
v-for="(dns, index) in dnsAccounts"
|
||||||
|
:key="index"
|
||||||
|
:label="dns.name + ' ( ' + dns.type + ' )'"
|
||||||
|
:value="dns.id"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('website.domain')" prop="domains">
|
||||||
|
<el-checkbox-group v-model="ssl.domains">
|
||||||
|
<el-checkbox v-for="domain in domains" :key="domain.domain" :label="domain.domain"></el-checkbox>
|
||||||
|
</el-checkbox-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<div>
|
||||||
|
<span>解析域名: {{ dnsResolve.key }}</span>
|
||||||
|
<span>记录值: {{ dnsResolve.value }}</span>
|
||||||
|
<span>类型: {{ dnsResolve.type }}</span>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="handleClose" :disabled="loading">{{ $t('commons.button.cancel') }}</el-button>
|
||||||
|
<el-button type="primary" @click="submit(sslForm)" :loading="loading">
|
||||||
|
{{ $t('commons.button.confirm') }}
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { WebSite } from '@/api/interface/website';
|
||||||
|
import { CreateSSL, GetDnsResolve, GetWebsite, SearchAcmeAccount, SearchDnsAccount } from '@/api/modules/website';
|
||||||
|
import { Rules } from '@/global/form-rules';
|
||||||
|
import i18n from '@/lang';
|
||||||
|
import { ElMessage, FormInstance } from 'element-plus';
|
||||||
|
import { computed, reactive, ref } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const id = computed(() => {
|
||||||
|
return props.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
let open = ref(false);
|
||||||
|
let loading = ref(false);
|
||||||
|
let dnsReq = reactive({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
});
|
||||||
|
let acmeReq = reactive({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
});
|
||||||
|
let dnsAccounts = ref<WebSite.DnsAccount[]>();
|
||||||
|
let acmeAccounts = ref<WebSite.AcmeAccount[]>();
|
||||||
|
let domains = ref<WebSite.Domain[]>([]);
|
||||||
|
let sslForm = ref<FormInstance>();
|
||||||
|
let rules = ref({
|
||||||
|
acmeAccountId: [Rules.requiredSelectBusiness],
|
||||||
|
dnsAccountId: [Rules.requiredSelectBusiness],
|
||||||
|
provider: [Rules.requiredInput],
|
||||||
|
domains: [Rules.requiredSelect],
|
||||||
|
});
|
||||||
|
let ssl = ref({
|
||||||
|
domains: [],
|
||||||
|
provider: 'dnsAccount',
|
||||||
|
websiteId: 0,
|
||||||
|
acmeAccountId: 0,
|
||||||
|
dnsAccountId: 0,
|
||||||
|
});
|
||||||
|
let dnsResolve = ref<WebSite.DNSResolve>({
|
||||||
|
key: '',
|
||||||
|
value: '',
|
||||||
|
type: '',
|
||||||
|
});
|
||||||
|
let hasResolve = ref(false);
|
||||||
|
|
||||||
|
const em = defineEmits(['close']);
|
||||||
|
const handleClose = () => {
|
||||||
|
resetForm();
|
||||||
|
open.value = false;
|
||||||
|
em('close', false);
|
||||||
|
};
|
||||||
|
const resetForm = () => {
|
||||||
|
sslForm.value?.resetFields();
|
||||||
|
ssl.value = {
|
||||||
|
domains: [],
|
||||||
|
provider: 'dnsAccount',
|
||||||
|
websiteId: 0,
|
||||||
|
acmeAccountId: 0,
|
||||||
|
dnsAccountId: 0,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const acceptParams = () => {
|
||||||
|
resetForm();
|
||||||
|
ssl.value.websiteId = Number(id.value);
|
||||||
|
getWebsite(id.value);
|
||||||
|
getAcmeAccounts();
|
||||||
|
getDnsAccounts();
|
||||||
|
open.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getAcmeAccounts = async () => {
|
||||||
|
const res = await SearchAcmeAccount(acmeReq);
|
||||||
|
acmeAccounts.value = res.data.items || [];
|
||||||
|
if (acmeAccounts.value.length > 0) {
|
||||||
|
ssl.value.acmeAccountId = res.data.items[0].id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getDnsAccounts = async () => {
|
||||||
|
const res = await SearchDnsAccount(dnsReq);
|
||||||
|
dnsAccounts.value = res.data.items || [];
|
||||||
|
if (dnsAccounts.value.length > 0) {
|
||||||
|
ssl.value.dnsAccountId = res.data.items[0].id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getWebsite = async (id: number) => {
|
||||||
|
domains.value = (await GetWebsite(id)).data.domains || [];
|
||||||
|
};
|
||||||
|
|
||||||
|
const getDnsResolve = async (acmeAccountId: number, domains: string[]) => {
|
||||||
|
hasResolve.value = false;
|
||||||
|
const res = await GetDnsResolve({ acmeAccountId: acmeAccountId, domains: domains });
|
||||||
|
if (res.data) {
|
||||||
|
dnsResolve.value = res.data;
|
||||||
|
hasResolve.value = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const submit = async (formEl: FormInstance | undefined) => {
|
||||||
|
if (!formEl) return;
|
||||||
|
await formEl.validate(async (valid) => {
|
||||||
|
if (!valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ssl.value.provider != 'dnsCommon' || hasResolve.value) {
|
||||||
|
loading.value = true;
|
||||||
|
await CreateSSL(ssl.value);
|
||||||
|
ElMessage.success(i18n.global.t('commons.msg.createSuccess'));
|
||||||
|
loading.value = false;
|
||||||
|
} else {
|
||||||
|
getDnsResolve(ssl.value.acmeAccountId, ssl.value.domains);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
acceptParams,
|
||||||
|
});
|
||||||
|
</script>
|
@ -2,20 +2,51 @@
|
|||||||
<div>
|
<div>
|
||||||
<ComplexTable :data="data" :pagination-config="paginationConfig" @search="search()">
|
<ComplexTable :data="data" :pagination-config="paginationConfig" @search="search()">
|
||||||
<template #toolbar>
|
<template #toolbar>
|
||||||
<el-button type="primary" plain>{{ $t('commons.button.create') }}</el-button>
|
<el-button type="primary" plain @click="openSSL()">{{ $t('commons.button.create') }}</el-button>
|
||||||
<el-button type="primary" plain @click="openAccount()">{{ $t('website.accountManage') }}</el-button>
|
<el-button type="primary" plain @click="openAccount()">{{ $t('website.accountManage') }}</el-button>
|
||||||
</template>
|
</template>
|
||||||
<el-table-column :label="$t('commons.table.name')" fix show-overflow-tooltip prop="name"></el-table-column>
|
<el-table-column :label="$t('website.domain')" fix show-overflow-tooltip prop="domain"></el-table-column>
|
||||||
|
<el-table-column :label="$t('website.brand')" fix show-overflow-tooltip prop="type"></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="expireDate"
|
||||||
|
:label="$t('website.expireDate')"
|
||||||
|
:formatter="dateFromat"
|
||||||
|
show-overflow-tooltip
|
||||||
|
/>
|
||||||
|
<fu-table-operations
|
||||||
|
:ellipsis="1"
|
||||||
|
:buttons="buttons"
|
||||||
|
:label="$t('commons.table.operate')"
|
||||||
|
fixed="right"
|
||||||
|
fix
|
||||||
|
/>
|
||||||
</ComplexTable>
|
</ComplexTable>
|
||||||
<Account ref="accountRef"></Account>
|
<Account ref="accountRef"></Account>
|
||||||
|
<Create :id="id" ref="sslCreateRef"></Create>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import ComplexTable from '@/components/complex-table/index.vue';
|
import ComplexTable from '@/components/complex-table/index.vue';
|
||||||
import { onMounted, reactive, ref } from 'vue';
|
import { computed, onMounted, reactive, ref } from 'vue';
|
||||||
import { SearchSSL } from '@/api/modules/website';
|
import { ApplySSL, DeleteSSL, SearchSSL } from '@/api/modules/website';
|
||||||
import Account from './account/index.vue';
|
import Account from './account/index.vue';
|
||||||
|
import Create from './create/index.vue';
|
||||||
|
import { dateFromat } from '@/utils/util';
|
||||||
|
import i18n from '@/lang';
|
||||||
|
import { WebSite } from '@/api/interface/website';
|
||||||
|
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const id = computed(() => {
|
||||||
|
return props.id;
|
||||||
|
});
|
||||||
|
|
||||||
const paginationConfig = reactive({
|
const paginationConfig = reactive({
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
@ -23,22 +54,65 @@ const paginationConfig = reactive({
|
|||||||
total: 0,
|
total: 0,
|
||||||
});
|
});
|
||||||
const accountRef = ref();
|
const accountRef = ref();
|
||||||
|
const sslCreateRef = ref();
|
||||||
let data = ref();
|
let data = ref();
|
||||||
|
let loading = ref(false);
|
||||||
|
|
||||||
|
const buttons = [
|
||||||
|
{
|
||||||
|
label: i18n.global.t('website.deploySSL'),
|
||||||
|
click: function (row: WebSite.WebSite) {
|
||||||
|
applySSL(row.id);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.global.t('app.delete'),
|
||||||
|
click: function (row: WebSite.WebSite) {
|
||||||
|
deleteSSL(row.id);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const search = () => {
|
const search = () => {
|
||||||
const req = {
|
const req = {
|
||||||
page: paginationConfig.currentPage,
|
page: paginationConfig.currentPage,
|
||||||
pageSize: paginationConfig.pageSize,
|
pageSize: paginationConfig.pageSize,
|
||||||
};
|
};
|
||||||
SearchSSL(req).then((res) => {
|
loading.value = true;
|
||||||
data.value = res.data.items;
|
SearchSSL(req)
|
||||||
paginationConfig.total = res.data.total;
|
.then((res) => {
|
||||||
});
|
data.value = res.data.items || [];
|
||||||
|
paginationConfig.total = res.data.total;
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const openAccount = () => {
|
const openAccount = () => {
|
||||||
accountRef.value.acceptParams();
|
accountRef.value.acceptParams();
|
||||||
};
|
};
|
||||||
|
const openSSL = () => {
|
||||||
|
sslCreateRef.value.acceptParams();
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteSSL = async (id: number) => {
|
||||||
|
loading.value = true;
|
||||||
|
await useDeleteData(DeleteSSL, id, 'commons.msg.delete', false);
|
||||||
|
loading.value = false;
|
||||||
|
search();
|
||||||
|
};
|
||||||
|
|
||||||
|
const applySSL = async (sslId: number) => {
|
||||||
|
loading.value = true;
|
||||||
|
const apply = {
|
||||||
|
websiteId: Number(id.value),
|
||||||
|
SSLId: sslId,
|
||||||
|
};
|
||||||
|
await useDeleteData(ApplySSL, apply, 'website.deploySSLHelper', false);
|
||||||
|
loading.value = false;
|
||||||
|
search();
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
search();
|
search();
|
||||||
|
2
go.mod
2
go.mod
@ -56,12 +56,12 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|
||||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||||
github.com/Microsoft/go-winio v0.6.0 // indirect
|
github.com/Microsoft/go-winio v0.6.0 // indirect
|
||||||
github.com/Microsoft/hcsshim v0.9.4 // indirect
|
github.com/Microsoft/hcsshim v0.9.4 // indirect
|
||||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||||
|
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755 // indirect
|
||||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
|
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
|
||||||
github.com/cespare/xxhash v1.1.0 // indirect
|
github.com/cespare/xxhash v1.1.0 // indirect
|
||||||
|
6
go.sum
6
go.sum
@ -139,6 +139,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
|
|||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
|
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
|
||||||
|
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755 h1:J45/QHgrzUdqe/Vco/Vxk0wRvdS2nKUxmf/zLgvfass=
|
||||||
|
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755/go.mod h1:RcDobYh8k5VP6TNybz9m++gL3ijVI5wueVr0EM10VsU=
|
||||||
github.com/aliyun/aliyun-oss-go-sdk v2.2.5+incompatible h1:QoRMR0TCctLDqBCMyOu1eXdZyMw3F7uGA9qPn2J4+R8=
|
github.com/aliyun/aliyun-oss-go-sdk v2.2.5+incompatible h1:QoRMR0TCctLDqBCMyOu1eXdZyMw3F7uGA9qPn2J4+R8=
|
||||||
github.com/aliyun/aliyun-oss-go-sdk v2.2.5+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
|
github.com/aliyun/aliyun-oss-go-sdk v2.2.5+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
|
||||||
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
|
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
|
||||||
@ -482,6 +484,7 @@ github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP
|
|||||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
|
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
|
||||||
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||||
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||||
github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs=
|
github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs=
|
||||||
@ -655,6 +658,7 @@ github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
|||||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
|
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||||
@ -665,6 +669,7 @@ github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwA
|
|||||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
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/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
|
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.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
@ -1653,6 +1658,7 @@ gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKW
|
|||||||
gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE=
|
gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE=
|
||||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||||
gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
|
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI=
|
gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI=
|
||||||
gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
||||||
|
Loading…
x
Reference in New Issue
Block a user