Jelajahi Sumber

refactor: structure of api-router directory

0xJacky 1 tahun lalu
induk
melakukan
50b4fbcda4

+ 4 - 4
api/analytic.go → 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"`
 }

+ 15 - 0
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)
+}

+ 3 - 1
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)

+ 0 - 24
api/backup.go

@@ -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)
-}

+ 25 - 23
api/cert.go → 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
 	}
 

+ 11 - 10
api/dns_credential.go → 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)

+ 22 - 0
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)
+}

+ 13 - 12
api/environment.go → 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
 	}
 

+ 3 - 2
api/node.go → 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()

+ 17 - 0
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)
+}

+ 11 - 10
api/config.go → 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
 		}
 	}

+ 10 - 0
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)
+}

+ 31 - 0
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),
+	})
+}

+ 10 - 32
api/ngx.go → 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),
-	})
-}

+ 3 - 2
api/nginx_log.go → 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
 	}
 

+ 18 - 0
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)
+}

+ 6 - 5
api/openai.go → 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
 	}
 

+ 9 - 0
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)
+}

+ 0 - 61
api/settings.go

@@ -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),
-	})
-}

+ 42 - 41
api/domain.go → 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
 	}
 

+ 16 - 0
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)
+}

+ 5 - 4
api/install.go → 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{

+ 20 - 0
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)
+}

+ 42 - 0
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)
+}

+ 3 - 3
api/translation.go → 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))
 }

+ 5 - 4
api/upgrade.go → 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
 	}
 

+ 11 - 0
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)
+}

+ 5 - 4
api/template.go → 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

+ 1 - 1
api/pty.go → api/terminal/pty.go

@@ -1,4 +1,4 @@
-package api
+package terminal
 
 import (
 	"github.com/0xJacky/Nginx-UI/internal/logger"

+ 7 - 0
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)
+}

+ 0 - 136
api/user.go

@@ -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{})
-}

+ 4 - 3
api/auth.go → 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
 	}

+ 27 - 0
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),
+	})
+}

+ 19 - 0
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)
+}

+ 137 - 0
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{})
+}

+ 1 - 1
app/src/version.json

@@ -1 +1 @@
-{"version":"2.0.0-beta.4","build_id":49,"total_build":253}
+{"version":"2.0.0-beta.4","build_id":50,"total_build":254}

+ 1 - 1
app/version.json

@@ -1 +1 @@
-{"version":"2.0.0-beta.4","build_id":49,"total_build":253}
+{"version":"2.0.0-beta.4","build_id":50,"total_build":254}

+ 63 - 150
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.Use(recovery())
-
-	r.Use(cacheJs())
-
-	//r.Use(OperationSync())
-
-	r.Use(static.Serve("/", mustFS("")))
-
-	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.POST("/login", api2.Login)
-		root.DELETE("/logout", api2.Logout)
-
-		root.GET("/casdoor_uri", api2.GetCasdoorUri)
-		root.POST("/casdoor_callback", api2.CasdoorCallback)
-
-		// 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
+    r := gin.New()
+    r.Use(gin.Logger())
+
+    r.Use(recovery())
+
+    r.Use(cacheJs())
+
+    //r.Use(OperationSync())
+
+    r.Use(static.Serve("/", mustFS("")))
+
+    r.NoRoute(func(c *gin.Context) {
+        c.JSON(http.StatusNotFound, gin.H{
+            "message": "not found",
+        })
+    })
+
+    root := r.Group("/api")
+    {
+        system.InitPublicRouter(root)
+        user.InitAuthRouter(root)
+
+        // 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)
+        }
+
+        // Authorization required and websocket request
+        w := root.Group("/", authRequired(), proxyWs())
+        {
+            analytic.InitWebSocketRouter(w)
+            terminal.InitRouter(w)
+            nginx.InitNginxLogRouter(w)
+        }
+
+    }
+
+    return r
 }