mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 18:35:51 +02:00
feat(site): sync operation
This commit is contained in:
parent
6c137e5229
commit
22e37e4b61
43 changed files with 4875 additions and 3712 deletions
|
@ -2,15 +2,14 @@ package sites
|
|||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/api"
|
||||
"github.com/0xJacky/Nginx-UI/internal/helper"
|
||||
"github.com/0xJacky/Nginx-UI/internal/nginx"
|
||||
"github.com/0xJacky/Nginx-UI/internal/site"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func DuplicateSite(c *gin.Context) {
|
||||
// Source name
|
||||
name := c.Param("name")
|
||||
src := c.Param("name")
|
||||
|
||||
// Destination name
|
||||
var json struct {
|
||||
|
@ -21,24 +20,13 @@ func DuplicateSite(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
src := nginx.GetConfPath("sites-available", name)
|
||||
dst := nginx.GetConfPath("sites-available", json.Name)
|
||||
|
||||
if helper.FileExists(dst) {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"message": "File exists",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
_, err := helper.CopyFile(src, dst)
|
||||
|
||||
err := site.Duplicate(src, json.Name)
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"dst": dst,
|
||||
"message": "ok",
|
||||
})
|
||||
}
|
||||
|
|
|
@ -3,17 +3,25 @@ package sites
|
|||
import "github.com/gin-gonic/gin"
|
||||
|
||||
func InitRouter(r *gin.RouterGroup) {
|
||||
r.GET("domains", GetSiteList)
|
||||
r.GET("domains/:name", GetSite)
|
||||
r.POST("domains/:name", SaveSite)
|
||||
r.PUT("domains", BatchUpdateSites)
|
||||
r.POST("domains/:name/enable", EnableSite)
|
||||
r.POST("domains/:name/disable", DisableSite)
|
||||
r.POST("domains/:name/advance", DomainEditByAdvancedMode)
|
||||
r.DELETE("domains/:name", DeleteSite)
|
||||
r.POST("domains/:name/duplicate", DuplicateSite)
|
||||
r.GET("sites", GetSiteList)
|
||||
r.GET("sites/:name", GetSite)
|
||||
r.PUT("sites", BatchUpdateSites)
|
||||
r.POST("sites/:name/advance", DomainEditByAdvancedMode)
|
||||
r.POST("auto_cert/:name", AddDomainToAutoCert)
|
||||
r.DELETE("auto_cert/:name", RemoveDomainFromAutoCert)
|
||||
|
||||
// rename site
|
||||
r.POST("sites/:name/rename", RenameSite)
|
||||
// enable site
|
||||
r.POST("sites/:name/enable", EnableSite)
|
||||
// disable site
|
||||
r.POST("sites/:name/disable", DisableSite)
|
||||
// save site
|
||||
r.POST("sites/:name", SaveSite)
|
||||
// delete site
|
||||
r.DELETE("sites/:name", DeleteSite)
|
||||
// duplicate site
|
||||
r.POST("sites/:name/duplicate", DuplicateSite)
|
||||
}
|
||||
|
||||
func InitCategoryRouter(r *gin.RouterGroup) {
|
||||
|
|
|
@ -3,8 +3,8 @@ package sites
|
|||
import (
|
||||
"github.com/0xJacky/Nginx-UI/api"
|
||||
"github.com/0xJacky/Nginx-UI/internal/cert"
|
||||
"github.com/0xJacky/Nginx-UI/internal/helper"
|
||||
"github.com/0xJacky/Nginx-UI/internal/nginx"
|
||||
"github.com/0xJacky/Nginx-UI/internal/site"
|
||||
"github.com/0xJacky/Nginx-UI/model"
|
||||
"github.com/0xJacky/Nginx-UI/query"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
@ -17,14 +17,8 @@ import (
|
|||
)
|
||||
|
||||
func GetSite(c *gin.Context) {
|
||||
rewriteName, ok := c.Get("rewriteConfigFileName")
|
||||
name := c.Param("name")
|
||||
|
||||
// for modify filename
|
||||
if ok {
|
||||
name = rewriteName.(string)
|
||||
}
|
||||
|
||||
path := nginx.GetConfPath("sites-available", name)
|
||||
file, err := os.Stat(path)
|
||||
if os.IsNotExist(err) {
|
||||
|
@ -51,7 +45,7 @@ func GetSite(c *gin.Context) {
|
|||
}
|
||||
|
||||
s := query.Site
|
||||
site, err := s.Where(s.Path.Eq(path)).FirstOrCreate()
|
||||
siteModel, err := s.Where(s.Path.Eq(path)).FirstOrCreate()
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
|
@ -62,7 +56,7 @@ func GetSite(c *gin.Context) {
|
|||
logger.Warn(err)
|
||||
}
|
||||
|
||||
if site.Advanced {
|
||||
if siteModel.Advanced {
|
||||
origContent, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
|
@ -71,7 +65,7 @@ func GetSite(c *gin.Context) {
|
|||
|
||||
c.JSON(http.StatusOK, Site{
|
||||
ModifiedAt: file.ModTime(),
|
||||
Site: site,
|
||||
Site: siteModel,
|
||||
Enabled: enabled,
|
||||
Name: name,
|
||||
Config: string(origContent),
|
||||
|
@ -103,8 +97,8 @@ func GetSite(c *gin.Context) {
|
|||
}
|
||||
|
||||
c.JSON(http.StatusOK, Site{
|
||||
Site: siteModel,
|
||||
ModifiedAt: file.ModTime(),
|
||||
Site: site,
|
||||
Enabled: enabled,
|
||||
Name: name,
|
||||
Config: nginxConfig.FmtCode(),
|
||||
|
@ -119,15 +113,7 @@ func GetSite(c *gin.Context) {
|
|||
func SaveSite(c *gin.Context) {
|
||||
name := c.Param("name")
|
||||
|
||||
if name == "" {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"message": "param name is empty",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var json struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
Content string `json:"content" binding:"required"`
|
||||
SiteCategoryID uint64 `json:"site_category_id"`
|
||||
SyncNodeIDs []uint64 `json:"sync_node_ids"`
|
||||
|
@ -138,129 +124,39 @@ func SaveSite(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
path := nginx.GetConfPath("sites-available", name)
|
||||
|
||||
if !json.Overwrite && helper.FileExists(path) {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"message": "File exists",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
err := os.WriteFile(path, []byte(json.Content), 0644)
|
||||
err := site.Save(name, json.Content, json.Overwrite, json.SiteCategoryID, json.SyncNodeIDs)
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
enabledConfigFilePath := nginx.GetConfPath("sites-enabled", name)
|
||||
s := query.Site
|
||||
|
||||
_, err = s.Where(s.Path.Eq(path)).
|
||||
Select(s.SiteCategoryID, s.SyncNodeIDs).
|
||||
Updates(&model.Site{
|
||||
SiteCategoryID: json.SiteCategoryID,
|
||||
SyncNodeIDs: json.SyncNodeIDs,
|
||||
})
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
// rename the config file if needed
|
||||
if name != json.Name {
|
||||
newPath := nginx.GetConfPath("sites-available", json.Name)
|
||||
_, _ = s.Where(s.Path.Eq(path)).Update(s.Path, newPath)
|
||||
|
||||
// check if dst file exists, do not rename
|
||||
if helper.FileExists(newPath) {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"message": "File exists",
|
||||
})
|
||||
return
|
||||
}
|
||||
// recreate a soft link
|
||||
if helper.FileExists(enabledConfigFilePath) {
|
||||
_ = os.Remove(enabledConfigFilePath)
|
||||
enabledConfigFilePath = nginx.GetConfPath("sites-enabled", json.Name)
|
||||
err = os.Symlink(newPath, enabledConfigFilePath)
|
||||
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = os.Rename(path, newPath)
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
name = json.Name
|
||||
c.Set("rewriteConfigFileName", name)
|
||||
}
|
||||
|
||||
enabledConfigFilePath = nginx.GetConfPath("sites-enabled", name)
|
||||
if helper.FileExists(enabledConfigFilePath) {
|
||||
// Test nginx configuration
|
||||
output := nginx.TestConf()
|
||||
|
||||
if nginx.GetLogLevel(output) > nginx.Warn {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": output,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
output = nginx.Reload()
|
||||
|
||||
if nginx.GetLogLevel(output) > nginx.Warn {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": output,
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
GetSite(c)
|
||||
}
|
||||
|
||||
func EnableSite(c *gin.Context) {
|
||||
configFilePath := nginx.GetConfPath("sites-available", c.Param("name"))
|
||||
enabledConfigFilePath := nginx.GetConfPath("sites-enabled", c.Param("name"))
|
||||
|
||||
_, err := os.Stat(configFilePath)
|
||||
func RenameSite(c *gin.Context) {
|
||||
oldName := c.Param("name")
|
||||
var json struct {
|
||||
NewName string `json:"new_name"`
|
||||
}
|
||||
if !cosy.BindAndValid(c, &json) {
|
||||
return
|
||||
}
|
||||
|
||||
err := site.Rename(oldName, json.NewName)
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
if _, err = os.Stat(enabledConfigFilePath); os.IsNotExist(err) {
|
||||
err = os.Symlink(configFilePath, enabledConfigFilePath)
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "ok",
|
||||
})
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Test nginx config, if not pass, then disable the site.
|
||||
output := nginx.TestConf()
|
||||
if nginx.GetLogLevel(output) > nginx.Warn {
|
||||
_ = os.Remove(enabledConfigFilePath)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": output,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
output = nginx.Reload()
|
||||
|
||||
if nginx.GetLogLevel(output) > nginx.Warn {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": output,
|
||||
})
|
||||
func EnableSite(c *gin.Context) {
|
||||
err := site.Enable(c.Param("name"))
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -270,71 +166,19 @@ func EnableSite(c *gin.Context) {
|
|||
}
|
||||
|
||||
func DisableSite(c *gin.Context) {
|
||||
enabledConfigFilePath := nginx.GetConfPath("sites-enabled", c.Param("name"))
|
||||
_, err := os.Stat(enabledConfigFilePath)
|
||||
err := site.Disable(c.Param("name"))
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = os.Remove(enabledConfigFilePath)
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
// delete auto cert record
|
||||
certModel := model.Cert{Filename: c.Param("name")}
|
||||
err = certModel.Remove()
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
output := nginx.Reload()
|
||||
if nginx.GetLogLevel(output) > nginx.Warn {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": output,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "ok",
|
||||
})
|
||||
}
|
||||
|
||||
func DeleteSite(c *gin.Context) {
|
||||
var err error
|
||||
name := c.Param("name")
|
||||
availablePath := nginx.GetConfPath("sites-available", name)
|
||||
|
||||
s := query.Site
|
||||
_, err = s.Where(s.Path.Eq(availablePath)).Unscoped().Delete(&model.Site{})
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
enabledPath := nginx.GetConfPath("sites-enabled", name)
|
||||
if _, err = os.Stat(availablePath); os.IsNotExist(err) {
|
||||
c.JSON(http.StatusNotFound, gin.H{
|
||||
"message": "site not found",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if _, err = os.Stat(enabledPath); err == nil {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"message": "site is enabled",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
certModel := model.Cert{Filename: name}
|
||||
_ = certModel.Remove()
|
||||
|
||||
err = os.Remove(availablePath)
|
||||
err := site.Delete(c.Param("name"))
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue