| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 | package sitesimport (	"github.com/0xJacky/Nginx-UI/api"	"github.com/0xJacky/Nginx-UI/internal/cert"	"github.com/0xJacky/Nginx-UI/internal/config"	"github.com/0xJacky/Nginx-UI/internal/helper"	"github.com/0xJacky/Nginx-UI/internal/logger"	"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")func GetDomains(c *gin.Context) {	name := c.Query("name")	orderBy := c.Query("order_by")	sort := c.DefaultQuery("sort", "desc")	configFiles, err := os.ReadDir(nginx.GetConfPath("sites-available"))	if err != nil {		api.ErrHandler(c, err)		return	}	enabledConfig, err := os.ReadDir(nginx.GetConfPath("sites-enabled"))	if err != nil {		api.ErrHandler(c, err)		return	}	enabledConfigMap := make(map[string]bool)	for i := range enabledConfig {		enabledConfigMap[enabledConfig[i].Name()] = true	}	var configs []config.Config	for i := range configFiles {		file := configFiles[i]		fileInfo, _ := file.Info()		if !file.IsDir() {			if name != "" && !strings.Contains(file.Name(), name) {				continue			}			configs = append(configs, config.Config{				Name:       file.Name(),				ModifiedAt: fileInfo.ModTime(),				Size:       fileInfo.Size(),				IsDir:      fileInfo.IsDir(),				Enabled:    enabledConfigMap[file.Name()],			})		}	}	configs = config.Sort(orderBy, sort, configs)	c.JSON(http.StatusOK, gin.H{		"data": configs,	})}func GetDomain(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) {		c.JSON(http.StatusNotFound, gin.H{			"message": "file not found",		})		return	}	enabled := true	if _, err := os.Stat(nginx.GetConfPath("sites-enabled", name)); os.IsNotExist(err) {		enabled = false	}	g := query.ChatGPTLog	chatgpt, err := g.Where(g.Name.Eq(path)).FirstOrCreate()	if err != nil {		api.ErrHandler(c, err)		return	}	if chatgpt.Content == nil {		chatgpt.Content = make([]openai.ChatCompletionMessage, 0)	}	s := query.Site	site, err := s.Where(s.Path.Eq(path)).FirstOrInit()	if err != nil {		api.ErrHandler(c, err)		return	}	certModel, err := model.FirstCert(name)	if err != nil {		logger.Warn(err)	}	if site.Advanced {		origContent, err := os.ReadFile(path)		if err != nil {			api.ErrHandler(c, err)			return		}		c.JSON(http.StatusOK, Site{			ModifiedAt:      file.ModTime(),			Advanced:        site.Advanced,			Enabled:         enabled,			Name:            name,			Config:          string(origContent),			AutoCert:        certModel.AutoCert == model.AutoCertEnabled,			ChatGPTMessages: chatgpt.Content,		})		return	}	nginxConfig, err := nginx.ParseNgxConfig(path)	if err != nil {		api.ErrHandler(c, err)		return	}	certInfoMap := make(map[int]*cert.Info)	for serverIdx, server := range nginxConfig.Servers {		for _, directive := range server.Directives {			if directive.Directive == "ssl_certificate" {				pubKey, err := cert.GetCertInfo(directive.Params)				if err != nil {					logger.Error("Failed to get certificate information", err)					break				}				certInfoMap[serverIdx] = pubKey				break			}		}	}	c.JSON(http.StatusOK, Site{		ModifiedAt:      file.ModTime(),		Advanced:        site.Advanced,		Enabled:         enabled,		Name:            name,		Config:          nginxConfig.FmtCode(),		Tokenized:       nginxConfig,		AutoCert:        certModel.AutoCert == model.AutoCertEnabled,		CertInfo:        certInfoMap,		ChatGPTMessages: chatgpt.Content,	})}func SaveDomain(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"`		Overwrite bool   `json:"overwrite"`	}	if !api.BindAndValid(c, &json) {		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)	if err != nil {		api.ErrHandler(c, err)		return	}	enabledConfigFilePath := nginx.GetConfPath("sites-enabled", name)	// rename the config file if needed	if name != json.Name {		newPath := nginx.GetConfPath("sites-available", json.Name)		s := query.Site		_, err = s.Where(s.Path.Eq(path)).Update(s.Path, newPath)		// check if dst file exists, do not rename		if helper.FileExists(newPath) {			c.JSON(http.StatusNotAcceptable, gin.H{				"message": "File exists",			})			return		}		// recreate 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		}	}	GetDomain(c)}func EnableDomain(c *gin.Context) {	configFilePath := nginx.GetConfPath("sites-available", c.Param("name"))	enabledConfigFilePath := nginx.GetConfPath("sites-enabled", c.Param("name"))	_, err := os.Stat(configFilePath)	if err != nil {		api.ErrHandler(c, err)		return	}	if _, err = os.Stat(enabledConfigFilePath); os.IsNotExist(err) {		err = os.Symlink(configFilePath, enabledConfigFilePath)		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,		})		return	}	c.JSON(http.StatusOK, gin.H{		"message": "ok",	})}func DisableDomain(c *gin.Context) {	enabledConfigFilePath := nginx.GetConfPath("sites-enabled", c.Param("name"))	_, err := os.Stat(enabledConfigFilePath)	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 DeleteDomain(c *gin.Context) {	var err error	name := c.Param("name")	availablePath := nginx.GetConfPath("sites-available", name)	enabledPath := nginx.GetConfPath("sites-enabled", name)	if _, err = os.Stat(availablePath); os.IsNotExist(err) {		c.JSON(http.StatusNotFound, gin.H{			"message": "site not found",		})		return	}	if _, err = os.Stat(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)	if err != nil {		api.ErrHandler(c, err)		return	}	c.JSON(http.StatusOK, gin.H{		"message": "ok",	})}
 |