mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-18 22:22:59 +08:00
feat: 自签证书增加续签功能 (#3079)
This commit is contained in:
parent
807a5071a7
commit
e41661e8d4
@ -116,3 +116,29 @@ func (b *BaseApi) ObtainWebsiteCA(c *gin.Context) {
|
||||
}
|
||||
helper.SuccessWithOutData(c)
|
||||
}
|
||||
|
||||
// @Tags Website CA
|
||||
// @Summary Obtain SSL
|
||||
// @Description 续签 SSL 证书
|
||||
// @Accept json
|
||||
// @Param request body request.WebsiteCAObtain true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/ca/obtain [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_cas","output_column":"name","output_value":"name"}],"formatZH":"自签 SSL 证书 [name]","formatEN":"Obtain SSL [name]"}
|
||||
func (b *BaseApi) RenewWebsiteCA(c *gin.Context) {
|
||||
var req request.WebsiteCARenew
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := websiteCAService.ObtainSSL(request.WebsiteCAObtain{
|
||||
SSLID: req.SSLID,
|
||||
Renew: true,
|
||||
Unit: "year",
|
||||
Time: 1,
|
||||
}); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithOutData(c)
|
||||
}
|
||||
|
@ -65,27 +65,6 @@ func (b *BaseApi) CreateWebsiteSSL(c *gin.Context) {
|
||||
helper.SuccessWithData(c, res)
|
||||
}
|
||||
|
||||
// @Tags Website SSL
|
||||
// @Summary Reset website ssl
|
||||
// @Description 重置网站 ssl
|
||||
// @Accept json
|
||||
// @Param request body request.WebsiteSSLRenew true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/ssl/renew [post]
|
||||
// @x-panel-log {"bodyKeys":["SSLId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"SSLId","isList":false,"db":"website_ssls","output_column":"primary_domain","output_value":"domain"}],"formatZH":"重置 ssl [domain]","formatEN":"Renew ssl [domain]"}
|
||||
func (b *BaseApi) RenewWebsiteSSL(c *gin.Context) {
|
||||
var req request.WebsiteSSLRenew
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := websiteSSLService.Renew(req.SSLID); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
// @Tags Website SSL
|
||||
// @Summary Apply ssl
|
||||
// @Description 申请证书
|
||||
|
@ -92,11 +92,18 @@ type WebsiteCACreate struct {
|
||||
}
|
||||
|
||||
type WebsiteCAObtain struct {
|
||||
ID uint `json:"id" validate:"required"`
|
||||
Domains string `json:"domains" validate:"required"`
|
||||
KeyType string `json:"keyType" validate:"required,oneof=P256 P384 2048 3072 4096 8192"`
|
||||
Time int `json:"time" validate:"required"`
|
||||
Unit string `json:"unit" validate:"required"`
|
||||
PushDir bool `json:"pushDir"`
|
||||
Dir string `json:"dir"`
|
||||
ID uint `json:"id" validate:"required"`
|
||||
Domains string `json:"domains" validate:"required"`
|
||||
KeyType string `json:"keyType" validate:"required,oneof=P256 P384 2048 3072 4096 8192"`
|
||||
Time int `json:"time" validate:"required"`
|
||||
Unit string `json:"unit" validate:"required"`
|
||||
PushDir bool `json:"pushDir"`
|
||||
Dir string `json:"dir"`
|
||||
AutoRenew bool `json:"autoRenew"`
|
||||
Renew bool `json:"renew"`
|
||||
SSLID uint `json:"sslID"`
|
||||
}
|
||||
|
||||
type WebsiteCARenew struct {
|
||||
SSLID uint `json:"SSLID" validate:"required"`
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ type WebsiteSSL struct {
|
||||
Organization string `gorm:"type:varchar(64);not null" json:"organization"`
|
||||
DnsAccountID uint `gorm:"type:integer;not null" json:"dnsAccountId"`
|
||||
AcmeAccountID uint `gorm:"type:integer;not null" json:"acmeAccountId"`
|
||||
CaID uint `gorm:"type:integer;not null;default:0" json:"caId"`
|
||||
AutoRenew bool `gorm:"type:varchar(64);not null" json:"autoRenew"`
|
||||
ExpireDate time.Time `json:"expireDate"`
|
||||
StartDate time.Time `json:"startDate"`
|
||||
|
@ -14,11 +14,12 @@ type ISSLRepo interface {
|
||||
WithByAlias(alias string) DBOption
|
||||
WithByAcmeAccountId(acmeAccountId uint) DBOption
|
||||
WithByDnsAccountId(dnsAccountId uint) DBOption
|
||||
WithByCAID(caID uint) DBOption
|
||||
Page(page, size int, opts ...DBOption) (int64, []model.WebsiteSSL, error)
|
||||
GetFirst(opts ...DBOption) (model.WebsiteSSL, error)
|
||||
GetFirst(opts ...DBOption) (*model.WebsiteSSL, error)
|
||||
List(opts ...DBOption) ([]model.WebsiteSSL, error)
|
||||
Create(ctx context.Context, ssl *model.WebsiteSSL) error
|
||||
Save(ssl model.WebsiteSSL) error
|
||||
Save(ssl *model.WebsiteSSL) error
|
||||
DeleteBy(opts ...DBOption) error
|
||||
}
|
||||
|
||||
@ -43,6 +44,12 @@ func (w WebsiteSSLRepo) WithByDnsAccountId(dnsAccountId uint) DBOption {
|
||||
}
|
||||
}
|
||||
|
||||
func (w WebsiteSSLRepo) WithByCAID(caID uint) DBOption {
|
||||
return func(db *gorm.DB) *gorm.DB {
|
||||
return db.Where("ca_id = ?", caID)
|
||||
}
|
||||
}
|
||||
|
||||
func (w WebsiteSSLRepo) Page(page, size int, opts ...DBOption) (int64, []model.WebsiteSSL, error) {
|
||||
var sslList []model.WebsiteSSL
|
||||
db := getDb(opts...).Model(&model.WebsiteSSL{})
|
||||
@ -52,8 +59,8 @@ func (w WebsiteSSLRepo) Page(page, size int, opts ...DBOption) (int64, []model.W
|
||||
return count, sslList, err
|
||||
}
|
||||
|
||||
func (w WebsiteSSLRepo) GetFirst(opts ...DBOption) (model.WebsiteSSL, error) {
|
||||
var website model.WebsiteSSL
|
||||
func (w WebsiteSSLRepo) GetFirst(opts ...DBOption) (*model.WebsiteSSL, error) {
|
||||
var website *model.WebsiteSSL
|
||||
db := getDb(opts...).Model(&model.WebsiteSSL{})
|
||||
if err := db.Preload("AcmeAccount").Preload("DnsAccount").First(&website).Error; err != nil {
|
||||
return website, err
|
||||
@ -74,7 +81,7 @@ 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 {
|
||||
return getDb().Save(&ssl).Error
|
||||
}
|
||||
|
||||
|
@ -619,7 +619,7 @@ func (w WebsiteService) GetWebsiteHTTPS(websiteId uint) (response.WebsiteHTTPS,
|
||||
if err != nil {
|
||||
return response.WebsiteHTTPS{}, err
|
||||
}
|
||||
res.SSL = websiteSSL
|
||||
res.SSL = *websiteSSL
|
||||
res.Enable = true
|
||||
if website.HttpConfig != "" {
|
||||
res.HttpConfig = website.HttpConfig
|
||||
@ -648,7 +648,7 @@ func (w WebsiteService) OpWebsiteHTTPS(ctx context.Context, req request.WebsiteH
|
||||
}
|
||||
var (
|
||||
res response.WebsiteHTTPS
|
||||
websiteSSL model.WebsiteSSL
|
||||
websiteSSL *model.WebsiteSSL
|
||||
)
|
||||
res.Enable = req.Enable
|
||||
res.SSLProtocol = req.SSLProtocol
|
||||
@ -698,7 +698,7 @@ func (w WebsiteService) OpWebsiteHTTPS(ctx context.Context, req request.WebsiteH
|
||||
return nil, err
|
||||
}
|
||||
website.WebsiteSSLID = websiteSSL.ID
|
||||
res.SSL = websiteSSL
|
||||
res.SSL = *websiteSSL
|
||||
}
|
||||
if req.Type == constant.SSLManual {
|
||||
var (
|
||||
@ -758,16 +758,16 @@ func (w WebsiteService) OpWebsiteHTTPS(ctx context.Context, req request.WebsiteH
|
||||
websiteSSL.PrivateKey = privateKey
|
||||
websiteSSL.Pem = certificate
|
||||
|
||||
res.SSL = websiteSSL
|
||||
res.SSL = *websiteSSL
|
||||
}
|
||||
website.Protocol = constant.ProtocolHTTPS
|
||||
if err := applySSL(website, websiteSSL, req); err != nil {
|
||||
if err := applySSL(website, *websiteSSL, req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
website.HttpConfig = req.HttpConfig
|
||||
|
||||
if websiteSSL.ID == 0 {
|
||||
if err := websiteSSLRepo.Create(ctx, &websiteSSL); err != nil {
|
||||
if err := websiteSSLRepo.Create(ctx, websiteSSL); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
website.WebsiteSSLID = websiteSSL.ID
|
||||
|
@ -149,48 +149,78 @@ func (w WebsiteCAService) GetCA(id uint) (response.WebsiteCADTO, error) {
|
||||
}
|
||||
|
||||
func (w WebsiteCAService) Delete(id uint) error {
|
||||
|
||||
ssls, _ := websiteSSLRepo.List(websiteSSLRepo.WithByCAID(id))
|
||||
if len(ssls) > 0 {
|
||||
return buserr.New("ErrDeleteCAWithSSL")
|
||||
}
|
||||
return websiteCARepo.DeleteBy(commonRepo.WithByID(id))
|
||||
}
|
||||
|
||||
func (w WebsiteCAService) ObtainSSL(req request.WebsiteCAObtain) error {
|
||||
ca, err := websiteCARepo.GetFirst(commonRepo.WithByID(req.ID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newSSL := &model.WebsiteSSL{
|
||||
Provider: constant.SelfSigned,
|
||||
KeyType: req.KeyType,
|
||||
PushDir: req.PushDir,
|
||||
}
|
||||
if req.PushDir {
|
||||
if !files.NewFileOp().Stat(req.Dir) {
|
||||
return buserr.New(constant.ErrLinkPathNotFound)
|
||||
}
|
||||
newSSL.Dir = req.Dir
|
||||
}
|
||||
|
||||
var (
|
||||
domains []string
|
||||
ips []net.IP
|
||||
domains []string
|
||||
ips []net.IP
|
||||
websiteSSL = &model.WebsiteSSL{}
|
||||
err error
|
||||
ca model.WebsiteCA
|
||||
)
|
||||
if req.Domains != "" {
|
||||
domainArray := strings.Split(req.Domains, "\n")
|
||||
for _, domain := range domainArray {
|
||||
if !common.IsValidDomain(domain) {
|
||||
err = buserr.WithName("ErrDomainFormat", domain)
|
||||
return err
|
||||
if req.Renew {
|
||||
websiteSSL, err = websiteSSLRepo.GetFirst(commonRepo.WithByID(req.SSLID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ca, err = websiteCARepo.GetFirst(commonRepo.WithByID(websiteSSL.CaID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existDomains := []string{websiteSSL.PrimaryDomain}
|
||||
if websiteSSL.Domains != "" {
|
||||
existDomains = append(existDomains, strings.Split(websiteSSL.Domains, ",")...)
|
||||
}
|
||||
for _, domain := range existDomains {
|
||||
if ipAddress := net.ParseIP(domain); ipAddress == nil {
|
||||
domains = append(domains, domain)
|
||||
} else {
|
||||
if ipAddress := net.ParseIP(domain); ipAddress == nil {
|
||||
domains = append(domains, domain)
|
||||
} else {
|
||||
ips = append(ips, ipAddress)
|
||||
}
|
||||
ips = append(ips, ipAddress)
|
||||
}
|
||||
}
|
||||
if len(domains) > 0 {
|
||||
newSSL.PrimaryDomain = domains[0]
|
||||
newSSL.Domains = strings.Join(domains[1:], ",")
|
||||
} else {
|
||||
ca, err = websiteCARepo.GetFirst(commonRepo.WithByID(req.ID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
websiteSSL = &model.WebsiteSSL{
|
||||
Provider: constant.SelfSigned,
|
||||
KeyType: req.KeyType,
|
||||
PushDir: req.PushDir,
|
||||
CaID: ca.ID,
|
||||
AutoRenew: req.AutoRenew,
|
||||
}
|
||||
if req.PushDir {
|
||||
if !files.NewFileOp().Stat(req.Dir) {
|
||||
return buserr.New(constant.ErrLinkPathNotFound)
|
||||
}
|
||||
websiteSSL.Dir = req.Dir
|
||||
}
|
||||
if req.Domains != "" {
|
||||
domainArray := strings.Split(req.Domains, "\n")
|
||||
for _, domain := range domainArray {
|
||||
if !common.IsValidDomain(domain) {
|
||||
err = buserr.WithName("ErrDomainFormat", domain)
|
||||
return err
|
||||
} else {
|
||||
if ipAddress := net.ParseIP(domain); ipAddress == nil {
|
||||
domains = append(domains, domain)
|
||||
} else {
|
||||
ips = append(ips, ipAddress)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(domains) > 0 {
|
||||
websiteSSL.PrimaryDomain = domains[0]
|
||||
websiteSSL.Domains = strings.Join(domains[1:], ",")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,7 +238,7 @@ func (w WebsiteCAService) ObtainSSL(req request.WebsiteCAObtain) error {
|
||||
}
|
||||
|
||||
var rootPrivateKey any
|
||||
if ssl.KeyType(ca.KeyType) == certcrypto.EC256 || ssl.KeyType(ca.KeyType) == certcrypto.EC384 {
|
||||
if ssl.KeyType(websiteSSL.KeyType) == certcrypto.EC256 || ssl.KeyType(websiteSSL.KeyType) == certcrypto.EC384 {
|
||||
rootPrivateKey, err = x509.ParseECPrivateKey(rootPrivateKeyBlock.Bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -219,7 +249,7 @@ func (w WebsiteCAService) ObtainSSL(req request.WebsiteCAObtain) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
interPrivateKey, interPublicKey, _, err := createPrivateKey(req.KeyType)
|
||||
interPrivateKey, interPublicKey, _, err := createPrivateKey(websiteSSL.KeyType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -249,7 +279,7 @@ func (w WebsiteCAService) ObtainSSL(req request.WebsiteCAObtain) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, publicKey, privateKeyBytes, err := createPrivateKey(req.KeyType)
|
||||
_, publicKey, privateKeyBytes, err := createPrivateKey(websiteSSL.KeyType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -281,21 +311,28 @@ func (w WebsiteCAService) ObtainSSL(req request.WebsiteCAObtain) error {
|
||||
Bytes: cert.Raw,
|
||||
}
|
||||
pemData := pem.EncodeToMemory(certBlock)
|
||||
newSSL.Pem = string(pemData)
|
||||
newSSL.PrivateKey = string(privateKeyBytes)
|
||||
newSSL.ExpireDate = cert.NotAfter
|
||||
newSSL.StartDate = cert.NotBefore
|
||||
newSSL.Type = cert.Issuer.CommonName
|
||||
newSSL.Organization = rootCsr.Subject.Organization[0]
|
||||
websiteSSL.Pem = string(pemData)
|
||||
websiteSSL.PrivateKey = string(privateKeyBytes)
|
||||
websiteSSL.ExpireDate = cert.NotAfter
|
||||
websiteSSL.StartDate = cert.NotBefore
|
||||
websiteSSL.Type = cert.Issuer.CommonName
|
||||
websiteSSL.Organization = rootCsr.Subject.Organization[0]
|
||||
|
||||
if err := websiteSSLRepo.Create(context.Background(), newSSL); err != nil {
|
||||
return err
|
||||
if req.Renew {
|
||||
if err := websiteSSLRepo.Save(websiteSSL); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := websiteSSLRepo.Create(context.Background(), websiteSSL); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
logFile, _ := os.OpenFile(path.Join(constant.SSLLogDir, fmt.Sprintf("%s-ssl-%d.log", newSSL.PrimaryDomain, newSSL.ID)), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
|
||||
|
||||
logFile, _ := os.OpenFile(path.Join(constant.SSLLogDir, fmt.Sprintf("%s-ssl-%d.log", websiteSSL.PrimaryDomain, websiteSSL.ID)), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
|
||||
defer logFile.Close()
|
||||
logger := log.New(logFile, "", log.LstdFlags)
|
||||
logger.Println(i18n.GetMsgWithMap("ApplySSLSuccess", map[string]interface{}{"domain": strings.Join(domains, ",")}))
|
||||
saveCertificateFile(*newSSL, logger)
|
||||
saveCertificateFile(websiteSSL, logger)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,6 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/backend/app/repo"
|
||||
"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/i18n"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||
@ -35,7 +34,6 @@ type IWebsiteSSLService interface {
|
||||
GetSSL(id uint) (*response.WebsiteSSLDTO, error)
|
||||
Search(req request.WebsiteSSLSearch) ([]response.WebsiteSSLDTO, error)
|
||||
Create(create request.WebsiteSSLCreate) (request.WebsiteSSLCreate, error)
|
||||
Renew(sslId uint) error
|
||||
GetDNSResolve(req request.WebsiteDNSReq) ([]response.WebsiteDNSRes, error)
|
||||
GetWebsiteSSL(websiteId uint) (response.WebsiteSSLDTO, error)
|
||||
Delete(ids []uint) error
|
||||
@ -72,7 +70,7 @@ func (w WebsiteSSLService) GetSSL(id uint) (*response.WebsiteSSLDTO, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res.WebsiteSSL = websiteSSL
|
||||
res.WebsiteSSL = *websiteSSL
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
@ -157,7 +155,7 @@ func (w WebsiteSSLService) Create(create request.WebsiteSSLCreate) (request.Webs
|
||||
func (w WebsiteSSLService) ObtainSSL(apply request.WebsiteSSLApply) error {
|
||||
var (
|
||||
err error
|
||||
websiteSSL model.WebsiteSSL
|
||||
websiteSSL *model.WebsiteSSL
|
||||
acmeAccount *model.WebsiteAcmeAccount
|
||||
dnsAccount *model.WebsiteDnsAccount
|
||||
)
|
||||
@ -257,91 +255,17 @@ func (w WebsiteSSLService) ObtainSSL(apply request.WebsiteSSLApply) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleError(websiteSSL model.WebsiteSSL, err error) {
|
||||
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()
|
||||
legoLogger.Logger.Println(i18n.GetErrMsg("ApplySSLFailed", map[string]interface{}{"domain": websiteSSL.PrimaryDomain, "err": err.Error()}))
|
||||
legoLogger.Logger.Println(i18n.GetErrMsg("ApplySSLFailed", map[string]interface{}{"domain": websiteSSL.PrimaryDomain, "detail": err.Error()}))
|
||||
_ = websiteSSLRepo.Save(websiteSSL)
|
||||
}
|
||||
|
||||
func (w WebsiteSSLService) Renew(sslId uint) error {
|
||||
websiteSSL, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(sslId))
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
if err := client.UseHTTP(path.Join(constant.AppInstallDir, constant.AppOpenresty, appInstall.Name, "root")); err != nil {
|
||||
return err
|
||||
}
|
||||
case constant.SelfSigned:
|
||||
|
||||
}
|
||||
|
||||
resource, err := client.RenewSSL(websiteSSL.CertURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
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 err
|
||||
}
|
||||
websiteSSL.ExpireDate = cert.NotAfter
|
||||
websiteSSL.StartDate = cert.NotBefore
|
||||
websiteSSL.Type = cert.Issuer.CommonName
|
||||
websiteSSL.Organization = cert.Issuer.Organization[0]
|
||||
|
||||
if err := websiteSSLRepo.Save(websiteSSL); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
websites, _ := websiteRepo.GetBy(websiteRepo.WithWebsiteSSLID(sslId))
|
||||
for _, website := range websites {
|
||||
if err := createPemFile(website, websiteSSL); err != nil {
|
||||
global.LOG.Errorf("create website [%s] ssl file failed! err:%s", website.PrimaryDomain, err.Error())
|
||||
}
|
||||
}
|
||||
if len(websites) > 0 {
|
||||
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := opNginx(nginxInstall.ContainerName, constant.NginxReload); err != nil {
|
||||
return buserr.New(constant.ErrSSLApply)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w WebsiteSSLService) GetDNSResolve(req request.WebsiteDNSReq) ([]response.WebsiteDNSRes, error) {
|
||||
acmeAccount, err := websiteAcmeRepo.GetFirst(commonRepo.WithByID(req.AcmeAccountID))
|
||||
if err != nil {
|
||||
@ -378,7 +302,7 @@ func (w WebsiteSSLService) GetWebsiteSSL(websiteId uint) (response.WebsiteSSLDTO
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
res.WebsiteSSL = websiteSSL
|
||||
res.WebsiteSSL = *websiteSSL
|
||||
return res, nil
|
||||
}
|
||||
|
||||
@ -391,9 +315,19 @@ func (w WebsiteSSLService) Delete(ids []uint) error {
|
||||
names = append(names, oldSSL.PrimaryDomain)
|
||||
}
|
||||
continue
|
||||
} else {
|
||||
_ = websiteSSLRepo.DeleteBy(commonRepo.WithByID(id))
|
||||
}
|
||||
sslSetting, _ := settingRepo.Get(settingRepo.WithByKey("SSL"))
|
||||
if sslSetting.Value == "enable" {
|
||||
sslID, _ := settingRepo.Get(settingRepo.WithByKey("SSLID"))
|
||||
idValue, _ := strconv.Atoi(sslID.Value)
|
||||
if idValue > 0 {
|
||||
oldSSL, _ := websiteSSLRepo.GetFirst(commonRepo.WithByID(uint(idValue)))
|
||||
if oldSSL.ID > 0 {
|
||||
return buserr.New("ErrDeleteWithPanelSSL")
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = websiteSSLRepo.DeleteBy(commonRepo.WithByID(id))
|
||||
}
|
||||
if len(names) > 0 {
|
||||
return buserr.WithName("ErrSSLCannotDelete", strings.Join(names, ","))
|
||||
@ -491,7 +425,7 @@ func (w WebsiteSSLService) SyncForRestart() error {
|
||||
if ssl.Status == constant.SSLApply {
|
||||
ssl.Status = constant.SystemRestart
|
||||
ssl.Message = "System restart causing interrupt"
|
||||
_ = websiteSSLRepo.Save(ssl)
|
||||
_ = websiteSSLRepo.Save(&ssl)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -750,7 +750,7 @@ func getWebsiteDomains(domains string, defaultPort int, websiteID uint) (domainM
|
||||
return
|
||||
}
|
||||
|
||||
func saveCertificateFile(websiteSSL model.WebsiteSSL, logger *log.Logger) {
|
||||
func saveCertificateFile(websiteSSL *model.WebsiteSSL, logger *log.Logger) {
|
||||
if websiteSSL.PushDir {
|
||||
fileOp := files.NewFileOp()
|
||||
var (
|
||||
|
@ -1,8 +1,10 @@
|
||||
package job
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/service"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/common"
|
||||
"time"
|
||||
@ -30,9 +32,25 @@ func (ssl *ssl) Run() {
|
||||
sub := expireDate.Sub(now)
|
||||
if sub.Hours() < 720 {
|
||||
global.LOG.Errorf("Update the SSL certificate for the [%s] domain", s.PrimaryDomain)
|
||||
if err := sslService.Renew(s.ID); err != nil {
|
||||
global.LOG.Errorf("Failed to update the SSL certificate for the [%s] domain , err:%s", s.PrimaryDomain, err.Error())
|
||||
continue
|
||||
if s.Provider == constant.SelfSigned {
|
||||
caService := service.NewIWebsiteCAService()
|
||||
if err := caService.ObtainSSL(request.WebsiteCAObtain{
|
||||
ID: s.CaID,
|
||||
SSLID: s.ID,
|
||||
Renew: true,
|
||||
Unit: "year",
|
||||
Time: 1,
|
||||
}); err != nil {
|
||||
global.LOG.Errorf("Failed to update the SSL certificate for the [%s] domain , err:%s", s.PrimaryDomain, err.Error())
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
if err := sslService.ObtainSSL(request.WebsiteSSLApply{
|
||||
ID: s.ID,
|
||||
}); err != nil {
|
||||
global.LOG.Errorf("Failed to update the SSL certificate for the [%s] domain , err:%s", s.PrimaryDomain, err.Error())
|
||||
continue
|
||||
}
|
||||
}
|
||||
global.LOG.Errorf("The SSL certificate for the [%s] domain has been successfully updated", s.PrimaryDomain)
|
||||
}
|
||||
|
@ -103,6 +103,8 @@ ApplySSLFailed: 'Application for [{{ .domain }}] certificate failed, {{.detail}}
|
||||
ApplySSLSuccess: 'Application for [{{ .domain }}] certificate successful! ! '
|
||||
DNSAccountName: 'DNS account [{{ .name }}] manufacturer [{{.type}}]'
|
||||
PushDirLog: 'Certificate pushed to directory [{{ .path }}] {{ .status }}'
|
||||
ErrDeleteCAWithSSL: "There is an issued certificate under the current organization and cannot be deleted"
|
||||
ErrDeleteWithPanelSSL: "Panel SSL configuration uses this certificate and cannot be deleted"
|
||||
|
||||
#mysql
|
||||
ErrUserIsExist: "The current user already exists. Please enter a new user"
|
||||
|
@ -103,6 +103,8 @@ ApplySSLFailed: '申請 [{{ .domain }}] 憑證失敗, {{.detail}} '
|
||||
ApplySSLSuccess: '申請 [{{ .domain }}] 憑證成功! ! '
|
||||
DNSAccountName: 'DNS 帳號 [{{ .name }}] 廠商 [{{.type}}]'
|
||||
PushDirLog: '憑證推送到目錄 [{{ .path }}] {{ .status }}'
|
||||
ErrDeleteCAWithSSL: "目前機構下存在已簽發證書,無法刪除"
|
||||
ErrDeleteWithPanelSSL: "面板 SSL 配置使用此證書,無法刪除"
|
||||
|
||||
|
||||
#mysql
|
||||
|
@ -103,6 +103,8 @@ ApplySSLFailed: '申请 [{{ .domain }}] 证书失败, {{.detail}} '
|
||||
ApplySSLSuccess: '申请 [{{ .domain }}] 证书成功!!'
|
||||
DNSAccountName: 'DNS 账号 [{{ .name }}] 厂商 [{{.type}}]'
|
||||
PushDirLog: '证书推送到目录 [{{ .path }}] {{ .status }}'
|
||||
ErrDeleteCAWithSSL: "当前机构下存在已签发证书,无法删除"
|
||||
ErrDeleteWithPanelSSL: "面板 SSL 配置使用此证书,无法删除"
|
||||
|
||||
#mysql
|
||||
ErrUserIsExist: "当前用户已存在,请重新输入"
|
||||
|
@ -27,7 +27,7 @@ var AddWebsiteCA = &gormigrate.Migration{
|
||||
}
|
||||
|
||||
var UpdateWebsiteSSL = &gormigrate.Migration{
|
||||
ID: "20231126-update-website-ssl",
|
||||
ID: "20231127-update-website-ssl",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.AutoMigrate(&model.WebsiteSSL{}); err != nil {
|
||||
return err
|
||||
|
@ -16,5 +16,6 @@ func (a *WebsiteDnsAccountRouter) InitWebsiteCARouter(Router *gin.RouterGroup) {
|
||||
groupRouter.POST("", baseApi.CreateWebsiteCA)
|
||||
groupRouter.POST("/del", baseApi.DeleteWebsiteCA)
|
||||
groupRouter.POST("/obtain", baseApi.ObtainWebsiteCA)
|
||||
groupRouter.POST("/renew", baseApi.RenewWebsiteCA)
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ func (a *WebsiteSSLRouter) InitWebsiteSSLRouter(Router *gin.RouterGroup) {
|
||||
baseApi := v1.ApiGroupApp.BaseApi
|
||||
{
|
||||
groupRouter.POST("/search", baseApi.PageWebsiteSSL)
|
||||
groupRouter.POST("/renew", baseApi.RenewWebsiteSSL)
|
||||
groupRouter.POST("", baseApi.CreateWebsiteSSL)
|
||||
groupRouter.POST("/resolve", baseApi.GetDNSResolve)
|
||||
groupRouter.POST("/del", baseApi.DeleteWebsiteSSL)
|
||||
|
@ -11119,7 +11119,7 @@ const docTemplate = `{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "自签 SSL 证书",
|
||||
"description": "续签 SSL 证书",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
@ -12930,57 +12930,6 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/websites/ssl/renew": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "重置网站 ssl",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Website SSL"
|
||||
],
|
||||
"summary": "Reset website ssl",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.WebsiteSSLRenew"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [
|
||||
{
|
||||
"db": "website_ssls",
|
||||
"input_column": "id",
|
||||
"input_value": "SSLId",
|
||||
"isList": false,
|
||||
"output_column": "primary_domain",
|
||||
"output_value": "domain"
|
||||
}
|
||||
],
|
||||
"bodyKeys": [
|
||||
"SSLId"
|
||||
],
|
||||
"formatEN": "Renew ssl [domain]",
|
||||
"formatZH": "重置 ssl [domain]",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/websites/ssl/resolve": {
|
||||
"post": {
|
||||
"security": [
|
||||
@ -17517,6 +17466,9 @@ const docTemplate = `{
|
||||
"autoRenew": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"caId": {
|
||||
"type": "integer"
|
||||
},
|
||||
"certURL": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -18979,6 +18931,9 @@ const docTemplate = `{
|
||||
"unit"
|
||||
],
|
||||
"properties": {
|
||||
"autoRenew": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"dir": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -19002,6 +18957,12 @@ const docTemplate = `{
|
||||
"pushDir": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"renew": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sslID": {
|
||||
"type": "integer"
|
||||
},
|
||||
"time": {
|
||||
"type": "integer"
|
||||
},
|
||||
@ -19537,17 +19498,6 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.WebsiteSSLRenew": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"SSLId"
|
||||
],
|
||||
"properties": {
|
||||
"SSLId": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.WebsiteSSLSearch": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
@ -11112,7 +11112,7 @@
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "自签 SSL 证书",
|
||||
"description": "续签 SSL 证书",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
@ -12923,57 +12923,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/websites/ssl/renew": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "重置网站 ssl",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Website SSL"
|
||||
],
|
||||
"summary": "Reset website ssl",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.WebsiteSSLRenew"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [
|
||||
{
|
||||
"db": "website_ssls",
|
||||
"input_column": "id",
|
||||
"input_value": "SSLId",
|
||||
"isList": false,
|
||||
"output_column": "primary_domain",
|
||||
"output_value": "domain"
|
||||
}
|
||||
],
|
||||
"bodyKeys": [
|
||||
"SSLId"
|
||||
],
|
||||
"formatEN": "Renew ssl [domain]",
|
||||
"formatZH": "重置 ssl [domain]",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/websites/ssl/resolve": {
|
||||
"post": {
|
||||
"security": [
|
||||
@ -17510,6 +17459,9 @@
|
||||
"autoRenew": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"caId": {
|
||||
"type": "integer"
|
||||
},
|
||||
"certURL": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -18972,6 +18924,9 @@
|
||||
"unit"
|
||||
],
|
||||
"properties": {
|
||||
"autoRenew": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"dir": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -18995,6 +18950,12 @@
|
||||
"pushDir": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"renew": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sslID": {
|
||||
"type": "integer"
|
||||
},
|
||||
"time": {
|
||||
"type": "integer"
|
||||
},
|
||||
@ -19530,17 +19491,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.WebsiteSSLRenew": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"SSLId"
|
||||
],
|
||||
"properties": {
|
||||
"SSLId": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.WebsiteSSLSearch": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
@ -2792,6 +2792,8 @@ definitions:
|
||||
type: integer
|
||||
autoRenew:
|
||||
type: boolean
|
||||
caId:
|
||||
type: integer
|
||||
certURL:
|
||||
type: string
|
||||
createdAt:
|
||||
@ -3770,6 +3772,8 @@ definitions:
|
||||
type: object
|
||||
request.WebsiteCAObtain:
|
||||
properties:
|
||||
autoRenew:
|
||||
type: boolean
|
||||
dir:
|
||||
type: string
|
||||
domains:
|
||||
@ -3787,6 +3791,10 @@ definitions:
|
||||
type: string
|
||||
pushDir:
|
||||
type: boolean
|
||||
renew:
|
||||
type: boolean
|
||||
sslID:
|
||||
type: integer
|
||||
time:
|
||||
type: integer
|
||||
unit:
|
||||
@ -4152,13 +4160,6 @@ definitions:
|
||||
- primaryDomain
|
||||
- provider
|
||||
type: object
|
||||
request.WebsiteSSLRenew:
|
||||
properties:
|
||||
SSLId:
|
||||
type: integer
|
||||
required:
|
||||
- SSLId
|
||||
type: object
|
||||
request.WebsiteSSLSearch:
|
||||
properties:
|
||||
acmeAccountID:
|
||||
@ -11773,7 +11774,7 @@ paths:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 自签 SSL 证书
|
||||
description: 续签 SSL 证书
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
@ -12904,39 +12905,6 @@ paths:
|
||||
formatEN: apply ssl [domain]
|
||||
formatZH: 申请证书 [domain]
|
||||
paramKeys: []
|
||||
/websites/ssl/renew:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 重置网站 ssl
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/request.WebsiteSSLRenew'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Reset website ssl
|
||||
tags:
|
||||
- Website SSL
|
||||
x-panel-log:
|
||||
BeforeFunctions:
|
||||
- db: website_ssls
|
||||
input_column: id
|
||||
input_value: SSLId
|
||||
isList: false
|
||||
output_column: primary_domain
|
||||
output_value: domain
|
||||
bodyKeys:
|
||||
- SSLId
|
||||
formatEN: Renew ssl [domain]
|
||||
formatZH: 重置 ssl [domain]
|
||||
paramKeys: []
|
||||
/websites/ssl/resolve:
|
||||
post:
|
||||
consumes:
|
||||
|
@ -165,10 +165,10 @@ export namespace Website {
|
||||
autoRenew: boolean;
|
||||
acmeAccountId?: number;
|
||||
status: string;
|
||||
domains: string;
|
||||
}
|
||||
|
||||
export interface SSLDTO extends SSL {
|
||||
domains: string;
|
||||
logPath: string;
|
||||
}
|
||||
|
||||
@ -485,4 +485,8 @@ export namespace Website {
|
||||
pushDir: boolean;
|
||||
dir: string;
|
||||
}
|
||||
|
||||
export interface RenewSSLByCA {
|
||||
SSLID: number;
|
||||
}
|
||||
}
|
||||
|
@ -124,10 +124,6 @@ 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);
|
||||
};
|
||||
|
||||
export const UpdateSSL = (req: Website.SSLUpdate) => {
|
||||
return http.post<any>(`/websites/ssl/update`, req);
|
||||
};
|
||||
@ -263,3 +259,7 @@ export const ObtainSSLByCA = (req: Website.SSLObtainByCA) => {
|
||||
export const DeleteCA = (req: Website.DelReq) => {
|
||||
return http.post<any>(`/websites/ca/del`, req);
|
||||
};
|
||||
|
||||
export const RenewSSLByCA = (req: Website.RenewSSLByCA) => {
|
||||
return http.post<any>(`/websites/ca/renew`, req);
|
||||
};
|
||||
|
@ -37,6 +37,7 @@ interface LogProps {
|
||||
type: string;
|
||||
style: string;
|
||||
name: string;
|
||||
tail: boolean;
|
||||
}
|
||||
|
||||
const open = ref(false);
|
||||
|
@ -46,6 +46,7 @@ interface LogProps {
|
||||
id?: number;
|
||||
type: string;
|
||||
name?: string;
|
||||
tail?: boolean;
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
@ -55,6 +56,7 @@ const props = defineProps({
|
||||
id: 0,
|
||||
type: '',
|
||||
name: '',
|
||||
tail: false,
|
||||
}),
|
||||
},
|
||||
style: {
|
||||
@ -224,9 +226,16 @@ function isScrolledToBottom(element: HTMLElement): boolean {
|
||||
}
|
||||
|
||||
const init = () => {
|
||||
tailLog.value = false;
|
||||
|
||||
if (props.config.tail) {
|
||||
tailLog.value = props.config.tail;
|
||||
} else {
|
||||
tailLog.value = false;
|
||||
}
|
||||
if (tailLog.value) {
|
||||
changeTail(false);
|
||||
}
|
||||
getContent();
|
||||
|
||||
nextTick(() => {
|
||||
if (scrollerElement.value) {
|
||||
scrollerElement.value.addEventListener('scroll', function () {
|
||||
|
@ -1809,12 +1809,12 @@ const message = {
|
||||
key: 'Private Key',
|
||||
startDate: 'Effective Time',
|
||||
organization: 'issuing organization',
|
||||
renewConfirm: 'Are you sure to renew? ',
|
||||
renewConfirm: 'Are you sure you want to apply for a certificate for domain name {0}? ',
|
||||
autoRenew: 'Automatic renewal',
|
||||
autoRenewHelper: 'Automatic renewal 7 days from the expiration time',
|
||||
renewSuccess: 'Renewal succeeded',
|
||||
autoRenewHelper: 'Automatically renew 30 days before expiration',
|
||||
renewSuccess: 'Renewal successful',
|
||||
renewWebsite:
|
||||
'This certificate has been associated with the following websites, and the renewal will be applied to these websites simultaneously',
|
||||
'This certificate has been associated with the following websites, and the application will be applied to these websites simultaneously',
|
||||
createAcme: 'Create Account',
|
||||
acmeHelper: 'Acme account is used to apply for free certificates',
|
||||
upload: 'Upload Certificate',
|
||||
|
@ -1698,11 +1698,11 @@ const message = {
|
||||
key: '私鑰',
|
||||
startDate: '生效時間',
|
||||
organization: '簽發機構',
|
||||
renewConfirm: '是否確定續簽?',
|
||||
renewConfirm: '是否確定給網域名稱 {0} 申請證書? ',
|
||||
autoRenew: '自動續簽',
|
||||
autoRenewHelper: '距離到期時間7天自動續簽',
|
||||
autoRenewHelper: '距離到期時間30天自動續約',
|
||||
renewSuccess: '續簽成功',
|
||||
renewWebsite: '該證書已經和以下網站關聯,續簽會同步應用到這些網站',
|
||||
renewWebsite: '該證書已經和以下網站關聯,申請會同步應用到這些網站',
|
||||
createAcme: '創建賬戶',
|
||||
acmeHelper: 'Acme 賬戶用於申請免費證書',
|
||||
upload: '上傳證書',
|
||||
|
@ -1698,11 +1698,11 @@ const message = {
|
||||
key: '私钥',
|
||||
startDate: '生效时间',
|
||||
organization: '签发机构',
|
||||
renewConfirm: '是否确定续签?',
|
||||
renewConfirm: '是否确定给域名 {0} 申请证书?',
|
||||
autoRenew: '自动续签',
|
||||
autoRenewHelper: '距离到期时间7天自动续签',
|
||||
autoRenewHelper: '距离到期时间30天自动续签',
|
||||
renewSuccess: '续签成功',
|
||||
renewWebsite: '该证书已经和以下网站关联,续签会同步应用到这些网站',
|
||||
renewWebsite: '该证书已经和以下网站关联,申请会同步应用到这些网站',
|
||||
createAcme: '创建账户',
|
||||
acmeHelper: 'Acme 账户用于申请免费证书',
|
||||
upload: '上传证书',
|
||||
|
@ -47,7 +47,7 @@ const open = ref(false);
|
||||
const loading = ref(false);
|
||||
const dnsResolve = ref<Website.DNSResolve[]>([]);
|
||||
const sslID = ref(0);
|
||||
const em = defineEmits(['close']);
|
||||
const em = defineEmits(['close', 'submit']);
|
||||
const handleClose = () => {
|
||||
open.value = false;
|
||||
em('close', false);
|
||||
@ -83,6 +83,7 @@ const submit = () => {
|
||||
.then(() => {
|
||||
MsgSuccess(i18n.global.t('ssl.applyStart'));
|
||||
handleClose();
|
||||
em('submit', sslID.value);
|
||||
})
|
||||
.finally(() => {});
|
||||
};
|
||||
|
@ -37,6 +37,9 @@
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="''" prop="autoRenew">
|
||||
<el-checkbox v-model="obtain.autoRenew" :label="$t('ssl.autoRenew')" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="''" prop="pushDir">
|
||||
<el-checkbox v-model="obtain.pushDir" :label="$t('ssl.pushDir')" />
|
||||
</el-form-item>
|
||||
@ -93,6 +96,7 @@ const initData = () => ({
|
||||
unit: 'day',
|
||||
pushDir: false,
|
||||
dir: '',
|
||||
autoRenew: true,
|
||||
});
|
||||
const obtain = ref(initData());
|
||||
|
||||
|
@ -96,7 +96,9 @@
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('website.log')" width="100px">
|
||||
<template #default="{ row }">
|
||||
<el-button @click="openLog(row)" link type="primary">{{ $t('website.check') }}</el-button>
|
||||
<el-button @click="openLog(row.id)" link type="primary">
|
||||
{{ $t('website.check') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
@ -108,11 +110,7 @@
|
||||
<el-table-column :label="$t('ssl.autoRenew')" fix width="100px">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
:disabled="
|
||||
row.provider === 'dnsManual' ||
|
||||
row.provider === 'manual' ||
|
||||
row.provider === 'selfSigned'
|
||||
"
|
||||
:disabled="row.provider === 'dnsManual' || row.provider === 'manual'"
|
||||
v-model="row.autoRenew"
|
||||
@change="updateConfig(row)"
|
||||
/>
|
||||
@ -138,10 +136,11 @@
|
||||
<Create ref="sslCreateRef" @close="search()"></Create>
|
||||
<Detail ref="detailRef"></Detail>
|
||||
<SSLUpload ref="sslUploadRef" @close="search()"></SSLUpload>
|
||||
<Apply ref="applyRef" @search="search" />
|
||||
<Apply ref="applyRef" @search="search" @submit="openLog" />
|
||||
<OpDialog ref="opRef" @search="search" @cancel="search" />
|
||||
<Log ref="logRef" @close="search()" />
|
||||
<CA ref="caRef" @close="search()" />
|
||||
<Obtain ref="obtainRef" @close="search()" @submit="openLog" />
|
||||
</LayoutContent>
|
||||
</div>
|
||||
</template>
|
||||
@ -149,7 +148,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, reactive, ref, computed } from 'vue';
|
||||
import OpDialog from '@/components/del-dialog/index.vue';
|
||||
import { DeleteSSL, ObtainSSL, SearchSSL, UpdateSSL } from '@/api/modules/website';
|
||||
import { DeleteSSL, SearchSSL, UpdateSSL } from '@/api/modules/website';
|
||||
import DnsAccount from './dns-account/index.vue';
|
||||
import AcmeAccount from './acme-account/index.vue';
|
||||
import CA from './ca/index.vue';
|
||||
@ -163,6 +162,7 @@ import { GlobalStore } from '@/store';
|
||||
import SSLUpload from './upload/index.vue';
|
||||
import Apply from './apply/index.vue';
|
||||
import Log from '@/components/log-dialog/index.vue';
|
||||
import Obtain from './obtain/index.vue';
|
||||
|
||||
const globalStore = GlobalStore();
|
||||
const paginationConfig = reactive({
|
||||
@ -183,6 +183,7 @@ const applyRef = ref();
|
||||
const logRef = ref();
|
||||
const caRef = ref();
|
||||
let selects = ref<any>([]);
|
||||
const obtainRef = ref();
|
||||
|
||||
const routerButton = [
|
||||
{
|
||||
@ -204,7 +205,7 @@ const buttons = [
|
||||
{
|
||||
label: i18n.global.t('ssl.apply'),
|
||||
disabled: function (row: Website.SSLDTO) {
|
||||
return row.status === 'applying' || row.provider === 'manual' || row.provider === 'selfSigned';
|
||||
return row.status === 'applying' || row.provider === 'manual';
|
||||
},
|
||||
click: function (row: Website.SSLDTO) {
|
||||
if (row.provider === 'dnsManual') {
|
||||
@ -268,23 +269,16 @@ const openUpload = () => {
|
||||
const openDetail = (id: number) => {
|
||||
detailRef.value.acceptParams(id);
|
||||
};
|
||||
const openLog = (row: Website.SSLDTO) => {
|
||||
logRef.value.acceptParams({ id: row.id, type: 'ssl' });
|
||||
const openLog = (id: number) => {
|
||||
logRef.value.acceptParams({ id: id, type: 'ssl', tail: true });
|
||||
};
|
||||
|
||||
const openCA = () => {
|
||||
caRef.value.acceptParams();
|
||||
};
|
||||
|
||||
const applySSL = (row: Website.SSLDTO) => {
|
||||
loading.value = true;
|
||||
ObtainSSL({ ID: row.id })
|
||||
.then(() => {
|
||||
MsgSuccess(i18n.global.t('ssl.applyStart'));
|
||||
search();
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
obtainRef.value.acceptParams({ ssl: row });
|
||||
};
|
||||
|
||||
const deleteSSL = async (row: any) => {
|
||||
|
@ -1,26 +1,26 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="open"
|
||||
:title="$t('website.renewSSL')"
|
||||
:title="$t('ssl.apply')"
|
||||
:destroy-on-close="true"
|
||||
:close-on-click-modal="false"
|
||||
width="30%"
|
||||
:before-close="handleClose"
|
||||
>
|
||||
<div style="text-align: center" v-loading="loading">
|
||||
<div v-if="websites.length > 0">
|
||||
<div class="text-center" v-loading="loading">
|
||||
<div v-if="ssl.websites && ssl.websites.length > 0">
|
||||
<span>{{ $t('ssl.renewWebsite') }}</span>
|
||||
<div>
|
||||
<br />
|
||||
<span>
|
||||
<span v-for="(website, index) in websites" :key="index">
|
||||
<span v-for="(website, index) in ssl.websites" :key="index">
|
||||
<el-tag>{{ website.primaryDomain }}</el-tag>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<br />
|
||||
</div>
|
||||
<span>{{ $t('ssl.renewConfirm') }}</span>
|
||||
<span>{{ $t('ssl.renewConfirm', [ssl.primaryDomain]) }}</span>
|
||||
</div>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
@ -35,44 +35,42 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Website } from '@/api/interface/website';
|
||||
import { RenewSSL } from '@/api/modules/website';
|
||||
import { ObtainSSL, RenewSSLByCA } from '@/api/modules/website';
|
||||
import i18n from '@/lang';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { reactive, ref } from 'vue';
|
||||
import { ref } from 'vue';
|
||||
|
||||
interface RenewProps {
|
||||
id: number;
|
||||
websites: Website.Website[];
|
||||
ssl: Website.SSL;
|
||||
}
|
||||
|
||||
let open = ref(false);
|
||||
let loading = ref(false);
|
||||
let renewReq = reactive({
|
||||
SSLId: 0,
|
||||
});
|
||||
const em = defineEmits(['close']);
|
||||
const open = ref(false);
|
||||
const loading = ref(false);
|
||||
const em = defineEmits(['close', 'submit']);
|
||||
const handleClose = () => {
|
||||
open.value = false;
|
||||
em('close', false);
|
||||
};
|
||||
const websites = ref([]);
|
||||
const ssl = ref();
|
||||
|
||||
const acceptParams = async (props: RenewProps) => {
|
||||
renewReq.SSLId = Number(props.id);
|
||||
websites.value = props.websites;
|
||||
ssl.value = props.ssl;
|
||||
open.value = true;
|
||||
};
|
||||
|
||||
const submit = () => {
|
||||
const submit = async () => {
|
||||
loading.value = true;
|
||||
RenewSSL(renewReq)
|
||||
.then(() => {
|
||||
handleClose();
|
||||
MsgSuccess(i18n.global.t('ssl.renewSuccess'));
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
try {
|
||||
if (ssl.value.provider == 'selfSigned') {
|
||||
await RenewSSLByCA({ SSLID: ssl.value.id });
|
||||
} else {
|
||||
await ObtainSSL({ ID: ssl.value.id });
|
||||
}
|
||||
handleClose();
|
||||
MsgSuccess(i18n.global.t('ssl.applyStart'));
|
||||
loading.value = false;
|
||||
em('submit', ssl.value.id);
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
defineExpose({
|
Loading…
Reference in New Issue
Block a user