2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 06:47:20 +08:00

feat: 添加用于更新证书的接口

This commit is contained in:
2025-05-15 04:06:19 +08:00
parent f39cceda18
commit 16f31120f5
9 changed files with 118 additions and 10 deletions

View File

@@ -37,6 +37,7 @@ type SettingRepo interface {
Set(key SettingKey, value string) error
SetSlice(key SettingKey, value []string) error
Delete(key SettingKey) error
GetPanelSetting() (*request.PanelSetting, error)
UpdatePanelSetting(req *request.PanelSetting) (bool, error)
GetPanel() (*request.SettingPanel, error)
UpdatePanel(req *request.SettingPanel) (bool, error)
UpdateCert(req *request.SettingCert) error
}

View File

@@ -35,5 +35,6 @@ type WebsiteRepo interface {
UpdateRemark(id uint, remark string) error
ResetConfig(id uint) error
UpdateStatus(id uint, status bool) error
UpdateCert(req *request.WebsiteUpdateCert) error
ObtainCert(ctx context.Context, id uint) error
}

View File

@@ -197,7 +197,7 @@ func (r *settingRepo) Delete(key biz.SettingKey) error {
return nil
}
func (r *settingRepo) GetPanelSetting() (*request.PanelSetting, error) {
func (r *settingRepo) GetPanel() (*request.SettingPanel, error) {
name, err := r.Get(biz.SettingKeyName)
if err != nil {
return nil, err
@@ -232,7 +232,7 @@ func (r *settingRepo) GetPanelSetting() (*request.PanelSetting, error) {
return nil, err
}
return &request.PanelSetting{
return &request.SettingPanel{
Name: name,
Channel: channel,
Locale: r.conf.String("app.locale"),
@@ -252,7 +252,7 @@ func (r *settingRepo) GetPanelSetting() (*request.PanelSetting, error) {
}, nil
}
func (r *settingRepo) UpdatePanelSetting(req *request.PanelSetting) (bool, error) {
func (r *settingRepo) UpdatePanel(req *request.SettingPanel) (bool, error) {
if err := r.Set(biz.SettingKeyName, req.Name); err != nil {
return false, err
}
@@ -350,3 +350,24 @@ func (r *settingRepo) UpdatePanelSetting(req *request.PanelSetting) (bool, error
return restartFlag, nil
}
func (r *settingRepo) UpdateCert(req *request.SettingCert) error {
if r.task.HasRunningTask() {
return errors.New(r.t.Get("background task is running, modifying some settings is prohibited, please try again later"))
}
if _, err := cert.ParseCert(req.Cert); err != nil {
return errors.New(r.t.Get("failed to parse certificate: %v", err))
}
if _, err := cert.ParseKey(req.Key); err != nil {
return errors.New(r.t.Get("failed to parse private key: %v", err))
}
if err := io.Write(filepath.Join(app.Root, "panel/storage/cert.pem"), req.Cert, 0644); err != nil {
return err
}
if err := io.Write(filepath.Join(app.Root, "panel/storage/cert.key"), req.Key, 0644); err != nil {
return err
}
return nil
}

View File

@@ -469,6 +469,12 @@ func (r *websiteRepo) Update(req *request.WebsiteUpdate) error {
}
website.Https = req.HTTPS
if req.HTTPS {
if _, err = cert.ParseCert(req.SSLCertificate); err != nil {
return errors.New(r.t.Get("failed to parse certificate: %v", err))
}
if _, err = cert.ParseKey(req.SSLCertificateKey); err != nil {
return errors.New(r.t.Get("failed to parse private key: %v", err))
}
if err = p.SetHTTPS(certPath, keyPath); err != nil {
return err
}
@@ -746,6 +752,38 @@ func (r *websiteRepo) UpdateStatus(id uint, status bool) error {
return nil
}
func (r *websiteRepo) UpdateCert(req *request.WebsiteUpdateCert) error {
website := new(biz.Website)
if err := r.db.Where("name", req.Name).First(&website).Error; err != nil {
return err
}
if _, err := cert.ParseCert(req.Cert); err != nil {
return errors.New(r.t.Get("failed to parse certificate: %v", err))
}
if _, err := cert.ParseKey(req.Key); err != nil {
return errors.New(r.t.Get("failed to parse private key: %v", err))
}
certPath := filepath.Join(app.Root, "server/vhost/cert", website.Name+".pem")
keyPath := filepath.Join(app.Root, "server/vhost/cert", website.Name+".key")
if err := io.Write(certPath, req.Cert, 0644); err != nil {
return err
}
if err := io.Write(keyPath, req.Key, 0644); err != nil {
return err
}
if website.Https {
if err := systemctl.Reload("nginx"); err != nil {
_, err = shell.Execf("nginx -t")
return err
}
}
return nil
}
func (r *websiteRepo) ObtainCert(ctx context.Context, id uint) error {
website, err := r.Get(id)
if err != nil {

View File

@@ -2,7 +2,7 @@ package request
import "net/http"
type PanelSetting struct {
type SettingPanel struct {
Name string `json:"name" validate:"required"`
Channel string `json:"channel" validate:"required|in:stable,beta"`
Locale string `json:"locale" validate:"required"`
@@ -22,10 +22,15 @@ type PanelSetting struct {
Key string `json:"key" validate:"required"`
}
func (r *PanelSetting) Rules(_ *http.Request) map[string]string {
func (r *SettingPanel) Rules(_ *http.Request) map[string]string {
return map[string]string{
"BindDomain.*": "required",
"BindIP.*": "required|ip",
"BindUA.*": "required",
}
}
type SettingCert struct {
Cert string `json:"cert" validate:"required"`
Key string `json:"key" validate:"required"`
}

View File

@@ -55,3 +55,9 @@ type WebsiteUpdateStatus struct {
ID uint `json:"id" form:"id" validate:"required|exists:websites,id"`
Status bool `json:"status" form:"status"`
}
type WebsiteUpdateCert struct {
Name uint `json:"name" validate:"required|exists:websites,name"`
Cert string `json:"cert" validate:"required"`
Key string `json:"key" validate:"required"`
}

View File

@@ -168,6 +168,7 @@ func (route *Http) Register(r *chi.Mux) {
r.Post("/{id}/update_remark", route.website.UpdateRemark)
r.Post("/{id}/reset_config", route.website.ResetConfig)
r.Post("/{id}/status", route.website.UpdateStatus)
r.Post("/{id}/cert", route.website.UpdateCert)
r.Post("/{id}/obtain_cert", route.website.ObtainCert)
})
@@ -366,6 +367,7 @@ func (route *Http) Register(r *chi.Mux) {
r.Route("/setting", func(r chi.Router) {
r.Get("/", route.setting.Get)
r.Post("/", route.setting.Update)
r.Post("/cert", route.setting.UpdateCert)
})
r.Route("/systemctl", func(r chi.Router) {

View File

@@ -19,7 +19,7 @@ func NewSettingService(setting biz.SettingRepo) *SettingService {
}
func (s *SettingService) Get(w http.ResponseWriter, r *http.Request) {
setting, err := s.settingRepo.GetPanelSetting()
setting, err := s.settingRepo.GetPanel()
if err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -29,14 +29,14 @@ func (s *SettingService) Get(w http.ResponseWriter, r *http.Request) {
}
func (s *SettingService) Update(w http.ResponseWriter, r *http.Request) {
req, err := Bind[request.PanelSetting](r)
req, err := Bind[request.SettingPanel](r)
if err != nil {
Error(w, http.StatusUnprocessableEntity, "%v", err)
return
}
restart := false
if restart, err = s.settingRepo.UpdatePanelSetting(req); err != nil {
if restart, err = s.settingRepo.UpdatePanel(req); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -47,3 +47,21 @@ func (s *SettingService) Update(w http.ResponseWriter, r *http.Request) {
Success(w, nil)
}
// UpdateCert 用于自动化工具更新证书
func (s *SettingService) UpdateCert(w http.ResponseWriter, r *http.Request) {
req, err := Bind[request.SettingCert](r)
if err != nil {
Error(w, http.StatusUnprocessableEntity, "%v", err)
return
}
if err = s.settingRepo.UpdateCert(req); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
tools.RestartPanel()
Success(w, nil)
}

View File

@@ -212,6 +212,22 @@ func (s *WebsiteService) UpdateStatus(w http.ResponseWriter, r *http.Request) {
Success(w, nil)
}
// UpdateCert 用于自动化工具更新证书
func (s *WebsiteService) UpdateCert(w http.ResponseWriter, r *http.Request) {
req, err := Bind[request.WebsiteUpdateCert](r)
if err != nil {
Error(w, http.StatusUnprocessableEntity, "%v", err)
return
}
if err = s.websiteRepo.UpdateCert(req); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
Success(w, nil)
}
func (s *WebsiteService) ObtainCert(w http.ResponseWriter, r *http.Request) {
req, err := Bind[request.ID](r)
if err != nil {