mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 10:17:17 +08:00
refactor: 重构网站管理
This commit is contained in:
@@ -66,7 +66,7 @@ func (receiver *CertRenew) Handle(ctx console.Context) error {
|
||||
facades.Log().Tags("面板", "证书管理").With(map[string]any{
|
||||
"cert_id": cert.ID,
|
||||
"error": err.Error(),
|
||||
}).Errorf("证书续签失败")
|
||||
}).Infof("证书续签失败")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ func (receiver *Monitoring) Handle(ctx console.Context) error {
|
||||
Info: info,
|
||||
})
|
||||
if err != nil {
|
||||
facades.Log().Errorf("[面板] 系统监控保存失败: %s", err.Error())
|
||||
facades.Log().Infof("[面板] 系统监控保存失败: %s", err.Error())
|
||||
color.Redf("[面板] 系统监控保存失败: %s", err.Error())
|
||||
return nil
|
||||
}
|
||||
@@ -69,7 +69,7 @@ func (receiver *Monitoring) Handle(ctx console.Context) error {
|
||||
}
|
||||
_, err = facades.Orm().Query().Where("created_at < ?", carbon.Now().SubDays(days).ToDateTimeString()).Delete(&models.Monitor{})
|
||||
if err != nil {
|
||||
facades.Log().Errorf("[面板] 系统监控删除过期数据失败: %s", err.Error())
|
||||
facades.Log().Infof("[面板] 系统监控删除过期数据失败: %s", err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -120,6 +120,7 @@ func (r *CertController) Algorithms(ctx http.Context) http.Response {
|
||||
// @Tags 证书管理
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data body commonrequests.Paginate true "分页信息"
|
||||
// @Success 200 {object} SuccessResponse{data=responses.CertList}
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
@@ -137,11 +138,11 @@ func (r *CertController) UserList(ctx http.Context) http.Response {
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("获取ACME用户列表失败")
|
||||
}).Info("获取ACME用户列表失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, &responses.UserList{
|
||||
return Success(ctx, responses.UserList{
|
||||
Total: total,
|
||||
Items: users,
|
||||
})
|
||||
@@ -170,7 +171,7 @@ func (r *CertController) UserStore(ctx http.Context) http.Response {
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("添加ACME用户失败")
|
||||
}).Info("添加ACME用户失败")
|
||||
return Error(ctx, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
@@ -202,7 +203,7 @@ func (r *CertController) UserUpdate(ctx http.Context) http.Response {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"userID": updateRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Error("更新ACME用户失败")
|
||||
}).Info("更新ACME用户失败")
|
||||
return Error(ctx, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
@@ -232,7 +233,7 @@ func (r *CertController) UserShow(ctx http.Context) http.Response {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"userID": showAndDestroyRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Error("获取ACME用户失败")
|
||||
}).Info("获取ACME用户失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -263,7 +264,7 @@ func (r *CertController) UserDestroy(ctx http.Context) http.Response {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"userID": showAndDestroyRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Error("删除ACME用户失败")
|
||||
}).Info("删除ACME用户失败")
|
||||
return Error(ctx, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
@@ -276,6 +277,7 @@ func (r *CertController) UserDestroy(ctx http.Context) http.Response {
|
||||
// @Tags 证书管理
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data body commonrequests.Paginate true "分页信息"
|
||||
// @Success 200 {object} SuccessResponse{data=responses.DNSList}
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
@@ -293,11 +295,11 @@ func (r *CertController) DNSList(ctx http.Context) http.Response {
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("获取DNS接口列表失败")
|
||||
}).Info("获取DNS接口列表失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, &responses.DNSList{
|
||||
return Success(ctx, responses.DNSList{
|
||||
Total: total,
|
||||
Items: dns,
|
||||
})
|
||||
@@ -326,7 +328,7 @@ func (r *CertController) DNSStore(ctx http.Context) http.Response {
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("添加DNS接口失败")
|
||||
}).Info("添加DNS接口失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -356,7 +358,7 @@ func (r *CertController) DNSShow(ctx http.Context) http.Response {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"dnsID": showAndDestroyRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Error("获取DNS接口失败")
|
||||
}).Info("获取DNS接口失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -388,7 +390,7 @@ func (r *CertController) DNSUpdate(ctx http.Context) http.Response {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"dnsID": updateRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Error("更新DNS接口失败")
|
||||
}).Info("更新DNS接口失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -419,7 +421,7 @@ func (r *CertController) DNSDestroy(ctx http.Context) http.Response {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"dnsID": showAndDestroyRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Error("删除DNS接口失败")
|
||||
}).Info("删除DNS接口失败")
|
||||
return Error(ctx, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
@@ -432,6 +434,7 @@ func (r *CertController) DNSDestroy(ctx http.Context) http.Response {
|
||||
// @Tags 证书管理
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data body commonrequests.Paginate true "分页信息"
|
||||
// @Success 200 {object} SuccessResponse{data=responses.CertList}
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
@@ -449,11 +452,11 @@ func (r *CertController) CertList(ctx http.Context) http.Response {
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("获取证书列表失败")
|
||||
}).Info("获取证书列表失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, &responses.CertList{
|
||||
return Success(ctx, responses.CertList{
|
||||
Total: total,
|
||||
Items: certs,
|
||||
})
|
||||
@@ -482,7 +485,7 @@ func (r *CertController) CertStore(ctx http.Context) http.Response {
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("添加证书失败")
|
||||
}).Info("添加证书失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -514,7 +517,7 @@ func (r *CertController) CertUpdate(ctx http.Context) http.Response {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"certID": updateRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Error("更新证书失败")
|
||||
}).Info("更新证书失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -544,7 +547,7 @@ func (r *CertController) CertShow(ctx http.Context) http.Response {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"certID": showAndDestroyRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Error("获取证书失败")
|
||||
}).Info("获取证书失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -575,7 +578,7 @@ func (r *CertController) CertDestroy(ctx http.Context) http.Response {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"certID": showAndDestroyRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Error("删除证书失败")
|
||||
}).Info("删除证书失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -606,7 +609,7 @@ func (r *CertController) Obtain(ctx http.Context) http.Response {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"certID": obtainRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Error("获取证书失败")
|
||||
}).Info("获取证书失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -618,7 +621,7 @@ func (r *CertController) Obtain(ctx http.Context) http.Response {
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("签发证书失败")
|
||||
}).Info("签发证书失败")
|
||||
return Error(ctx, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
@@ -648,7 +651,7 @@ func (r *CertController) Renew(ctx http.Context) http.Response {
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("续签证书失败")
|
||||
}).Info("续签证书失败")
|
||||
return Error(ctx, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
@@ -678,7 +681,7 @@ func (r *CertController) ManualDNS(ctx http.Context) http.Response {
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("获取手动DNS记录失败")
|
||||
}).Info("获取手动DNS记录失败")
|
||||
return Error(ctx, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ func Check(ctx http.Context, slug string) http.Response {
|
||||
installedPlugin := services.NewPluginImpl().GetInstalledBySlug(slug)
|
||||
installedPlugins, err := services.NewPluginImpl().AllInstalled()
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][插件] 获取已安装插件失败")
|
||||
facades.Log().Info("[面板][插件] 获取已安装插件失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ func (c *CronController) List(ctx http.Context) http.Response {
|
||||
var total int64
|
||||
err := facades.Orm().Query().Paginate(page, limit, &crons, &total)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][CronController] 查询计划任务列表失败 ", err)
|
||||
facades.Log().Info("[面板][CronController] 查询计划任务列表失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -111,16 +111,16 @@ panel cutoff ${name} ${save} 2>&1
|
||||
shellDir := "/www/server/cron/"
|
||||
shellLogDir := "/www/server/cron/logs/"
|
||||
if !tools.Exists(shellDir) {
|
||||
facades.Log().Error("[面板][CronController] 计划任务目录不存在")
|
||||
facades.Log().Info("[面板][CronController] 计划任务目录不存在")
|
||||
return Error(ctx, http.StatusInternalServerError, "计划任务目录不存在")
|
||||
}
|
||||
if !tools.Exists(shellLogDir) {
|
||||
facades.Log().Error("[面板][CronController] 计划任务日志目录不存在")
|
||||
facades.Log().Info("[面板][CronController] 计划任务日志目录不存在")
|
||||
return Error(ctx, http.StatusInternalServerError, "计划任务日志目录不存在")
|
||||
}
|
||||
shellFile := strconv.Itoa(int(carbon.Now().Timestamp())) + tools.RandomString(16)
|
||||
if !tools.Write(shellDir+shellFile+".sh", shell, 0700) {
|
||||
facades.Log().Error("[面板][CronController] 创建计划任务脚本失败 ", err)
|
||||
if err = tools.Write(shellDir+shellFile+".sh", shell, 0700); err != nil {
|
||||
facades.Log().Info("[面板][CronController] 创建计划任务脚本失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
tools.Exec("dos2unix " + shellDir + shellFile + ".sh")
|
||||
@@ -135,7 +135,7 @@ panel cutoff ${name} ${save} 2>&1
|
||||
|
||||
err = facades.Orm().Query().Create(&cron)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][CronController] 创建计划任务失败 ", err)
|
||||
facades.Log().Info("[面板][CronController] 创建计划任务失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -190,12 +190,12 @@ func (c *CronController) Update(ctx http.Context) http.Response {
|
||||
cron.Name = ctx.Request().Input("name")
|
||||
err = facades.Orm().Query().Save(&cron)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][CronController] 更新计划任务失败 ", err)
|
||||
facades.Log().Info("[面板][CronController] 更新计划任务失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
if !tools.Write(cron.Shell, ctx.Request().Input("script"), 0644) {
|
||||
facades.Log().Error("[面板][CronController] 更新计划任务脚本失败 ", err)
|
||||
if err = tools.Write(cron.Shell, ctx.Request().Input("script"), 0644); err != nil {
|
||||
facades.Log().Info("[面板][CronController] 更新计划任务脚本失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
tools.Exec("dos2unix " + cron.Shell)
|
||||
@@ -221,7 +221,7 @@ func (c *CronController) Delete(ctx http.Context) http.Response {
|
||||
|
||||
_, err = facades.Orm().Query().Delete(&cron)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][CronController] 删除计划任务失败 ", err)
|
||||
facades.Log().Info("[面板][CronController] 删除计划任务失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -249,7 +249,7 @@ func (c *CronController) Status(ctx http.Context) http.Response {
|
||||
cron.Status = ctx.Request().InputBool("status")
|
||||
err = facades.Orm().Query().Save(&cron)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][CronController] 更新计划任务状态失败 ", err)
|
||||
facades.Log().Info("[面板][CronController] 更新计划任务状态失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ func (c *InfoController) Name(ctx http.Context) http.Response {
|
||||
var setting models.Setting
|
||||
err := facades.Orm().Query().Where("key", "name").First(&setting)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][InfoController] 查询面板名称失败 ", err)
|
||||
facades.Log().Info("[面板][InfoController] 查询面板名称失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ func (c *InfoController) HomePlugins(ctx http.Context) http.Response {
|
||||
var plugins []models.Plugin
|
||||
err := facades.Orm().Query().Where("show", 1).Find(&plugins)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][InfoController] 查询首页插件失败 ", err)
|
||||
facades.Log().Info("[面板][InfoController] 查询首页插件失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ func (c *InfoController) CountInfo(ctx http.Context) http.Response {
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("[面板][InfoController] 获取数据库列表失败")
|
||||
}).Info("[面板][InfoController] 获取数据库列表失败")
|
||||
databaseCount = -1
|
||||
} else {
|
||||
defer db.Close()
|
||||
@@ -129,7 +129,7 @@ func (c *InfoController) CountInfo(ctx http.Context) http.Response {
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("[面板][InfoController] 获取数据库列表失败")
|
||||
}).Info("[面板][InfoController] 获取数据库列表失败")
|
||||
databaseCount = -1
|
||||
} else {
|
||||
defer rows.Close()
|
||||
@@ -307,7 +307,7 @@ func (c *InfoController) Update(ctx http.Context) http.Response {
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("[面板][InfoController] 获取最新版本失败")
|
||||
}).Info("[面板][InfoController] 获取最新版本失败")
|
||||
return Error(ctx, http.StatusInternalServerError, "获取最新版本失败")
|
||||
}
|
||||
|
||||
@@ -315,7 +315,7 @@ func (c *InfoController) Update(ctx http.Context) http.Response {
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("[面板][InfoController] 更新面板失败")
|
||||
}).Info("[面板][InfoController] 更新面板失败")
|
||||
return Error(ctx, http.StatusInternalServerError, "更新失败: "+err.Error())
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ func (r *MonitorController) Switch(ctx http.Context) http.Response {
|
||||
value := ctx.Request().InputBool("monitor")
|
||||
err := r.setting.Set(models.SettingKeyMonitor, cast.ToString(value))
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][MonitorController] 更新监控开关失败 ", err)
|
||||
facades.Log().Info("[面板][MonitorController] 更新监控开关失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ func (r *MonitorController) SaveDays(ctx http.Context) http.Response {
|
||||
days := ctx.Request().Input("days")
|
||||
err := r.setting.Set(models.SettingKeyMonitorDays, days)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][MonitorController] 更新监控天数失败 ", err)
|
||||
facades.Log().Info("[面板][MonitorController] 更新监控天数失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ func (r *MonitorController) SwitchAndDays(ctx http.Context) http.Response {
|
||||
func (r *MonitorController) Clear(ctx http.Context) http.Response {
|
||||
_, err := facades.Orm().Query().Where("1 = 1").Delete(&models.Monitor{})
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][MonitorController] 清空监控数据失败 ", err)
|
||||
facades.Log().Info("[面板][MonitorController] 清空监控数据失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ func (r *MonitorController) List(ctx http.Context) http.Response {
|
||||
var monitors []models.Monitor
|
||||
err := facades.Orm().Query().Where("created_at >= ?", startTime.ToDateTimeString()).Where("created_at <= ?", endTime.ToDateTimeString()).Get(&monitors)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][MonitorController] 查询监控数据失败 ", err)
|
||||
facades.Log().Info("[面板][MonitorController] 查询监控数据失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ func (r *PluginController) Install(ctx http.Context) http.Response {
|
||||
installedPlugin := r.plugin.GetInstalledBySlug(slug)
|
||||
installedPlugins, err := r.plugin.AllInstalled()
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][PluginController] 获取已安装插件失败")
|
||||
facades.Log().Info("[面板][PluginController] 获取已安装插件失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ func (r *PluginController) Install(ctx http.Context) http.Response {
|
||||
task.Shell = plugin.Install + " >> /tmp/" + plugin.Slug + ".log 2>&1"
|
||||
task.Log = "/tmp/" + plugin.Slug + ".log"
|
||||
if err := facades.Orm().Query().Create(&task); err != nil {
|
||||
facades.Log().Error("[面板][PluginController] 创建任务失败: " + err.Error())
|
||||
facades.Log().Info("[面板][PluginController] 创建任务失败: " + err.Error())
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ func (r *PluginController) Uninstall(ctx http.Context) http.Response {
|
||||
installedPlugin := r.plugin.GetInstalledBySlug(slug)
|
||||
installedPlugins, err := r.plugin.AllInstalled()
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][PluginController] 获取已安装插件失败")
|
||||
facades.Log().Info("[面板][PluginController] 获取已安装插件失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ func (r *PluginController) Uninstall(ctx http.Context) http.Response {
|
||||
task.Shell = plugin.Uninstall + " >> /tmp/" + plugin.Slug + ".log 2>&1"
|
||||
task.Log = "/tmp/" + plugin.Slug + ".log"
|
||||
if err := facades.Orm().Query().Create(&task); err != nil {
|
||||
facades.Log().Error("[面板][PluginController] 创建任务失败: " + err.Error())
|
||||
facades.Log().Info("[面板][PluginController] 创建任务失败: " + err.Error())
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ func (r *PluginController) Update(ctx http.Context) http.Response {
|
||||
installedPlugin := r.plugin.GetInstalledBySlug(slug)
|
||||
installedPlugins, err := r.plugin.AllInstalled()
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][PluginController] 获取已安装插件失败")
|
||||
facades.Log().Info("[面板][PluginController] 获取已安装插件失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -253,7 +253,7 @@ func (r *PluginController) Update(ctx http.Context) http.Response {
|
||||
task.Shell = plugin.Update + " >> /tmp/" + plugin.Slug + ".log 2>&1"
|
||||
task.Log = "/tmp/" + plugin.Slug + ".log"
|
||||
if err := facades.Orm().Query().Create(&task); err != nil {
|
||||
facades.Log().Error("[面板][PluginController] 创建任务失败: " + err.Error())
|
||||
facades.Log().Info("[面板][PluginController] 创建任务失败: " + err.Error())
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@ func (r *PluginController) UpdateShow(ctx http.Context) http.Response {
|
||||
|
||||
var plugin models.Plugin
|
||||
if err := facades.Orm().Query().Where("slug", slug).First(&plugin); err != nil {
|
||||
facades.Log().Error("[面板][PluginController] 查询插件失败: " + err.Error())
|
||||
facades.Log().Info("[面板][PluginController] 查询插件失败: " + err.Error())
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
if plugin.ID == 0 {
|
||||
@@ -277,7 +277,7 @@ func (r *PluginController) UpdateShow(ctx http.Context) http.Response {
|
||||
|
||||
plugin.Show = show
|
||||
if err := facades.Orm().Query().Save(&plugin); err != nil {
|
||||
facades.Log().Error("[面板][PluginController] 更新插件失败: " + err.Error())
|
||||
facades.Log().Info("[面板][PluginController] 更新插件失败: " + err.Error())
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
|
||||
@@ -236,7 +236,7 @@ func (r *Fail2banController) Add(ctx http.Context) http.Response {
|
||||
if err != nil {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "网站不存在")
|
||||
}
|
||||
config, err := r.website.GetConfig(int(website.ID))
|
||||
config, err := r.website.GetConfig(website.ID)
|
||||
if err != nil {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "获取网站配置失败")
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ func (r *Mysql57Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "配置不能为空")
|
||||
}
|
||||
|
||||
if !tools.Write("/www/server/mysql/conf/my.cnf", config, 0644) {
|
||||
if err := tools.Write("/www/server/mysql/conf/my.cnf", config, 0644); err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "写入MySQL配置失败")
|
||||
}
|
||||
|
||||
@@ -345,14 +345,14 @@ func (r *Mysql57Controller) DatabaseList(ctx http.Context) http.Response {
|
||||
|
||||
db, err := sql.Open("mysql", "root:"+rootPassword+"@unix(/tmp/mysql.sock)/")
|
||||
if err != nil {
|
||||
facades.Log().Error("[MySQL57] 连接数据库失败" + err.Error())
|
||||
facades.Log().Info("[MySQL57] 连接数据库失败" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "连接数据库失败")
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
rows, err := db.Query("SHOW DATABASES")
|
||||
if err != nil {
|
||||
facades.Log().Error("[MySQL57] 获取数据库列表失败" + err.Error())
|
||||
facades.Log().Info("[MySQL57] 获取数据库列表失败" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取数据库列表失败")
|
||||
}
|
||||
defer rows.Close()
|
||||
@@ -369,7 +369,7 @@ func (r *Mysql57Controller) DatabaseList(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
facades.Log().Error("[MySQL57] 获取数据库列表失败" + err.Error())
|
||||
facades.Log().Info("[MySQL57] 获取数据库列表失败" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取数据库列表失败")
|
||||
}
|
||||
|
||||
@@ -459,7 +459,7 @@ func (r *Mysql57Controller) BackupList(ctx http.Context) http.Response {
|
||||
|
||||
backupList, err := r.backup.MysqlList()
|
||||
if err != nil {
|
||||
facades.Log().Error("[MySQL57] 获取备份列表失败:" + err.Error())
|
||||
facades.Log().Info("[MySQL57] 获取备份列表失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取备份列表失败")
|
||||
}
|
||||
|
||||
@@ -533,7 +533,7 @@ func (r *Mysql57Controller) CreateBackup(ctx http.Context) http.Response {
|
||||
database := ctx.Request().Input("database")
|
||||
err = r.backup.MysqlBackup(database)
|
||||
if err != nil {
|
||||
facades.Log().Error("[MYSQL57] 创建备份失败:" + err.Error())
|
||||
facades.Log().Info("[MYSQL57] 创建备份失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "创建备份失败")
|
||||
}
|
||||
|
||||
@@ -584,7 +584,7 @@ func (r *Mysql57Controller) RestoreBackup(ctx http.Context) http.Response {
|
||||
|
||||
err = r.backup.MysqlRestore(ctx.Request().Input("database"), ctx.Request().Input("backup"))
|
||||
if err != nil {
|
||||
facades.Log().Error("[MYSQL57] 还原失败:" + err.Error())
|
||||
facades.Log().Info("[MYSQL57] 还原失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "还原失败: "+err.Error())
|
||||
}
|
||||
|
||||
@@ -607,14 +607,14 @@ func (r *Mysql57Controller) UserList(ctx http.Context) http.Response {
|
||||
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
db, err := sql.Open("mysql", "root:"+rootPassword+"@unix(/tmp/mysql.sock)/")
|
||||
if err != nil {
|
||||
facades.Log().Error("[MYSQL57] 连接数据库失败:" + err.Error())
|
||||
facades.Log().Info("[MYSQL57] 连接数据库失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "连接数据库失败")
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
rows, err := db.Query("SELECT user, host FROM mysql.user")
|
||||
if err != nil {
|
||||
facades.Log().Error("[MYSQL57] 查询数据库失败:" + err.Error())
|
||||
facades.Log().Info("[MYSQL57] 查询数据库失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "查询数据库失败")
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
@@ -155,7 +155,7 @@ func (r *Mysql80Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "配置不能为空")
|
||||
}
|
||||
|
||||
if !tools.Write("/www/server/mysql/conf/my.cnf", config, 0644) {
|
||||
if err := tools.Write("/www/server/mysql/conf/my.cnf", config, 0644); err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "写入MySQL配置失败")
|
||||
}
|
||||
|
||||
@@ -345,14 +345,14 @@ func (r *Mysql80Controller) DatabaseList(ctx http.Context) http.Response {
|
||||
|
||||
db, err := sql.Open("mysql", "root:"+rootPassword+"@unix(/tmp/mysql.sock)/")
|
||||
if err != nil {
|
||||
facades.Log().Error("[MySQL80] 连接数据库失败" + err.Error())
|
||||
facades.Log().Info("[MySQL80] 连接数据库失败" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "连接数据库失败")
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
rows, err := db.Query("SHOW DATABASES")
|
||||
if err != nil {
|
||||
facades.Log().Error("[MySQL80] 获取数据库列表失败" + err.Error())
|
||||
facades.Log().Info("[MySQL80] 获取数据库列表失败" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取数据库列表失败")
|
||||
}
|
||||
defer rows.Close()
|
||||
@@ -369,7 +369,7 @@ func (r *Mysql80Controller) DatabaseList(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
facades.Log().Error("[MySQL80] 获取数据库列表失败" + err.Error())
|
||||
facades.Log().Info("[MySQL80] 获取数据库列表失败" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取数据库列表失败")
|
||||
}
|
||||
|
||||
@@ -459,7 +459,7 @@ func (r *Mysql80Controller) BackupList(ctx http.Context) http.Response {
|
||||
|
||||
backupList, err := r.backup.MysqlList()
|
||||
if err != nil {
|
||||
facades.Log().Error("[MySQL80] 获取备份列表失败:" + err.Error())
|
||||
facades.Log().Info("[MySQL80] 获取备份列表失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取备份列表失败")
|
||||
}
|
||||
|
||||
@@ -533,7 +533,7 @@ func (r *Mysql80Controller) CreateBackup(ctx http.Context) http.Response {
|
||||
database := ctx.Request().Input("database")
|
||||
err = r.backup.MysqlBackup(database)
|
||||
if err != nil {
|
||||
facades.Log().Error("[MYSQL80] 创建备份失败:" + err.Error())
|
||||
facades.Log().Info("[MYSQL80] 创建备份失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "创建备份失败")
|
||||
}
|
||||
|
||||
@@ -584,7 +584,7 @@ func (r *Mysql80Controller) RestoreBackup(ctx http.Context) http.Response {
|
||||
|
||||
err = r.backup.MysqlRestore(ctx.Request().Input("database"), ctx.Request().Input("backup"))
|
||||
if err != nil {
|
||||
facades.Log().Error("[MYSQL80] 还原失败:" + err.Error())
|
||||
facades.Log().Info("[MYSQL80] 还原失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "还原失败: "+err.Error())
|
||||
}
|
||||
|
||||
@@ -607,14 +607,14 @@ func (r *Mysql80Controller) UserList(ctx http.Context) http.Response {
|
||||
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
db, err := sql.Open("mysql", "root:"+rootPassword+"@unix(/tmp/mysql.sock)/")
|
||||
if err != nil {
|
||||
facades.Log().Error("[MYSQL80] 连接数据库失败:" + err.Error())
|
||||
facades.Log().Info("[MYSQL80] 连接数据库失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "连接数据库失败")
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
rows, err := db.Query("SELECT user, host FROM mysql.user")
|
||||
if err != nil {
|
||||
facades.Log().Error("[MYSQL80] 查询数据库失败:" + err.Error())
|
||||
facades.Log().Info("[MYSQL80] 查询数据库失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "查询数据库失败")
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
@@ -149,7 +149,7 @@ func (r *OpenRestyController) SaveConfig(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "配置不能为空")
|
||||
}
|
||||
|
||||
if !tools.Write("/www/server/openresty/conf/nginx.conf", config, 0644) {
|
||||
if err := tools.Write("/www/server/openresty/conf/nginx.conf", config, 0644); err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "保存OpenResty配置失败")
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ func (r *OpenRestyController) Load(ctx http.Context) http.Response {
|
||||
client := req.C().SetTimeout(10 * time.Second)
|
||||
resp, err := client.R().Get("http://127.0.0.1/nginx_status")
|
||||
if err != nil || !resp.IsSuccessState() {
|
||||
facades.Log().Error("[OpenResty] 获取OpenResty负载失败: " + err.Error())
|
||||
facades.Log().Info("[OpenResty] 获取OpenResty负载失败: " + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取OpenResty负载失败")
|
||||
}
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ func (r *Php74Controller) Load(ctx http.Context) http.Response {
|
||||
client := req.C().SetTimeout(10 * time.Second)
|
||||
resp, err := client.R().Get("http://127.0.0.1/phpfpm_status/" + r.version)
|
||||
if err != nil || !resp.IsSuccessState() {
|
||||
facades.Log().Error("获取PHP-" + r.version + "运行状态失败")
|
||||
facades.Log().Info("获取PHP-" + r.version + "运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "[PHP-"+r.version+"] 获取运行状态失败")
|
||||
}
|
||||
|
||||
@@ -259,7 +259,7 @@ func (r *Php74Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' install ` + r.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Log = "/tmp/" + item.Slug + ".log"
|
||||
if err := facades.Orm().Query().Create(&task); err != nil {
|
||||
facades.Log().Error("[PHP-" + r.version + "] 创建安装拓展任务失败:" + err.Error())
|
||||
facades.Log().Info("[PHP-" + r.version + "] 创建安装拓展任务失败:" + err.Error())
|
||||
return controllers.ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -296,7 +296,7 @@ func (r *Php74Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' uninstall ` + r.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Log = "/tmp/" + item.Slug + ".log"
|
||||
if err := facades.Orm().Query().Create(&task); err != nil {
|
||||
facades.Log().Error("[PHP-" + r.version + "] 创建卸载拓展任务失败:" + err.Error())
|
||||
facades.Log().Info("[PHP-" + r.version + "] 创建卸载拓展任务失败:" + err.Error())
|
||||
return controllers.ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ func (r *Php80Controller) Load(ctx http.Context) http.Response {
|
||||
client := req.C().SetTimeout(10 * time.Second)
|
||||
resp, err := client.R().Get("http://127.0.0.1/phpfpm_status/" + r.version)
|
||||
if err != nil || !resp.IsSuccessState() {
|
||||
facades.Log().Error("获取PHP-" + r.version + "运行状态失败")
|
||||
facades.Log().Info("获取PHP-" + r.version + "运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "[PHP-"+r.version+"] 获取运行状态失败")
|
||||
}
|
||||
|
||||
@@ -259,7 +259,7 @@ func (r *Php80Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' install ` + r.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Log = "/tmp/" + item.Slug + ".log"
|
||||
if err := facades.Orm().Query().Create(&task); err != nil {
|
||||
facades.Log().Error("[PHP-" + r.version + "] 创建安装拓展任务失败:" + err.Error())
|
||||
facades.Log().Info("[PHP-" + r.version + "] 创建安装拓展任务失败:" + err.Error())
|
||||
return controllers.ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -296,7 +296,7 @@ func (r *Php80Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' uninstall ` + r.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Log = "/tmp/" + item.Slug + ".log"
|
||||
if err := facades.Orm().Query().Create(&task); err != nil {
|
||||
facades.Log().Error("[PHP-" + r.version + "] 创建卸载拓展任务失败:" + err.Error())
|
||||
facades.Log().Info("[PHP-" + r.version + "] 创建卸载拓展任务失败:" + err.Error())
|
||||
return controllers.ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ func (r *Php81Controller) Load(ctx http.Context) http.Response {
|
||||
client := req.C().SetTimeout(10 * time.Second)
|
||||
resp, err := client.R().Get("http://127.0.0.1/phpfpm_status/" + r.version)
|
||||
if err != nil || !resp.IsSuccessState() {
|
||||
facades.Log().Error("获取PHP-" + r.version + "运行状态失败")
|
||||
facades.Log().Info("获取PHP-" + r.version + "运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "[PHP-"+r.version+"] 获取运行状态失败")
|
||||
}
|
||||
|
||||
@@ -259,7 +259,7 @@ func (r *Php81Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' install ` + r.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Log = "/tmp/" + item.Slug + ".log"
|
||||
if err := facades.Orm().Query().Create(&task); err != nil {
|
||||
facades.Log().Error("[PHP-" + r.version + "] 创建安装拓展任务失败:" + err.Error())
|
||||
facades.Log().Info("[PHP-" + r.version + "] 创建安装拓展任务失败:" + err.Error())
|
||||
return controllers.ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -296,7 +296,7 @@ func (r *Php81Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' uninstall ` + r.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Log = "/tmp/" + item.Slug + ".log"
|
||||
if err := facades.Orm().Query().Create(&task); err != nil {
|
||||
facades.Log().Error("[PHP-" + r.version + "] 创建卸载拓展任务失败:" + err.Error())
|
||||
facades.Log().Info("[PHP-" + r.version + "] 创建卸载拓展任务失败:" + err.Error())
|
||||
return controllers.ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ func (r *Php82Controller) Load(ctx http.Context) http.Response {
|
||||
client := req.C().SetTimeout(10 * time.Second)
|
||||
resp, err := client.R().Get("http://127.0.0.1/phpfpm_status/" + r.version)
|
||||
if err != nil || !resp.IsSuccessState() {
|
||||
facades.Log().Error("获取PHP-" + r.version + "运行状态失败")
|
||||
facades.Log().Info("获取PHP-" + r.version + "运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "[PHP-"+r.version+"] 获取运行状态失败")
|
||||
}
|
||||
|
||||
@@ -259,7 +259,7 @@ func (r *Php82Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' install ` + r.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Log = "/tmp/" + item.Slug + ".log"
|
||||
if err := facades.Orm().Query().Create(&task); err != nil {
|
||||
facades.Log().Error("[PHP-" + r.version + "] 创建安装拓展任务失败:" + err.Error())
|
||||
facades.Log().Info("[PHP-" + r.version + "] 创建安装拓展任务失败:" + err.Error())
|
||||
return controllers.ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -296,7 +296,7 @@ func (r *Php82Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' uninstall ` + r.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Log = "/tmp/" + item.Slug + ".log"
|
||||
if err := facades.Orm().Query().Create(&task); err != nil {
|
||||
facades.Log().Error("[PHP-" + r.version + "] 创建卸载拓展任务失败:" + err.Error())
|
||||
facades.Log().Info("[PHP-" + r.version + "] 创建卸载拓展任务失败:" + err.Error())
|
||||
return controllers.ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"panel/app/http/controllers"
|
||||
@@ -65,7 +66,13 @@ func (r *PhpMyAdminController) SetPort(ctx http.Context) http.Response {
|
||||
|
||||
conf := tools.Read("/www/server/vhost/phpmyadmin.conf")
|
||||
conf = regexp.MustCompile(`listen\s+(\d+);`).ReplaceAllString(conf, "listen "+port+";")
|
||||
tools.Write("/www/server/vhost/phpmyadmin.conf", conf, 0644)
|
||||
err := tools.Write("/www/server/vhost/phpmyadmin.conf", conf, 0644)
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("插件", "phpMyAdmin").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Info("修改 phpMyAdmin 端口失败")
|
||||
return controllers.ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
if tools.IsRHEL() {
|
||||
tools.Exec("firewall-cmd --zone=public --add-port=" + port + "/tcp --permanent")
|
||||
|
||||
@@ -168,7 +168,7 @@ func (r *Postgresql15Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "配置不能为空")
|
||||
}
|
||||
|
||||
if !tools.Write("/www/server/postgresql/data/postgresql.conf", config, 0644) {
|
||||
if err := tools.Write("/www/server/postgresql/data/postgresql.conf", config, 0644); err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "写入PostgreSQL配置失败")
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ func (r *Postgresql15Controller) SaveUserConfig(ctx http.Context) http.Response
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "配置不能为空")
|
||||
}
|
||||
|
||||
if !tools.Write("/www/server/postgresql/data/pg_hba.conf", config, 0644) {
|
||||
if err := tools.Write("/www/server/postgresql/data/pg_hba.conf", config, 0644); err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "写入PostgreSQL配置失败")
|
||||
}
|
||||
|
||||
@@ -369,7 +369,7 @@ func (r *Postgresql15Controller) BackupList(ctx http.Context) http.Response {
|
||||
|
||||
backupList, err := r.backup.PostgresqlList()
|
||||
if err != nil {
|
||||
facades.Log().Error("[PostgreSQL] 获取备份列表失败:" + err.Error())
|
||||
facades.Log().Info("[PostgreSQL] 获取备份列表失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取备份列表失败")
|
||||
}
|
||||
|
||||
@@ -443,7 +443,7 @@ func (r *Postgresql15Controller) CreateBackup(ctx http.Context) http.Response {
|
||||
database := ctx.Request().Input("database")
|
||||
err = r.backup.PostgresqlBackup(database)
|
||||
if err != nil {
|
||||
facades.Log().Error("[PostgreSQL] 创建备份失败:" + err.Error())
|
||||
facades.Log().Info("[PostgreSQL] 创建备份失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "创建备份失败")
|
||||
}
|
||||
|
||||
@@ -494,7 +494,7 @@ func (r *Postgresql15Controller) RestoreBackup(ctx http.Context) http.Response {
|
||||
|
||||
err = r.backup.PostgresqlRestore(ctx.Request().Input("database"), ctx.Request().Input("backup"))
|
||||
if err != nil {
|
||||
facades.Log().Error("[PostgreSQL] 还原失败:" + err.Error())
|
||||
facades.Log().Info("[PostgreSQL] 还原失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "还原失败: "+err.Error())
|
||||
}
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ func (r *Postgresql16Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "配置不能为空")
|
||||
}
|
||||
|
||||
if !tools.Write("/www/server/postgresql/data/postgresql.conf", config, 0644) {
|
||||
if err := tools.Write("/www/server/postgresql/data/postgresql.conf", config, 0644); err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "写入PostgreSQL配置失败")
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ func (r *Postgresql16Controller) SaveUserConfig(ctx http.Context) http.Response
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "配置不能为空")
|
||||
}
|
||||
|
||||
if !tools.Write("/www/server/postgresql/data/pg_hba.conf", config, 0644) {
|
||||
if err := tools.Write("/www/server/postgresql/data/pg_hba.conf", config, 0644); err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "写入PostgreSQL配置失败")
|
||||
}
|
||||
|
||||
@@ -369,7 +369,7 @@ func (r *Postgresql16Controller) BackupList(ctx http.Context) http.Response {
|
||||
|
||||
backupList, err := r.backup.PostgresqlList()
|
||||
if err != nil {
|
||||
facades.Log().Error("[PostgreSQL] 获取备份列表失败:" + err.Error())
|
||||
facades.Log().Info("[PostgreSQL] 获取备份列表失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取备份列表失败")
|
||||
}
|
||||
|
||||
@@ -443,7 +443,7 @@ func (r *Postgresql16Controller) CreateBackup(ctx http.Context) http.Response {
|
||||
database := ctx.Request().Input("database")
|
||||
err = r.backup.PostgresqlBackup(database)
|
||||
if err != nil {
|
||||
facades.Log().Error("[PostgreSQL] 创建备份失败:" + err.Error())
|
||||
facades.Log().Info("[PostgreSQL] 创建备份失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "创建备份失败")
|
||||
}
|
||||
|
||||
@@ -494,7 +494,7 @@ func (r *Postgresql16Controller) RestoreBackup(ctx http.Context) http.Response {
|
||||
|
||||
err = r.backup.PostgresqlRestore(ctx.Request().Input("database"), ctx.Request().Input("backup"))
|
||||
if err != nil {
|
||||
facades.Log().Error("[PostgreSQL] 还原失败:" + err.Error())
|
||||
facades.Log().Info("[PostgreSQL] 还原失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "还原失败: "+err.Error())
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ func (r *RedisController) SaveConfig(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "配置不能为空")
|
||||
}
|
||||
|
||||
if !tools.Write("/www/server/redis/redis.conf", config, 0644) {
|
||||
if err := tools.Write("/www/server/redis/redis.conf", config, 0644); err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "写入Redis配置失败")
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ func (r *SettingController) List(ctx http.Context) http.Response {
|
||||
var settings []models.Setting
|
||||
err := facades.Orm().Query().Get(&settings)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SettingController] 查询设置列表失败 ", err)
|
||||
facades.Log().Info("[面板][SettingController] 查询设置列表失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ func (r *SettingController) List(ctx http.Context) http.Response {
|
||||
var user models.User
|
||||
err = facades.Auth().User(ctx, &user)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SettingController] 获取用户失败 ", err)
|
||||
facades.Log().Info("[面板][SettingController] 获取用户失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
result.Username = user.Username
|
||||
@@ -83,7 +83,7 @@ func (r *SettingController) Update(ctx http.Context) http.Response {
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "面板设置").Error("保存面板名称失败")
|
||||
}).Tags("面板", "面板设置").Info("保存面板名称失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ func (r *SettingController) Update(ctx http.Context) http.Response {
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "面板设置").Error("保存备份目录失败")
|
||||
}).Tags("面板", "面板设置").Info("保存备份目录失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
if !tools.Exists(updateRequest.WebsitePath) {
|
||||
@@ -105,7 +105,7 @@ func (r *SettingController) Update(ctx http.Context) http.Response {
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "面板设置").Error("保存建站目录失败")
|
||||
}).Tags("面板", "面板设置").Info("保存建站目录失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ func (r *SettingController) Update(ctx http.Context) http.Response {
|
||||
if err = facades.Orm().Query().Save(&user); err != nil {
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "面板设置").Error("保存用户信息失败")
|
||||
}).Tags("面板", "面板设置").Info("保存用户信息失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
|
||||
@@ -69,22 +69,22 @@ func (r *SshController) UpdateInfo(ctx http.Context) http.Response {
|
||||
password := ctx.Request().Input("password")
|
||||
err = r.setting.Set(models.SettingKeySshHost, host)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SSH] 更新配置失败 ", err)
|
||||
facades.Log().Info("[面板][SSH] 更新配置失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
err = r.setting.Set(models.SettingKeySshPort, port)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SSH] 更新配置失败 ", err)
|
||||
facades.Log().Info("[面板][SSH] 更新配置失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
err = r.setting.Set(models.SettingKeySshUser, user)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SSH] 更新配置失败 ", err)
|
||||
facades.Log().Info("[面板][SSH] 更新配置失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
err = r.setting.Set(models.SettingKeySshPassword, password)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SSH] 更新配置失败 ", err)
|
||||
facades.Log().Info("[面板][SSH] 更新配置失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -142,21 +142,21 @@ func (r *SshController) Session(ctx http.Context) http.Response {
|
||||
defer wg.Done()
|
||||
err := turn.LoopRead(logBuff, ctx2)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SSH] 读取数据失败 ", err.Error())
|
||||
facades.Log().Info("[面板][SSH] 读取数据失败 ", err.Error())
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
err := turn.SessionWait()
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SSH] 会话失败 ", err.Error())
|
||||
facades.Log().Info("[面板][SSH] 会话失败 ", err.Error())
|
||||
}
|
||||
cancel()
|
||||
}()
|
||||
wg.Wait()
|
||||
})
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SSH] 建立连接失败 ", err)
|
||||
facades.Log().Info("[面板][SSH] 建立连接失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ func (r *TaskController) List(ctx http.Context) http.Response {
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("[面板][TaskController] 查询任务列表失败")
|
||||
}).Info("[面板][TaskController] 查询任务列表失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ func (r *TaskController) Log(ctx http.Context) http.Response {
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"id": ctx.Request().QueryInt("id"),
|
||||
"error": err.Error(),
|
||||
}).Error("[面板][TaskController] 查询任务失败")
|
||||
}).Info("[面板][TaskController] 查询任务失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ func (r *TaskController) Delete(ctx http.Context) http.Response {
|
||||
facades.Log().With(map[string]any{
|
||||
"id": ctx.Request().QueryInt("id"),
|
||||
"error": err.Error(),
|
||||
}).Error("[面板][TaskController] 删除任务失败")
|
||||
}).Info("[面板][TaskController] 删除任务失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ func (r *UserController) Login(ctx http.Context) http.Response {
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "用户").Error("查询用户失败")
|
||||
}).Tags("面板", "用户").Info("查询用户失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ func (r *UserController) Login(ctx http.Context) http.Response {
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "用户").Error("更新密码失败")
|
||||
}).Tags("面板", "用户").Info("更新密码失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ func (r *UserController) Login(ctx http.Context) http.Response {
|
||||
if loginErr != nil {
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "用户").Error("登录失败")
|
||||
}).Tags("面板", "用户").Info("登录失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ func (r *UserController) Info(ctx http.Context) http.Response {
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "用户").Error("获取用户信息失败")
|
||||
}).Tags("面板", "用户").Info("获取用户信息失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,12 +3,14 @@ package controllers
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
commonrequests "panel/app/http/requests/common"
|
||||
requests "panel/app/http/requests/website"
|
||||
responses "panel/app/http/responses/website"
|
||||
"panel/app/models"
|
||||
"panel/app/services"
|
||||
"panel/pkg/tools"
|
||||
@@ -28,84 +30,133 @@ func NewWebsiteController() *WebsiteController {
|
||||
}
|
||||
}
|
||||
|
||||
// List 网站列表
|
||||
// List
|
||||
// @Summary 获取网站列表
|
||||
// @Description 获取网站管理的网站列表
|
||||
// @Tags 网站管理
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data body commonrequests.Paginate true "分页信息"
|
||||
// @Success 200 {object} SuccessResponse{data=responses.List}
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 403 {object} ErrorResponse "插件需更新"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/website [get]
|
||||
func (c *WebsiteController) List(ctx http.Context) http.Response {
|
||||
limit := ctx.Request().QueryInt("limit", 10)
|
||||
page := ctx.Request().QueryInt("page", 1)
|
||||
var paginateRequest commonrequests.Paginate
|
||||
sanitize := Sanitize(ctx, &paginateRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
total, websites, err := c.website.List(page, limit)
|
||||
total, websites, err := c.website.List(paginateRequest.Page, paginateRequest.Limit)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 获取网站列表失败 ", err)
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "网站管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Info("获取网站列表失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, http.Json{
|
||||
"total": total,
|
||||
"items": websites,
|
||||
return Success(ctx, responses.List{
|
||||
Total: total,
|
||||
Items: websites,
|
||||
})
|
||||
}
|
||||
|
||||
// Add 添加网站
|
||||
// Add
|
||||
// @Summary 添加网站
|
||||
// @Description 添加网站到网站管理
|
||||
// @Tags 网站管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data body requests.Add true "网站信息"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 403 {object} ErrorResponse "插件需更新"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/website [post]
|
||||
func (c *WebsiteController) Add(ctx http.Context) http.Response {
|
||||
check := Check(ctx, "openresty")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
validator, err := ctx.Request().Validate(map[string]string{
|
||||
"name": "required|regex:^[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)*$|not_exists:websites,name",
|
||||
"domains": "required|slice",
|
||||
"ports": "required|slice",
|
||||
"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 {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, err.Error())
|
||||
}
|
||||
if validator.Fails() {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One())
|
||||
var addRequest requests.Add
|
||||
sanitize := Sanitize(ctx, &addRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
var website services.PanelWebsite
|
||||
website.Name = ctx.Request().Input("name")
|
||||
website.Domains = ctx.Request().InputArray("domains")
|
||||
website.Ports = ctx.Request().InputArray("ports")
|
||||
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")
|
||||
website := services.PanelWebsite{
|
||||
Name: addRequest.Name,
|
||||
Domains: addRequest.Domains,
|
||||
Ports: addRequest.Ports,
|
||||
Php: addRequest.Php,
|
||||
Db: addRequest.Db,
|
||||
DbType: addRequest.DbType,
|
||||
DbName: addRequest.DbName,
|
||||
DbUser: addRequest.DbUser,
|
||||
DbPassword: addRequest.DbPassword,
|
||||
}
|
||||
|
||||
newSite, err := c.website.Add(website)
|
||||
_, err := c.website.Add(website)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 添加网站失败 ", err)
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "网站管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Info("添加网站失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, newSite)
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// Delete 删除网站
|
||||
// Delete
|
||||
// @Summary 删除网站
|
||||
// @Description 删除网站管理的网站
|
||||
// @Tags 网站管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param id path int true "网站 ID"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 403 {object} ErrorResponse "插件需更新"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/website/{id} [delete]
|
||||
func (c *WebsiteController) Delete(ctx http.Context) http.Response {
|
||||
check := Check(ctx, "openresty")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
id := ctx.Request().InputInt("id")
|
||||
err := c.website.Delete(id)
|
||||
|
||||
var idRequest requests.ID
|
||||
sanitize := Sanitize(ctx, &idRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
err := c.website.Delete(idRequest.ID)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 删除网站失败 ", err)
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "网站管理").With(map[string]any{
|
||||
"id": idRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Info("删除网站失败")
|
||||
return Error(ctx, http.StatusInternalServerError, "删除网站失败: "+err.Error())
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// GetDefaultConfig 获取默认配置
|
||||
// GetDefaultConfig
|
||||
// @Summary 获取默认配置
|
||||
// @Description 获取默认首页和停止页配置
|
||||
// @Tags 网站管理
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Success 200 {object} SuccessResponse{data=map[string]string}
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 403 {object} ErrorResponse "插件需更新"
|
||||
// @Router /panel/website/defaultConfig [get]
|
||||
func (c *WebsiteController) GetDefaultConfig(ctx http.Context) http.Response {
|
||||
check := Check(ctx, "openresty")
|
||||
if check != nil {
|
||||
@@ -120,7 +171,19 @@ func (c *WebsiteController) GetDefaultConfig(ctx http.Context) http.Response {
|
||||
})
|
||||
}
|
||||
|
||||
// SaveDefaultConfig 保存默认配置
|
||||
// SaveDefaultConfig
|
||||
// @Summary 保存默认配置
|
||||
// @Description 保存默认首页和停止页配置
|
||||
// @Tags 网站管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data body map[string]string true "页面信息"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 403 {object} ErrorResponse "插件需更新"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/website/defaultConfig [post]
|
||||
func (c *WebsiteController) SaveDefaultConfig(ctx http.Context) http.Response {
|
||||
check := Check(ctx, "openresty")
|
||||
if check != nil {
|
||||
@@ -129,347 +192,240 @@ func (c *WebsiteController) SaveDefaultConfig(ctx http.Context) http.Response {
|
||||
index := ctx.Request().Input("index")
|
||||
stop := ctx.Request().Input("stop")
|
||||
|
||||
if !tools.Write("/www/server/openresty/html/index.html", index, 0644) {
|
||||
facades.Log().Error("[面板][WebsiteController] 保存默认配置失败")
|
||||
if err := tools.Write("/www/server/openresty/html/index.html", index, 0644); err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "网站管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Info("保存默认首页配置失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
if !tools.Write("/www/server/openresty/html/stop.html", stop, 0644) {
|
||||
facades.Log().Error("[面板][WebsiteController] 保存默认配置失败")
|
||||
if err := tools.Write("/www/server/openresty/html/stop.html", stop, 0644); err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "网站管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Info("保存默认停止页配置失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// GetConfig 获取配置
|
||||
// GetConfig
|
||||
// @Summary 获取配置
|
||||
// @Description 获取网站的配置
|
||||
// @Tags 网站管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param id path int true "网站 ID"
|
||||
// @Success 200 {object} SuccessResponse{data=services.PanelWebsite}
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/website/config/{id} [get]
|
||||
func (c *WebsiteController) GetConfig(ctx http.Context) http.Response {
|
||||
check := Check(ctx, "openresty")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
id := ctx.Request().InputInt("id")
|
||||
if id == 0 {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "参数错误")
|
||||
|
||||
var idRequest requests.ID
|
||||
sanitize := Sanitize(ctx, &idRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
config, err := c.website.GetConfig(id)
|
||||
config, err := c.website.GetConfig(idRequest.ID)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 获取网站配置失败 ", err)
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "网站管理").With(map[string]any{
|
||||
"id": idRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Info("获取网站配置失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, config)
|
||||
}
|
||||
|
||||
// SaveConfig 保存配置
|
||||
// SaveConfig
|
||||
// @Summary 保存配置
|
||||
// @Description 保存网站的配置
|
||||
// @Tags 网站管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param id path int true "网站 ID"
|
||||
// @Param data body requests.SaveConfig true "网站配置"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/website/config/{id} [post]
|
||||
func (c *WebsiteController) SaveConfig(ctx http.Context) http.Response {
|
||||
check := Check(ctx, "openresty")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
validator, err := ctx.Request().Validate(map[string]string{
|
||||
"domains": "required|slice",
|
||||
"ports": "required|slice",
|
||||
"hsts": "bool",
|
||||
"ssl": "bool",
|
||||
"http_redirect": "bool",
|
||||
"open_basedir": "bool",
|
||||
"waf": "bool",
|
||||
"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",
|
||||
})
|
||||
|
||||
var saveConfigRequest requests.SaveConfig
|
||||
sanitize := Sanitize(ctx, &saveConfigRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
err := c.website.SaveConfig(saveConfigRequest)
|
||||
if err != nil {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, err.Error())
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "网站管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Info("保存网站配置失败")
|
||||
return Error(ctx, http.StatusInternalServerError, "保存网站配置失败: "+err.Error())
|
||||
}
|
||||
if validator.Fails() {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One())
|
||||
}
|
||||
|
||||
var website models.Website
|
||||
if facades.Orm().Query().Where("id", ctx.Request().Input("id")).FirstOrFail(&website) != nil {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "网站不存在")
|
||||
}
|
||||
|
||||
if !website.Status {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "网站已停用,请先启用")
|
||||
}
|
||||
|
||||
// 原文
|
||||
raw := tools.Read("/www/server/vhost/" + website.Name + ".conf")
|
||||
if strings.TrimSpace(raw) != strings.TrimSpace(ctx.Request().Input("raw")) {
|
||||
tools.Write("/www/server/vhost/"+website.Name+".conf", ctx.Request().Input("raw"), 0644)
|
||||
tools.Exec("systemctl reload openresty")
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// 目录
|
||||
path := ctx.Request().Input("path")
|
||||
if !tools.Exists(path) {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "网站目录不存在")
|
||||
}
|
||||
website.Path = path
|
||||
|
||||
// 域名
|
||||
domain := "server_name"
|
||||
domains := ctx.Request().InputArray("domains")
|
||||
if len(domains) == 0 {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "域名不能为空")
|
||||
}
|
||||
for _, v := range domains {
|
||||
if v == "" {
|
||||
continue
|
||||
}
|
||||
domain += " " + v
|
||||
}
|
||||
domain += ";"
|
||||
domainConfigOld := tools.Cut(raw, "# server_name标记位开始", "# server_name标记位结束")
|
||||
if len(strings.TrimSpace(domainConfigOld)) == 0 {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "配置文件中缺少server_name标记位")
|
||||
}
|
||||
raw = strings.Replace(raw, domainConfigOld, "\n "+domain+"\n ", -1)
|
||||
|
||||
// 端口
|
||||
var port strings.Builder
|
||||
ports := ctx.Request().InputArray("ports")
|
||||
if len(ports) == 0 {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "端口不能为空")
|
||||
}
|
||||
for i, v := range ports {
|
||||
if _, err := strconv.Atoi(v); err != nil && v != "443 ssl http2" {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "端口格式错误")
|
||||
}
|
||||
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 {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "配置文件中缺少port标记位")
|
||||
}
|
||||
raw = strings.Replace(raw, portConfigOld, "\n"+port.String()+"\n ", -1)
|
||||
|
||||
// 运行目录
|
||||
root := tools.Cut(raw, "# root标记位开始", "# root标记位结束")
|
||||
if len(strings.TrimSpace(root)) == 0 {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "配置文件中缺少root标记位")
|
||||
}
|
||||
match := regexp.MustCompile(`root\s+(.+);`).FindStringSubmatch(root)
|
||||
if len(match) != 2 {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "配置文件中root标记位格式错误")
|
||||
}
|
||||
rootNew := strings.Replace(root, match[1], ctx.Request().Input("root"), -1)
|
||||
raw = strings.Replace(raw, root, rootNew, -1)
|
||||
|
||||
// 默认文件
|
||||
index := tools.Cut(raw, "# index标记位开始", "# index标记位结束")
|
||||
if len(strings.TrimSpace(index)) == 0 {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "配置文件中缺少index标记位")
|
||||
}
|
||||
match = regexp.MustCompile(`index\s+(.+);`).FindStringSubmatch(index)
|
||||
if len(match) != 2 {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "配置文件中index标记位格式错误")
|
||||
}
|
||||
indexNew := strings.Replace(index, match[1], ctx.Request().Input("index"), -1)
|
||||
raw = strings.Replace(raw, index, indexNew, -1)
|
||||
|
||||
// 防跨站
|
||||
root = ctx.Request().Input("root")
|
||||
if !strings.HasSuffix(root, "/") {
|
||||
root += "/"
|
||||
}
|
||||
if ctx.Request().InputBool("open_basedir") {
|
||||
tools.Write(root+".user.ini", "open_basedir="+path+":/tmp/", 0644)
|
||||
} else {
|
||||
if tools.Exists(root + ".user.ini") {
|
||||
tools.Remove(root + ".user.ini")
|
||||
}
|
||||
}
|
||||
|
||||
// WAF
|
||||
waf := ctx.Request().InputBool("waf")
|
||||
wafStr := "off"
|
||||
if waf {
|
||||
wafStr = "on"
|
||||
}
|
||||
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 ` + wafStr + `;
|
||||
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
|
||||
tools.Write("/www/server/vhost/ssl/"+website.Name+".pem", ctx.Request().Input("ssl_certificate"), 0644)
|
||||
tools.Write("/www/server/vhost/ssl/"+website.Name+".key", ctx.Request().Input("ssl_certificate_key"), 0644)
|
||||
if ssl {
|
||||
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)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
tools.Write("/www/server/vhost/"+website.Name+".conf", raw, 0644)
|
||||
tools.Write("/www/server/vhost/rewrite/"+website.Name+".conf", ctx.Request().Input("rewrite"), 0644)
|
||||
tools.Exec("systemctl reload openresty")
|
||||
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// ClearLog 清空日志
|
||||
// ClearLog
|
||||
// @Summary 清空日志
|
||||
// @Description 清空网站的日志
|
||||
// @Tags 网站管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param id path int true "网站 ID"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/website/log/{id} [delete]
|
||||
func (c *WebsiteController) ClearLog(ctx http.Context) http.Response {
|
||||
check := Check(ctx, "openresty")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
id := ctx.Request().InputInt("id")
|
||||
if id == 0 {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "参数错误")
|
||||
|
||||
var idRequest requests.ID
|
||||
sanitize := Sanitize(ctx, &idRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
website := models.Website{}
|
||||
err := facades.Orm().Query().Where("id", id).Get(&website)
|
||||
err := facades.Orm().Query().Where("id", idRequest.ID).Get(&website)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 获取网站信息失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
tools.Remove("/www/wwwlogs/" + website.Name + ".log")
|
||||
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// UpdateRemark 更新备注
|
||||
// UpdateRemark
|
||||
// @Summary 更新备注
|
||||
// @Description 更新网站的备注
|
||||
// @Tags 网站管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param id path int true "网站 ID"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/website/updateRemark/{id} [post]
|
||||
func (c *WebsiteController) UpdateRemark(ctx http.Context) http.Response {
|
||||
id := ctx.Request().InputInt("id")
|
||||
if id == 0 {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "参数错误")
|
||||
var idRequest requests.ID
|
||||
sanitize := Sanitize(ctx, &idRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
website := models.Website{}
|
||||
err := facades.Orm().Query().Where("id", id).Get(&website)
|
||||
err := facades.Orm().Query().Where("id", idRequest.ID).Get(&website)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 获取网站信息失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
website.Remark = ctx.Request().Input("remark")
|
||||
err = facades.Orm().Query().Save(&website)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 保存网站备注失败 ", err)
|
||||
if err = facades.Orm().Query().Save(&website); err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "网站管理").With(map[string]any{
|
||||
"id": idRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Info("更新网站备注失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// BackupList 备份列表
|
||||
// BackupList
|
||||
// @Summary 获取备份列表
|
||||
// @Description 获取网站的备份列表
|
||||
// @Tags 网站管理
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Success 200 {object} SuccessResponse{data=[]services.BackupFile}
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/website/backupList [get]
|
||||
func (c *WebsiteController) BackupList(ctx http.Context) http.Response {
|
||||
backupList, err := c.backup.WebsiteList()
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 获取网站备份列表失败 ", err)
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "网站管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Info("获取备份列表失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, backupList)
|
||||
}
|
||||
|
||||
// CreateBackup 创建备份
|
||||
// CreateBackup
|
||||
// @Summary 创建备份
|
||||
// @Description 创建网站的备份
|
||||
// @Tags 网站管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data body requests.ID true "网站 ID"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/website/createBackup [post]
|
||||
func (c *WebsiteController) CreateBackup(ctx http.Context) http.Response {
|
||||
id := ctx.Request().InputInt("id")
|
||||
if id == 0 {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "参数错误")
|
||||
var idRequest requests.ID
|
||||
sanitize := Sanitize(ctx, &idRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
website := models.Website{}
|
||||
err := facades.Orm().Query().Where("id", id).Get(&website)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 获取网站信息失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "获取网站信息失败: "+err.Error())
|
||||
if err := facades.Orm().Query().Where("id", idRequest.ID).Get(&website); err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "网站管理").With(map[string]any{
|
||||
"id": idRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Info("获取网站信息失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
err = c.backup.WebSiteBackup(website)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 备份网站失败 ", err)
|
||||
if err := c.backup.WebSiteBackup(website); err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "网站管理").With(map[string]any{
|
||||
"id": idRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Info("备份网站失败")
|
||||
return Error(ctx, http.StatusInternalServerError, "备份网站失败: "+err.Error())
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// UploadBackup 上传备份
|
||||
// UploadBackup
|
||||
// @Summary 上传备份
|
||||
// @Description 上传网站的备份
|
||||
// @Tags 网站管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param file formData file true "备份文件"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 422 {object} ErrorResponse "上传文件失败"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/website/uploadBackup [post]
|
||||
func (c *WebsiteController) UploadBackup(ctx http.Context) http.Response {
|
||||
file, err := ctx.Request().File("file")
|
||||
if err != nil {
|
||||
@@ -484,44 +440,70 @@ func (c *WebsiteController) UploadBackup(ctx http.Context) http.Response {
|
||||
name := file.GetClientOriginalName()
|
||||
_, err = file.StoreAs(backupPath, name)
|
||||
if err != nil {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "上传文件失败")
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "网站管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Info("上传备份失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, "上传文件成功")
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// RestoreBackup 还原备份
|
||||
// RestoreBackup
|
||||
// @Summary 还原备份
|
||||
// @Description 还原网站的备份
|
||||
// @Tags 网站管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data body requests.RestoreBackup true "备份信息"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 422 {object} ErrorResponse "参数错误"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/website/restoreBackup [post]
|
||||
func (c *WebsiteController) RestoreBackup(ctx http.Context) http.Response {
|
||||
id := ctx.Request().InputInt("id")
|
||||
if id == 0 {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "参数错误")
|
||||
}
|
||||
fileName := ctx.Request().Input("name")
|
||||
if len(fileName) == 0 {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "参数错误")
|
||||
var restoreBackupRequest requests.RestoreBackup
|
||||
sanitize := Sanitize(ctx, &restoreBackupRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
website := models.Website{}
|
||||
err := facades.Orm().Query().Where("id", id).Get(&website)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 获取网站信息失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "获取网站信息失败: "+err.Error())
|
||||
if err := facades.Orm().Query().Where("id", restoreBackupRequest.ID).Get(&website); err != nil {
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
err = c.backup.WebsiteRestore(website, fileName)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 还原网站失败 ", err)
|
||||
if err := c.backup.WebsiteRestore(website, restoreBackupRequest.Name); err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "网站管理").With(map[string]any{
|
||||
"id": restoreBackupRequest.ID,
|
||||
"file": restoreBackupRequest.Name,
|
||||
"error": err.Error(),
|
||||
}).Info("还原网站失败")
|
||||
return Error(ctx, http.StatusInternalServerError, "还原网站失败: "+err.Error())
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// DeleteBackup 删除备份
|
||||
// DeleteBackup
|
||||
// @Summary 删除备份
|
||||
// @Description 删除网站的备份
|
||||
// @Tags 网站管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data body requests.DeleteBackup true "备份信息"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 422 {object} ErrorResponse "参数错误"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/website/deleteBackup [delete]
|
||||
func (c *WebsiteController) DeleteBackup(ctx http.Context) http.Response {
|
||||
fileName := ctx.Request().Input("name")
|
||||
if len(fileName) == 0 {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "参数错误")
|
||||
var deleteBackupRequest requests.DeleteBackup
|
||||
sanitize := Sanitize(ctx, &deleteBackupRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
backupPath := c.setting.Get(models.SettingKeyBackupPath) + "/website"
|
||||
@@ -529,34 +511,50 @@ func (c *WebsiteController) DeleteBackup(ctx http.Context) http.Response {
|
||||
tools.Mkdir(backupPath, 0644)
|
||||
}
|
||||
|
||||
if !tools.Remove(backupPath + "/" + fileName) {
|
||||
if !tools.Remove(backupPath + "/" + deleteBackupRequest.Name) {
|
||||
return Error(ctx, http.StatusInternalServerError, "删除备份失败")
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// ResetConfig 重置配置
|
||||
// ResetConfig
|
||||
// @Summary 重置配置
|
||||
// @Description 重置网站的配置
|
||||
// @Tags 网站管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data body requests.ID true "网站 ID"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 422 {object} ErrorResponse "参数错误"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/website/resetConfig [post]
|
||||
func (c *WebsiteController) ResetConfig(ctx http.Context) http.Response {
|
||||
check := Check(ctx, "openresty")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
id := ctx.Request().InputInt("id")
|
||||
if id == 0 {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "参数错误")
|
||||
|
||||
var idRequest requests.ID
|
||||
sanitize := Sanitize(ctx, &idRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
website := models.Website{}
|
||||
if err := facades.Orm().Query().Where("id", id).Get(&website); err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 获取网站信息失败 ", err)
|
||||
if err := facades.Orm().Query().Where("id", idRequest.ID).Get(&website); err != nil {
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
website.Status = true
|
||||
website.Ssl = false
|
||||
if err := facades.Orm().Query().Save(&website); err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 保存网站配置失败 ", err)
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "网站管理").With(map[string]any{
|
||||
"id": idRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Info("保存网站配置失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -618,34 +616,51 @@ server
|
||||
}
|
||||
|
||||
`, website.Path, website.Php, website.Name, website.Name, website.Name)
|
||||
|
||||
tools.Write("/www/server/vhost/"+website.Name+".conf", raw, 0644)
|
||||
tools.Write("/www/server/vhost/rewrite"+website.Name+".conf", "", 0644)
|
||||
if err := tools.Write("/www/server/vhost/"+website.Name+".conf", raw, 0644); err != nil {
|
||||
return nil
|
||||
}
|
||||
if err := tools.Write("/www/server/vhost/rewrite"+website.Name+".conf", "", 0644); err != nil {
|
||||
return nil
|
||||
}
|
||||
tools.Exec("systemctl reload openresty")
|
||||
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// Status 网站状态
|
||||
// Status
|
||||
// @Summary 状态
|
||||
// @Description 启用或停用网站
|
||||
// @Tags 网站管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param id path int true "网站 ID"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 422 {object} ErrorResponse "参数错误"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/website/status/{id} [post]
|
||||
func (c *WebsiteController) Status(ctx http.Context) http.Response {
|
||||
check := Check(ctx, "openresty")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
id := ctx.Request().InputInt("id")
|
||||
if id == 0 {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "参数错误")
|
||||
|
||||
var idRequest requests.ID
|
||||
sanitize := Sanitize(ctx, &idRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
website := models.Website{}
|
||||
if err := facades.Orm().Query().Where("id", id).Get(&website); err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 获取网站信息失败 ", err)
|
||||
if err := facades.Orm().Query().Where("id", idRequest.ID).Get(&website); err != nil {
|
||||
facades.Log().Info("[面板][WebsiteController] 获取网站信息失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
website.Status = ctx.Request().InputBool("status")
|
||||
if err := facades.Orm().Query().Save(&website); err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 保存网站配置失败 ", err)
|
||||
facades.Log().Info("[面板][WebsiteController] 保存网站配置失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
@@ -675,7 +690,9 @@ func (c *WebsiteController) Status(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
tools.Write("/www/server/vhost/"+website.Name+".conf", raw, 0644)
|
||||
if err := tools.Write("/www/server/vhost/"+website.Name+".conf", raw, 0644); err != nil {
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
tools.Exec("systemctl reload openresty")
|
||||
|
||||
return Success(ctx, nil)
|
||||
|
||||
48
app/http/requests/website/add.go
Normal file
48
app/http/requests/website/add.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
)
|
||||
|
||||
type Add struct {
|
||||
Name string `form:"name" json:"name"`
|
||||
Domains []string `form:"domains" json:"domains"`
|
||||
Ports []string `form:"ports" json:"ports"`
|
||||
Php int `form:"php" json:"php"`
|
||||
Db bool `form:"db" json:"db"`
|
||||
DbType string `form:"db_type" json:"db_type"`
|
||||
DbName string `form:"db_name" json:"db_name"`
|
||||
DbUser string `form:"db_user" json:"db_user"`
|
||||
DbPassword string `form:"db_password" json:"db_password"`
|
||||
}
|
||||
|
||||
func (r *Add) Authorize(ctx http.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Add) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"name": "required|regex:^[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)*$|not_exists:websites,name",
|
||||
"domains": "required|slice",
|
||||
"ports": "required|slice",
|
||||
"php": "required",
|
||||
"db": "bool",
|
||||
"db_type": "required_if:db,true|in:mysql,postgresql",
|
||||
"db_name": "required_if:db,true|regex:^[a-zA-Z0-9_-]+$",
|
||||
"db_user": "required_if:db,true|regex:^[a-zA-Z0-9_-]+$",
|
||||
"db_password": "required_if:db,true|min_len:8",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Add) Messages(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *Add) Attributes(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *Add) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
return nil
|
||||
}
|
||||
32
app/http/requests/website/delete_backup.go
Normal file
32
app/http/requests/website/delete_backup.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
)
|
||||
|
||||
type DeleteBackup struct {
|
||||
Name string `form:"name" json:"name"`
|
||||
}
|
||||
|
||||
func (r *DeleteBackup) Authorize(ctx http.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *DeleteBackup) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"name": "required|string",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *DeleteBackup) Messages(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *DeleteBackup) Attributes(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *DeleteBackup) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
return nil
|
||||
}
|
||||
32
app/http/requests/website/id.go
Normal file
32
app/http/requests/website/id.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
)
|
||||
|
||||
type ID struct {
|
||||
ID uint `form:"id" json:"id" filter:"uint"`
|
||||
}
|
||||
|
||||
func (r *ID) Authorize(ctx http.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ID) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"id": "required|exists:websites,id",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ID) Messages(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *ID) Attributes(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *ID) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
return nil
|
||||
}
|
||||
34
app/http/requests/website/restore_backup.go
Normal file
34
app/http/requests/website/restore_backup.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
)
|
||||
|
||||
type RestoreBackup struct {
|
||||
ID uint `form:"id" json:"id" filter:"uint"`
|
||||
Name string `form:"name" json:"name"`
|
||||
}
|
||||
|
||||
func (r *RestoreBackup) Authorize(ctx http.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *RestoreBackup) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"id": "required|exists:websites,id",
|
||||
"name": "required|string",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RestoreBackup) Messages(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *RestoreBackup) Attributes(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *RestoreBackup) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
return nil
|
||||
}
|
||||
87
app/http/requests/website/save_config.go
Normal file
87
app/http/requests/website/save_config.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
)
|
||||
|
||||
type SaveConfig struct {
|
||||
ID uint `form:"id" json:"id" filter:"uint"`
|
||||
Domains []string `form:"domains" json:"domains"`
|
||||
Ports []string `form:"ports" json:"ports"`
|
||||
Hsts bool `form:"hsts" json:"hsts"`
|
||||
Ssl bool `form:"ssl" json:"ssl"`
|
||||
HttpRedirect bool `form:"http_redirect" json:"http_redirect"`
|
||||
OpenBasedir bool `form:"open_basedir" json:"open_basedir"`
|
||||
Waf bool `form:"waf" json:"waf"`
|
||||
WafCache string `form:"waf_cache" json:"waf_cache"`
|
||||
WafMode string `form:"waf_mode" json:"waf_mode"`
|
||||
WafCcDeny string `form:"waf_cc_deny" json:"waf_cc_deny"`
|
||||
Index string `form:"index" json:"index"`
|
||||
Path string `form:"path" json:"path"`
|
||||
Root string `form:"root" json:"root"`
|
||||
Raw string `form:"raw" json:"raw"`
|
||||
Rewrite string `form:"rewrite" json:"rewrite"`
|
||||
Php int `form:"php" json:"php" filter:"uint"`
|
||||
SslCertificate string `form:"ssl_certificate" json:"ssl_certificate"`
|
||||
SslCertificateKey string `form:"ssl_certificate_key" json:"ssl_certificate_key"`
|
||||
}
|
||||
|
||||
func (r *SaveConfig) Authorize(ctx http.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *SaveConfig) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"id": "required|exists:websites,id",
|
||||
"domains": "required|slice",
|
||||
"ports": "required|slice",
|
||||
"hsts": "required|bool",
|
||||
"ssl": "required|bool",
|
||||
"http_redirect": "required|bool",
|
||||
"open_basedir": "required|bool",
|
||||
"waf": "required|bool",
|
||||
"waf_cache": "required|string",
|
||||
"waf_mode": "required|string",
|
||||
"waf_cc_deny": "required|string",
|
||||
"index": "required|string",
|
||||
"path": "required|string",
|
||||
"root": "required|string",
|
||||
"raw": "required|string",
|
||||
"rewrite": "string",
|
||||
"php": "required|uint",
|
||||
"ssl_certificate": "required_if:ssl,true",
|
||||
"ssl_certificate_key": "required_if:ssl,true",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *SaveConfig) Messages(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *SaveConfig) Attributes(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *SaveConfig) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
_, exist := data.Get("waf_mode")
|
||||
if !exist {
|
||||
if err := data.Set("waf_mode", "DYNAMIC"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, exist = data.Get("waf_cc_deny")
|
||||
if !exist {
|
||||
if err := data.Set("waf_cc_deny", "rate=1000r/m duration=60m"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, exist = data.Get("waf_cache")
|
||||
if !exist {
|
||||
if err := data.Set("waf_cache", "capacity=50"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
8
app/http/responses/website/list.go
Normal file
8
app/http/responses/website/list.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package responses
|
||||
|
||||
import "panel/app/models"
|
||||
|
||||
type List struct {
|
||||
Total int64 `json:"total"`
|
||||
Items []models.Website `json:"items"`
|
||||
}
|
||||
@@ -22,7 +22,7 @@ func (receiver *ProcessTask) Signature() string {
|
||||
func (receiver *ProcessTask) Handle(args ...any) error {
|
||||
taskID, ok := args[0].(uint)
|
||||
if !ok {
|
||||
facades.Log().Error("[面板][ProcessTask] 任务ID参数错误")
|
||||
facades.Log().Info("[面板][ProcessTask] 任务ID参数错误")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -35,13 +35,13 @@ func (receiver *ProcessTask) Handle(args ...any) error {
|
||||
|
||||
var task models.Task
|
||||
if err := facades.Orm().Query().Where("id = ?", taskID).Get(&task); err != nil {
|
||||
facades.Log().Errorf("[面板][ProcessTask] 获取任务%d失败: %s", taskID, err.Error())
|
||||
facades.Log().Infof("[面板][ProcessTask] 获取任务%d失败: %s", taskID, err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
task.Status = models.TaskStatusRunning
|
||||
if err := facades.Orm().Query().Save(&task); err != nil {
|
||||
facades.Log().Errorf("[面板][ProcessTask] 更新任务%d失败: %s", taskID, err.Error())
|
||||
facades.Log().Infof("[面板][ProcessTask] 更新任务%d失败: %s", taskID, err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -51,16 +51,16 @@ func (receiver *ProcessTask) Handle(args ...any) error {
|
||||
if err != nil {
|
||||
task.Status = models.TaskStatusFailed
|
||||
if err := facades.Orm().Query().Save(&task); err != nil {
|
||||
facades.Log().Errorf("[面板][ProcessTask] 更新任务%d失败: %s", taskID, err.Error())
|
||||
facades.Log().Infof("[面板][ProcessTask] 更新任务%d失败: %s", taskID, err.Error())
|
||||
return nil
|
||||
}
|
||||
facades.Log().Errorf("[面板][ProcessTask] 任务%d执行失败: %s", taskID, err.Error())
|
||||
facades.Log().Infof("[面板][ProcessTask] 任务%d执行失败: %s", taskID, err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
task.Status = models.TaskStatusSuccess
|
||||
if err := facades.Orm().Query().Save(&task); err != nil {
|
||||
facades.Log().Errorf("[面板][ProcessTask] 更新任务%d失败: %s", taskID, err.Error())
|
||||
facades.Log().Infof("[面板][ProcessTask] 更新任务%d失败: %s", taskID, err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ func (receiver *ProcessTask) Handle(args ...any) error {
|
||||
func haveRunningTask() bool {
|
||||
var task models.Task
|
||||
if err := facades.Orm().Query().Where("status = ?", models.TaskStatusRunning).Get(&task); err != nil {
|
||||
facades.Log().Error("[面板][ProcessTask] 获取任务失败: " + err.Error())
|
||||
facades.Log().Info("[面板][ProcessTask] 获取任务失败: " + err.Error())
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ func (receiver *ValidationServiceProvider) Register(app foundation.Application)
|
||||
|
||||
func (receiver *ValidationServiceProvider) Boot(app foundation.Application) {
|
||||
if err := facades.Validation().AddRules(receiver.rules()); err != nil {
|
||||
facades.Log().Errorf("add rules error: %+v", err)
|
||||
facades.Log().Infof("add rules error: %+v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ func (r *TaskImpl) Process(taskID uint) {
|
||||
{Type: "uint", Value: taskID},
|
||||
}).Dispatch()
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][TaskService] 运行任务失败: " + err.Error())
|
||||
facades.Log().Info("[面板][TaskService] 运行任务失败: " + err.Error())
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
"github.com/goravel/framework/facades"
|
||||
"golang.org/x/exp/slices"
|
||||
requests "panel/app/http/requests/website"
|
||||
|
||||
"panel/app/models"
|
||||
"panel/pkg/tools"
|
||||
@@ -20,8 +21,9 @@ import (
|
||||
type Website interface {
|
||||
List(page int, limit int) (int64, []models.Website, error)
|
||||
Add(website PanelWebsite) (models.Website, error)
|
||||
Delete(id int) error
|
||||
GetConfig(id int) (WebsiteSetting, error)
|
||||
SaveConfig(config requests.SaveConfig) error
|
||||
Delete(id uint) error
|
||||
GetConfig(id uint) (WebsiteSetting, error)
|
||||
GetConfigByName(name string) (WebsiteSetting, error)
|
||||
}
|
||||
|
||||
@@ -292,8 +294,208 @@ server
|
||||
return w, nil
|
||||
}
|
||||
|
||||
// SaveConfig 保存网站配置
|
||||
func (r *WebsiteImpl) SaveConfig(config requests.SaveConfig) error {
|
||||
var website models.Website
|
||||
if err := facades.Orm().Query().Where("id", config.ID).First(&website); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !website.Status {
|
||||
return errors.New("网站已停用,请先启用")
|
||||
}
|
||||
|
||||
// 原文
|
||||
raw := tools.Read("/www/server/vhost/" + website.Name + ".conf")
|
||||
if strings.TrimSpace(raw) != strings.TrimSpace(config.Raw) {
|
||||
err := tools.Write("/www/server/vhost/"+website.Name+".conf", config.Raw, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tools.Exec("systemctl reload openresty")
|
||||
return nil
|
||||
}
|
||||
|
||||
// 目录
|
||||
path := config.Path
|
||||
if !tools.Exists(path) {
|
||||
return errors.New("网站目录不存在")
|
||||
}
|
||||
website.Path = path
|
||||
|
||||
// 域名
|
||||
domain := "server_name"
|
||||
domains := config.Domains
|
||||
for _, v := range domains {
|
||||
if v == "" {
|
||||
continue
|
||||
}
|
||||
domain += " " + v
|
||||
}
|
||||
domain += ";"
|
||||
domainConfigOld := tools.Cut(raw, "# server_name标记位开始", "# server_name标记位结束")
|
||||
if len(strings.TrimSpace(domainConfigOld)) == 0 {
|
||||
return errors.New("配置文件中缺少server_name标记位")
|
||||
}
|
||||
raw = strings.Replace(raw, domainConfigOld, "\n "+domain+"\n ", -1)
|
||||
|
||||
// 端口
|
||||
var port strings.Builder
|
||||
ports := config.Ports
|
||||
for i, v := range ports {
|
||||
if _, err := strconv.Atoi(v); err != nil && v != "443 ssl http2" {
|
||||
return errors.New("端口格式错误")
|
||||
}
|
||||
if v == "443" && config.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 {
|
||||
return errors.New("配置文件中缺少port标记位")
|
||||
}
|
||||
raw = strings.Replace(raw, portConfigOld, "\n"+port.String()+"\n ", -1)
|
||||
|
||||
// 运行目录
|
||||
root := tools.Cut(raw, "# root标记位开始", "# root标记位结束")
|
||||
if len(strings.TrimSpace(root)) == 0 {
|
||||
return errors.New("配置文件中缺少root标记位")
|
||||
}
|
||||
match := regexp.MustCompile(`root\s+(.+);`).FindStringSubmatch(root)
|
||||
if len(match) != 2 {
|
||||
return errors.New("配置文件中root标记位格式错误")
|
||||
}
|
||||
rootNew := strings.Replace(root, match[1], config.Root, -1)
|
||||
raw = strings.Replace(raw, root, rootNew, -1)
|
||||
|
||||
// 默认文件
|
||||
index := tools.Cut(raw, "# index标记位开始", "# index标记位结束")
|
||||
if len(strings.TrimSpace(index)) == 0 {
|
||||
return errors.New("配置文件中缺少index标记位")
|
||||
}
|
||||
match = regexp.MustCompile(`index\s+(.+);`).FindStringSubmatch(index)
|
||||
if len(match) != 2 {
|
||||
return errors.New("配置文件中index标记位格式错误")
|
||||
}
|
||||
indexNew := strings.Replace(index, match[1], config.Index, -1)
|
||||
raw = strings.Replace(raw, index, indexNew, -1)
|
||||
|
||||
// 防跨站
|
||||
root = config.Root
|
||||
if !strings.HasSuffix(root, "/") {
|
||||
root += "/"
|
||||
}
|
||||
if config.OpenBasedir {
|
||||
if err := tools.Write(root+".user.ini", "open_basedir="+path+":/tmp/", 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if tools.Exists(root + ".user.ini") {
|
||||
tools.Remove(root + ".user.ini")
|
||||
}
|
||||
}
|
||||
|
||||
// WAF
|
||||
waf := config.Waf
|
||||
wafStr := "off"
|
||||
if waf {
|
||||
wafStr = "on"
|
||||
}
|
||||
wafMode := config.WafMode
|
||||
wafCcDeny := config.WafCcDeny
|
||||
wafCache := config.WafCache
|
||||
wafConfig := `# waf标记位开始
|
||||
waf ` + wafStr + `;
|
||||
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 := config.Ssl
|
||||
website.Ssl = ssl
|
||||
if err := tools.Write("/www/server/vhost/ssl/"+website.Name+".pem", config.SslCertificate, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tools.Write("/www/server/vhost/ssl/"+website.Name+".key", config.SslCertificateKey, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
if ssl {
|
||||
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 config.HttpRedirect {
|
||||
sslConfig += `# http重定向标记位开始
|
||||
if ($server_port !~ 443){
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
error_page 497 https://$host$request_uri;
|
||||
# http重定向标记位结束
|
||||
`
|
||||
}
|
||||
if config.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 != config.Php {
|
||||
website.Php = config.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)
|
||||
}
|
||||
}
|
||||
|
||||
if err := facades.Orm().Query().Save(&website); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tools.Write("/www/server/vhost/"+website.Name+".conf", raw, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tools.Write("/www/server/vhost/rewrite/"+website.Name+".conf", config.Rewrite, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
tools.Exec("systemctl reload openresty")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete 删除网站
|
||||
func (r *WebsiteImpl) Delete(id int) error {
|
||||
func (r *WebsiteImpl) Delete(id uint) error {
|
||||
var website models.Website
|
||||
if err := facades.Orm().Query().With("Cert").Where("id", id).FirstOrFail(&website); err != nil {
|
||||
return err
|
||||
@@ -319,7 +521,7 @@ func (r *WebsiteImpl) Delete(id int) error {
|
||||
}
|
||||
|
||||
// GetConfig 获取网站配置
|
||||
func (r *WebsiteImpl) GetConfig(id int) (WebsiteSetting, error) {
|
||||
func (r *WebsiteImpl) GetConfig(id uint) (WebsiteSetting, error) {
|
||||
var website models.Website
|
||||
if err := facades.Orm().Query().Where("id", id).First(&website); err != nil {
|
||||
return WebsiteSetting{}, err
|
||||
@@ -421,5 +623,5 @@ func (r *WebsiteImpl) GetConfigByName(name string) (WebsiteSetting, error) {
|
||||
return WebsiteSetting{}, err
|
||||
}
|
||||
|
||||
return r.GetConfig(int(website.ID))
|
||||
return r.GetConfig(website.ID)
|
||||
}
|
||||
|
||||
1137
docs/docs.go
1137
docs/docs.go
File diff suppressed because it is too large
Load Diff
1137
docs/swagger.json
1137
docs/swagger.json
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,13 @@ definitions:
|
||||
value:
|
||||
type: string
|
||||
type: object
|
||||
commonrequests.Paginate:
|
||||
properties:
|
||||
limit:
|
||||
type: integer
|
||||
page:
|
||||
type: integer
|
||||
type: object
|
||||
controllers.ErrorResponse:
|
||||
properties:
|
||||
code:
|
||||
@@ -144,6 +151,31 @@ definitions:
|
||||
updated_at:
|
||||
type: string
|
||||
type: object
|
||||
requests.Add:
|
||||
properties:
|
||||
db:
|
||||
type: boolean
|
||||
db_name:
|
||||
type: string
|
||||
db_password:
|
||||
type: string
|
||||
db_type:
|
||||
type: string
|
||||
db_user:
|
||||
type: string
|
||||
domains:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
type: string
|
||||
php:
|
||||
type: integer
|
||||
ports:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type: object
|
||||
requests.CertStore:
|
||||
properties:
|
||||
auto_renew:
|
||||
@@ -200,6 +232,16 @@ definitions:
|
||||
type:
|
||||
type: string
|
||||
type: object
|
||||
requests.DeleteBackup:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
type: object
|
||||
requests.ID:
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
type: object
|
||||
requests.Login:
|
||||
properties:
|
||||
password:
|
||||
@@ -217,6 +259,58 @@ definitions:
|
||||
id:
|
||||
type: integer
|
||||
type: object
|
||||
requests.RestoreBackup:
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
name:
|
||||
type: string
|
||||
type: object
|
||||
requests.SaveConfig:
|
||||
properties:
|
||||
domains:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
hsts:
|
||||
type: boolean
|
||||
http_redirect:
|
||||
type: boolean
|
||||
id:
|
||||
type: integer
|
||||
index:
|
||||
type: string
|
||||
open_basedir:
|
||||
type: boolean
|
||||
path:
|
||||
type: string
|
||||
php:
|
||||
type: integer
|
||||
ports:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
raw:
|
||||
type: string
|
||||
rewrite:
|
||||
type: string
|
||||
root:
|
||||
type: string
|
||||
ssl:
|
||||
type: boolean
|
||||
ssl_certificate:
|
||||
type: string
|
||||
ssl_certificate_key:
|
||||
type: string
|
||||
waf:
|
||||
type: boolean
|
||||
waf_cache:
|
||||
type: string
|
||||
waf_cc_deny:
|
||||
type: string
|
||||
waf_mode:
|
||||
type: string
|
||||
type: object
|
||||
requests.Update:
|
||||
properties:
|
||||
backup_path:
|
||||
@@ -295,6 +389,15 @@ definitions:
|
||||
username:
|
||||
type: string
|
||||
type: object
|
||||
responses.List:
|
||||
properties:
|
||||
items:
|
||||
items:
|
||||
$ref: '#/definitions/models.Website'
|
||||
type: array
|
||||
total:
|
||||
type: integer
|
||||
type: object
|
||||
responses.Settings:
|
||||
properties:
|
||||
backup_path:
|
||||
@@ -314,6 +417,46 @@ definitions:
|
||||
website_path:
|
||||
type: string
|
||||
type: object
|
||||
services.BackupFile:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
size:
|
||||
type: string
|
||||
type: object
|
||||
services.PanelWebsite:
|
||||
properties:
|
||||
db:
|
||||
type: boolean
|
||||
db_name:
|
||||
type: string
|
||||
db_password:
|
||||
type: string
|
||||
db_type:
|
||||
type: string
|
||||
db_user:
|
||||
type: string
|
||||
domains:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
type: string
|
||||
path:
|
||||
type: string
|
||||
php:
|
||||
type: integer
|
||||
ports:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
remark:
|
||||
type: string
|
||||
ssl:
|
||||
type: boolean
|
||||
status:
|
||||
type: boolean
|
||||
type: object
|
||||
info:
|
||||
contact:
|
||||
email: i@haozi.net
|
||||
@@ -363,6 +506,13 @@ paths:
|
||||
/panel/cert/certs:
|
||||
get:
|
||||
description: 获取面板证书管理的证书列表
|
||||
parameters:
|
||||
- description: 分页信息
|
||||
in: body
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/commonrequests.Paginate'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
@@ -522,6 +672,13 @@ paths:
|
||||
/panel/cert/dns:
|
||||
get:
|
||||
description: 获取面板证书管理的 DNS 接口列表
|
||||
parameters:
|
||||
- description: 分页信息
|
||||
in: body
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/commonrequests.Paginate'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
@@ -803,6 +960,13 @@ paths:
|
||||
/panel/cert/users:
|
||||
get:
|
||||
description: 获取面板证书管理的 ACME 用户列表
|
||||
parameters:
|
||||
- description: 分页信息
|
||||
in: body
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/commonrequests.Paginate'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
@@ -1077,6 +1241,556 @@ paths:
|
||||
summary: 登录
|
||||
tags:
|
||||
- 用户鉴权
|
||||
/panel/website:
|
||||
get:
|
||||
description: 获取网站管理的网站列表
|
||||
parameters:
|
||||
- description: 分页信息
|
||||
in: body
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/commonrequests.Paginate'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/controllers.SuccessResponse'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/responses.List'
|
||||
type: object
|
||||
"401":
|
||||
description: 登录已过期
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"403":
|
||||
description: 插件需更新
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"500":
|
||||
description: 系统内部错误
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 获取网站列表
|
||||
tags:
|
||||
- 网站管理
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 添加网站到网站管理
|
||||
parameters:
|
||||
- description: 网站信息
|
||||
in: body
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/requests.Add'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.SuccessResponse'
|
||||
"401":
|
||||
description: 登录已过期
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"403":
|
||||
description: 插件需更新
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"500":
|
||||
description: 系统内部错误
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 添加网站
|
||||
tags:
|
||||
- 网站管理
|
||||
/panel/website/{id}:
|
||||
delete:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 删除网站管理的网站
|
||||
parameters:
|
||||
- description: 网站 ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.SuccessResponse'
|
||||
"401":
|
||||
description: 登录已过期
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"403":
|
||||
description: 插件需更新
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"500":
|
||||
description: 系统内部错误
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 删除网站
|
||||
tags:
|
||||
- 网站管理
|
||||
/panel/website/backupList:
|
||||
get:
|
||||
description: 获取网站的备份列表
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/controllers.SuccessResponse'
|
||||
- properties:
|
||||
data:
|
||||
items:
|
||||
$ref: '#/definitions/services.BackupFile'
|
||||
type: array
|
||||
type: object
|
||||
"401":
|
||||
description: 登录已过期
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"500":
|
||||
description: 系统内部错误
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 获取备份列表
|
||||
tags:
|
||||
- 网站管理
|
||||
/panel/website/config/{id}:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 获取网站的配置
|
||||
parameters:
|
||||
- description: 网站 ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/controllers.SuccessResponse'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/services.PanelWebsite'
|
||||
type: object
|
||||
"401":
|
||||
description: 登录已过期
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"500":
|
||||
description: 系统内部错误
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 获取配置
|
||||
tags:
|
||||
- 网站管理
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 保存网站的配置
|
||||
parameters:
|
||||
- description: 网站 ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: integer
|
||||
- description: 网站配置
|
||||
in: body
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/requests.SaveConfig'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.SuccessResponse'
|
||||
"401":
|
||||
description: 登录已过期
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"500":
|
||||
description: 系统内部错误
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 保存配置
|
||||
tags:
|
||||
- 网站管理
|
||||
/panel/website/createBackup:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 创建网站的备份
|
||||
parameters:
|
||||
- description: 网站 ID
|
||||
in: body
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/requests.ID'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.SuccessResponse'
|
||||
"401":
|
||||
description: 登录已过期
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"500":
|
||||
description: 系统内部错误
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 创建备份
|
||||
tags:
|
||||
- 网站管理
|
||||
/panel/website/defaultConfig:
|
||||
get:
|
||||
description: 获取默认首页和停止页配置
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/controllers.SuccessResponse'
|
||||
- properties:
|
||||
data:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
"401":
|
||||
description: 登录已过期
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"403":
|
||||
description: 插件需更新
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 获取默认配置
|
||||
tags:
|
||||
- 网站管理
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 保存默认首页和停止页配置
|
||||
parameters:
|
||||
- description: 页面信息
|
||||
in: body
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.SuccessResponse'
|
||||
"401":
|
||||
description: 登录已过期
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"403":
|
||||
description: 插件需更新
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"500":
|
||||
description: 系统内部错误
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 保存默认配置
|
||||
tags:
|
||||
- 网站管理
|
||||
/panel/website/deleteBackup:
|
||||
delete:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 删除网站的备份
|
||||
parameters:
|
||||
- description: 备份信息
|
||||
in: body
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/requests.DeleteBackup'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.SuccessResponse'
|
||||
"401":
|
||||
description: 登录已过期
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"422":
|
||||
description: 参数错误
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"500":
|
||||
description: 系统内部错误
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 删除备份
|
||||
tags:
|
||||
- 网站管理
|
||||
/panel/website/log/{id}:
|
||||
delete:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 清空网站的日志
|
||||
parameters:
|
||||
- description: 网站 ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.SuccessResponse'
|
||||
"401":
|
||||
description: 登录已过期
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"500":
|
||||
description: 系统内部错误
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 清空日志
|
||||
tags:
|
||||
- 网站管理
|
||||
/panel/website/resetConfig:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 重置网站的配置
|
||||
parameters:
|
||||
- description: 网站 ID
|
||||
in: body
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/requests.ID'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.SuccessResponse'
|
||||
"401":
|
||||
description: 登录已过期
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"422":
|
||||
description: 参数错误
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"500":
|
||||
description: 系统内部错误
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 重置配置
|
||||
tags:
|
||||
- 网站管理
|
||||
/panel/website/restoreBackup:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 还原网站的备份
|
||||
parameters:
|
||||
- description: 备份信息
|
||||
in: body
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/requests.RestoreBackup'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.SuccessResponse'
|
||||
"401":
|
||||
description: 登录已过期
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"422":
|
||||
description: 参数错误
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"500":
|
||||
description: 系统内部错误
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 还原备份
|
||||
tags:
|
||||
- 网站管理
|
||||
/panel/website/status/{id}:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 启用或停用网站
|
||||
parameters:
|
||||
- description: 网站 ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.SuccessResponse'
|
||||
"401":
|
||||
description: 登录已过期
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"422":
|
||||
description: 参数错误
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"500":
|
||||
description: 系统内部错误
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 状态
|
||||
tags:
|
||||
- 网站管理
|
||||
/panel/website/updateRemark/{id}:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 更新网站的备注
|
||||
parameters:
|
||||
- description: 网站 ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.SuccessResponse'
|
||||
"401":
|
||||
description: 登录已过期
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"500":
|
||||
description: 系统内部错误
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 更新备注
|
||||
tags:
|
||||
- 网站管理
|
||||
/panel/website/uploadBackup:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 上传网站的备份
|
||||
parameters:
|
||||
- description: 备份文件
|
||||
in: formData
|
||||
name: file
|
||||
required: true
|
||||
type: file
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.SuccessResponse'
|
||||
"401":
|
||||
description: 登录已过期
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"422":
|
||||
description: 上传文件失败
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
"500":
|
||||
description: 系统内部错误
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.ErrorResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 上传备份
|
||||
tags:
|
||||
- 网站管理
|
||||
/swagger:
|
||||
get:
|
||||
description: Swagger UI
|
||||
|
||||
2
go.mod
2
go.mod
@@ -9,7 +9,7 @@ require (
|
||||
github.com/gookit/color v1.5.4
|
||||
github.com/gookit/validate v1.5.1
|
||||
github.com/goravel/fiber v1.1.11-0.20231108081345-36e967f101d0
|
||||
github.com/goravel/framework v1.13.1-0.20231109083801-f2c86a7c0796
|
||||
github.com/goravel/framework v1.13.1-0.20231110075143-376f1d9f92e1
|
||||
github.com/iancoleman/strcase v0.3.0
|
||||
github.com/imroc/req/v3 v3.42.1
|
||||
github.com/mojocn/base64Captcha v1.3.5
|
||||
|
||||
4
go.sum
4
go.sum
@@ -385,8 +385,8 @@ github.com/goravel/file-rotatelogs v0.0.0-20211215053220-2ab31dd9575c h1:obhFK91
|
||||
github.com/goravel/file-rotatelogs v0.0.0-20211215053220-2ab31dd9575c/go.mod h1:YSWsLXlG16u5CWFaXNZHhEQD10+NwF3xfgDV816OwLE=
|
||||
github.com/goravel/file-rotatelogs/v2 v2.4.1 h1:ogkeIFcTHSBRUBpZYiyJbpul8hkVXxHPuDbOaP78O1M=
|
||||
github.com/goravel/file-rotatelogs/v2 v2.4.1/go.mod h1:euk9qr52WrzM8ICs1hecFcR4CZ/ZZOPdacHfvHgbOf0=
|
||||
github.com/goravel/framework v1.13.1-0.20231109083801-f2c86a7c0796 h1:4ZqUXMfPP8M10joipSdP9PGgDoVD51vZIcCPds/EyGk=
|
||||
github.com/goravel/framework v1.13.1-0.20231109083801-f2c86a7c0796/go.mod h1:5jKFbJzfqhaQTP3HCgbyrpnrCyoJjxN5JWSXO96H0iQ=
|
||||
github.com/goravel/framework v1.13.1-0.20231110075143-376f1d9f92e1 h1:J0FjRp0EGsyno2XNfUHIz2ghuE0dyg2/VUlR10/KRZA=
|
||||
github.com/goravel/framework v1.13.1-0.20231110075143-376f1d9f92e1/go.mod h1:9vNb8pNm1HBF/1I4SOD88F5rP+/SvzrniJDx9t15OzU=
|
||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
|
||||
|
||||
2
main.go
2
main.go
@@ -41,7 +41,7 @@ func main() {
|
||||
// 启动 HTTP 服务
|
||||
go func() {
|
||||
if err := facades.Route().Run(); err != nil {
|
||||
facades.Log().Errorf("Route run error: %v", err)
|
||||
facades.Log().Infof("Route run error: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
@@ -12,27 +12,17 @@ import (
|
||||
)
|
||||
|
||||
// Write 写入文件
|
||||
func Write(path string, data string, permission os.FileMode) bool {
|
||||
func Write(path string, data string, permission os.FileMode) error {
|
||||
if err := os.MkdirAll(filepath.Dir(path), permission); err != nil {
|
||||
facades.Log().With(map[string]any{
|
||||
"path": filepath.Dir(path),
|
||||
"permission": permission,
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "工具函数").Error("创建目录失败")
|
||||
return false
|
||||
return err
|
||||
}
|
||||
|
||||
err := os.WriteFile(path, []byte(data), permission)
|
||||
if err != nil {
|
||||
facades.Log().With(map[string]any{
|
||||
"path": path,
|
||||
"permission": permission,
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "工具函数").Error("写入文件失败")
|
||||
return false
|
||||
return err
|
||||
}
|
||||
|
||||
return true
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read 读取文件
|
||||
@@ -42,7 +32,7 @@ func Read(path string) string {
|
||||
facades.Log().With(map[string]any{
|
||||
"path": path,
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "工具函数").Error("读取文件失败")
|
||||
}).Tags("面板", "工具函数").Info("读取文件失败")
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -55,7 +45,7 @@ func Remove(path string) bool {
|
||||
facades.Log().With(map[string]any{
|
||||
"path": path,
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "工具函数").Error("删除文件/目录失败")
|
||||
}).Tags("面板", "工具函数").Info("删除文件/目录失败")
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -76,7 +66,7 @@ func Exec(shell string) string {
|
||||
facades.Log().With(map[string]any{
|
||||
"shell": shell,
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "工具函数").Error("执行命令失败")
|
||||
}).Tags("面板", "工具函数").Info("执行命令失败")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -102,7 +92,7 @@ func ExecAsync(shell string) error {
|
||||
facades.Log().With(map[string]any{
|
||||
"shell": shell,
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "工具函数").Error("异步执行命令失败")
|
||||
}).Tags("面板", "工具函数").Info("异步执行命令失败")
|
||||
}
|
||||
}
|
||||
}()
|
||||
@@ -117,7 +107,7 @@ func Mkdir(path string, permission os.FileMode) bool {
|
||||
"path": path,
|
||||
"permission": permission,
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "工具函数").Error("创建目录失败")
|
||||
}).Tags("面板", "工具函数").Info("创建目录失败")
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -130,7 +120,7 @@ func Chmod(path string, permission os.FileMode) bool {
|
||||
facades.Log().With(map[string]any{
|
||||
"path": path,
|
||||
"permission": permission,
|
||||
}).Tags("面板", "工具函数").Error("修改文件/目录权限失败")
|
||||
}).Tags("面板", "工具函数").Info("修改文件/目录权限失败")
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -148,7 +138,7 @@ func Chown(path, user, group string) bool {
|
||||
"user": user,
|
||||
"group": group,
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "工具函数").Error("修改文件/目录所有者失败")
|
||||
}).Tags("面板", "工具函数").Info("修改文件/目录所有者失败")
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ func (s *SystemHelperTestSuite) TestWrite() {
|
||||
filePath := "/tmp/testfile"
|
||||
defer os.Remove(filePath)
|
||||
|
||||
s.True(Write(filePath, "test data", 0644))
|
||||
s.Nil(Write(filePath, "test data", 0644))
|
||||
s.FileExists(filePath)
|
||||
|
||||
content, _ := os.ReadFile(filePath)
|
||||
|
||||
@@ -37,9 +37,9 @@ func Api() {
|
||||
})
|
||||
r.Prefix("website").Middleware(middleware.Jwt()).Group(func(r route.Router) {
|
||||
websiteController := controllers.NewWebsiteController()
|
||||
r.Get("list", websiteController.List)
|
||||
r.Post("add", websiteController.Add)
|
||||
r.Delete("delete/{id}", websiteController.Delete)
|
||||
r.Get("/", websiteController.List)
|
||||
r.Post("/", websiteController.Add)
|
||||
r.Delete("{id}", websiteController.Delete)
|
||||
r.Get("defaultConfig", websiteController.GetDefaultConfig)
|
||||
r.Post("defaultConfig", websiteController.SaveDefaultConfig)
|
||||
r.Get("config/{id}", websiteController.GetConfig)
|
||||
@@ -49,9 +49,9 @@ func Api() {
|
||||
r.Get("backupList", websiteController.BackupList)
|
||||
r.Post("createBackup", websiteController.CreateBackup)
|
||||
r.Post("uploadBackup", websiteController.UploadBackup)
|
||||
r.Post("restoreBackup/{id}", websiteController.RestoreBackup)
|
||||
r.Post("deleteBackup/{id}", websiteController.DeleteBackup)
|
||||
r.Post("resetConfig/{id}", websiteController.ResetConfig)
|
||||
r.Post("restoreBackup", websiteController.RestoreBackup)
|
||||
r.Post("deleteBackup", websiteController.DeleteBackup)
|
||||
r.Post("resetConfig", websiteController.ResetConfig)
|
||||
r.Post("status/{id}", websiteController.Status)
|
||||
})
|
||||
r.Prefix("cert").Middleware(middleware.Jwt()).Group(func(r route.Router) {
|
||||
|
||||
Reference in New Issue
Block a user