mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2024-12-15 17:29:00 +08:00
1257 lines
37 KiB
Go
1257 lines
37 KiB
Go
package service
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
|
|
|
|
"github.com/1Panel-dev/1Panel/agent/buserr"
|
|
"github.com/1Panel-dev/1Panel/agent/global"
|
|
"github.com/1Panel-dev/1Panel/agent/i18n"
|
|
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
|
|
"github.com/1Panel-dev/1Panel/agent/utils/common"
|
|
"github.com/1Panel-dev/1Panel/agent/utils/nginx/components"
|
|
"gopkg.in/yaml.v3"
|
|
|
|
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
|
|
|
|
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
|
"github.com/1Panel-dev/1Panel/agent/app/model"
|
|
"github.com/1Panel-dev/1Panel/agent/cmd/server/nginx_conf"
|
|
"github.com/1Panel-dev/1Panel/agent/constant"
|
|
"github.com/1Panel-dev/1Panel/agent/utils/files"
|
|
"github.com/1Panel-dev/1Panel/agent/utils/nginx"
|
|
"github.com/1Panel-dev/1Panel/agent/utils/nginx/parser"
|
|
"github.com/pkg/errors"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func handleChineseDomain(domain string) (string, error) {
|
|
if common.ContainsChinese(domain) {
|
|
return common.PunycodeEncode(domain)
|
|
}
|
|
return domain, nil
|
|
}
|
|
|
|
func createIndexFile(website *model.Website, runtime *model.Runtime) error {
|
|
var (
|
|
indexPath string
|
|
indexContent string
|
|
websiteService = NewIWebsiteService()
|
|
indexFolder = GetSitePath(*website, SiteIndexDir)
|
|
)
|
|
|
|
switch website.Type {
|
|
case constant.Static:
|
|
indexPath = path.Join(indexFolder, "index.html")
|
|
indexHtml, _ := websiteService.GetDefaultHtml("index")
|
|
indexContent = indexHtml.Content
|
|
case constant.Runtime:
|
|
if runtime.Type == constant.RuntimePHP {
|
|
indexPath = path.Join(indexFolder, "index.php")
|
|
indexPhp, _ := websiteService.GetDefaultHtml("php")
|
|
indexContent = indexPhp.Content
|
|
}
|
|
}
|
|
|
|
fileOp := files.NewFileOp()
|
|
if !fileOp.Stat(indexFolder) {
|
|
if err := fileOp.CreateDir(indexFolder, 0755); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if !fileOp.Stat(indexPath) {
|
|
if err := fileOp.CreateFile(indexPath); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if website.Type == constant.Runtime && runtime.Resource == constant.ResourceAppstore {
|
|
if err := chownRootDir(indexFolder); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if err := fileOp.WriteFile(indexPath, strings.NewReader(indexContent), 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
html404, _ := websiteService.GetDefaultHtml("404")
|
|
path404 := path.Join(indexFolder, "404.html")
|
|
if err := fileOp.WriteFile(path404, strings.NewReader(html404.Content), 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func createProxyFile(website *model.Website) error {
|
|
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
proxyFolder := path.Join(constant.AppInstallDir, constant.AppOpenresty, nginxInstall.Name, "www", "sites", website.Alias, "proxy")
|
|
filePath := path.Join(proxyFolder, "root.conf")
|
|
fileOp := files.NewFileOp()
|
|
if !fileOp.Stat(proxyFolder) {
|
|
if err := fileOp.CreateDir(proxyFolder, 0755); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if !fileOp.Stat(filePath) {
|
|
if err := fileOp.CreateFile(filePath); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
config, err := parser.NewStringParser(string(nginx_conf.Proxy)).Parse()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
config.FilePath = filePath
|
|
directives := config.Directives
|
|
location, ok := directives[0].(*components.Location)
|
|
if !ok {
|
|
return errors.New("error")
|
|
}
|
|
location.ChangePath("^~", "/")
|
|
location.UpdateDirective("proxy_pass", []string{website.Proxy})
|
|
location.UpdateDirective("proxy_set_header", []string{"Host", "$host"})
|
|
if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
|
return buserr.WithErr(constant.ErrUpdateBuWebsite, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func createWebsiteFolder(website *model.Website, runtime *model.Runtime) error {
|
|
siteFolder := GteSiteDir(website.Alias)
|
|
fileOp := files.NewFileOp()
|
|
if !fileOp.Stat(siteFolder) {
|
|
if err := fileOp.CreateDir(siteFolder, 0755); err != nil {
|
|
return err
|
|
}
|
|
if err := fileOp.CreateDir(path.Join(siteFolder, "log"), 0755); err != nil {
|
|
return err
|
|
}
|
|
if err := fileOp.CreateFile(path.Join(siteFolder, "log", "access.log")); err != nil {
|
|
return err
|
|
}
|
|
if err := fileOp.CreateFile(path.Join(siteFolder, "log", "error.log")); err != nil {
|
|
return err
|
|
}
|
|
if err := fileOp.CreateDir(path.Join(siteFolder, "index"), 0775); err != nil {
|
|
return err
|
|
}
|
|
if err := fileOp.CreateDir(path.Join(siteFolder, "ssl"), 0755); err != nil {
|
|
return err
|
|
}
|
|
if website.Type == constant.Runtime {
|
|
if runtime.Type == constant.RuntimePHP && runtime.Resource == constant.ResourceLocal {
|
|
phpPoolDir := path.Join(siteFolder, "php-pool")
|
|
if err := fileOp.CreateDir(phpPoolDir, 0755); err != nil {
|
|
return err
|
|
}
|
|
if err := fileOp.CreateFile(path.Join(phpPoolDir, "php-fpm.sock")); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
if website.Type == constant.Static || (website.Type == constant.Runtime && runtime.Type == constant.RuntimePHP) {
|
|
if err := createIndexFile(website, runtime); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if website.Type == constant.Proxy {
|
|
if err := createProxyFile(website); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, appInstall *model.AppInstall, runtime *model.Runtime) error {
|
|
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err = createWebsiteFolder(website, runtime); err != nil {
|
|
return err
|
|
}
|
|
configPath := GetSitePath(*website, SiteConf)
|
|
nginxContent := string(nginx_conf.WebsiteDefault)
|
|
config, err := parser.NewStringParser(nginxContent).Parse()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
servers := config.FindServers()
|
|
if len(servers) == 0 {
|
|
return errors.New("nginx config is not valid")
|
|
}
|
|
server := servers[0]
|
|
server.DeleteListen("80")
|
|
var serverNames []string
|
|
for _, domain := range domains {
|
|
serverNames = append(serverNames, domain.Domain)
|
|
setListen(server, strconv.Itoa(domain.Port), website.IPV6, false, website.DefaultServer, false)
|
|
}
|
|
server.UpdateServerName(serverNames)
|
|
|
|
siteFolder := path.Join("/www", "sites", website.Alias)
|
|
server.UpdateDirective("access_log", []string{path.Join(siteFolder, "log", "access.log"), "main"})
|
|
server.UpdateDirective("error_log", []string{path.Join(siteFolder, "log", "error.log")})
|
|
|
|
rootIndex := path.Join("/www/sites", website.Alias, "index")
|
|
switch website.Type {
|
|
case constant.Deployment:
|
|
proxy := fmt.Sprintf("http://127.0.0.1:%d", appInstall.HttpPort)
|
|
server.UpdateRootProxy([]string{proxy})
|
|
case constant.Static:
|
|
server.UpdateRoot(rootIndex)
|
|
server.UpdateDirective("error_page", []string{"404", "/404.html"})
|
|
case constant.Proxy:
|
|
nginxInclude := fmt.Sprintf("/www/sites/%s/proxy/*.conf", website.Alias)
|
|
server.UpdateDirective("include", []string{nginxInclude})
|
|
case constant.Runtime:
|
|
switch runtime.Type {
|
|
case constant.RuntimePHP:
|
|
server.UpdateDirective("error_page", []string{"404", "/404.html"})
|
|
if runtime.Resource == constant.ResourceLocal {
|
|
server.UpdateRoot(rootIndex)
|
|
localPath := path.Join(GetSitePath(*website, SiteIndexDir), "index.php")
|
|
server.UpdatePHPProxy([]string{website.Proxy}, localPath)
|
|
} else {
|
|
server.UpdateRoot(rootIndex)
|
|
server.UpdatePHPProxy([]string{website.Proxy}, "")
|
|
}
|
|
case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo:
|
|
proxy := fmt.Sprintf("http://127.0.0.1:%d", runtime.Port)
|
|
server.UpdateRootProxy([]string{proxy})
|
|
}
|
|
case constant.Subsite:
|
|
parentWebsite, err := websiteRepo.GetFirst(commonRepo.WithByID(website.ParentWebsiteID))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
website.Proxy = parentWebsite.Proxy
|
|
rootIndex = path.Join("/www/sites", parentWebsite.Alias, "index", website.SiteDir)
|
|
server.UpdateDirective("error_page", []string{"404", "/404.html"})
|
|
if parentWebsite.Type == constant.Runtime {
|
|
parentRuntime, err := runtimeRepo.GetFirst(commonRepo.WithByID(parentWebsite.RuntimeID))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
website.RuntimeID = parentRuntime.ID
|
|
if parentRuntime.Type == constant.RuntimePHP {
|
|
if parentRuntime.Resource == constant.ResourceLocal {
|
|
server.UpdateRoot(rootIndex)
|
|
localPath := path.Join(nginxInstall.GetPath(), rootIndex, "index.php")
|
|
server.UpdatePHPProxy([]string{website.Proxy}, localPath)
|
|
} else {
|
|
server.UpdateRoot(rootIndex)
|
|
server.UpdatePHPProxy([]string{website.Proxy}, "")
|
|
}
|
|
}
|
|
}
|
|
if parentWebsite.Type == constant.Static {
|
|
server.UpdateRoot(rootIndex)
|
|
}
|
|
}
|
|
|
|
config.FilePath = configPath
|
|
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
|
return err
|
|
}
|
|
if err = opNginx(nginxInstall.ContainerName, constant.NginxCheck); err != nil {
|
|
return err
|
|
}
|
|
if err = opNginx(nginxInstall.ContainerName, constant.NginxReload); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func createWafConfig(website *model.Website, domains []model.WebsiteDomain) error {
|
|
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if !common.CompareVersion(nginxInstall.Version, "1.21.4.3-2-0") {
|
|
return nil
|
|
}
|
|
wafDataPath := path.Join(nginxInstall.GetPath(), "1pwaf", "data")
|
|
fileOp := files.NewFileOp()
|
|
if !fileOp.Stat(wafDataPath) {
|
|
return nil
|
|
}
|
|
websitesConfigPath := path.Join(wafDataPath, "conf", "sites.json")
|
|
content, err := fileOp.GetContent(websitesConfigPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var websitesArray []request.WafWebsite
|
|
if len(content) != 0 {
|
|
if err := json.Unmarshal(content, &websitesArray); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
wafWebsite := request.WafWebsite{
|
|
Key: website.Alias,
|
|
Domains: make([]string, 0),
|
|
Host: make([]string, 0),
|
|
}
|
|
|
|
for _, domain := range domains {
|
|
wafWebsite.Domains = append(wafWebsite.Domains, domain.Domain)
|
|
wafWebsite.Host = append(wafWebsite.Host, domain.Domain+":"+strconv.Itoa(domain.Port))
|
|
}
|
|
websitesArray = append(websitesArray, wafWebsite)
|
|
websitesContent, err := json.Marshal(websitesArray)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := fileOp.SaveFileWithByte(websitesConfigPath, websitesContent, 0644); err != nil {
|
|
return err
|
|
}
|
|
|
|
var (
|
|
sitesDir = path.Join(wafDataPath, "sites")
|
|
defaultConfigPath = path.Join(wafDataPath, "conf", "siteConfig.json")
|
|
defaultRuleDir = path.Join(wafDataPath, "rules")
|
|
websiteDir = path.Join(sitesDir, website.Alias)
|
|
)
|
|
|
|
defaultConfigContent, err := fileOp.GetContent(defaultConfigPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if !fileOp.Stat(websiteDir) {
|
|
if err = fileOp.CreateDir(websiteDir, 0755); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
defer func() {
|
|
if err != nil {
|
|
_ = fileOp.DeleteDir(websiteDir)
|
|
}
|
|
}()
|
|
|
|
if err = fileOp.SaveFileWithByte(path.Join(websiteDir, "config.json"), defaultConfigContent, 0644); err != nil {
|
|
return err
|
|
}
|
|
|
|
websiteRuleDir := path.Join(websiteDir, "rules")
|
|
if !fileOp.Stat(websiteRuleDir) {
|
|
if err := fileOp.CreateDir(websiteRuleDir, 0755); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
defaultRulesName := []string{"acl", "args", "cookie", "defaultUaBlack", "defaultUrlBlack", "fileExt", "header", "methodWhite", "cdn"}
|
|
for _, ruleName := range defaultRulesName {
|
|
srcPath := path.Join(defaultRuleDir, ruleName+".json")
|
|
if fileOp.Stat(srcPath) {
|
|
_ = fileOp.Copy(srcPath, websiteRuleDir)
|
|
}
|
|
}
|
|
|
|
if err = opNginx(nginxInstall.ContainerName, constant.NginxCheck); err != nil {
|
|
return err
|
|
}
|
|
if err = opNginx(nginxInstall.ContainerName, constant.NginxReload); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func delNginxConfig(website model.Website, force bool) error {
|
|
configPath := GetSitePath(website, SiteConf)
|
|
fileOp := files.NewFileOp()
|
|
|
|
if !fileOp.Stat(configPath) {
|
|
return nil
|
|
}
|
|
if err := fileOp.DeleteFile(configPath); err != nil {
|
|
return err
|
|
}
|
|
sitePath := GteSiteDir(website.Alias)
|
|
if fileOp.Stat(sitePath) {
|
|
xpack.RemoveTamper(website.Alias)
|
|
_ = fileOp.DeleteDir(sitePath)
|
|
}
|
|
|
|
nginxApp, err := appRepo.GetFirst(appRepo.WithKey(constant.AppOpenresty))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
nginxInstall, err := appInstallRepo.GetFirst(appInstallRepo.WithAppId(nginxApp.ID))
|
|
if err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
if err := opNginx(nginxInstall.ContainerName, constant.NginxReload); err != nil {
|
|
if force {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func delWafConfig(website model.Website, force bool) error {
|
|
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !common.CompareVersion(nginxInstall.Version, "1.21.4.3-2-0") {
|
|
return nil
|
|
}
|
|
wafDataPath := path.Join(nginxInstall.GetPath(), "1pwaf", "data")
|
|
fileOp := files.NewFileOp()
|
|
if !fileOp.Stat(wafDataPath) {
|
|
return nil
|
|
}
|
|
monitorDir := path.Join(wafDataPath, "db", "sites", website.Alias)
|
|
if fileOp.Stat(monitorDir) {
|
|
_ = fileOp.DeleteDir(monitorDir)
|
|
}
|
|
websitesConfigPath := path.Join(wafDataPath, "conf", "sites.json")
|
|
content, err := fileOp.GetContent(websitesConfigPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var websitesArray []request.WafWebsite
|
|
var newWebsiteArray []request.WafWebsite
|
|
if len(content) > 0 {
|
|
if err = json.Unmarshal(content, &websitesArray); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
for _, wafWebsite := range websitesArray {
|
|
if wafWebsite.Key != website.Alias {
|
|
newWebsiteArray = append(newWebsiteArray, wafWebsite)
|
|
}
|
|
}
|
|
websitesContent, err := json.Marshal(newWebsiteArray)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := fileOp.SaveFileWithByte(websitesConfigPath, websitesContent, 0644); err != nil {
|
|
return err
|
|
}
|
|
|
|
_ = fileOp.DeleteDir(path.Join(wafDataPath, "sites", website.Alias))
|
|
|
|
if err := opNginx(nginxInstall.ContainerName, constant.NginxReload); err != nil {
|
|
if force {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func isHttp3(server *components.Server) bool {
|
|
for _, listen := range server.Listens {
|
|
for _, param := range listen.Parameters {
|
|
if param == "quic" {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func addListenAndServerName(website model.Website, domains []model.WebsiteDomain) error {
|
|
nginxFull, err := getNginxFull(&website)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
nginxConfig := nginxFull.SiteConfig
|
|
config := nginxFull.SiteConfig.Config
|
|
server := config.FindServers()[0]
|
|
http3 := isHttp3(server)
|
|
|
|
for _, domain := range domains {
|
|
setListen(server, strconv.Itoa(domain.Port), website.IPV6, http3, website.DefaultServer, website.Protocol == constant.ProtocolHTTPS && domain.SSL)
|
|
server.UpdateServerName([]string{domain.Domain})
|
|
}
|
|
|
|
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
|
return err
|
|
}
|
|
return nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxFull.Install.ContainerName)
|
|
}
|
|
|
|
func deleteListenAndServerName(website model.Website, binds []string, domains []string) error {
|
|
nginxFull, err := getNginxFull(&website)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
nginxConfig := nginxFull.SiteConfig
|
|
config := nginxFull.SiteConfig.Config
|
|
server := config.FindServers()[0]
|
|
for _, bind := range binds {
|
|
server.DeleteListen(bind)
|
|
server.DeleteListen("[::]:" + bind)
|
|
}
|
|
for _, domain := range domains {
|
|
server.DeleteServerName(domain)
|
|
}
|
|
|
|
if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
|
return err
|
|
}
|
|
return nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxFull.Install.ContainerName)
|
|
}
|
|
|
|
func setListen(server *components.Server, port string, ipv6, http3, defaultServer, ssl bool) {
|
|
var params []string
|
|
if ssl {
|
|
params = []string{"ssl"}
|
|
}
|
|
server.UpdateListen(port, defaultServer, params...)
|
|
if ssl && http3 {
|
|
server.UpdateListen(port, defaultServer, "quic")
|
|
}
|
|
if !ipv6 {
|
|
return
|
|
}
|
|
server.UpdateListen("[::]:"+port, defaultServer, params...)
|
|
if ssl && http3 {
|
|
server.UpdateListen("[::]:"+port, defaultServer, "quic")
|
|
}
|
|
}
|
|
|
|
func removeSSLListen(website model.Website, binds []string) error {
|
|
nginxFull, err := getNginxFull(&website)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
nginxConfig := nginxFull.SiteConfig
|
|
config := nginxFull.SiteConfig.Config
|
|
server := config.FindServers()[0]
|
|
http3 := isHttp3(server)
|
|
for _, bind := range binds {
|
|
server.DeleteListen(bind)
|
|
if website.IPV6 {
|
|
server.DeleteListen("[::]:" + bind)
|
|
}
|
|
setListen(server, bind, website.IPV6, http3, website.DefaultServer, website.Protocol == constant.ProtocolHTTPS)
|
|
}
|
|
if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
|
return err
|
|
}
|
|
return nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxFull.Install.ContainerName)
|
|
}
|
|
|
|
func createPemFile(website model.Website, websiteSSL model.WebsiteSSL) error {
|
|
configDir := GetSitePath(website, SiteSSLDir)
|
|
fileOp := files.NewFileOp()
|
|
|
|
if !fileOp.Stat(configDir) {
|
|
if err := fileOp.CreateDir(configDir, 0775); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
fullChainFile := path.Join(configDir, "fullchain.pem")
|
|
privatePemFile := path.Join(configDir, "privkey.pem")
|
|
|
|
if !fileOp.Stat(fullChainFile) {
|
|
if err := fileOp.CreateFile(fullChainFile); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if !fileOp.Stat(privatePemFile) {
|
|
if err := fileOp.CreateFile(privatePemFile); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if err := fileOp.WriteFile(fullChainFile, strings.NewReader(websiteSSL.Pem), 0644); err != nil {
|
|
return err
|
|
}
|
|
if err := fileOp.WriteFile(privatePemFile, strings.NewReader(websiteSSL.PrivateKey), 0644); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func getHttpsPort(website *model.Website) ([]int, error) {
|
|
websiteDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(website.ID))
|
|
var httpsPorts []int
|
|
for _, domain := range websiteDomains {
|
|
if domain.SSL {
|
|
httpsPorts = append(httpsPorts, domain.Port)
|
|
}
|
|
}
|
|
if len(httpsPorts) == 0 {
|
|
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
httpsPorts = append(httpsPorts, nginxInstall.HttpsPort)
|
|
}
|
|
return httpsPorts, nil
|
|
}
|
|
|
|
func applySSL(website *model.Website, websiteSSL model.WebsiteSSL, req request.WebsiteHTTPSOp) error {
|
|
nginxFull, err := getNginxFull(website)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
domains, err := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(website.ID))
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
noDefaultPort := true
|
|
for _, domain := range domains {
|
|
if domain.Port == 80 {
|
|
noDefaultPort = false
|
|
}
|
|
}
|
|
config := nginxFull.SiteConfig.Config
|
|
server := config.FindServers()[0]
|
|
|
|
httpPort := strconv.Itoa(nginxFull.Install.HttpPort)
|
|
httpsPort, err := getHttpsPort(website)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
httpPortIPV6 := "[::]:" + httpPort
|
|
|
|
for _, port := range httpsPort {
|
|
setListen(server, strconv.Itoa(port), website.IPV6, req.Http3, website.DefaultServer, true)
|
|
}
|
|
|
|
server.UpdateDirective("http2", []string{"on"})
|
|
|
|
switch req.HttpConfig {
|
|
case constant.HTTPSOnly:
|
|
server.RemoveListenByBind(httpPort)
|
|
server.RemoveListenByBind(httpPortIPV6)
|
|
server.RemoveDirective("if", []string{"($scheme"})
|
|
case constant.HTTPToHTTPS:
|
|
if !noDefaultPort {
|
|
server.UpdateListen(httpPort, website.DefaultServer)
|
|
}
|
|
if website.IPV6 {
|
|
server.UpdateListen(httpPortIPV6, website.DefaultServer)
|
|
}
|
|
server.AddHTTP2HTTPS()
|
|
case constant.HTTPAlso:
|
|
if !noDefaultPort {
|
|
server.UpdateListen(httpPort, website.DefaultServer)
|
|
}
|
|
server.RemoveDirective("if", []string{"($scheme"})
|
|
if website.IPV6 {
|
|
server.UpdateListen(httpPortIPV6, website.DefaultServer)
|
|
}
|
|
}
|
|
|
|
if !req.Hsts {
|
|
server.RemoveDirective("add_header", []string{"Strict-Transport-Security", "\"max-age=31536000\""})
|
|
}
|
|
if !req.Http3 {
|
|
for _, port := range httpsPort {
|
|
server.RemoveListen(strconv.Itoa(port), "quic")
|
|
if website.IPV6 {
|
|
httpsPortIPV6 := "[::]:" + strconv.Itoa(port)
|
|
server.RemoveListen(httpsPortIPV6, "quic")
|
|
}
|
|
}
|
|
server.RemoveDirective("add_header", []string{"Alt-Svc"})
|
|
}
|
|
|
|
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
|
return err
|
|
}
|
|
if err = createPemFile(*website, websiteSSL); err != nil {
|
|
return err
|
|
}
|
|
nginxParams := getNginxParamsFromStaticFile(dto.SSL, []dto.NginxParam{})
|
|
for i, param := range nginxParams {
|
|
if param.Name == "ssl_certificate" {
|
|
nginxParams[i].Params = []string{path.Join("/www", "sites", website.Alias, "ssl", "fullchain.pem")}
|
|
}
|
|
if param.Name == "ssl_certificate_key" {
|
|
nginxParams[i].Params = []string{path.Join("/www", "sites", website.Alias, "ssl", "privkey.pem")}
|
|
}
|
|
if param.Name == "ssl_protocols" {
|
|
nginxParams[i].Params = req.SSLProtocol
|
|
}
|
|
if param.Name == "ssl_ciphers" {
|
|
nginxParams[i].Params = []string{req.Algorithm}
|
|
}
|
|
}
|
|
if req.Hsts {
|
|
nginxParams = append(nginxParams, dto.NginxParam{
|
|
Name: "add_header",
|
|
Params: []string{"Strict-Transport-Security", "\"max-age=31536000\""},
|
|
})
|
|
}
|
|
if req.Http3 {
|
|
nginxParams = append(nginxParams, dto.NginxParam{
|
|
Name: "add_header",
|
|
Params: []string{"Alt-Svc", "'h3=\":443\"; ma=2592000'"},
|
|
})
|
|
}
|
|
|
|
if err := updateNginxConfig(constant.NginxScopeServer, nginxParams, website); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func getParamArray(key string, param interface{}) []string {
|
|
var res []string
|
|
switch p := param.(type) {
|
|
case string:
|
|
if key == "index" {
|
|
res = strings.Split(p, "\n")
|
|
return res
|
|
}
|
|
|
|
res = strings.Split(p, " ")
|
|
return res
|
|
}
|
|
return res
|
|
}
|
|
|
|
func handleParamMap(paramMap map[string]string, keys []string) []dto.NginxParam {
|
|
var nginxParams []dto.NginxParam
|
|
for k, v := range paramMap {
|
|
for _, name := range keys {
|
|
if name == k {
|
|
param := dto.NginxParam{
|
|
Name: k,
|
|
Params: getParamArray(k, v),
|
|
}
|
|
nginxParams = append(nginxParams, param)
|
|
}
|
|
}
|
|
}
|
|
return nginxParams
|
|
}
|
|
|
|
func getNginxParams(params interface{}, keys []string) []dto.NginxParam {
|
|
var nginxParams []dto.NginxParam
|
|
|
|
switch p := params.(type) {
|
|
case map[string]interface{}:
|
|
return handleParamMap(toMapStr(p), keys)
|
|
case []interface{}:
|
|
for _, mA := range p {
|
|
if m, ok := mA.(map[string]interface{}); ok {
|
|
nginxParams = append(nginxParams, handleParamMap(toMapStr(m), keys)...)
|
|
}
|
|
}
|
|
}
|
|
return nginxParams
|
|
}
|
|
|
|
func toMapStr(m map[string]interface{}) map[string]string {
|
|
ret := make(map[string]string, len(m))
|
|
for k, v := range m {
|
|
ret[k] = fmt.Sprint(v)
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func deleteWebsiteFolder(nginxInstall model.AppInstall, website *model.Website) error {
|
|
nginxFolder := path.Join(constant.AppInstallDir, constant.AppOpenresty, nginxInstall.Name)
|
|
siteFolder := path.Join(nginxFolder, "www", "sites", website.Alias)
|
|
fileOp := files.NewFileOp()
|
|
if fileOp.Stat(siteFolder) {
|
|
_ = fileOp.DeleteDir(siteFolder)
|
|
}
|
|
nginxFilePath := path.Join(nginxFolder, "conf", "conf.d", website.PrimaryDomain+".conf")
|
|
if fileOp.Stat(nginxFilePath) {
|
|
_ = fileOp.DeleteFile(nginxFilePath)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func opWebsite(website *model.Website, operate string) error {
|
|
nginxInstall, err := getNginxFull(website)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
config := nginxInstall.SiteConfig.Config
|
|
servers := config.FindServers()
|
|
if len(servers) == 0 {
|
|
return errors.New("nginx config is not valid")
|
|
}
|
|
server := servers[0]
|
|
if operate == constant.StopWeb {
|
|
proxyInclude := fmt.Sprintf("/www/sites/%s/proxy/*.conf", website.Alias)
|
|
server.RemoveDirective("include", []string{proxyInclude})
|
|
rewriteInclude := fmt.Sprintf("/www/sites/%s/rewrite/%s.conf", website.Alias, website.Alias)
|
|
server.RemoveDirective("include", []string{rewriteInclude})
|
|
|
|
switch website.Type {
|
|
case constant.Deployment:
|
|
server.RemoveDirective("location", []string{"/"})
|
|
case constant.Runtime:
|
|
runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(website.RuntimeID))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if runtime.Type == constant.RuntimePHP {
|
|
server.RemoveDirective("location", []string{"~", "[^/]\\.php(/|$)"})
|
|
} else {
|
|
server.RemoveDirective("location", []string{"/"})
|
|
}
|
|
}
|
|
server.UpdateRoot("/usr/share/nginx/html/stop")
|
|
website.Status = constant.WebStopped
|
|
}
|
|
if operate == constant.StartWeb {
|
|
absoluteIncludeDir := path.Join(nginxInstall.Install.GetPath(), fmt.Sprintf("/www/sites/%s/proxy", website.Alias))
|
|
fileOp := files.NewFileOp()
|
|
if fileOp.Stat(absoluteIncludeDir) && !files.IsEmptyDir(absoluteIncludeDir) {
|
|
proxyInclude := fmt.Sprintf("/www/sites/%s/proxy/*.conf", website.Alias)
|
|
server.UpdateDirective("include", []string{proxyInclude})
|
|
}
|
|
rewriteInclude := fmt.Sprintf("/www/sites/%s/rewrite/%s.conf", website.Alias, website.Alias)
|
|
absoluteRewritePath := path.Join(nginxInstall.Install.GetPath(), rewriteInclude)
|
|
if fileOp.Stat(absoluteRewritePath) {
|
|
server.UpdateDirective("include", []string{rewriteInclude})
|
|
}
|
|
rootIndex := path.Join("/www/sites", website.Alias, "index")
|
|
if website.SiteDir != "/" {
|
|
rootIndex = path.Join(rootIndex, website.SiteDir)
|
|
}
|
|
switch website.Type {
|
|
case constant.Deployment:
|
|
server.RemoveDirective("root", nil)
|
|
appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
proxy := fmt.Sprintf("http://127.0.0.1:%d", appInstall.HttpPort)
|
|
server.UpdateRootProxy([]string{proxy})
|
|
case constant.Static:
|
|
server.UpdateRoot(rootIndex)
|
|
server.UpdateRootLocation()
|
|
case constant.Proxy:
|
|
server.RemoveDirective("root", nil)
|
|
case constant.Runtime:
|
|
server.UpdateRoot(rootIndex)
|
|
localPath := ""
|
|
runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(website.RuntimeID))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if runtime.Type == constant.RuntimePHP {
|
|
if website.ProxyType == constant.RuntimeProxyUnix || website.ProxyType == constant.RuntimeProxyTcp {
|
|
localPath = path.Join(nginxInstall.Install.GetPath(), rootIndex, "index.php")
|
|
}
|
|
server.UpdatePHPProxy([]string{website.Proxy}, localPath)
|
|
} else {
|
|
proxy := fmt.Sprintf("http://127.0.0.1:%d", runtime.Port)
|
|
server.UpdateRootProxy([]string{proxy})
|
|
}
|
|
}
|
|
website.Status = constant.WebRunning
|
|
now := time.Now()
|
|
if website.ExpireDate.Before(now) {
|
|
defaultDate, _ := time.Parse(constant.DateLayout, constant.DefaultDate)
|
|
website.ExpireDate = defaultDate
|
|
}
|
|
}
|
|
|
|
if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
|
return err
|
|
}
|
|
return nginxCheckAndReload(nginxInstall.SiteConfig.OldContent, config.FilePath, nginxInstall.Install.ContainerName)
|
|
}
|
|
|
|
func changeIPV6(website model.Website, enable bool) error {
|
|
nginxFull, err := getNginxFull(&website)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
config := nginxFull.SiteConfig.Config
|
|
server := config.FindServers()[0]
|
|
listens := server.Listens
|
|
if enable {
|
|
for _, listen := range listens {
|
|
if strings.HasPrefix(listen.Bind, "[::]:") {
|
|
continue
|
|
}
|
|
exist := false
|
|
ipv6Bind := fmt.Sprintf("[::]:%s", listen.Bind)
|
|
for _, li := range listens {
|
|
if li.Bind == ipv6Bind {
|
|
exist = true
|
|
break
|
|
}
|
|
}
|
|
if !exist {
|
|
server.UpdateListen(ipv6Bind, false, listen.GetParameters()[1:]...)
|
|
}
|
|
}
|
|
} else {
|
|
for _, listen := range listens {
|
|
if strings.HasPrefix(listen.Bind, "[::]:") {
|
|
server.RemoveListenByBind(listen.Bind)
|
|
}
|
|
}
|
|
}
|
|
if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
|
return err
|
|
}
|
|
return nginxCheckAndReload(nginxFull.SiteConfig.OldContent, config.FilePath, nginxFull.Install.ContainerName)
|
|
}
|
|
|
|
func checkIsLinkApp(website model.Website) bool {
|
|
if website.Type == constant.Deployment {
|
|
return true
|
|
}
|
|
if website.Type == constant.Runtime {
|
|
runtime, _ := runtimeRepo.GetFirst(commonRepo.WithByID(website.RuntimeID))
|
|
return runtime.Resource == constant.ResourceAppstore
|
|
}
|
|
return false
|
|
}
|
|
|
|
func chownRootDir(path string) error {
|
|
_, err := cmd.ExecWithTimeOut(fmt.Sprintf(`chown -R 1000:1000 "%s"`, path), 1*time.Second)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func changeServiceName(newComposeContent, newServiceName string) (composeByte []byte, err error) {
|
|
composeMap := make(map[string]interface{})
|
|
if err = yaml.Unmarshal([]byte(newComposeContent), &composeMap); err != nil {
|
|
return
|
|
}
|
|
value, ok := composeMap["services"]
|
|
if !ok || value == nil {
|
|
err = buserr.New(constant.ErrFileParse)
|
|
return
|
|
}
|
|
servicesMap := value.(map[string]interface{})
|
|
|
|
index := 0
|
|
serviceName := ""
|
|
for k := range servicesMap {
|
|
serviceName = k
|
|
if index > 0 {
|
|
continue
|
|
}
|
|
index++
|
|
}
|
|
if newServiceName != serviceName {
|
|
servicesMap[newServiceName] = servicesMap[serviceName]
|
|
delete(servicesMap, serviceName)
|
|
}
|
|
|
|
return yaml.Marshal(composeMap)
|
|
}
|
|
|
|
func getWebsiteDomains(domains []request.WebsiteDomain, defaultPort int, websiteID uint) (domainModels []model.WebsiteDomain, addPorts []int, addDomains []string, err error) {
|
|
var (
|
|
ports = make(map[int]struct{})
|
|
existPort = make(map[int]struct{})
|
|
)
|
|
existDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(websiteID))
|
|
for _, domain := range existDomains {
|
|
existPort[domain.Port] = struct{}{}
|
|
}
|
|
for _, domain := range domains {
|
|
if domain.Domain == "" {
|
|
continue
|
|
}
|
|
if !common.IsValidDomain(domain.Domain) {
|
|
err = buserr.WithName("ErrDomainFormat", domain.Domain)
|
|
return
|
|
}
|
|
var domainModel model.WebsiteDomain
|
|
domainModel.Domain, err = handleChineseDomain(domain.Domain)
|
|
if err != nil {
|
|
return
|
|
}
|
|
domainModel.Port = domain.Port
|
|
if domain.Port == 0 {
|
|
domain.Port = defaultPort
|
|
}
|
|
domainModel.SSL = domain.SSL
|
|
domainModel.WebsiteID = websiteID
|
|
domainModels = append(domainModels, domainModel)
|
|
if _, ok := existPort[domainModel.Port]; !ok {
|
|
ports[domainModel.Port] = struct{}{}
|
|
}
|
|
if exist, _ := websiteDomainRepo.GetFirst(websiteDomainRepo.WithDomain(domainModel.Domain), websiteDomainRepo.WithWebsiteId(websiteID)); exist.ID == 0 {
|
|
addDomains = append(addDomains, domainModel.Domain)
|
|
}
|
|
}
|
|
for _, domain := range domainModels {
|
|
if exist, _ := websiteDomainRepo.GetFirst(websiteDomainRepo.WithDomain(domain.Domain), websiteDomainRepo.WithPort(domain.Port)); exist.ID > 0 {
|
|
website, _ := websiteRepo.GetFirst(commonRepo.WithByID(exist.WebsiteID))
|
|
err = buserr.WithName(constant.ErrDomainIsUsed, website.PrimaryDomain)
|
|
return
|
|
}
|
|
}
|
|
|
|
for port := range ports {
|
|
if port == defaultPort {
|
|
addPorts = append(addPorts, port)
|
|
continue
|
|
}
|
|
if existPorts, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithPort(port)); len(existPorts) == 0 {
|
|
errMap := make(map[string]interface{})
|
|
errMap["port"] = port
|
|
appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithPort(port))
|
|
if appInstall.ID > 0 {
|
|
errMap["type"] = i18n.GetMsgByKey("TYPE_APP")
|
|
errMap["name"] = appInstall.Name
|
|
err = buserr.WithMap("ErrPortExist", errMap, nil)
|
|
return
|
|
}
|
|
runtime, _ := runtimeRepo.GetFirst(runtimeRepo.WithPort(port))
|
|
if runtime != nil {
|
|
errMap["type"] = i18n.GetMsgByKey("TYPE_RUNTIME")
|
|
errMap["name"] = runtime.Name
|
|
err = buserr.WithMap("ErrPortExist", errMap, nil)
|
|
return
|
|
}
|
|
if common.ScanPort(port) {
|
|
err = buserr.WithDetail(constant.ErrPortInUsed, port, nil)
|
|
return
|
|
}
|
|
}
|
|
if existPorts, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(websiteID), websiteDomainRepo.WithPort(port)); len(existPorts) == 0 {
|
|
addPorts = append(addPorts, port)
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func saveCertificateFile(websiteSSL *model.WebsiteSSL, logger *log.Logger) {
|
|
if websiteSSL.PushDir {
|
|
fileOp := files.NewFileOp()
|
|
var (
|
|
pushErr error
|
|
MsgMap = map[string]interface{}{"path": websiteSSL.Dir, "status": i18n.GetMsgByKey("Success")}
|
|
)
|
|
if pushErr = fileOp.SaveFile(path.Join(websiteSSL.Dir, "privkey.pem"), websiteSSL.PrivateKey, 0666); pushErr != nil {
|
|
MsgMap["status"] = i18n.GetMsgByKey("Failed")
|
|
logger.Println(i18n.GetMsgWithMap("PushDirLog", MsgMap))
|
|
logger.Println("Push dir failed:" + pushErr.Error())
|
|
}
|
|
if pushErr = fileOp.SaveFile(path.Join(websiteSSL.Dir, "fullchain.pem"), websiteSSL.Pem, 0666); pushErr != nil {
|
|
MsgMap["status"] = i18n.GetMsgByKey("Failed")
|
|
logger.Println(i18n.GetMsgWithMap("PushDirLog", MsgMap))
|
|
logger.Println("Push dir failed:" + pushErr.Error())
|
|
}
|
|
if pushErr == nil {
|
|
logger.Println(i18n.GetMsgWithMap("PushDirLog", MsgMap))
|
|
}
|
|
}
|
|
}
|
|
|
|
func GetSystemSSL() (bool, uint) {
|
|
sslSetting, err := settingRepo.Get(settingRepo.WithByKey("SSL"))
|
|
if err != nil {
|
|
global.LOG.Errorf("load service ssl from setting failed, err: %v", err)
|
|
return false, 0
|
|
}
|
|
if sslSetting.Value == "enable" {
|
|
sslID, _ := settingRepo.Get(settingRepo.WithByKey("SSLID"))
|
|
idValue, _ := strconv.Atoi(sslID.Value)
|
|
if idValue > 0 {
|
|
return true, uint(idValue)
|
|
}
|
|
}
|
|
return false, 0
|
|
}
|
|
|
|
func UpdateSSLConfig(websiteSSL model.WebsiteSSL) error {
|
|
websites, _ := websiteRepo.GetBy(websiteRepo.WithWebsiteSSLID(websiteSSL.ID))
|
|
if len(websites) > 0 {
|
|
for _, website := range websites {
|
|
if err := createPemFile(website, websiteSSL); err != nil {
|
|
return buserr.WithMap("ErrUpdateWebsiteSSL", map[string]interface{}{"name": website.PrimaryDomain, "err": err.Error()}, err)
|
|
}
|
|
}
|
|
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := opNginx(nginxInstall.ContainerName, constant.NginxReload); err != nil {
|
|
return buserr.WithErr(constant.ErrSSLApply, err)
|
|
}
|
|
}
|
|
enable, sslID := GetSystemSSL()
|
|
if enable && sslID == websiteSSL.ID {
|
|
fileOp := files.NewFileOp()
|
|
secretDir := path.Join(global.CONF.System.BaseDir, "1panel/secret")
|
|
if err := fileOp.WriteFile(path.Join(secretDir, "server.crt"), strings.NewReader(websiteSSL.Pem), 0600); err != nil {
|
|
global.LOG.Errorf("Failed to update the SSL certificate File for 1Panel System domain [%s] , err:%s", websiteSSL.PrimaryDomain, err.Error())
|
|
return err
|
|
}
|
|
if err := fileOp.WriteFile(path.Join(secretDir, "server.key"), strings.NewReader(websiteSSL.PrivateKey), 0600); err != nil {
|
|
global.LOG.Errorf("Failed to update the SSL certificate for 1Panel System domain [%s] , err:%s", websiteSSL.PrimaryDomain, err.Error())
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func ChangeHSTSConfig(enable bool, nginxInstall model.AppInstall, website model.Website) error {
|
|
includeDir := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "proxy")
|
|
fileOp := files.NewFileOp()
|
|
if !fileOp.Stat(includeDir) {
|
|
return nil
|
|
}
|
|
err := filepath.Walk(includeDir, func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !info.IsDir() {
|
|
if filepath.Ext(path) == ".conf" {
|
|
par, err := parser.NewParser(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
config, err := par.Parse()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
config.FilePath = path
|
|
directives := config.Directives
|
|
location, ok := directives[0].(*components.Location)
|
|
if !ok {
|
|
return nil
|
|
}
|
|
if enable {
|
|
location.UpdateDirective("add_header", []string{"Strict-Transport-Security", "\"max-age=31536000\""})
|
|
} else {
|
|
location.RemoveDirective("add_header", []string{"Strict-Transport-Security", "\"max-age=31536000\""})
|
|
}
|
|
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
|
return buserr.WithErr(constant.ErrUpdateBuWebsite, err)
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func checkSSLStatus(expireDate time.Time) string {
|
|
now := time.Now()
|
|
daysUntilExpiry := int(expireDate.Sub(now).Hours() / 24)
|
|
|
|
if daysUntilExpiry < 0 {
|
|
return "danger"
|
|
} else if daysUntilExpiry <= 10 {
|
|
return "warning"
|
|
}
|
|
return "success"
|
|
}
|
|
|
|
func getResourceContent(fileOp files.FileOp, resourcePath string) (string, error) {
|
|
if fileOp.Stat(resourcePath) {
|
|
content, err := fileOp.GetContent(resourcePath)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return string(content), nil
|
|
}
|
|
return "", nil
|
|
}
|
|
|
|
func GetWebSiteRootDir() string {
|
|
siteSetting, _ := settingRepo.Get(settingRepo.WithByKey("WEBSITE_DIR"))
|
|
dir := siteSetting.Value
|
|
if dir == "" {
|
|
dir = path.Join(constant.DataDir, "www")
|
|
}
|
|
return dir
|
|
}
|
|
|
|
func GteSiteDir(alias string) string {
|
|
return path.Join(GetWebSiteRootDir(), "sites", alias)
|
|
}
|
|
|
|
const (
|
|
SiteConf = "SiteConf"
|
|
SiteAccessLog = "access.log"
|
|
SiteErrorLog = "error.log"
|
|
WebsiteRootDir = "WebsiteRootDir"
|
|
SiteDir = "SiteDir"
|
|
SiteIndexDir = "SiteIndexDir"
|
|
SiteProxyDir = "SiteProxyDir"
|
|
SiteSSLDir = "SiteSSLDir"
|
|
SiteReWritePath = "SiteReWritePath"
|
|
SiteRedirectDir = "SiteRedirectDir"
|
|
SiteCacheDir = "SiteCacheDir"
|
|
SiteConfDir = "SiteConfDir"
|
|
)
|
|
|
|
func GetSitePath(website model.Website, confType string) string {
|
|
switch confType {
|
|
case SiteConf:
|
|
return path.Join(GetWebSiteRootDir(), "conf.d", website.Alias+".conf")
|
|
case SiteAccessLog:
|
|
return path.Join(GteSiteDir(website.Alias), "log", "access.log")
|
|
case SiteErrorLog:
|
|
return path.Join(GteSiteDir(website.Alias), "log", "error.log")
|
|
case WebsiteRootDir:
|
|
return GetWebSiteRootDir()
|
|
case SiteDir:
|
|
return GteSiteDir(website.Alias)
|
|
case SiteIndexDir:
|
|
return path.Join(GteSiteDir(website.Alias), "index")
|
|
case SiteCacheDir:
|
|
return path.Join(GteSiteDir(website.Alias), "cache")
|
|
case SiteProxyDir:
|
|
return path.Join(GteSiteDir(website.Alias), "proxy")
|
|
case SiteSSLDir:
|
|
return path.Join(GteSiteDir(website.Alias), "ssl")
|
|
case SiteReWritePath:
|
|
return path.Join(GteSiteDir(website.Alias), "rewrite", website.Alias+".conf")
|
|
case SiteRedirectDir:
|
|
return path.Join(GteSiteDir(website.Alias), "redirect")
|
|
case SiteConfDir:
|
|
return path.Join(GetWebSiteRootDir(), "conf.d")
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func openProxyCache(website model.Website) error {
|
|
cacheDir := GetSitePath(website, SiteCacheDir)
|
|
fileOp := files.NewFileOp()
|
|
if !fileOp.Stat(cacheDir) {
|
|
_ = fileOp.CreateDir(cacheDir, 0755)
|
|
}
|
|
content, err := fileOp.GetContent(GetSitePath(website, SiteConf))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if strings.Contains(string(content), "proxy_cache_path") {
|
|
return nil
|
|
}
|
|
proxyCachePath := fmt.Sprintf("/www/sites/%s/cache levels=1:2 keys_zone=proxy_cache_zone_of_%s:5m max_size=1g inactive=24h", website.Alias, website.Alias)
|
|
return updateNginxConfig("", []dto.NginxParam{{Name: "proxy_cache_path", Params: []string{proxyCachePath}}}, &website)
|
|
}
|