From 50b4fbcda4eabbe562a9cc07685911ebc8007336 Mon Sep 17 00:00:00 2001 From: 0xJacky Date: Mon, 27 Nov 2023 23:53:23 +0800 Subject: [PATCH] refactor: structure of api-router directory --- api/{ => analytic}/analytic.go | 8 +- api/analytic/router.go | 15 ++ api/api.go | 4 +- api/backup.go | 24 --- api/{ => certificate}/cert.go | 48 +++--- api/{ => certificate}/dns_credential.go | 21 +-- api/certificate/router.go | 22 +++ api/{ => cluster}/environment.go | 25 +-- api/{ => cluster}/node.go | 5 +- api/cluster/router.go | 17 +++ api/{ => config}/config.go | 21 +-- api/config/router.go | 10 ++ api/nginx/control.go | 31 ++++ api/{ngx.go => nginx/nginx.go} | 42 ++---- api/{ => nginx}/nginx_log.go | 5 +- api/nginx/router.go | 18 +++ api/{ => openai}/openai.go | 11 +- api/openai/router.go | 9 ++ api/settings.go | 61 -------- api/{ => sites}/domain.go | 83 +++++----- api/sites/router.go | 16 ++ api/{ => system}/install.go | 9 +- api/system/router.go | 20 +++ api/system/settings.go | 42 ++++++ api/{ => system}/translation.go | 6 +- api/{ => system}/upgrade.go | 9 +- api/template/router.go | 11 ++ api/{ => template}/template.go | 9 +- api/{ => terminal}/pty.go | 2 +- api/terminal/router.go | 7 + api/user.go | 136 ----------------- api/{ => user}/auth.go | 7 +- api/user/casdoor.go | 27 ++++ api/user/router.go | 19 +++ api/user/user.go | 137 +++++++++++++++++ app/src/version.json | 2 +- app/version.json | 2 +- router/routers.go | 193 +++++++----------------- 38 files changed, 610 insertions(+), 524 deletions(-) rename api/{ => analytic}/analytic.go (96%) create mode 100644 api/analytic/router.go delete mode 100644 api/backup.go rename api/{ => certificate}/cert.go (89%) rename api/{ => certificate}/dns_credential.go (88%) create mode 100644 api/certificate/router.go rename api/{ => cluster}/environment.go (87%) rename api/{ => cluster}/node.go (92%) create mode 100644 api/cluster/router.go rename api/{ => config}/config.go (93%) create mode 100644 api/config/router.go create mode 100644 api/nginx/control.go rename api/{ngx.go => nginx/nginx.go} (57%) rename api/{ => nginx}/nginx_log.go (98%) create mode 100644 api/nginx/router.go rename api/{ => openai}/openai.go (95%) create mode 100644 api/openai/router.go delete mode 100644 api/settings.go rename api/{ => sites}/domain.go (89%) create mode 100644 api/sites/router.go rename api/{ => system}/install.go (92%) create mode 100644 api/system/router.go create mode 100644 api/system/settings.go rename api/{ => system}/translation.go (59%) rename api/{ => system}/upgrade.go (95%) create mode 100644 api/template/router.go rename api/{ => template}/template.go (92%) rename api/{ => terminal}/pty.go (97%) create mode 100644 api/terminal/router.go delete mode 100644 api/user.go rename api/{ => user}/auth.go (96%) create mode 100644 api/user/casdoor.go create mode 100644 api/user/router.go create mode 100644 api/user/user.go diff --git a/api/analytic.go b/api/analytic/analytic.go similarity index 96% rename from api/analytic.go rename to api/analytic/analytic.go index 11af1b0b..600a0a21 100644 --- a/api/analytic.go +++ b/api/analytic/analytic.go @@ -1,4 +1,4 @@ -package api +package analytic import ( "fmt" @@ -26,9 +26,9 @@ type CPUStat struct { type Stat struct { Uptime uint64 `json:"uptime"` - LoadAvg *load.AvgStat `json:"loadavg"` - CPU CPUStat `json:"cpu"` - Memory analytic2.MemStat `json:"memory"` + LoadAvg *load.AvgStat `json:"loadavg"` + CPU CPUStat `json:"cpu"` + Memory analytic2.MemStat `json:"memory"` Disk analytic2.DiskStat `json:"disk"` Network net.IOCountersStat `json:"network"` } diff --git a/api/analytic/router.go b/api/analytic/router.go new file mode 100644 index 00000000..ab157560 --- /dev/null +++ b/api/analytic/router.go @@ -0,0 +1,15 @@ +package analytic + +import ( + "github.com/gin-gonic/gin" +) + +func InitWebSocketRouter(r *gin.RouterGroup) { + r.GET("analytic", Analytic) + r.GET("analytic/intro", GetNodeStat) + r.GET("analytic/nodes", GetNodesAnalytic) +} + +func InitRouter(r *gin.RouterGroup) { + r.GET("analytic/init", GetAnalyticInit) +} diff --git a/api/api.go b/api/api.go index e730d8d9..fe4a4780 100644 --- a/api/api.go +++ b/api/api.go @@ -1,6 +1,7 @@ package api import ( + "errors" "github.com/0xJacky/Nginx-UI/internal/logger" "github.com/gin-gonic/gin" val "github.com/go-playground/validator/v10" @@ -26,7 +27,8 @@ func BindAndValid(c *gin.Context, target interface{}) bool { if err != nil { logger.Error("bind err", err) - verrs, ok := err.(val.ValidationErrors) + var verrs val.ValidationErrors + ok := errors.As(err, &verrs) if !ok { logger.Error("valid err", verrs) diff --git a/api/backup.go b/api/backup.go deleted file mode 100644 index 0081649e..00000000 --- a/api/backup.go +++ /dev/null @@ -1,24 +0,0 @@ -package api - -import ( - "github.com/0xJacky/Nginx-UI/model" - "github.com/gin-gonic/gin" - "github.com/unknwon/com" - "net/http" -) - -func GetFileBackupList(c *gin.Context) { - path := c.Query("path") - backups := model.GetBackupList(path) - - c.JSON(http.StatusOK, gin.H{ - "backups": backups, - }) -} - -func GetFileBackup(c *gin.Context) { - id := c.Param("id") - backup := model.GetBackup(com.StrTo(id).MustInt()) - - c.JSON(http.StatusOK, backup) -} diff --git a/api/cert.go b/api/certificate/cert.go similarity index 89% rename from api/cert.go rename to api/certificate/cert.go index a86a5d13..2c006755 100644 --- a/api/cert.go +++ b/api/certificate/cert.go @@ -1,6 +1,8 @@ -package api +package certificate import ( + "github.com/0xJacky/Nginx-UI/api" + "github.com/0xJacky/Nginx-UI/api/sites" "github.com/0xJacky/Nginx-UI/internal/cert" "github.com/0xJacky/Nginx-UI/internal/cert/dns" "github.com/0xJacky/Nginx-UI/internal/logger" @@ -157,13 +159,13 @@ func GetCertList(c *gin.Context) { func getCert(c *gin.Context, certModel *model.Cert) { type resp struct { *model.Cert - SSLCertification string `json:"ssl_certification"` - SSLCertificationKey string `json:"ssl_certification_key"` - CertificateInfo *CertificateInfo `json:"certificate_info,omitempty"` + SSLCertification string `json:"ssl_certification"` + SSLCertificationKey string `json:"ssl_certification_key"` + CertificateInfo *sites.CertificateInfo `json:"certificate_info,omitempty"` } var sslCertificationBytes, sslCertificationKeyBytes []byte - var certificateInfo *CertificateInfo + var certificateInfo *sites.CertificateInfo if certModel.SSLCertificatePath != "" { if _, err := os.Stat(certModel.SSLCertificatePath); err == nil { sslCertificationBytes, _ = os.ReadFile(certModel.SSLCertificatePath) @@ -172,11 +174,11 @@ func getCert(c *gin.Context, certModel *model.Cert) { pubKey, err := cert.GetCertInfo(certModel.SSLCertificatePath) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } - certificateInfo = &CertificateInfo{ + certificateInfo = &sites.CertificateInfo{ SubjectName: pubKey.Subject.CommonName, IssuerName: pubKey.Issuer.CommonName, NotAfter: pubKey.NotAfter, @@ -202,7 +204,7 @@ func GetCert(c *gin.Context) { certModel, err := model.FirstCertByID(cast.ToInt(c.Param("id"))) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -217,7 +219,7 @@ func AddCert(c *gin.Context) { SSLCertification string `json:"ssl_certification"` SSLCertificationKey string `json:"ssl_certification_key"` } - if !BindAndValid(c, &json) { + if !api.BindAndValid(c, &json) { return } certModel := &model.Cert{ @@ -229,26 +231,26 @@ func AddCert(c *gin.Context) { err := certModel.Insert() if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } err = os.MkdirAll(filepath.Dir(json.SSLCertificatePath), 0644) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } err = os.MkdirAll(filepath.Dir(json.SSLCertificateKeyPath), 0644) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } if json.SSLCertification != "" { err = os.WriteFile(json.SSLCertificatePath, []byte(json.SSLCertification), 0644) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } } @@ -256,7 +258,7 @@ func AddCert(c *gin.Context) { if json.SSLCertificationKey != "" { err = os.WriteFile(json.SSLCertificateKeyPath, []byte(json.SSLCertificationKey), 0644) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } } @@ -275,13 +277,13 @@ func ModifyCert(c *gin.Context) { SSLCertificationKey string `json:"ssl_certification_key"` } - if !BindAndValid(c, &json) { + if !api.BindAndValid(c, &json) { return } certModel, err := model.FirstCertByID(id) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -292,26 +294,26 @@ func ModifyCert(c *gin.Context) { }) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } err = os.MkdirAll(filepath.Dir(json.SSLCertificatePath), 0644) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } err = os.MkdirAll(filepath.Dir(json.SSLCertificateKeyPath), 0644) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } if json.SSLCertification != "" { err = os.WriteFile(json.SSLCertificatePath, []byte(json.SSLCertification), 0644) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } } @@ -319,7 +321,7 @@ func ModifyCert(c *gin.Context) { if json.SSLCertificationKey != "" { err = os.WriteFile(json.SSLCertificateKeyPath, []byte(json.SSLCertificationKey), 0644) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } } @@ -332,14 +334,14 @@ func RemoveCert(c *gin.Context) { certModel, err := model.FirstCertByID(id) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } err = certModel.Remove() if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } diff --git a/api/dns_credential.go b/api/certificate/dns_credential.go similarity index 88% rename from api/dns_credential.go rename to api/certificate/dns_credential.go index 24599de3..0c3a9709 100644 --- a/api/dns_credential.go +++ b/api/certificate/dns_credential.go @@ -1,6 +1,7 @@ -package api +package certificate import ( + "github.com/0xJacky/Nginx-UI/api" "github.com/0xJacky/Nginx-UI/internal/cert/dns" model2 "github.com/0xJacky/Nginx-UI/model" "github.com/0xJacky/Nginx-UI/query" @@ -16,7 +17,7 @@ func GetDnsCredential(c *gin.Context) { dnsCredential, err := d.FirstByID(id) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } type apiDnsCredential struct { @@ -43,7 +44,7 @@ func GetDnsCredentialList(c *gin.Context) { } if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } c.JSON(http.StatusOK, gin.H{ @@ -59,7 +60,7 @@ type DnsCredentialManageJson struct { func AddDnsCredential(c *gin.Context) { var json DnsCredentialManageJson - if !BindAndValid(c, &json) { + if !api.BindAndValid(c, &json) { return } @@ -74,7 +75,7 @@ func AddDnsCredential(c *gin.Context) { err := d.Create(&dnsCredential) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -85,7 +86,7 @@ func EditDnsCredential(c *gin.Context) { id := cast.ToInt(c.Param("id")) var json DnsCredentialManageJson - if !BindAndValid(c, &json) { + if !api.BindAndValid(c, &json) { return } @@ -93,7 +94,7 @@ func EditDnsCredential(c *gin.Context) { dnsCredential, err := d.FirstByID(id) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -105,7 +106,7 @@ func EditDnsCredential(c *gin.Context) { }) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -118,12 +119,12 @@ func DeleteDnsCredential(c *gin.Context) { dnsCredential, err := d.FirstByID(id) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } err = d.DeleteByID(dnsCredential.ID) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } c.JSON(http.StatusNoContent, nil) diff --git a/api/certificate/router.go b/api/certificate/router.go new file mode 100644 index 00000000..d37e8ce5 --- /dev/null +++ b/api/certificate/router.go @@ -0,0 +1,22 @@ +package certificate + +import "github.com/gin-gonic/gin" + +func InitDNSCredentialRouter(r *gin.RouterGroup) { + r.GET("dns_credentials", GetDnsCredentialList) + r.GET("dns_credential/:id", GetDnsCredential) + r.POST("dns_credential", AddDnsCredential) + r.POST("dns_credential/:id", EditDnsCredential) + r.DELETE("dns_credential/:id", DeleteDnsCredential) +} + +func InitCertificateRouter(r *gin.RouterGroup) { + r.GET("domain/:name/cert", IssueCert) + r.GET("certs", GetCertList) + r.GET("cert/:id", GetCert) + r.POST("cert", AddCert) + r.POST("cert/:id", ModifyCert) + r.DELETE("cert/:id", RemoveCert) + r.GET("auto_cert/dns/providers", GetDNSProvidersList) + r.GET("auto_cert/dns/provider/:code", GetDNSProvider) +} diff --git a/api/environment.go b/api/cluster/environment.go similarity index 87% rename from api/environment.go rename to api/cluster/environment.go index 064e776f..9bbfb344 100644 --- a/api/environment.go +++ b/api/cluster/environment.go @@ -1,6 +1,7 @@ -package api +package cluster import ( + "github.com/0xJacky/Nginx-UI/api" "github.com/0xJacky/Nginx-UI/internal/analytic" "github.com/0xJacky/Nginx-UI/internal/environment" "github.com/0xJacky/Nginx-UI/model" @@ -18,7 +19,7 @@ func GetEnvironment(c *gin.Context) { env, err := envQuery.FirstByID(id) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -28,7 +29,7 @@ func GetEnvironment(c *gin.Context) { func GetEnvironmentList(c *gin.Context) { data, err := environment.RetrieveEnvironmentList() if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } c.JSON(http.StatusOK, gin.H{ @@ -54,11 +55,11 @@ func validateRegex(data EnvironmentManageJson) error { func AddEnvironment(c *gin.Context) { var json EnvironmentManageJson - if !BindAndValid(c, &json) { + if !api.BindAndValid(c, &json) { return } if err := validateRegex(json); err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -74,7 +75,7 @@ func AddEnvironment(c *gin.Context) { err := envQuery.Create(&env) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -87,11 +88,11 @@ func EditEnvironment(c *gin.Context) { id := cast.ToInt(c.Param("id")) var json EnvironmentManageJson - if !BindAndValid(c, &json) { + if !api.BindAndValid(c, &json) { return } if err := validateRegex(json); err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -99,7 +100,7 @@ func EditEnvironment(c *gin.Context) { env, err := envQuery.FirstByID(id) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -112,7 +113,7 @@ func EditEnvironment(c *gin.Context) { }) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -127,12 +128,12 @@ func DeleteEnvironment(c *gin.Context) { env, err := envQuery.FirstByID(id) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } err = envQuery.DeleteByID(env.ID) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } diff --git a/api/node.go b/api/cluster/node.go similarity index 92% rename from api/node.go rename to api/cluster/node.go index 948837f5..57848efb 100644 --- a/api/node.go +++ b/api/cluster/node.go @@ -1,6 +1,7 @@ -package api +package cluster import ( + "github.com/0xJacky/Nginx-UI/api" analytic2 "github.com/0xJacky/Nginx-UI/internal/analytic" "github.com/0xJacky/Nginx-UI/internal/upgrader" "github.com/dustin/go-humanize" @@ -20,7 +21,7 @@ func GetCurrentNode(c *gin.Context) { runtimeInfo, err := upgrader.GetRuntimeInfo() if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } cpuInfo, _ := cpu.Info() diff --git a/api/cluster/router.go b/api/cluster/router.go new file mode 100644 index 00000000..b9ec1067 --- /dev/null +++ b/api/cluster/router.go @@ -0,0 +1,17 @@ +package cluster + +import "github.com/gin-gonic/gin" + +func InitRouter(r *gin.RouterGroup) { + // Environment + r.GET("environments", GetEnvironmentList) + envGroup := r.Group("environment") + { + envGroup.GET("/:id", GetEnvironment) + envGroup.POST("", AddEnvironment) + envGroup.POST("/:id", EditEnvironment) + envGroup.DELETE("/:id", DeleteEnvironment) + } + // Node + r.GET("node", GetCurrentNode) +} diff --git a/api/config.go b/api/config/config.go similarity index 93% rename from api/config.go rename to api/config/config.go index 4960eff6..08903ac1 100644 --- a/api/config.go +++ b/api/config/config.go @@ -1,6 +1,7 @@ -package api +package config import ( + "github.com/0xJacky/Nginx-UI/api" "github.com/0xJacky/Nginx-UI/internal/config_list" "github.com/0xJacky/Nginx-UI/internal/logger" nginx2 "github.com/0xJacky/Nginx-UI/internal/nginx" @@ -25,7 +26,7 @@ func GetConfigs(c *gin.Context) { configFiles, err := os.ReadDir(nginx2.GetConfPath(dir)) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -82,14 +83,14 @@ func GetConfig(c *gin.Context) { stat, err := os.Stat(path) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } content, err := os.ReadFile(path) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -97,7 +98,7 @@ func GetConfig(c *gin.Context) { chatgpt, err := g.Where(g.Name.Eq(path)).FirstOrCreate() if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -123,7 +124,7 @@ func AddConfig(c *gin.Context) { var request AddConfigJson err := c.BindJSON(&request) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -142,7 +143,7 @@ func AddConfig(c *gin.Context) { if content != "" { err = os.WriteFile(path, []byte(content), 0644) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } } @@ -171,7 +172,7 @@ func EditConfig(c *gin.Context) { var request EditConfigJson err := c.BindJSON(&request) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } path := nginx2.GetConfPath("/", name) @@ -179,7 +180,7 @@ func EditConfig(c *gin.Context) { origContent, err := os.ReadFile(path) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -187,7 +188,7 @@ func EditConfig(c *gin.Context) { // model.CreateBackup(path) err = os.WriteFile(path, []byte(content), 0644) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } } diff --git a/api/config/router.go b/api/config/router.go new file mode 100644 index 00000000..594744fc --- /dev/null +++ b/api/config/router.go @@ -0,0 +1,10 @@ +package config + +import "github.com/gin-gonic/gin" + +func InitRouter(r *gin.RouterGroup) { + r.GET("configs", GetConfigs) + r.GET("config/*name", GetConfig) + r.POST("config", AddConfig) + r.POST("config/*name", EditConfig) +} diff --git a/api/nginx/control.go b/api/nginx/control.go new file mode 100644 index 00000000..50d22e0e --- /dev/null +++ b/api/nginx/control.go @@ -0,0 +1,31 @@ +package nginx + +import ( + nginx2 "github.com/0xJacky/Nginx-UI/internal/nginx" + "github.com/gin-gonic/gin" + "net/http" +) + +func Reload(c *gin.Context) { + output := nginx2.Reload() + c.JSON(http.StatusOK, gin.H{ + "message": output, + "level": nginx2.GetLogLevel(output), + }) +} + +func Test(c *gin.Context) { + output := nginx2.TestConf() + c.JSON(http.StatusOK, gin.H{ + "message": output, + "level": nginx2.GetLogLevel(output), + }) +} + +func Restart(c *gin.Context) { + output := nginx2.Restart() + c.JSON(http.StatusOK, gin.H{ + "message": output, + "level": nginx2.GetLogLevel(output), + }) +} diff --git a/api/ngx.go b/api/nginx/nginx.go similarity index 57% rename from api/ngx.go rename to api/nginx/nginx.go index b43eb2a9..76a84c67 100644 --- a/api/ngx.go +++ b/api/nginx/nginx.go @@ -1,15 +1,16 @@ -package api +package nginx import ( - nginx2 "github.com/0xJacky/Nginx-UI/internal/nginx" - "github.com/gin-gonic/gin" - "net/http" - "os" + "github.com/0xJacky/Nginx-UI/api" + nginx2 "github.com/0xJacky/Nginx-UI/internal/nginx" + "github.com/gin-gonic/gin" + "net/http" + "os" ) func BuildNginxConfig(c *gin.Context) { var ngxConf nginx2.NgxConfig - if !BindAndValid(c, &ngxConf) { + if !api.BindAndValid(c, &ngxConf) { return } c.Set("maybe_error", "nginx_config_syntax_error") @@ -23,7 +24,7 @@ func TokenizeNginxConfig(c *gin.Context) { Content string `json:"content" binding:"required"` } - if !BindAndValid(c, &json) { + if !api.BindAndValid(c, &json) { return } @@ -39,7 +40,7 @@ func FormatNginxConfig(c *gin.Context) { Content string `json:"content" binding:"required"` } - if !BindAndValid(c, &json) { + if !api.BindAndValid(c, &json) { return } @@ -49,7 +50,7 @@ func FormatNginxConfig(c *gin.Context) { }) } -func NginxStatus(c *gin.Context) { +func Status(c *gin.Context) { pidPath := nginx2.GetNginxPIDPath() running := true @@ -62,26 +63,3 @@ func NginxStatus(c *gin.Context) { }) } -func ReloadNginx(c *gin.Context) { - output := nginx2.Reload() - c.JSON(http.StatusOK, gin.H{ - "message": output, - "level": nginx2.GetLogLevel(output), - }) -} - -func TestNginx(c *gin.Context) { - output := nginx2.TestConf() - c.JSON(http.StatusOK, gin.H{ - "message": output, - "level": nginx2.GetLogLevel(output), - }) -} - -func RestartNginx(c *gin.Context) { - output := nginx2.Restart() - c.JSON(http.StatusOK, gin.H{ - "message": output, - "level": nginx2.GetLogLevel(output), - }) -} diff --git a/api/nginx_log.go b/api/nginx/nginx_log.go similarity index 98% rename from api/nginx_log.go rename to api/nginx/nginx_log.go index 09cf6b31..a78fe9e7 100644 --- a/api/nginx_log.go +++ b/api/nginx/nginx_log.go @@ -1,7 +1,8 @@ -package api +package nginx import ( "encoding/json" + "github.com/0xJacky/Nginx-UI/api" "github.com/0xJacky/Nginx-UI/internal/helper" "github.com/0xJacky/Nginx-UI/internal/logger" nginx2 "github.com/0xJacky/Nginx-UI/internal/nginx" @@ -39,7 +40,7 @@ func GetNginxLogPage(c *gin.Context) { } var control controlStruct - if !BindAndValid(c, &control) { + if !api.BindAndValid(c, &control) { return } diff --git a/api/nginx/router.go b/api/nginx/router.go new file mode 100644 index 00000000..899187c7 --- /dev/null +++ b/api/nginx/router.go @@ -0,0 +1,18 @@ +package nginx + +import "github.com/gin-gonic/gin" + +func InitRouter(r *gin.RouterGroup) { + r.POST("ngx/build_config", BuildNginxConfig) + r.POST("ngx/tokenize_config", TokenizeNginxConfig) + r.POST("ngx/format_code", FormatNginxConfig) + r.POST("nginx/reload", Reload) + r.POST("nginx/restart", Restart) + r.POST("nginx/test", Test) + r.GET("nginx/status", Status) + r.POST("nginx_log", GetNginxLogPage) +} + +func InitNginxLogRouter(r *gin.RouterGroup) { + r.GET("nginx_log", NginxLog) +} diff --git a/api/openai.go b/api/openai/openai.go similarity index 95% rename from api/openai.go rename to api/openai/openai.go index a7b16ea7..3a042988 100644 --- a/api/openai.go +++ b/api/openai/openai.go @@ -1,8 +1,9 @@ -package api +package openai import ( "context" "fmt" + "github.com/0xJacky/Nginx-UI/api" "github.com/0xJacky/Nginx-UI/model" "github.com/0xJacky/Nginx-UI/query" "github.com/0xJacky/Nginx-UI/settings" @@ -22,7 +23,7 @@ func MakeChatCompletionRequest(c *gin.Context) { Messages []openai.ChatCompletionMessage `json:"messages"` } - if !BindAndValid(c, &json) { + if !api.BindAndValid(c, &json) { return } @@ -139,7 +140,7 @@ func StoreChatGPTRecord(c *gin.Context) { Messages []openai.ChatCompletionMessage `json:"messages"` } - if !BindAndValid(c, &json) { + if !api.BindAndValid(c, &json) { return } @@ -148,7 +149,7 @@ func StoreChatGPTRecord(c *gin.Context) { _, err := g.Where(g.Name.Eq(name)).FirstOrCreate() if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -158,7 +159,7 @@ func StoreChatGPTRecord(c *gin.Context) { }) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } diff --git a/api/openai/router.go b/api/openai/router.go new file mode 100644 index 00000000..2ada146c --- /dev/null +++ b/api/openai/router.go @@ -0,0 +1,9 @@ +package openai + +import "github.com/gin-gonic/gin" + +func InitRouter(r *gin.RouterGroup) { + // ChatGPT + r.POST("chat_gpt", MakeChatCompletionRequest) + r.POST("chat_gpt_record", StoreChatGPTRecord) +} diff --git a/api/settings.go b/api/settings.go deleted file mode 100644 index f972803f..00000000 --- a/api/settings.go +++ /dev/null @@ -1,61 +0,0 @@ -package api - -import ( - "fmt" - "github.com/0xJacky/Nginx-UI/settings" - "github.com/gin-gonic/gin" - "net/http" - "net/url" -) - -func GetSettings(c *gin.Context) { - c.JSON(http.StatusOK, gin.H{ - "server": settings.ServerSettings, - "nginx": settings.NginxSettings, - "openai": settings.OpenAISettings, - }) -} - -func SaveSettings(c *gin.Context) { - var json struct { - Server settings.Server `json:"server"` - Nginx settings.Nginx `json:"nginx"` - Openai settings.OpenAI `json:"openai"` - } - - if !BindAndValid(c, &json) { - return - } - - settings.ServerSettings = json.Server - settings.NginxSettings = json.Nginx - settings.OpenAISettings = json.Openai - - settings.ReflectFrom() - - err := settings.Save() - if err != nil { - ErrHandler(c, err) - return - } - - GetSettings(c) -} - -func GetCasdoorUri(c *gin.Context) { - endpoint := settings.ServerSettings.CasdoorEndpoint - clientId := settings.ServerSettings.CasdoorClientId - redirectUri := settings.ServerSettings.CasdoorRedirectUri - state := settings.ServerSettings.CasdoorApplication - fmt.Println(redirectUri) - if endpoint == "" || clientId == "" || redirectUri == "" || state == "" { - c.JSON(http.StatusOK, gin.H{ - "uri": "", - }) - return - } - encodedRedirectUri := url.QueryEscape(redirectUri) - c.JSON(http.StatusOK, gin.H{ - "uri": fmt.Sprintf("%s/login/oauth/authorize?client_id=%s&response_type=code&redirect_uri=%s&state=%s&scope=read", endpoint, clientId, encodedRedirectUri, state), - }) -} diff --git a/api/domain.go b/api/sites/domain.go similarity index 89% rename from api/domain.go rename to api/sites/domain.go index 30f5e2f0..ac007635 100644 --- a/api/domain.go +++ b/api/sites/domain.go @@ -1,19 +1,20 @@ -package api +package sites import ( - "github.com/0xJacky/Nginx-UI/internal/cert" - "github.com/0xJacky/Nginx-UI/internal/config_list" - helper2 "github.com/0xJacky/Nginx-UI/internal/helper" - "github.com/0xJacky/Nginx-UI/internal/logger" - nginx2 "github.com/0xJacky/Nginx-UI/internal/nginx" - "github.com/0xJacky/Nginx-UI/model" - "github.com/0xJacky/Nginx-UI/query" - "github.com/gin-gonic/gin" - "github.com/sashabaranov/go-openai" - "net/http" - "os" - "strings" - "time" + "github.com/0xJacky/Nginx-UI/api" + "github.com/0xJacky/Nginx-UI/internal/cert" + "github.com/0xJacky/Nginx-UI/internal/config_list" + helper2 "github.com/0xJacky/Nginx-UI/internal/helper" + "github.com/0xJacky/Nginx-UI/internal/logger" + nginx2 "github.com/0xJacky/Nginx-UI/internal/nginx" + "github.com/0xJacky/Nginx-UI/model" + "github.com/0xJacky/Nginx-UI/query" + "github.com/gin-gonic/gin" + "github.com/sashabaranov/go-openai" + "net/http" + "os" + "strings" + "time" ) func GetDomains(c *gin.Context) { @@ -30,14 +31,14 @@ func GetDomains(c *gin.Context) { configFiles, err := os.ReadDir(nginx2.GetConfPath("sites-available")) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } enabledConfig, err := os.ReadDir(nginx2.GetConfPath("sites-enabled")) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -107,7 +108,7 @@ func GetDomain(c *gin.Context) { chatgpt, err := g.Where(g.Name.Eq(path)).FirstOrCreate() if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -119,7 +120,7 @@ func GetDomain(c *gin.Context) { site, err := s.Where(s.Path.Eq(path)).FirstOrInit() if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -132,7 +133,7 @@ func GetDomain(c *gin.Context) { if site.Advanced { origContent, err := os.ReadFile(path) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -152,7 +153,7 @@ func GetDomain(c *gin.Context) { config, err := nginx2.ParseNgxConfig(path) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -214,7 +215,7 @@ func SaveDomain(c *gin.Context) { Overwrite bool `json:"overwrite"` } - if !BindAndValid(c, &json) { + if !api.BindAndValid(c, &json) { return } @@ -229,7 +230,7 @@ func SaveDomain(c *gin.Context) { err := os.WriteFile(path, []byte(json.Content), 0644) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } enabledConfigFilePath := nginx2.GetConfPath("sites-enabled", name) @@ -253,14 +254,14 @@ func SaveDomain(c *gin.Context) { err = os.Symlink(newPath, enabledConfigFilePath) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } } err = os.Rename(path, newPath) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -301,7 +302,7 @@ func EnableDomain(c *gin.Context) { _, err := os.Stat(configFilePath) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -309,7 +310,7 @@ func EnableDomain(c *gin.Context) { err = os.Symlink(configFilePath, enabledConfigFilePath) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } } @@ -345,14 +346,14 @@ func DisableDomain(c *gin.Context) { _, err := os.Stat(enabledConfigFilePath) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } err = os.Remove(enabledConfigFilePath) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -360,7 +361,7 @@ func DisableDomain(c *gin.Context) { certModel := model.Cert{Filename: c.Param("name")} err = certModel.Remove() if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -404,7 +405,7 @@ func DeleteDomain(c *gin.Context) { err = os.Remove(availablePath) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -418,18 +419,18 @@ func AddDomainToAutoCert(c *gin.Context) { name := c.Param("name") var json struct { - model.Cert + model.Cert Domains []string `json:"domains"` } - if !BindAndValid(c, &json) { + if !api.BindAndValid(c, &json) { return } certModel, err := model.FirstOrCreateCert(name) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -442,7 +443,7 @@ func AddDomainToAutoCert(c *gin.Context) { }) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -454,7 +455,7 @@ func RemoveDomainFromAutoCert(c *gin.Context) { certModel, err := model.FirstCert(name) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -463,7 +464,7 @@ func RemoveDomainFromAutoCert(c *gin.Context) { }) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } c.JSON(http.StatusOK, nil) @@ -476,7 +477,7 @@ func DuplicateSite(c *gin.Context) { Name string `json:"name" binding:"required"` } - if !BindAndValid(c, &json) { + if !api.BindAndValid(c, &json) { return } @@ -493,7 +494,7 @@ func DuplicateSite(c *gin.Context) { _, err := helper2.CopyFile(src, dst) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -507,7 +508,7 @@ func DomainEditByAdvancedMode(c *gin.Context) { Advanced bool `json:"advanced"` } - if !BindAndValid(c, &json) { + if !api.BindAndValid(c, &json) { return } @@ -518,14 +519,14 @@ func DomainEditByAdvancedMode(c *gin.Context) { _, err := s.Where(s.Path.Eq(path)).FirstOrCreate() if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } _, err = s.Where(s.Path.Eq(path)).Update(s.Advanced, json.Advanced) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } diff --git a/api/sites/router.go b/api/sites/router.go new file mode 100644 index 00000000..847d223d --- /dev/null +++ b/api/sites/router.go @@ -0,0 +1,16 @@ +package sites + +import "github.com/gin-gonic/gin" + +func InitRouter(r *gin.RouterGroup) { + r.GET("domains", GetDomains) + r.GET("domain/:name", GetDomain) + r.POST("domain/:name", SaveDomain) + r.POST("domain/:name/enable", EnableDomain) + r.POST("domain/:name/disable", DisableDomain) + r.POST("domain/:name/advance", DomainEditByAdvancedMode) + r.DELETE("domain/:name", DeleteDomain) + r.POST("domain/:name/duplicate", DuplicateSite) + r.POST("auto_cert/:name", AddDomainToAutoCert) + r.DELETE("auto_cert/:name", RemoveDomainFromAutoCert) +} diff --git a/api/install.go b/api/system/install.go similarity index 92% rename from api/install.go rename to api/system/install.go index 404382df..f34a90d9 100644 --- a/api/install.go +++ b/api/system/install.go @@ -1,6 +1,7 @@ -package api +package system import ( + "github.com/0xJacky/Nginx-UI/api" "github.com/0xJacky/Nginx-UI/internal/boot" "github.com/0xJacky/Nginx-UI/model" "github.com/0xJacky/Nginx-UI/query" @@ -37,7 +38,7 @@ func InstallNginxUI(c *gin.Context) { return } var json InstallJson - ok := BindAndValid(c, &json) + ok := api.BindAndValid(c, &json) if !ok { return } @@ -52,7 +53,7 @@ func InstallNginxUI(c *gin.Context) { err := settings.Save() if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -68,7 +69,7 @@ func InstallNginxUI(c *gin.Context) { }) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } c.JSON(http.StatusOK, gin.H{ diff --git a/api/system/router.go b/api/system/router.go new file mode 100644 index 00000000..e9b516d9 --- /dev/null +++ b/api/system/router.go @@ -0,0 +1,20 @@ +package system + +import ( + "github.com/gin-gonic/gin" +) + +func InitPublicRouter(r *gin.RouterGroup) { + r.GET("install", InstallLockCheck) + r.POST("install", InstallNginxUI) + r.GET("translation/:code", GetTranslation) +} + +func InitPrivateRouter(r *gin.RouterGroup) { + r.GET("settings", GetSettings) + r.POST("settings", SaveSettings) + + r.GET("upgrade/release", GetRelease) + r.GET("upgrade/current", GetCurrentVersion) + r.GET("upgrade/perform", PerformCoreUpgrade) +} diff --git a/api/system/settings.go b/api/system/settings.go new file mode 100644 index 00000000..6908111c --- /dev/null +++ b/api/system/settings.go @@ -0,0 +1,42 @@ +package system + +import ( + "github.com/0xJacky/Nginx-UI/api" + "github.com/0xJacky/Nginx-UI/settings" + "github.com/gin-gonic/gin" + "net/http" +) + +func GetSettings(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{ + "server": settings.ServerSettings, + "nginx": settings.NginxSettings, + "openai": settings.OpenAISettings, + }) +} + +func SaveSettings(c *gin.Context) { + var json struct { + Server settings.Server `json:"server"` + Nginx settings.Nginx `json:"nginx"` + Openai settings.OpenAI `json:"openai"` + } + + if !api.BindAndValid(c, &json) { + return + } + + settings.ServerSettings = json.Server + settings.NginxSettings = json.Nginx + settings.OpenAISettings = json.Openai + + settings.ReflectFrom() + + err := settings.Save() + if err != nil { + api.ErrHandler(c, err) + return + } + + GetSettings(c) +} diff --git a/api/translation.go b/api/system/translation.go similarity index 59% rename from api/translation.go rename to api/system/translation.go index b7373e64..fc9cc70e 100644 --- a/api/translation.go +++ b/api/system/translation.go @@ -1,4 +1,4 @@ -package api +package system import ( "github.com/0xJacky/Nginx-UI/internal/translation" @@ -7,7 +7,7 @@ import ( ) func GetTranslation(c *gin.Context) { - code := c.Param("code") + code := c.Param("code") - c.JSON(http.StatusOK, translation.GetTranslation(code)) + c.JSON(http.StatusOK, translation.GetTranslation(code)) } diff --git a/api/upgrade.go b/api/system/upgrade.go similarity index 95% rename from api/upgrade.go rename to api/system/upgrade.go index f42f27e0..83de6ab3 100644 --- a/api/upgrade.go +++ b/api/system/upgrade.go @@ -1,6 +1,7 @@ -package api +package system import ( + "github.com/0xJacky/Nginx-UI/api" "github.com/0xJacky/Nginx-UI/internal/logger" "github.com/0xJacky/Nginx-UI/internal/upgrader" "github.com/0xJacky/Nginx-UI/settings" @@ -13,12 +14,12 @@ import ( func GetRelease(c *gin.Context) { data, err := upgrader.GetRelease(c.Query("channel")) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } runtimeInfo, err := upgrader.GetRuntimeInfo() if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } type resp struct { @@ -33,7 +34,7 @@ func GetRelease(c *gin.Context) { func GetCurrentVersion(c *gin.Context) { curVer, err := upgrader.GetCurrentVersion() if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } diff --git a/api/template/router.go b/api/template/router.go new file mode 100644 index 00000000..0b58073a --- /dev/null +++ b/api/template/router.go @@ -0,0 +1,11 @@ +package template + +import "github.com/gin-gonic/gin" + +func InitRouter(r *gin.RouterGroup) { + r.GET("template", GetTemplate) + r.GET("template/configs", GetTemplateConfList) + r.GET("template/blocks", GetTemplateBlockList) + r.GET("template/block/:name", GetTemplateBlock) + r.POST("template/block/:name", GetTemplateBlock) +} diff --git a/api/template.go b/api/template/template.go similarity index 92% rename from api/template.go rename to api/template/template.go index c2f362c0..d635e40e 100644 --- a/api/template.go +++ b/api/template/template.go @@ -1,6 +1,7 @@ -package api +package template import ( + "github.com/0xJacky/Nginx-UI/api" "github.com/0xJacky/Nginx-UI/internal/nginx" "github.com/0xJacky/Nginx-UI/internal/template" "github.com/gin-gonic/gin" @@ -48,7 +49,7 @@ func GetTemplateConfList(c *gin.Context) { configList, err := template.GetTemplateList("conf") if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -61,7 +62,7 @@ func GetTemplateBlockList(c *gin.Context) { configList, err := template.GetTemplateList("block") if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } @@ -85,7 +86,7 @@ func GetTemplateBlock(c *gin.Context) { detail, err := template.ParseTemplate("block", c.Param("name"), bindData) if err != nil { - ErrHandler(c, err) + api.ErrHandler(c, err) return } info.Variables = bindData diff --git a/api/pty.go b/api/terminal/pty.go similarity index 97% rename from api/pty.go rename to api/terminal/pty.go index e2227d0c..c8cde40b 100644 --- a/api/pty.go +++ b/api/terminal/pty.go @@ -1,4 +1,4 @@ -package api +package terminal import ( "github.com/0xJacky/Nginx-UI/internal/logger" diff --git a/api/terminal/router.go b/api/terminal/router.go new file mode 100644 index 00000000..594b43de --- /dev/null +++ b/api/terminal/router.go @@ -0,0 +1,7 @@ +package terminal + +import "github.com/gin-gonic/gin" + +func InitRouter(r *gin.RouterGroup) { + r.GET("pty", Pty) +} diff --git a/api/user.go b/api/user.go deleted file mode 100644 index 3593b3b9..00000000 --- a/api/user.go +++ /dev/null @@ -1,136 +0,0 @@ -package api - -import ( - "github.com/0xJacky/Nginx-UI/model" - "github.com/0xJacky/Nginx-UI/query" - "github.com/0xJacky/Nginx-UI/settings" - "github.com/gin-gonic/gin" - "github.com/spf13/cast" - "golang.org/x/crypto/bcrypt" - "net/http" -) - -func GetUsers(c *gin.Context) { - data := model.GetUserList(c, c.Query("name")) - - c.JSON(http.StatusOK, data) -} - -func GetUser(c *gin.Context) { - id := cast.ToInt(c.Param("id")) - - u := query.Auth - - user, err := u.FirstByID(id) - - if err != nil { - ErrHandler(c, err) - return - } - - c.JSON(http.StatusOK, user) -} - -type UserJson struct { - Name string `json:"name" binding:"required,max=255"` - Password string `json:"password" binding:"max=255"` -} - -func AddUser(c *gin.Context) { - var json UserJson - ok := BindAndValid(c, &json) - if !ok { - return - } - - u := query.Auth - - pwd, err := bcrypt.GenerateFromPassword([]byte(json.Password), bcrypt.DefaultCost) - if err != nil { - ErrHandler(c, err) - return - } - json.Password = string(pwd) - - user := model.Auth{ - Name: json.Name, - Password: json.Password, - } - - err = u.Create(&user) - - if err != nil { - ErrHandler(c, err) - return - } - - c.JSON(http.StatusOK, user) - -} - -func EditUser(c *gin.Context) { - userId := cast.ToInt(c.Param("id")) - - if settings.ServerSettings.Demo && userId == 1 { - c.JSON(http.StatusNotAcceptable, gin.H{ - "message": "Prohibit changing root password in demo", - }) - return - } - - var json UserJson - ok := BindAndValid(c, &json) - if !ok { - return - } - - u := query.Auth - user, err := u.FirstByID(userId) - - if err != nil { - ErrHandler(c, err) - return - } - edit := &model.Auth{ - Name: json.Name, - } - - // encrypt password - if json.Password != "" { - var pwd []byte - pwd, err = bcrypt.GenerateFromPassword([]byte(json.Password), bcrypt.DefaultCost) - if err != nil { - ErrHandler(c, err) - return - } - edit.Password = string(pwd) - } - - _, err = u.Where(u.ID.Eq(userId)).Updates(&edit) - - if err != nil { - ErrHandler(c, err) - return - } - - c.JSON(http.StatusOK, user) -} - -func DeleteUser(c *gin.Context) { - id := cast.ToInt(c.Param("id")) - - if cast.ToInt(id) == 1 { - c.JSON(http.StatusNotAcceptable, gin.H{ - "message": "Prohibit deleting the default user", - }) - return - } - - u := query.Auth - err := u.DeleteByID(id) - if err != nil { - ErrHandler(c, err) - return - } - c.JSON(http.StatusNoContent, gin.H{}) -} diff --git a/api/auth.go b/api/user/auth.go similarity index 96% rename from api/auth.go rename to api/user/auth.go index ecf63ed1..2e35b816 100644 --- a/api/auth.go +++ b/api/user/auth.go @@ -1,7 +1,8 @@ -package api +package user import ( "fmt" + "github.com/0xJacky/Nginx-UI/api" "github.com/0xJacky/Nginx-UI/model" "github.com/0xJacky/Nginx-UI/settings" "net/http" @@ -20,7 +21,7 @@ type LoginUser struct { func Login(c *gin.Context) { var user LoginUser - ok := BindAndValid(c, &user) + ok := api.BindAndValid(c, &user) if !ok { return } @@ -70,7 +71,7 @@ type CasdoorLoginUser struct { func CasdoorCallback(c *gin.Context) { var loginUser CasdoorLoginUser fmt.Println("CasdoorCallback called") - ok := BindAndValid(c, &loginUser) + ok := api.BindAndValid(c, &loginUser) if !ok { return } diff --git a/api/user/casdoor.go b/api/user/casdoor.go new file mode 100644 index 00000000..d76a9b9b --- /dev/null +++ b/api/user/casdoor.go @@ -0,0 +1,27 @@ +package user + +import ( + "fmt" + "github.com/0xJacky/Nginx-UI/settings" + "github.com/gin-gonic/gin" + "net/http" + "net/url" +) + +func GetCasdoorUri(c *gin.Context) { + endpoint := settings.ServerSettings.CasdoorEndpoint + clientId := settings.ServerSettings.CasdoorClientId + redirectUri := settings.ServerSettings.CasdoorRedirectUri + state := settings.ServerSettings.CasdoorApplication + fmt.Println(redirectUri) + if endpoint == "" || clientId == "" || redirectUri == "" || state == "" { + c.JSON(http.StatusOK, gin.H{ + "uri": "", + }) + return + } + encodedRedirectUri := url.QueryEscape(redirectUri) + c.JSON(http.StatusOK, gin.H{ + "uri": fmt.Sprintf("%s/login/oauth/authorize?client_id=%s&response_type=code&redirect_uri=%s&state=%s&scope=read", endpoint, clientId, encodedRedirectUri, state), + }) +} diff --git a/api/user/router.go b/api/user/router.go new file mode 100644 index 00000000..ee50f702 --- /dev/null +++ b/api/user/router.go @@ -0,0 +1,19 @@ +package user + +import "github.com/gin-gonic/gin" + +func InitAuthRouter(r *gin.RouterGroup) { + r.POST("/login", Login) + r.DELETE("/logout", Logout) + + r.GET("/casdoor_uri", GetCasdoorUri) + r.POST("/casdoor_callback", CasdoorCallback) +} + +func InitManageUserRouter(r *gin.RouterGroup) { + r.GET("users", GetUsers) + r.GET("user/:id", GetUser) + r.POST("user", AddUser) + r.POST("user/:id", EditUser) + r.DELETE("user/:id", DeleteUser) +} diff --git a/api/user/user.go b/api/user/user.go new file mode 100644 index 00000000..b3865a64 --- /dev/null +++ b/api/user/user.go @@ -0,0 +1,137 @@ +package user + +import ( + "github.com/0xJacky/Nginx-UI/api" + "github.com/0xJacky/Nginx-UI/model" + "github.com/0xJacky/Nginx-UI/query" + "github.com/0xJacky/Nginx-UI/settings" + "github.com/gin-gonic/gin" + "github.com/spf13/cast" + "golang.org/x/crypto/bcrypt" + "net/http" +) + +func GetUsers(c *gin.Context) { + data := model.GetUserList(c, c.Query("name")) + + c.JSON(http.StatusOK, data) +} + +func GetUser(c *gin.Context) { + id := cast.ToInt(c.Param("id")) + + u := query.Auth + + user, err := u.FirstByID(id) + + if err != nil { + api.ErrHandler(c, err) + return + } + + c.JSON(http.StatusOK, user) +} + +type UserJson struct { + Name string `json:"name" binding:"required,max=255"` + Password string `json:"password" binding:"max=255"` +} + +func AddUser(c *gin.Context) { + var json UserJson + ok := api.BindAndValid(c, &json) + if !ok { + return + } + + u := query.Auth + + pwd, err := bcrypt.GenerateFromPassword([]byte(json.Password), bcrypt.DefaultCost) + if err != nil { + api.ErrHandler(c, err) + return + } + json.Password = string(pwd) + + user := model.Auth{ + Name: json.Name, + Password: json.Password, + } + + err = u.Create(&user) + + if err != nil { + api.ErrHandler(c, err) + return + } + + c.JSON(http.StatusOK, user) + +} + +func EditUser(c *gin.Context) { + userId := cast.ToInt(c.Param("id")) + + if settings.ServerSettings.Demo && userId == 1 { + c.JSON(http.StatusNotAcceptable, gin.H{ + "message": "Prohibit changing root password in demo", + }) + return + } + + var json UserJson + ok := api.BindAndValid(c, &json) + if !ok { + return + } + + u := query.Auth + user, err := u.FirstByID(userId) + + if err != nil { + api.ErrHandler(c, err) + return + } + edit := &model.Auth{ + Name: json.Name, + } + + // encrypt password + if json.Password != "" { + var pwd []byte + pwd, err = bcrypt.GenerateFromPassword([]byte(json.Password), bcrypt.DefaultCost) + if err != nil { + api.ErrHandler(c, err) + return + } + edit.Password = string(pwd) + } + + _, err = u.Where(u.ID.Eq(userId)).Updates(&edit) + + if err != nil { + api.ErrHandler(c, err) + return + } + + c.JSON(http.StatusOK, user) +} + +func DeleteUser(c *gin.Context) { + id := cast.ToInt(c.Param("id")) + + if cast.ToInt(id) == 1 { + c.JSON(http.StatusNotAcceptable, gin.H{ + "message": "Prohibit deleting the default user", + }) + return + } + + u := query.Auth + err := u.DeleteByID(id) + if err != nil { + api.ErrHandler(c, err) + return + } + c.JSON(http.StatusNoContent, gin.H{}) +} diff --git a/app/src/version.json b/app/src/version.json index f7d1cff5..ad38315e 100644 --- a/app/src/version.json +++ b/app/src/version.json @@ -1 +1 @@ -{"version":"2.0.0-beta.4","build_id":49,"total_build":253} \ No newline at end of file +{"version":"2.0.0-beta.4","build_id":50,"total_build":254} \ No newline at end of file diff --git a/app/version.json b/app/version.json index f7d1cff5..ad38315e 100644 --- a/app/version.json +++ b/app/version.json @@ -1 +1 @@ -{"version":"2.0.0-beta.4","build_id":49,"total_build":253} \ No newline at end of file +{"version":"2.0.0-beta.4","build_id":50,"total_build":254} \ No newline at end of file diff --git a/router/routers.go b/router/routers.go index fb9295ef..baa912c8 100644 --- a/router/routers.go +++ b/router/routers.go @@ -1,157 +1,70 @@ package router import ( - api2 "github.com/0xJacky/Nginx-UI/api" - "github.com/gin-contrib/static" - "github.com/gin-gonic/gin" - "net/http" + "github.com/0xJacky/Nginx-UI/api/analytic" + "github.com/0xJacky/Nginx-UI/api/certificate" + "github.com/0xJacky/Nginx-UI/api/cluster" + "github.com/0xJacky/Nginx-UI/api/config" + "github.com/0xJacky/Nginx-UI/api/nginx" + "github.com/0xJacky/Nginx-UI/api/openai" + "github.com/0xJacky/Nginx-UI/api/sites" + "github.com/0xJacky/Nginx-UI/api/system" + "github.com/0xJacky/Nginx-UI/api/template" + "github.com/0xJacky/Nginx-UI/api/terminal" + "github.com/0xJacky/Nginx-UI/api/user" + "github.com/gin-contrib/static" + "github.com/gin-gonic/gin" + "net/http" ) func InitRouter() *gin.Engine { - r := gin.New() - r.Use(gin.Logger()) + r := gin.New() + r.Use(gin.Logger()) - r.Use(recovery()) + r.Use(recovery()) - r.Use(cacheJs()) + r.Use(cacheJs()) - //r.Use(OperationSync()) + //r.Use(OperationSync()) - r.Use(static.Serve("/", mustFS(""))) + r.Use(static.Serve("/", mustFS(""))) - r.NoRoute(func(c *gin.Context) { - c.JSON(http.StatusNotFound, gin.H{ - "message": "not found", - }) - }) + r.NoRoute(func(c *gin.Context) { + c.JSON(http.StatusNotFound, gin.H{ + "message": "not found", + }) + }) - root := r.Group("/api") - { - root.GET("install", api2.InstallLockCheck) - root.POST("install", api2.InstallNginxUI) + root := r.Group("/api") + { + system.InitPublicRouter(root) + user.InitAuthRouter(root) - root.POST("/login", api2.Login) - root.DELETE("/logout", api2.Logout) + // Authorization required not websocket request + g := root.Group("/", authRequired(), proxy()) + { + analytic.InitRouter(g) + user.InitManageUserRouter(g) + nginx.InitRouter(g) + sites.InitRouter(g) + config.InitRouter(g) + template.InitRouter(g) + certificate.InitCertificateRouter(g) + certificate.InitDNSCredentialRouter(g) + system.InitPrivateRouter(g) + openai.InitRouter(g) + cluster.InitRouter(g) + } - root.GET("/casdoor_uri", api2.GetCasdoorUri) - root.POST("/casdoor_callback", api2.CasdoorCallback) + // Authorization required and websocket request + w := root.Group("/", authRequired(), proxyWs()) + { + analytic.InitWebSocketRouter(w) + terminal.InitRouter(w) + nginx.InitNginxLogRouter(w) + } - // translation - root.GET("translation/:code", api2.GetTranslation) + } - w := root.Group("/", authRequired(), proxyWs()) - { - // Analytic - w.GET("analytic", api2.Analytic) - w.GET("analytic/intro", api2.GetNodeStat) - w.GET("analytic/nodes", api2.GetNodesAnalytic) - // pty - w.GET("pty", api2.Pty) - // Nginx log - w.GET("nginx_log", api2.NginxLog) - } - - g := root.Group("/", authRequired(), proxy()) - { - - g.GET("analytic/init", api2.GetAnalyticInit) - - g.GET("users", api2.GetUsers) - g.GET("user/:id", api2.GetUser) - g.POST("user", api2.AddUser) - g.POST("user/:id", api2.EditUser) - g.DELETE("user/:id", api2.DeleteUser) - - g.GET("domains", api2.GetDomains) - g.GET("domain/:name", api2.GetDomain) - - // Modify site configuration directly - g.POST("domain/:name", api2.SaveDomain) - - // Transform NgxConf to nginx configuration - g.POST("ngx/build_config", api2.BuildNginxConfig) - // Tokenized nginx configuration to NgxConf - g.POST("ngx/tokenize_config", api2.TokenizeNginxConfig) - // Format nginx configuration code - g.POST("ngx/format_code", api2.FormatNginxConfig) - - g.POST("nginx/reload", api2.ReloadNginx) - g.POST("nginx/restart", api2.RestartNginx) - g.POST("nginx/test", api2.TestNginx) - g.GET("nginx/status", api2.NginxStatus) - - g.POST("domain/:name/enable", api2.EnableDomain) - g.POST("domain/:name/disable", api2.DisableDomain) - g.POST("domain/:name/advance", api2.DomainEditByAdvancedMode) - - g.DELETE("domain/:name", api2.DeleteDomain) - - g.POST("domain/:name/duplicate", api2.DuplicateSite) - g.GET("domain/:name/cert", api2.IssueCert) - - g.GET("configs", api2.GetConfigs) - g.GET("config/*name", api2.GetConfig) - g.POST("config", api2.AddConfig) - g.POST("config/*name", api2.EditConfig) - - //g.GET("backups", api.GetFileBackupList) - //g.GET("backup/:id", api.GetFileBackup) - - g.GET("template", api2.GetTemplate) - g.GET("template/configs", api2.GetTemplateConfList) - g.GET("template/blocks", api2.GetTemplateBlockList) - g.GET("template/block/:name", api2.GetTemplateBlock) - g.POST("template/block/:name", api2.GetTemplateBlock) - - g.GET("certs", api2.GetCertList) - g.GET("cert/:id", api2.GetCert) - g.POST("cert", api2.AddCert) - g.POST("cert/:id", api2.ModifyCert) - g.DELETE("cert/:id", api2.RemoveCert) - - // Add domain to auto-renew cert list - g.POST("auto_cert/:name", api2.AddDomainToAutoCert) - // Delete domain from auto-renew cert list - g.DELETE("auto_cert/:name", api2.RemoveDomainFromAutoCert) - g.GET("auto_cert/dns/providers", api2.GetDNSProvidersList) - g.GET("auto_cert/dns/provider/:code", api2.GetDNSProvider) - - // DNS Credential - g.GET("dns_credentials", api2.GetDnsCredentialList) - g.GET("dns_credential/:id", api2.GetDnsCredential) - g.POST("dns_credential", api2.AddDnsCredential) - g.POST("dns_credential/:id", api2.EditDnsCredential) - g.DELETE("dns_credential/:id", api2.DeleteDnsCredential) - - g.POST("nginx_log", api2.GetNginxLogPage) - - // Settings - g.GET("settings", api2.GetSettings) - g.POST("settings", api2.SaveSettings) - - // Upgrade - g.GET("upgrade/release", api2.GetRelease) - g.GET("upgrade/current", api2.GetCurrentVersion) - g.GET("upgrade/perform", api2.PerformCoreUpgrade) - - // ChatGPT - g.POST("chat_gpt", api2.MakeChatCompletionRequest) - g.POST("chat_gpt_record", api2.StoreChatGPTRecord) - - // Environment - g.GET("environments", api2.GetEnvironmentList) - envGroup := g.Group("environment") - { - envGroup.GET("/:id", api2.GetEnvironment) - envGroup.POST("", api2.AddEnvironment) - envGroup.POST("/:id", api2.EditEnvironment) - envGroup.DELETE("/:id", api2.DeleteEnvironment) - } - - // node - g.GET("node", api2.GetCurrentNode) - } - } - - return r + return r }