mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 10:25:52 +02:00
refactor(cert): introducing new management page
1. User can now view the latest renew logs of the certain certificate. 2. Add manually renew button in certificate modify page for managed certificate (auto cert)
This commit is contained in:
parent
7c47f08a72
commit
ac68fd05c9
36 changed files with 1908 additions and 1286 deletions
|
@ -3,48 +3,31 @@ package certificate
|
|||
import (
|
||||
"github.com/0xJacky/Nginx-UI/api"
|
||||
"github.com/0xJacky/Nginx-UI/api/cosy"
|
||||
"github.com/0xJacky/Nginx-UI/api/sites"
|
||||
"github.com/0xJacky/Nginx-UI/internal/cert"
|
||||
"github.com/0xJacky/Nginx-UI/model"
|
||||
"github.com/0xJacky/Nginx-UI/query"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/spf13/cast"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func GetCertList(c *gin.Context) {
|
||||
cosy.Core[model.Cert](c).SetFussy("name", "domain").PagingList()
|
||||
type APICertificate struct {
|
||||
*model.Cert
|
||||
SSLCertificate string `json:"ssl_certificate,omitempty"`
|
||||
SSLCertificateKey string `json:"ssl_certificate_key,omitempty"`
|
||||
CertificateInfo *cert.Info `json:"certificate_info,omitempty"`
|
||||
}
|
||||
|
||||
func getCert(c *gin.Context, certModel *model.Cert) {
|
||||
type resp struct {
|
||||
*model.Cert
|
||||
SSLCertificate string `json:"ssl_certificate"`
|
||||
SSLCertificateKey string `json:"ssl_certificate_key"`
|
||||
CertificateInfo *sites.CertificateInfo `json:"certificate_info,omitempty"`
|
||||
}
|
||||
|
||||
func Transformer(certModel *model.Cert) (certificate *APICertificate) {
|
||||
var sslCertificationBytes, sslCertificationKeyBytes []byte
|
||||
var certificateInfo *sites.CertificateInfo
|
||||
var certificateInfo *cert.Info
|
||||
if certModel.SSLCertificatePath != "" {
|
||||
if _, err := os.Stat(certModel.SSLCertificatePath); err == nil {
|
||||
sslCertificationBytes, _ = os.ReadFile(certModel.SSLCertificatePath)
|
||||
}
|
||||
|
||||
pubKey, err := cert.GetCertInfo(certModel.SSLCertificatePath)
|
||||
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
certificateInfo = &sites.CertificateInfo{
|
||||
SubjectName: pubKey.Subject.CommonName,
|
||||
IssuerName: pubKey.Issuer.CommonName,
|
||||
NotAfter: pubKey.NotAfter,
|
||||
NotBefore: pubKey.NotBefore,
|
||||
}
|
||||
certificateInfo, _ = cert.GetCertInfo(certModel.SSLCertificatePath)
|
||||
}
|
||||
|
||||
if certModel.SSLCertificateKeyPath != "" {
|
||||
|
@ -53,23 +36,37 @@ func getCert(c *gin.Context, certModel *model.Cert) {
|
|||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, resp{
|
||||
certModel,
|
||||
string(sslCertificationBytes),
|
||||
string(sslCertificationKeyBytes),
|
||||
certificateInfo,
|
||||
})
|
||||
return &APICertificate{
|
||||
Cert: certModel,
|
||||
SSLCertificate: string(sslCertificationBytes),
|
||||
SSLCertificateKey: string(sslCertificationKeyBytes),
|
||||
CertificateInfo: certificateInfo,
|
||||
}
|
||||
}
|
||||
|
||||
func GetCertList(c *gin.Context) {
|
||||
cosy.Core[model.Cert](c).SetFussy("name", "domain").SetTransformer(func(m *model.Cert) any {
|
||||
|
||||
info, _ := cert.GetCertInfo(m.SSLCertificatePath)
|
||||
|
||||
return APICertificate{
|
||||
Cert: m,
|
||||
CertificateInfo: info,
|
||||
}
|
||||
}).PagingList()
|
||||
}
|
||||
|
||||
func GetCert(c *gin.Context) {
|
||||
certModel, err := model.FirstCertByID(cast.ToInt(c.Param("id")))
|
||||
q := query.Cert
|
||||
|
||||
certModel, err := q.FirstByID(cast.ToInt(c.Param("id")))
|
||||
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
getCert(c, &certModel)
|
||||
c.JSON(http.StatusOK, Transformer(certModel))
|
||||
}
|
||||
|
||||
func AddCert(c *gin.Context) {
|
||||
|
@ -77,8 +74,10 @@ func AddCert(c *gin.Context) {
|
|||
Name string `json:"name"`
|
||||
SSLCertificatePath string `json:"ssl_certificate_path" binding:"required"`
|
||||
SSLCertificateKeyPath string `json:"ssl_certificate_key_path" binding:"required"`
|
||||
SSLCertification string `json:"ssl_certification"`
|
||||
SSLCertificationKey string `json:"ssl_certification_key"`
|
||||
SSLCertificate string `json:"ssl_certificate"`
|
||||
SSLCertificateKey string `json:"ssl_certificate_key"`
|
||||
ChallengeMethod string `json:"challenge_method"`
|
||||
DnsCredentialID int `json:"dns_credential_id"`
|
||||
}
|
||||
if !api.BindAndValid(c, &json) {
|
||||
return
|
||||
|
@ -87,6 +86,8 @@ func AddCert(c *gin.Context) {
|
|||
Name: json.Name,
|
||||
SSLCertificatePath: json.SSLCertificatePath,
|
||||
SSLCertificateKeyPath: json.SSLCertificateKeyPath,
|
||||
ChallengeMethod: json.ChallengeMethod,
|
||||
DnsCredentialID: json.DnsCredentialID,
|
||||
}
|
||||
|
||||
err := certModel.Insert()
|
||||
|
@ -96,35 +97,21 @@ func AddCert(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
err = os.MkdirAll(filepath.Dir(json.SSLCertificatePath), 0644)
|
||||
content := &cert.Content{
|
||||
SSLCertificatePath: json.SSLCertificatePath,
|
||||
SSLCertificateKeyPath: json.SSLCertificateKeyPath,
|
||||
SSLCertificate: json.SSLCertificate,
|
||||
SSLCertificateKey: json.SSLCertificateKey,
|
||||
}
|
||||
|
||||
err = content.WriteFile()
|
||||
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = os.MkdirAll(filepath.Dir(json.SSLCertificateKeyPath), 0644)
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
if json.SSLCertification != "" {
|
||||
err = os.WriteFile(json.SSLCertificatePath, []byte(json.SSLCertification), 0644)
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if json.SSLCertificationKey != "" {
|
||||
err = os.WriteFile(json.SSLCertificateKeyPath, []byte(json.SSLCertificationKey), 0644)
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
getCert(c, certModel)
|
||||
c.JSON(http.StatusOK, Transformer(certModel))
|
||||
}
|
||||
|
||||
func ModifyCert(c *gin.Context) {
|
||||
|
@ -136,13 +123,17 @@ func ModifyCert(c *gin.Context) {
|
|||
SSLCertificateKeyPath string `json:"ssl_certificate_key_path" binding:"required"`
|
||||
SSLCertificate string `json:"ssl_certificate"`
|
||||
SSLCertificateKey string `json:"ssl_certificate_key"`
|
||||
ChallengeMethod string `json:"challenge_method"`
|
||||
DnsCredentialID int `json:"dns_credential_id"`
|
||||
}
|
||||
|
||||
if !api.BindAndValid(c, &json) {
|
||||
return
|
||||
}
|
||||
|
||||
certModel, err := model.FirstCertByID(id)
|
||||
q := query.Cert
|
||||
|
||||
certModel, err := q.FirstByID(id)
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
|
@ -152,6 +143,8 @@ func ModifyCert(c *gin.Context) {
|
|||
Name: json.Name,
|
||||
SSLCertificatePath: json.SSLCertificatePath,
|
||||
SSLCertificateKeyPath: json.SSLCertificateKeyPath,
|
||||
ChallengeMethod: json.ChallengeMethod,
|
||||
DnsCredentialID: json.DnsCredentialID,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
@ -159,34 +152,20 @@ func ModifyCert(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
err = os.MkdirAll(filepath.Dir(json.SSLCertificatePath), 0644)
|
||||
content := &cert.Content{
|
||||
SSLCertificatePath: json.SSLCertificatePath,
|
||||
SSLCertificateKeyPath: json.SSLCertificateKeyPath,
|
||||
SSLCertificate: json.SSLCertificate,
|
||||
SSLCertificateKey: json.SSLCertificateKey,
|
||||
}
|
||||
|
||||
err = content.WriteFile()
|
||||
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = os.MkdirAll(filepath.Dir(json.SSLCertificateKeyPath), 0644)
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
if json.SSLCertificate != "" {
|
||||
err = os.WriteFile(json.SSLCertificatePath, []byte(json.SSLCertificate), 0644)
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if json.SSLCertificateKeyPath != "" {
|
||||
err = os.WriteFile(json.SSLCertificateKeyPath, []byte(json.SSLCertificateKey), 0644)
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
GetCert(c)
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ type IssueCertResponse struct {
|
|||
SSLCertificateKey string `json:"ssl_certificate_key,omitempty"`
|
||||
}
|
||||
|
||||
func handleIssueCertLogChan(conn *websocket.Conn, logChan chan string) {
|
||||
func handleIssueCertLogChan(conn *websocket.Conn, log *cert.Logger, logChan chan string) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
logger.Error(err)
|
||||
|
@ -33,6 +33,8 @@ func handleIssueCertLogChan(conn *websocket.Conn, logChan chan string) {
|
|||
|
||||
for logString := range logChan {
|
||||
|
||||
log.Info(logString)
|
||||
|
||||
err := conn.WriteJSON(IssueCertResponse{
|
||||
Status: Info,
|
||||
Message: logString,
|
||||
|
@ -42,7 +44,6 @@ func handleIssueCertLogChan(conn *websocket.Conn, logChan chan string) {
|
|||
logger.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,9 +66,9 @@ func IssueCert(c *gin.Context) {
|
|||
}(ws)
|
||||
|
||||
// read
|
||||
buffer := &cert.ConfigPayload{}
|
||||
payload := &cert.ConfigPayload{}
|
||||
|
||||
err = ws.ReadJSON(buffer)
|
||||
err = ws.ReadJSON(payload)
|
||||
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
|
@ -84,15 +85,20 @@ func IssueCert(c *gin.Context) {
|
|||
logChan := make(chan string, 1)
|
||||
errChan := make(chan error, 1)
|
||||
|
||||
go cert.IssueCert(buffer, logChan, errChan)
|
||||
log := &cert.Logger{}
|
||||
log.SetCertModel(&certModel)
|
||||
|
||||
go handleIssueCertLogChan(ws, logChan)
|
||||
go cert.IssueCert(payload, logChan, errChan)
|
||||
|
||||
go handleIssueCertLogChan(ws, log, logChan)
|
||||
|
||||
// block, until errChan closes
|
||||
for err = range errChan {
|
||||
errLog := &cert.AutoCertErrorLog{}
|
||||
errLog.SetCertModel(&certModel)
|
||||
errLog.Exit("issue cert", err)
|
||||
|
||||
log.Error(err)
|
||||
|
||||
// Save logs to db
|
||||
log.Exit()
|
||||
|
||||
err = ws.WriteJSON(IssueCertResponse{
|
||||
Status: Error,
|
||||
|
@ -107,12 +113,12 @@ func IssueCert(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
certDirName := strings.Join(buffer.ServerName, "_")
|
||||
certDirName := strings.Join(payload.ServerName, "_")
|
||||
sslCertificatePath := nginx.GetConfPath("ssl", certDirName, "fullchain.cer")
|
||||
sslCertificateKeyPath := nginx.GetConfPath("ssl", certDirName, "private.key")
|
||||
|
||||
err = certModel.Updates(&model.Cert{
|
||||
Domains: buffer.ServerName,
|
||||
Domains: payload.ServerName,
|
||||
SSLCertificatePath: sslCertificatePath,
|
||||
SSLCertificateKeyPath: sslCertificateKeyPath,
|
||||
})
|
||||
|
@ -126,7 +132,8 @@ func IssueCert(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
certModel.ClearLog()
|
||||
// Save logs to db
|
||||
log.Exit()
|
||||
|
||||
err = ws.WriteJSON(IssueCertResponse{
|
||||
Status: Success,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue