From 509d059ceb73875e48c0843457b7329041c41f69 Mon Sep 17 00:00:00 2001 From: 0xJacky Date: Mon, 22 May 2023 19:02:09 +0800 Subject: [PATCH] fix: abort only when log level higher than warn --- frontend/src/version.json | 2 +- frontend/version.json | 2 +- server/api/domain.go | 800 +++++++++++++++++++------------------- 3 files changed, 402 insertions(+), 402 deletions(-) diff --git a/frontend/src/version.json b/frontend/src/version.json index 23741352..3d2c6311 100644 --- a/frontend/src/version.json +++ b/frontend/src/version.json @@ -1 +1 @@ -{"version":"1.9.9","build_id":133,"total_build":203} \ No newline at end of file +{"version":"1.9.9","build_id":134,"total_build":204} \ No newline at end of file diff --git a/frontend/version.json b/frontend/version.json index 23741352..3d2c6311 100644 --- a/frontend/version.json +++ b/frontend/version.json @@ -1 +1 @@ -{"version":"1.9.9","build_id":133,"total_build":203} \ No newline at end of file +{"version":"1.9.9","build_id":134,"total_build":204} \ No newline at end of file diff --git a/server/api/domain.go b/server/api/domain.go index 4e6e6eb3..0d1902fc 100644 --- a/server/api/domain.go +++ b/server/api/domain.go @@ -1,535 +1,535 @@ package api import ( - "github.com/0xJacky/Nginx-UI/server/internal/cert" - "github.com/0xJacky/Nginx-UI/server/internal/config_list" - "github.com/0xJacky/Nginx-UI/server/internal/helper" - "github.com/0xJacky/Nginx-UI/server/internal/logger" - "github.com/0xJacky/Nginx-UI/server/internal/nginx" - "github.com/0xJacky/Nginx-UI/server/model" - "github.com/0xJacky/Nginx-UI/server/query" - "github.com/gin-gonic/gin" - "github.com/sashabaranov/go-openai" - "net/http" - "os" - "strings" - "time" + "github.com/0xJacky/Nginx-UI/server/internal/cert" + "github.com/0xJacky/Nginx-UI/server/internal/config_list" + "github.com/0xJacky/Nginx-UI/server/internal/helper" + "github.com/0xJacky/Nginx-UI/server/internal/logger" + "github.com/0xJacky/Nginx-UI/server/internal/nginx" + "github.com/0xJacky/Nginx-UI/server/model" + "github.com/0xJacky/Nginx-UI/server/query" + "github.com/gin-gonic/gin" + "github.com/sashabaranov/go-openai" + "net/http" + "os" + "strings" + "time" ) func GetDomains(c *gin.Context) { - name := c.Query("name") - orderBy := c.Query("order_by") - sort := c.DefaultQuery("sort", "desc") + name := c.Query("name") + orderBy := c.Query("order_by") + sort := c.DefaultQuery("sort", "desc") - mySort := map[string]string{ - "enabled": "bool", - "name": "string", - "modify": "time", - } + mySort := map[string]string{ + "enabled": "bool", + "name": "string", + "modify": "time", + } - configFiles, err := os.ReadDir(nginx.GetConfPath("sites-available")) + configFiles, err := os.ReadDir(nginx.GetConfPath("sites-available")) - if err != nil { - ErrHandler(c, err) - return - } + if err != nil { + ErrHandler(c, err) + return + } - enabledConfig, err := os.ReadDir(nginx.GetConfPath("sites-enabled")) + enabledConfig, err := os.ReadDir(nginx.GetConfPath("sites-enabled")) - if err != nil { - ErrHandler(c, err) - return - } + if err != nil { + ErrHandler(c, err) + return + } - enabledConfigMap := make(map[string]bool) - for i := range enabledConfig { - enabledConfigMap[enabledConfig[i].Name()] = true - } + enabledConfigMap := make(map[string]bool) + for i := range enabledConfig { + enabledConfigMap[enabledConfig[i].Name()] = true + } - var configs []gin.H + var configs []gin.H - for i := range configFiles { - file := configFiles[i] - fileInfo, _ := file.Info() - if !file.IsDir() { - if name != "" && !strings.Contains(file.Name(), name) { - continue - } - configs = append(configs, gin.H{ - "name": file.Name(), - "size": fileInfo.Size(), - "modify": fileInfo.ModTime(), - "enabled": enabledConfigMap[file.Name()], - }) - } - } + for i := range configFiles { + file := configFiles[i] + fileInfo, _ := file.Info() + if !file.IsDir() { + if name != "" && !strings.Contains(file.Name(), name) { + continue + } + configs = append(configs, gin.H{ + "name": file.Name(), + "size": fileInfo.Size(), + "modify": fileInfo.ModTime(), + "enabled": enabledConfigMap[file.Name()], + }) + } + } - configs = config_list.Sort(orderBy, sort, mySort[orderBy], configs) + configs = config_list.Sort(orderBy, sort, mySort[orderBy], configs) - c.JSON(http.StatusOK, gin.H{ - "data": configs, - }) + c.JSON(http.StatusOK, gin.H{ + "data": configs, + }) } type CertificateInfo struct { - SubjectName string `json:"subject_name"` - IssuerName string `json:"issuer_name"` - NotAfter time.Time `json:"not_after"` - NotBefore time.Time `json:"not_before"` + SubjectName string `json:"subject_name"` + IssuerName string `json:"issuer_name"` + NotAfter time.Time `json:"not_after"` + NotBefore time.Time `json:"not_before"` } func GetDomain(c *gin.Context) { - rewriteName, ok := c.Get("rewriteConfigFileName") + rewriteName, ok := c.Get("rewriteConfigFileName") - name := c.Param("name") + name := c.Param("name") - // for modify filename - if ok { - name = rewriteName.(string) - } + // for modify filename + if ok { + name = rewriteName.(string) + } - path := nginx.GetConfPath("sites-available", name) - file, err := os.Stat(path) - if os.IsNotExist(err) { - c.JSON(http.StatusNotFound, gin.H{ - "message": "file not found", - }) - return - } + path := nginx.GetConfPath("sites-available", name) + file, err := os.Stat(path) + if os.IsNotExist(err) { + c.JSON(http.StatusNotFound, gin.H{ + "message": "file not found", + }) + return + } - enabled := true + enabled := true - if _, err := os.Stat(nginx.GetConfPath("sites-enabled", name)); os.IsNotExist(err) { - enabled = false - } + if _, err := os.Stat(nginx.GetConfPath("sites-enabled", name)); os.IsNotExist(err) { + enabled = false + } - g := query.ChatGPTLog - chatgpt, err := g.Where(g.Name.Eq(path)).FirstOrCreate() + g := query.ChatGPTLog + chatgpt, err := g.Where(g.Name.Eq(path)).FirstOrCreate() - if err != nil { - ErrHandler(c, err) - return - } + if err != nil { + ErrHandler(c, err) + return + } - if chatgpt.Content == nil { - chatgpt.Content = make([]openai.ChatCompletionMessage, 0) - } + if chatgpt.Content == nil { + chatgpt.Content = make([]openai.ChatCompletionMessage, 0) + } - s := query.Site - site, err := s.Where(s.Path.Eq(path)).FirstOrInit() + s := query.Site + site, err := s.Where(s.Path.Eq(path)).FirstOrInit() - if err != nil { - ErrHandler(c, err) - return - } + if err != nil { + ErrHandler(c, err) + return + } - certModel, err := model.FirstCert(name) + certModel, err := model.FirstCert(name) - if err != nil { - logger.Warn("cert", err) - } + if err != nil { + logger.Warn("cert", err) + } - if site.Advanced { - origContent, err := os.ReadFile(path) - if err != nil { - ErrHandler(c, err) - return - } + if site.Advanced { + origContent, err := os.ReadFile(path) + if err != nil { + ErrHandler(c, err) + return + } - c.JSON(http.StatusOK, gin.H{ - "modified_at": file.ModTime(), - "advanced": site.Advanced, - "enabled": enabled, - "name": name, - "config": string(origContent), - "auto_cert": certModel.AutoCert == model.AutoCertEnabled, - "chatgpt_messages": chatgpt.Content, - }) - return - } + c.JSON(http.StatusOK, gin.H{ + "modified_at": file.ModTime(), + "advanced": site.Advanced, + "enabled": enabled, + "name": name, + "config": string(origContent), + "auto_cert": certModel.AutoCert == model.AutoCertEnabled, + "chatgpt_messages": chatgpt.Content, + }) + return + } - c.Set("maybe_error", "nginx_config_syntax_error") - config, err := nginx.ParseNgxConfig(path) + c.Set("maybe_error", "nginx_config_syntax_error") + config, err := nginx.ParseNgxConfig(path) - if err != nil { - ErrHandler(c, err) - return - } + if err != nil { + ErrHandler(c, err) + return + } - c.Set("maybe_error", "") + c.Set("maybe_error", "") - certInfoMap := make(map[int]CertificateInfo) - for serverIdx, server := range config.Servers { - for _, directive := range server.Directives { - if directive.Directive == "ssl_certificate" { + certInfoMap := make(map[int]CertificateInfo) + for serverIdx, server := range config.Servers { + for _, directive := range server.Directives { + if directive.Directive == "ssl_certificate" { - pubKey, err := cert.GetCertInfo(directive.Params) + pubKey, err := cert.GetCertInfo(directive.Params) - if err != nil { - logger.Error("Failed to get certificate information", err) - break - } + if err != nil { + logger.Error("Failed to get certificate information", err) + break + } - certInfoMap[serverIdx] = CertificateInfo{ - SubjectName: pubKey.Subject.CommonName, - IssuerName: pubKey.Issuer.CommonName, - NotAfter: pubKey.NotAfter, - NotBefore: pubKey.NotBefore, - } + certInfoMap[serverIdx] = CertificateInfo{ + SubjectName: pubKey.Subject.CommonName, + IssuerName: pubKey.Issuer.CommonName, + NotAfter: pubKey.NotAfter, + NotBefore: pubKey.NotBefore, + } - break - } - } - } + break + } + } + } - c.Set("maybe_error", "nginx_config_syntax_error") + c.Set("maybe_error", "nginx_config_syntax_error") - c.JSON(http.StatusOK, gin.H{ - "modified_at": file.ModTime(), - "advanced": site.Advanced, - "enabled": enabled, - "name": name, - "config": config.FmtCode(), - "tokenized": config, - "auto_cert": certModel.AutoCert == model.AutoCertEnabled, - "cert_info": certInfoMap, - "chatgpt_messages": chatgpt.Content, - }) + c.JSON(http.StatusOK, gin.H{ + "modified_at": file.ModTime(), + "advanced": site.Advanced, + "enabled": enabled, + "name": name, + "config": config.FmtCode(), + "tokenized": config, + "auto_cert": certModel.AutoCert == model.AutoCertEnabled, + "cert_info": certInfoMap, + "chatgpt_messages": chatgpt.Content, + }) } func SaveDomain(c *gin.Context) { - name := c.Param("name") + name := c.Param("name") - if name == "" { - c.JSON(http.StatusNotAcceptable, gin.H{ - "message": "param name is empty", - }) - return - } + if name == "" { + c.JSON(http.StatusNotAcceptable, gin.H{ + "message": "param name is empty", + }) + return + } - var json struct { - Name string `json:"name" binding:"required"` - Content string `json:"content" binding:"required"` - Overwrite bool `json:"overwrite"` - } + var json struct { + Name string `json:"name" binding:"required"` + Content string `json:"content" binding:"required"` + Overwrite bool `json:"overwrite"` + } - if !BindAndValid(c, &json) { - return - } + if !BindAndValid(c, &json) { + return + } - path := nginx.GetConfPath("sites-available", name) + path := nginx.GetConfPath("sites-available", name) - if !json.Overwrite && helper.FileExists(path) { - c.JSON(http.StatusNotAcceptable, gin.H{ - "message": "File exists", - }) - return - } + if !json.Overwrite && helper.FileExists(path) { + c.JSON(http.StatusNotAcceptable, gin.H{ + "message": "File exists", + }) + return + } - err := os.WriteFile(path, []byte(json.Content), 0644) - if err != nil { - ErrHandler(c, err) - return - } - enabledConfigFilePath := nginx.GetConfPath("sites-enabled", name) - // rename the config file if needed - if name != json.Name { - newPath := nginx.GetConfPath("sites-available", json.Name) - s := query.Site - _, err = s.Where(s.Path.Eq(path)).Update(s.Path, newPath) + err := os.WriteFile(path, []byte(json.Content), 0644) + if err != nil { + ErrHandler(c, err) + return + } + enabledConfigFilePath := nginx.GetConfPath("sites-enabled", name) + // rename the config file if needed + if name != json.Name { + newPath := nginx.GetConfPath("sites-available", json.Name) + s := query.Site + _, err = s.Where(s.Path.Eq(path)).Update(s.Path, newPath) - // check if dst file exists, do not rename - if helper.FileExists(newPath) { - c.JSON(http.StatusNotAcceptable, gin.H{ - "message": "File exists", - }) - return - } - // recreate soft link - if helper.FileExists(enabledConfigFilePath) { - _ = os.Remove(enabledConfigFilePath) - enabledConfigFilePath = nginx.GetConfPath("sites-enabled", json.Name) - err = os.Symlink(newPath, enabledConfigFilePath) + // check if dst file exists, do not rename + if helper.FileExists(newPath) { + c.JSON(http.StatusNotAcceptable, gin.H{ + "message": "File exists", + }) + return + } + // recreate soft link + if helper.FileExists(enabledConfigFilePath) { + _ = os.Remove(enabledConfigFilePath) + enabledConfigFilePath = nginx.GetConfPath("sites-enabled", json.Name) + err = os.Symlink(newPath, enabledConfigFilePath) - if err != nil { - ErrHandler(c, err) - return - } - } + if err != nil { + ErrHandler(c, err) + return + } + } - err = os.Rename(path, newPath) - if err != nil { - ErrHandler(c, err) - return - } + err = os.Rename(path, newPath) + if err != nil { + ErrHandler(c, err) + return + } - name = json.Name - c.Set("rewriteConfigFileName", name) - } + name = json.Name + c.Set("rewriteConfigFileName", name) + } - enabledConfigFilePath = nginx.GetConfPath("sites-enabled", name) - if helper.FileExists(enabledConfigFilePath) { - // Test nginx configuration - output := nginx.TestConf() - if nginx.GetLogLevel(output) > nginx.Warn { - c.JSON(http.StatusInternalServerError, gin.H{ - "message": output, - "error": "nginx_config_syntax_error", - }) - return - } + enabledConfigFilePath = nginx.GetConfPath("sites-enabled", name) + if helper.FileExists(enabledConfigFilePath) { + // Test nginx configuration + output := nginx.TestConf() + if nginx.GetLogLevel(output) > nginx.Warn { + c.JSON(http.StatusInternalServerError, gin.H{ + "message": output, + "error": "nginx_config_syntax_error", + }) + return + } - output = nginx.Reload() + output = nginx.Reload() - if nginx.GetLogLevel(output) > nginx.Warn { - c.JSON(http.StatusInternalServerError, gin.H{ - "message": output, - }) - return - } - } + if nginx.GetLogLevel(output) > nginx.Warn { + c.JSON(http.StatusInternalServerError, gin.H{ + "message": output, + }) + return + } + } - GetDomain(c) + GetDomain(c) } func EnableDomain(c *gin.Context) { - configFilePath := nginx.GetConfPath("sites-available", c.Param("name")) - enabledConfigFilePath := nginx.GetConfPath("sites-enabled", c.Param("name")) + configFilePath := nginx.GetConfPath("sites-available", c.Param("name")) + enabledConfigFilePath := nginx.GetConfPath("sites-enabled", c.Param("name")) - _, err := os.Stat(configFilePath) + _, err := os.Stat(configFilePath) - if err != nil { - ErrHandler(c, err) - return - } + if err != nil { + ErrHandler(c, err) + return + } - if _, err = os.Stat(enabledConfigFilePath); os.IsNotExist(err) { - err = os.Symlink(configFilePath, enabledConfigFilePath) + if _, err = os.Stat(enabledConfigFilePath); os.IsNotExist(err) { + err = os.Symlink(configFilePath, enabledConfigFilePath) - if err != nil { - ErrHandler(c, err) - return - } - } + if err != nil { + ErrHandler(c, err) + return + } + } - // Test nginx config, if not pass then disable the site. - output := nginx.TestConf() + // Test nginx config, if not pass then disable the site. + output := nginx.TestConf() - if nginx.GetLogLevel(output) >= nginx.Warn { - _ = os.Remove(enabledConfigFilePath) - c.JSON(http.StatusInternalServerError, gin.H{ - "message": output, - }) - return - } + if nginx.GetLogLevel(output) > nginx.Warn { + _ = os.Remove(enabledConfigFilePath) + c.JSON(http.StatusInternalServerError, gin.H{ + "message": output, + }) + return + } - output = nginx.Reload() + output = nginx.Reload() - if nginx.GetLogLevel(output) >= nginx.Warn { - c.JSON(http.StatusInternalServerError, gin.H{ - "message": output, - }) - return - } + if nginx.GetLogLevel(output) > nginx.Warn { + c.JSON(http.StatusInternalServerError, gin.H{ + "message": output, + }) + return + } - c.JSON(http.StatusOK, gin.H{ - "message": "ok", - }) + c.JSON(http.StatusOK, gin.H{ + "message": "ok", + }) } func DisableDomain(c *gin.Context) { - enabledConfigFilePath := nginx.GetConfPath("sites-enabled", c.Param("name")) + enabledConfigFilePath := nginx.GetConfPath("sites-enabled", c.Param("name")) - _, err := os.Stat(enabledConfigFilePath) + _, err := os.Stat(enabledConfigFilePath) - if err != nil { - ErrHandler(c, err) - return - } + if err != nil { + ErrHandler(c, err) + return + } - err = os.Remove(enabledConfigFilePath) + err = os.Remove(enabledConfigFilePath) - if err != nil { - ErrHandler(c, err) - return - } + if err != nil { + ErrHandler(c, err) + return + } - // delete auto cert record - certModel := model.Cert{Filename: c.Param("name")} - err = certModel.Remove() - if err != nil { - ErrHandler(c, err) - return - } + // delete auto cert record + certModel := model.Cert{Filename: c.Param("name")} + err = certModel.Remove() + if err != nil { + ErrHandler(c, err) + return + } - output := nginx.Reload() + output := nginx.Reload() - if nginx.GetLogLevel(output) >= nginx.Warn { - c.JSON(http.StatusInternalServerError, gin.H{ - "message": output, - }) - return - } + if nginx.GetLogLevel(output) > nginx.Warn { + c.JSON(http.StatusInternalServerError, gin.H{ + "message": output, + }) + return + } - c.JSON(http.StatusOK, gin.H{ - "message": "ok", - }) + c.JSON(http.StatusOK, gin.H{ + "message": "ok", + }) } func DeleteDomain(c *gin.Context) { - var err error - name := c.Param("name") - availablePath := nginx.GetConfPath("sites-available", name) - enabledPath := nginx.GetConfPath("sites-enabled", name) + var err error + name := c.Param("name") + availablePath := nginx.GetConfPath("sites-available", name) + enabledPath := nginx.GetConfPath("sites-enabled", name) - if _, err = os.Stat(availablePath); os.IsNotExist(err) { - c.JSON(http.StatusNotFound, gin.H{ - "message": "site not found", - }) - return - } + if _, err = os.Stat(availablePath); os.IsNotExist(err) { + c.JSON(http.StatusNotFound, gin.H{ + "message": "site not found", + }) + return + } - if _, err = os.Stat(enabledPath); err == nil { - c.JSON(http.StatusNotAcceptable, gin.H{ - "message": "site is enabled", - }) - return - } + if _, err = os.Stat(enabledPath); err == nil { + c.JSON(http.StatusNotAcceptable, gin.H{ + "message": "site is enabled", + }) + return + } - certModel := model.Cert{Filename: name} - _ = certModel.Remove() + certModel := model.Cert{Filename: name} + _ = certModel.Remove() - err = os.Remove(availablePath) + err = os.Remove(availablePath) - if err != nil { - ErrHandler(c, err) - return - } + if err != nil { + ErrHandler(c, err) + return + } - c.JSON(http.StatusOK, gin.H{ - "message": "ok", - }) + c.JSON(http.StatusOK, gin.H{ + "message": "ok", + }) } func AddDomainToAutoCert(c *gin.Context) { - name := c.Param("name") + name := c.Param("name") - var json struct { - model.Cert - Domains []string `json:"domains"` - } + var json struct { + model.Cert + Domains []string `json:"domains"` + } - if !BindAndValid(c, &json) { - return - } + if !BindAndValid(c, &json) { + return + } - certModel, err := model.FirstOrCreateCert(name) + certModel, err := model.FirstOrCreateCert(name) - if err != nil { - ErrHandler(c, err) - return - } + if err != nil { + ErrHandler(c, err) + return + } - err = certModel.Updates(&model.Cert{ - Name: name, - Domains: json.Domains, - AutoCert: model.AutoCertEnabled, - DnsCredentialID: json.DnsCredentialID, - ChallengeMethod: json.ChallengeMethod, - }) + err = certModel.Updates(&model.Cert{ + Name: name, + Domains: json.Domains, + AutoCert: model.AutoCertEnabled, + DnsCredentialID: json.DnsCredentialID, + ChallengeMethod: json.ChallengeMethod, + }) - if err != nil { - ErrHandler(c, err) - return - } + if err != nil { + ErrHandler(c, err) + return + } - c.JSON(http.StatusOK, certModel) + c.JSON(http.StatusOK, certModel) } func RemoveDomainFromAutoCert(c *gin.Context) { - name := c.Param("name") - certModel, err := model.FirstCert(name) + name := c.Param("name") + certModel, err := model.FirstCert(name) - if err != nil { - ErrHandler(c, err) - return - } + if err != nil { + ErrHandler(c, err) + return + } - err = certModel.Updates(&model.Cert{ - AutoCert: model.AutoCertDisabled, - }) + err = certModel.Updates(&model.Cert{ + AutoCert: model.AutoCertDisabled, + }) - if err != nil { - ErrHandler(c, err) - return - } - c.JSON(http.StatusOK, nil) + if err != nil { + ErrHandler(c, err) + return + } + c.JSON(http.StatusOK, nil) } func DuplicateSite(c *gin.Context) { - name := c.Param("name") + name := c.Param("name") - var json struct { - Name string `json:"name" binding:"required"` - } + var json struct { + Name string `json:"name" binding:"required"` + } - if !BindAndValid(c, &json) { - return - } + if !BindAndValid(c, &json) { + return + } - src := nginx.GetConfPath("sites-available", name) - dst := nginx.GetConfPath("sites-available", json.Name) + src := nginx.GetConfPath("sites-available", name) + dst := nginx.GetConfPath("sites-available", json.Name) - if helper.FileExists(dst) { - c.JSON(http.StatusNotAcceptable, gin.H{ - "message": "File exists", - }) - return - } + if helper.FileExists(dst) { + c.JSON(http.StatusNotAcceptable, gin.H{ + "message": "File exists", + }) + return + } - _, err := helper.CopyFile(src, dst) + _, err := helper.CopyFile(src, dst) - if err != nil { - ErrHandler(c, err) - return - } + if err != nil { + ErrHandler(c, err) + return + } - c.JSON(http.StatusOK, gin.H{ - "dst": dst, - }) + c.JSON(http.StatusOK, gin.H{ + "dst": dst, + }) } func DomainEditByAdvancedMode(c *gin.Context) { - var json struct { - Advanced bool `json:"advanced"` - } + var json struct { + Advanced bool `json:"advanced"` + } - if !BindAndValid(c, &json) { - return - } + if !BindAndValid(c, &json) { + return + } - name := c.Param("name") - path := nginx.GetConfPath("sites-available", name) + name := c.Param("name") + path := nginx.GetConfPath("sites-available", name) - s := query.Site + s := query.Site - _, err := s.Where(s.Path.Eq(path)).FirstOrCreate() - if err != nil { - ErrHandler(c, err) - return - } + _, err := s.Where(s.Path.Eq(path)).FirstOrCreate() + if err != nil { + ErrHandler(c, err) + return + } - _, err = s.Where(s.Path.Eq(path)).Update(s.Advanced, json.Advanced) + _, err = s.Where(s.Path.Eq(path)).Update(s.Advanced, json.Advanced) - if err != nil { - ErrHandler(c, err) - return - } + if err != nil { + ErrHandler(c, err) + return + } - c.JSON(http.StatusOK, gin.H{ - "message": "ok", - }) + c.JSON(http.StatusOK, gin.H{ + "message": "ok", + }) }