mirror of
https://github.com/acepanel/panel.git
synced 2026-02-05 00:39:32 +08:00
715 lines
21 KiB
Go
715 lines
21 KiB
Go
package controllers
|
||
|
||
import (
|
||
"fmt"
|
||
"regexp"
|
||
"strconv"
|
||
"strings"
|
||
|
||
"github.com/goravel/framework/contracts/http"
|
||
"github.com/goravel/framework/facades"
|
||
|
||
"panel/app/models"
|
||
"panel/app/services"
|
||
"panel/pkg/tools"
|
||
)
|
||
|
||
type WebsiteController struct {
|
||
website services.Website
|
||
setting services.Setting
|
||
backup services.Backup
|
||
}
|
||
|
||
func NewWebsiteController() *WebsiteController {
|
||
return &WebsiteController{
|
||
website: services.NewWebsiteImpl(),
|
||
setting: services.NewSettingImpl(),
|
||
backup: services.NewBackupImpl(),
|
||
}
|
||
}
|
||
|
||
// List 网站列表
|
||
func (c *WebsiteController) List(ctx http.Context) {
|
||
limit := ctx.Request().QueryInt("limit")
|
||
page := ctx.Request().QueryInt("page")
|
||
|
||
total, websites, err := c.website.List(page, limit)
|
||
if err != nil {
|
||
facades.Log().Error("[面板][WebsiteController] 获取网站列表失败 ", err)
|
||
Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||
return
|
||
}
|
||
|
||
Success(ctx, http.Json{
|
||
"total": total,
|
||
"items": websites,
|
||
})
|
||
}
|
||
|
||
// Add 添加网站
|
||
func (c *WebsiteController) Add(ctx http.Context) {
|
||
if !Check(ctx, "openresty") {
|
||
return
|
||
}
|
||
validator, err := ctx.Request().Validate(map[string]string{
|
||
"name": "required|regex:^[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)*$",
|
||
"domain": "required",
|
||
"php": "required",
|
||
"db": "bool",
|
||
"db_type": "required_if:db,true",
|
||
"db_name": "required_if:db,true",
|
||
"db_user": "required_if:db,true",
|
||
"db_password": "required_if:db,true",
|
||
})
|
||
if err != nil {
|
||
Error(ctx, http.StatusBadRequest, err.Error())
|
||
return
|
||
}
|
||
if validator.Fails() {
|
||
Error(ctx, http.StatusBadRequest, validator.Errors().One())
|
||
return
|
||
}
|
||
|
||
var website services.PanelWebsite
|
||
website.Name = ctx.Request().Input("name")
|
||
website.Domain = ctx.Request().Input("domain")
|
||
website.Php = ctx.Request().InputInt("php")
|
||
website.Db = ctx.Request().InputBool("db")
|
||
website.DbType = ctx.Request().Input("db_type")
|
||
website.DbName = ctx.Request().Input("db_name")
|
||
website.DbUser = ctx.Request().Input("db_user")
|
||
website.DbPassword = ctx.Request().Input("db_password")
|
||
|
||
newSite, err := c.website.Add(website)
|
||
if err != nil {
|
||
facades.Log().Error("[面板][WebsiteController] 添加网站失败 ", err)
|
||
Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||
return
|
||
}
|
||
|
||
Success(ctx, newSite)
|
||
}
|
||
|
||
// Delete 删除网站
|
||
func (c *WebsiteController) Delete(ctx http.Context) {
|
||
if !Check(ctx, "openresty") {
|
||
return
|
||
}
|
||
id := ctx.Request().InputInt("id")
|
||
err := c.website.Delete(id)
|
||
if err != nil {
|
||
facades.Log().Error("[面板][WebsiteController] 删除网站失败 ", err)
|
||
Error(ctx, http.StatusInternalServerError, "删除网站失败: "+err.Error())
|
||
return
|
||
}
|
||
|
||
Success(ctx, nil)
|
||
}
|
||
|
||
// GetDefaultConfig 获取默认配置
|
||
func (c *WebsiteController) GetDefaultConfig(ctx http.Context) {
|
||
if !Check(ctx, "openresty") {
|
||
return
|
||
}
|
||
index := tools.ReadFile("/www/server/openresty/html/index.html")
|
||
stop := tools.ReadFile("/www/server/openresty/html/stop.html")
|
||
|
||
Success(ctx, http.Json{
|
||
"index": index,
|
||
"stop": stop,
|
||
})
|
||
}
|
||
|
||
// SaveDefaultConfig 保存默认配置
|
||
func (c *WebsiteController) SaveDefaultConfig(ctx http.Context) {
|
||
if !Check(ctx, "openresty") {
|
||
return
|
||
}
|
||
index := ctx.Request().Input("index")
|
||
stop := ctx.Request().Input("stop")
|
||
|
||
if !tools.WriteFile("/www/server/openresty/html/index.html", index, 0644) {
|
||
facades.Log().Error("[面板][WebsiteController] 保存默认配置失败")
|
||
Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||
return
|
||
}
|
||
|
||
if !tools.WriteFile("/www/server/openresty/html/stop.html", stop, 0644) {
|
||
facades.Log().Error("[面板][WebsiteController] 保存默认配置失败")
|
||
Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||
return
|
||
}
|
||
|
||
Success(ctx, nil)
|
||
}
|
||
|
||
// GetConfig 获取配置
|
||
func (c *WebsiteController) GetConfig(ctx http.Context) {
|
||
if !Check(ctx, "openresty") {
|
||
return
|
||
}
|
||
id := ctx.Request().InputInt("id")
|
||
if id == 0 {
|
||
Error(ctx, http.StatusBadRequest, "参数错误")
|
||
return
|
||
}
|
||
|
||
config, err := c.website.GetConfig(id)
|
||
if err != nil {
|
||
facades.Log().Error("[面板][WebsiteController] 获取网站配置失败 ", err)
|
||
Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||
return
|
||
}
|
||
|
||
Success(ctx, config)
|
||
}
|
||
|
||
// SaveConfig 保存配置
|
||
func (c *WebsiteController) SaveConfig(ctx http.Context) {
|
||
if !Check(ctx, "openresty") {
|
||
return
|
||
}
|
||
validator, err := ctx.Request().Validate(map[string]string{
|
||
"id": "required",
|
||
"domains": "required",
|
||
"ports": "required",
|
||
"hsts": "bool",
|
||
"ssl": "bool",
|
||
"http_redirect": "bool",
|
||
"open_basedir": "bool",
|
||
"waf": "required",
|
||
"waf_cache": "required",
|
||
"waf_mode": "required",
|
||
"waf_cc_deny": "required",
|
||
"index": "required",
|
||
"path": "required",
|
||
"root": "required",
|
||
"raw": "required",
|
||
"php": "required",
|
||
"ssl_certificate": "required_if:ssl,true",
|
||
"ssl_certificate_key": "required_if:ssl,true",
|
||
})
|
||
if err != nil {
|
||
Error(ctx, http.StatusBadRequest, err.Error())
|
||
return
|
||
}
|
||
if validator.Fails() {
|
||
Error(ctx, http.StatusBadRequest, validator.Errors().One())
|
||
return
|
||
}
|
||
|
||
var website models.Website
|
||
if facades.Orm().Query().Where("id", ctx.Request().Input("id")).FirstOrFail(&website) != nil {
|
||
Error(ctx, http.StatusBadRequest, "网站不存在")
|
||
return
|
||
}
|
||
|
||
if !website.Status {
|
||
Error(ctx, http.StatusBadRequest, "网站已停用,请先启用")
|
||
return
|
||
}
|
||
|
||
// 原文
|
||
raw := tools.ReadFile("/www/server/vhost/" + website.Name + ".conf")
|
||
if strings.TrimSpace(raw) != strings.TrimSpace(ctx.Request().Input("raw")) {
|
||
tools.WriteFile("/www/server/vhost/"+website.Name+".conf", ctx.Request().Input("raw"), 0644)
|
||
Success(ctx, nil)
|
||
return
|
||
}
|
||
|
||
// 目录
|
||
path := ctx.Request().Input("path")
|
||
if !tools.Exists(path) {
|
||
Error(ctx, http.StatusBadRequest, "网站目录不存在")
|
||
return
|
||
}
|
||
website.Path = path
|
||
|
||
// 域名
|
||
domain := "server_name"
|
||
domains := strings.Split(ctx.Request().Input("domains"), "\n")
|
||
if len(domains) == 0 {
|
||
Error(ctx, http.StatusBadRequest, "域名不能为空")
|
||
return
|
||
}
|
||
for _, v := range domains {
|
||
if v == "" {
|
||
continue
|
||
}
|
||
domain += " " + v
|
||
}
|
||
domain += ";"
|
||
domainConfigOld := tools.Cut(raw, "# server_name标记位开始", "# server_name标记位结束")
|
||
if len(strings.TrimSpace(domainConfigOld)) == 0 {
|
||
Error(ctx, http.StatusBadRequest, "配置文件中缺少server_name标记位")
|
||
return
|
||
}
|
||
raw = strings.Replace(raw, domainConfigOld, "\n "+domain+"\n ", -1)
|
||
|
||
// 端口
|
||
var port strings.Builder
|
||
ports := strings.Split(ctx.Request().Input("ports"), "\n")
|
||
if len(ports) == 0 {
|
||
Error(ctx, http.StatusBadRequest, "端口不能为空")
|
||
return
|
||
}
|
||
for i, v := range ports {
|
||
if _, err := strconv.Atoi(v); err != nil && v != "443 ssl http2" {
|
||
Error(ctx, http.StatusBadRequest, "端口格式错误")
|
||
return
|
||
}
|
||
if v == "443" && ctx.Request().InputBool("ssl") {
|
||
v = "443 ssl http2"
|
||
}
|
||
if i != len(ports)-1 {
|
||
port.WriteString(" listen " + v + ";\n")
|
||
} else {
|
||
port.WriteString(" listen " + v + ";")
|
||
}
|
||
}
|
||
portConfigOld := tools.Cut(raw, "# port标记位开始", "# port标记位结束")
|
||
if len(strings.TrimSpace(portConfigOld)) == 0 {
|
||
Error(ctx, http.StatusBadRequest, "配置文件中缺少port标记位")
|
||
return
|
||
}
|
||
raw = strings.Replace(raw, portConfigOld, "\n"+port.String()+"\n ", -1)
|
||
|
||
// 运行目录
|
||
root := tools.Cut(raw, "# root标记位开始", "# root标记位结束")
|
||
if len(strings.TrimSpace(root)) == 0 {
|
||
Error(ctx, http.StatusBadRequest, "配置文件中缺少root标记位")
|
||
return
|
||
}
|
||
match := regexp.MustCompile(`root\s+(.+);`).FindStringSubmatch(root)
|
||
if len(match) != 2 {
|
||
Error(ctx, http.StatusBadRequest, "配置文件中root标记位格式错误")
|
||
return
|
||
}
|
||
rootNew := strings.Replace(root, match[1], path, -1)
|
||
raw = strings.Replace(raw, root, rootNew, -1)
|
||
|
||
// 默认文件
|
||
index := tools.Cut(raw, "# index标记位开始", "# index标记位结束")
|
||
if len(strings.TrimSpace(index)) == 0 {
|
||
Error(ctx, http.StatusBadRequest, "配置文件中缺少index标记位")
|
||
return
|
||
}
|
||
match = regexp.MustCompile(`index\s+(.+);`).FindStringSubmatch(index)
|
||
if len(match) != 2 {
|
||
Error(ctx, http.StatusBadRequest, "配置文件中index标记位格式错误")
|
||
return
|
||
}
|
||
indexNew := strings.Replace(index, match[1], ctx.Request().Input("index"), -1)
|
||
raw = strings.Replace(raw, index, indexNew, -1)
|
||
|
||
// 防跨站
|
||
if !strings.HasSuffix(path, "/") {
|
||
path += "/"
|
||
}
|
||
if ctx.Request().InputBool("open_basedir") {
|
||
tools.WriteFile(path+".user.ini", "open_basedir="+path+":/tmp/", 0644)
|
||
} else {
|
||
if tools.Exists(path + ".user.ini") {
|
||
tools.RemoveFile(path + ".user.ini")
|
||
}
|
||
}
|
||
|
||
// WAF
|
||
waf := ctx.Request().Input("waf")
|
||
wafMode := ctx.Request().Input("waf_mode", "DYNAMIC")
|
||
wafCcDeny := ctx.Request().Input("waf_cc_deny", "rate=1000r/m duration=60m")
|
||
wafCache := ctx.Request().Input("waf_cache", "capacity=50")
|
||
wafConfig := `# waf标记位开始
|
||
waf ` + waf + `;
|
||
waf_rule_path /www/server/openresty/ngx_waf/assets/rules/;
|
||
waf_mode ` + wafMode + `;
|
||
waf_cc_deny ` + wafCcDeny + `;
|
||
waf_cache ` + wafCache + `;
|
||
`
|
||
wafConfigOld := tools.Cut(raw, "# waf标记位开始", "# waf标记位结束")
|
||
if len(strings.TrimSpace(wafConfigOld)) != 0 {
|
||
raw = strings.Replace(raw, wafConfigOld, "", -1)
|
||
}
|
||
raw = strings.Replace(raw, "# waf标记位开始", wafConfig, -1)
|
||
|
||
// SSL
|
||
ssl := ctx.Request().InputBool("ssl")
|
||
website.Ssl = ssl
|
||
if ssl {
|
||
tools.WriteFile("/www/server/vhost/ssl/"+website.Name+".pem", ctx.Request().Input("ssl_certificate"), 0644)
|
||
tools.WriteFile("/www/server/vhost/ssl/"+website.Name+".key", ctx.Request().Input("ssl_certificate_key"), 0644)
|
||
sslConfig := `# ssl标记位开始
|
||
ssl_certificate /www/server/vhost/ssl/` + website.Name + `.pem;
|
||
ssl_certificate_key /www/server/vhost/ssl/` + website.Name + `.key;
|
||
ssl_session_timeout 1d;
|
||
ssl_session_cache shared:SSL:10m;
|
||
ssl_session_tickets off;
|
||
ssl_protocols TLSv1.2 TLSv1.3;
|
||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
|
||
ssl_prefer_server_ciphers off;
|
||
`
|
||
if ctx.Request().InputBool("http_redirect") {
|
||
sslConfig += `# http重定向标记位开始
|
||
if (\$server_port !~ 443){
|
||
return 301 https://\$host\$request_uri;
|
||
}
|
||
error_page 497 https://\$host\$request_uri;
|
||
# http重定向标记位结束
|
||
`
|
||
}
|
||
if ctx.Request().InputBool("hsts") {
|
||
sslConfig += `# hsts标记位开始
|
||
add_header Strict-Transport-Security "max-age=63072000" always;
|
||
# hsts标记位结束
|
||
`
|
||
}
|
||
sslConfigOld := tools.Cut(raw, "# ssl标记位开始", "# ssl标记位结束")
|
||
if len(strings.TrimSpace(sslConfigOld)) != 0 {
|
||
raw = strings.Replace(raw, sslConfigOld, "", -1)
|
||
}
|
||
raw = strings.Replace(raw, "# ssl标记位开始", sslConfig, -1)
|
||
} else {
|
||
sslConfigOld := tools.Cut(raw, "# ssl标记位开始", "# ssl标记位结束")
|
||
if len(strings.TrimSpace(sslConfigOld)) != 0 {
|
||
raw = strings.Replace(raw, sslConfigOld, "\n ", -1)
|
||
}
|
||
}
|
||
|
||
if website.Php != ctx.Request().InputInt("php") {
|
||
website.Php = ctx.Request().InputInt("php")
|
||
phpConfigOld := tools.Cut(raw, "# php标记位开始", "# php标记位结束")
|
||
phpConfig := `
|
||
include enable-php-` + strconv.Itoa(website.Php) + `.conf;
|
||
`
|
||
if len(strings.TrimSpace(phpConfigOld)) != 0 {
|
||
raw = strings.Replace(raw, phpConfigOld, phpConfig, -1)
|
||
}
|
||
}
|
||
|
||
err = facades.Orm().Query().Save(&website)
|
||
if err != nil {
|
||
facades.Log().Error("[面板][WebsiteController] 保存网站配置失败 ", err)
|
||
Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||
return
|
||
}
|
||
|
||
tools.WriteFile("/www/server/vhost/"+website.Name+".conf", raw, 0644)
|
||
tools.WriteFile("/www/server/vhost/rewrite/"+website.Name+".conf", ctx.Request().Input("rewrite"), 0644)
|
||
tools.ExecShell("systemctl reload openresty")
|
||
|
||
Success(ctx, nil)
|
||
}
|
||
|
||
// ClearLog 清空日志
|
||
func (c *WebsiteController) ClearLog(ctx http.Context) {
|
||
if !Check(ctx, "openresty") {
|
||
return
|
||
}
|
||
id := ctx.Request().InputInt("id")
|
||
if id == 0 {
|
||
Error(ctx, http.StatusBadRequest, "参数错误")
|
||
return
|
||
}
|
||
|
||
website := models.Website{}
|
||
err := facades.Orm().Query().Where("id", id).Get(&website)
|
||
if err != nil {
|
||
facades.Log().Error("[面板][WebsiteController] 获取网站信息失败 ", err)
|
||
Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||
return
|
||
}
|
||
|
||
tools.RemoveFile("/www/wwwlogs/" + website.Name + ".log")
|
||
|
||
Success(ctx, nil)
|
||
}
|
||
|
||
// UpdateRemark 更新备注
|
||
func (c *WebsiteController) UpdateRemark(ctx http.Context) {
|
||
id := ctx.Request().InputInt("id")
|
||
if id == 0 {
|
||
Error(ctx, http.StatusBadRequest, "参数错误")
|
||
return
|
||
}
|
||
|
||
website := models.Website{}
|
||
err := facades.Orm().Query().Where("id", id).Get(&website)
|
||
if err != nil {
|
||
facades.Log().Error("[面板][WebsiteController] 获取网站信息失败 ", err)
|
||
Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||
return
|
||
}
|
||
|
||
website.Remark = ctx.Request().Input("remark")
|
||
err = facades.Orm().Query().Save(&website)
|
||
if err != nil {
|
||
facades.Log().Error("[面板][WebsiteController] 保存网站备注失败 ", err)
|
||
Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||
return
|
||
}
|
||
|
||
Success(ctx, nil)
|
||
}
|
||
|
||
// BackupList 备份列表
|
||
func (c *WebsiteController) BackupList(ctx http.Context) {
|
||
backupList, err := c.backup.WebsiteList()
|
||
if err != nil {
|
||
facades.Log().Error("[面板][WebsiteController] 获取网站备份列表失败 ", err)
|
||
Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||
return
|
||
}
|
||
|
||
Success(ctx, backupList)
|
||
}
|
||
|
||
// CreateBackup 创建备份
|
||
func (c *WebsiteController) CreateBackup(ctx http.Context) {
|
||
id := ctx.Request().InputInt("id")
|
||
if id == 0 {
|
||
Error(ctx, http.StatusBadRequest, "参数错误")
|
||
return
|
||
}
|
||
|
||
website := models.Website{}
|
||
err := facades.Orm().Query().Where("id", id).Get(&website)
|
||
if err != nil {
|
||
facades.Log().Error("[面板][WebsiteController] 获取网站信息失败 ", err)
|
||
Error(ctx, http.StatusInternalServerError, "获取网站信息失败: "+err.Error())
|
||
return
|
||
}
|
||
|
||
err = c.backup.WebSiteBackup(website)
|
||
if err != nil {
|
||
facades.Log().Error("[面板][WebsiteController] 备份网站失败 ", err)
|
||
Error(ctx, http.StatusInternalServerError, "备份网站失败: "+err.Error())
|
||
return
|
||
}
|
||
|
||
Success(ctx, nil)
|
||
}
|
||
|
||
// UploadBackup 上传备份
|
||
func (c *WebsiteController) UploadBackup(ctx http.Context) {
|
||
file, err := ctx.Request().File("file")
|
||
if err != nil {
|
||
Error(ctx, http.StatusBadRequest, "上传文件失败")
|
||
return
|
||
}
|
||
|
||
backupPath := c.setting.Get(models.SettingKeyBackupPath) + "/website"
|
||
if !tools.Exists(backupPath) {
|
||
tools.Mkdir(backupPath, 0644)
|
||
}
|
||
|
||
name := file.GetClientOriginalName()
|
||
_, err = file.StoreAs(backupPath, name)
|
||
if err != nil {
|
||
Error(ctx, http.StatusBadRequest, "上传文件失败")
|
||
return
|
||
}
|
||
|
||
Success(ctx, "上传文件成功")
|
||
}
|
||
|
||
// RestoreBackup 还原备份
|
||
func (c *WebsiteController) RestoreBackup(ctx http.Context) {
|
||
id := ctx.Request().InputInt("id")
|
||
if id == 0 {
|
||
Error(ctx, http.StatusBadRequest, "参数错误")
|
||
return
|
||
}
|
||
fileName := ctx.Request().Input("name")
|
||
if len(fileName) == 0 {
|
||
Error(ctx, http.StatusBadRequest, "参数错误")
|
||
return
|
||
}
|
||
|
||
website := models.Website{}
|
||
err := facades.Orm().Query().Where("id", id).Get(&website)
|
||
if err != nil {
|
||
facades.Log().Error("[面板][WebsiteController] 获取网站信息失败 ", err)
|
||
Error(ctx, http.StatusInternalServerError, "获取网站信息失败: "+err.Error())
|
||
return
|
||
}
|
||
|
||
err = c.backup.WebsiteRestore(website, fileName)
|
||
if err != nil {
|
||
facades.Log().Error("[面板][WebsiteController] 还原网站失败 ", err)
|
||
Error(ctx, http.StatusInternalServerError, "还原网站失败: "+err.Error())
|
||
return
|
||
}
|
||
|
||
Success(ctx, nil)
|
||
}
|
||
|
||
// DeleteBackup 删除备份
|
||
func (c *WebsiteController) DeleteBackup(ctx http.Context) {
|
||
fileName := ctx.Request().Input("name")
|
||
if len(fileName) == 0 {
|
||
Error(ctx, http.StatusBadRequest, "参数错误")
|
||
return
|
||
}
|
||
|
||
backupPath := c.setting.Get(models.SettingKeyBackupPath) + "/website"
|
||
if !tools.Exists(backupPath) {
|
||
tools.Mkdir(backupPath, 0644)
|
||
}
|
||
|
||
if !tools.RemoveFile(backupPath + "/" + fileName) {
|
||
Error(ctx, http.StatusInternalServerError, "删除备份失败")
|
||
return
|
||
}
|
||
|
||
Success(ctx, nil)
|
||
}
|
||
|
||
// ResetConfig 重置配置
|
||
func (c *WebsiteController) ResetConfig(ctx http.Context) {
|
||
if !Check(ctx, "openresty") {
|
||
return
|
||
}
|
||
id := ctx.Request().InputInt("id")
|
||
if id == 0 {
|
||
Error(ctx, http.StatusBadRequest, "参数错误")
|
||
return
|
||
}
|
||
|
||
website := models.Website{}
|
||
if err := facades.Orm().Query().Where("id", id).Get(&website); err != nil {
|
||
facades.Log().Error("[面板][WebsiteController] 获取网站信息失败 ", err)
|
||
Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||
return
|
||
}
|
||
|
||
website.Status = true
|
||
website.Ssl = false
|
||
if err := facades.Orm().Query().Save(&website); err != nil {
|
||
facades.Log().Error("[面板][WebsiteController] 保存网站配置失败 ", err)
|
||
Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||
return
|
||
}
|
||
|
||
raw := fmt.Sprintf(`
|
||
# 配置文件中的标记位请勿随意修改,改错将导致面板无法识别!
|
||
# 有自定义配置需求的,请将自定义的配置写在各标记位下方。
|
||
server
|
||
{
|
||
# port标记位开始
|
||
listen 80;
|
||
# port标记位结束
|
||
# server_name标记位开始
|
||
server_name localhost;
|
||
# server_name标记位结束
|
||
# index标记位开始
|
||
index index.php index.html;
|
||
# index标记位结束
|
||
# root标记位开始
|
||
root %s;
|
||
# root标记位结束
|
||
|
||
# ssl标记位开始
|
||
# ssl标记位结束
|
||
|
||
# php标记位开始
|
||
include enable-php-%d.conf;
|
||
# php标记位结束
|
||
|
||
# waf标记位开始
|
||
waf on;
|
||
waf_rule_path /www/server/openresty/ngx_waf/assets/rules/;
|
||
waf_mode DYNAMIC;
|
||
waf_cc_deny rate=1000r/m duration=60m;
|
||
waf_cache capacity=50;
|
||
# waf标记位结束
|
||
|
||
# 错误页配置,可自行设置
|
||
#error_page 404 /404.html;
|
||
#error_page 502 /502.html;
|
||
|
||
# 伪静态规则引入,修改后将导致面板设置的伪静态规则失效
|
||
include /www/server/vhost/rewrite/%s.conf;
|
||
|
||
# 面板默认禁止访问部分敏感目录,可自行修改
|
||
location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn)
|
||
{
|
||
return 404;
|
||
}
|
||
# 面板默认不记录静态资源的访问日志并开启1小时浏览器缓存,可自行修改
|
||
location ~ .*\.(js|css)$
|
||
{
|
||
expires 1h;
|
||
error_log /dev/null;
|
||
access_log /dev/null;
|
||
}
|
||
|
||
access_log /www/wwwlogs/%s.log;
|
||
error_log /www/wwwlogs/%s.log;
|
||
}
|
||
|
||
`, website.Path, website.Php, website.Name, website.Name, website.Name)
|
||
|
||
tools.WriteFile("/www/server/vhost/"+website.Name+".conf", raw, 0644)
|
||
tools.WriteFile("/www/server/vhost/rewrite"+website.Name+".conf", "", 0644)
|
||
tools.ExecShell("systemctl reload openresty")
|
||
|
||
Success(ctx, nil)
|
||
}
|
||
|
||
// Status 网站状态
|
||
func (c *WebsiteController) Status(ctx http.Context) {
|
||
if !Check(ctx, "openresty") {
|
||
return
|
||
}
|
||
id := ctx.Request().InputInt("id")
|
||
if id == 0 {
|
||
Error(ctx, http.StatusBadRequest, "参数错误")
|
||
return
|
||
}
|
||
|
||
website := models.Website{}
|
||
if err := facades.Orm().Query().Where("id", id).Get(&website); err != nil {
|
||
facades.Log().Error("[面板][WebsiteController] 获取网站信息失败 ", err)
|
||
Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||
return
|
||
}
|
||
|
||
website.Status = ctx.Request().InputBool("status")
|
||
if err := facades.Orm().Query().Save(&website); err != nil {
|
||
facades.Log().Error("[面板][WebsiteController] 保存网站配置失败 ", err)
|
||
Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||
return
|
||
}
|
||
|
||
raw := tools.ReadFile("/www/server/vhost/" + website.Name + ".conf")
|
||
|
||
// 运行目录
|
||
rootConfig := tools.Cut(raw, "# root标记位开始\n", "# root标记位结束")
|
||
match := regexp.MustCompile(`root\s+(.+);`).FindStringSubmatch(rootConfig)
|
||
if len(match) == 2 {
|
||
if website.Status {
|
||
root := regexp.MustCompile(`# root\s+(.+);`).FindStringSubmatch(rootConfig)
|
||
raw = strings.ReplaceAll(raw, rootConfig, " root "+root[1]+";\n ")
|
||
} else {
|
||
raw = strings.ReplaceAll(raw, rootConfig, " root /www/server/openresty/html;\n # root "+match[1]+";\n ")
|
||
}
|
||
}
|
||
|
||
// 默认文件
|
||
indexConfig := tools.Cut(raw, "# index标记位开始\n", "# index标记位结束")
|
||
match = regexp.MustCompile(`index\s+(.+);`).FindStringSubmatch(indexConfig)
|
||
if len(match) == 2 {
|
||
if website.Status {
|
||
index := regexp.MustCompile(`# index\s+(.+);`).FindStringSubmatch(indexConfig)
|
||
raw = strings.ReplaceAll(raw, indexConfig, " index "+index[1]+";\n ")
|
||
} else {
|
||
raw = strings.ReplaceAll(raw, indexConfig, " index stop.html;\n # index "+match[1]+";\n ")
|
||
}
|
||
}
|
||
|
||
tools.WriteFile("/www/server/vhost/"+website.Name+".conf", raw, 0644)
|
||
tools.ExecShell("systemctl reload openresty")
|
||
|
||
Success(ctx, nil)
|
||
}
|