mirror of
https://github.com/nezhahq/nezha.git
synced 2025-01-22 12:48:14 -05:00
remove old sources
This commit is contained in:
parent
d7012e36bf
commit
40c811c143
@ -1,257 +0,0 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/hashicorp/go-uuid"
|
||||
|
||||
"github.com/naiba/nezha/model"
|
||||
"github.com/naiba/nezha/pkg/utils"
|
||||
"github.com/naiba/nezha/pkg/websocketx"
|
||||
"github.com/naiba/nezha/proto"
|
||||
"github.com/naiba/nezha/service/rpc"
|
||||
"github.com/naiba/nezha/service/singleton"
|
||||
)
|
||||
|
||||
type commonPage struct {
|
||||
r *gin.Engine
|
||||
}
|
||||
|
||||
func (cp *commonPage) serve() {
|
||||
cr := cp.r.Group("")
|
||||
// TODO: 界面直接跳转使用该接口
|
||||
cr.GET("/network/:id", cp.network)
|
||||
cr.GET("/network", cp.network)
|
||||
cr.GET("/file", cp.createFM)
|
||||
cr.GET("/file/:id", cp.fm)
|
||||
}
|
||||
|
||||
func (cp *commonPage) network(c *gin.Context) {
|
||||
var (
|
||||
monitorHistory *model.ServiceHistory
|
||||
servers []model.Server
|
||||
serverIdsWithMonitor []uint64
|
||||
monitorInfos = []byte("{}")
|
||||
id uint64
|
||||
)
|
||||
if len(singleton.SortedServerList) > 0 {
|
||||
id = singleton.SortedServerList[0].ID
|
||||
}
|
||||
if err := singleton.DB.Model(&model.ServiceHistory{}).Select("monitor_id, server_id").
|
||||
Where("monitor_id != 0 and server_id != 0").Limit(1).First(&monitorHistory).Error; err != nil {
|
||||
// mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||
// Code: http.StatusForbidden,
|
||||
// Title: "请求失败",
|
||||
// Msg: "请求参数有误:" + "server monitor history not found",
|
||||
// Link: "/",
|
||||
// Btn: "返回重试",
|
||||
// }, true)
|
||||
return
|
||||
} else {
|
||||
if monitorHistory == nil || monitorHistory.ServerID == 0 {
|
||||
if len(singleton.SortedServerList) > 0 {
|
||||
id = singleton.SortedServerList[0].ID
|
||||
}
|
||||
} else {
|
||||
id = monitorHistory.ServerID
|
||||
}
|
||||
}
|
||||
|
||||
idStr := c.Param("id")
|
||||
if idStr != "" {
|
||||
var err error
|
||||
id, err = strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
// mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||
// Code: http.StatusForbidden,
|
||||
// Title: "请求失败",
|
||||
// Msg: "请求参数有误:" + err.Error(),
|
||||
// Link: "/",
|
||||
// Btn: "返回重试",
|
||||
// }, true)
|
||||
return
|
||||
}
|
||||
_, ok := singleton.ServerList[id]
|
||||
if !ok {
|
||||
// mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||
// Code: http.StatusForbidden,
|
||||
// Title: "请求失败",
|
||||
// Msg: "请求参数有误:" + "server id not found",
|
||||
// Link: "/",
|
||||
// Btn: "返回重试",
|
||||
// }, true)
|
||||
return
|
||||
}
|
||||
}
|
||||
_, isMember := c.Get(model.CtxKeyAuthorizedUser)
|
||||
var isViewPasswordVerfied bool
|
||||
|
||||
if err := singleton.DB.Model(&model.ServiceHistory{}).
|
||||
Select("distinct(server_id)").
|
||||
Where("server_id != 0").
|
||||
Find(&serverIdsWithMonitor).
|
||||
Error; err != nil {
|
||||
// mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||
// Code: http.StatusForbidden,
|
||||
// Title: "请求失败",
|
||||
// Msg: "请求参数有误:" + "no server with monitor histories",
|
||||
// Link: "/",
|
||||
// Btn: "返回重试",
|
||||
// }, true)
|
||||
return
|
||||
}
|
||||
if isMember || isViewPasswordVerfied {
|
||||
for _, server := range singleton.SortedServerList {
|
||||
for _, id := range serverIdsWithMonitor {
|
||||
if server.ID == id {
|
||||
servers = append(servers, *server)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, server := range singleton.SortedServerListForGuest {
|
||||
for _, id := range serverIdsWithMonitor {
|
||||
if server.ID == id {
|
||||
servers = append(servers, *server)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
serversBytes, _ := utils.Json.Marshal(model.StreamServerData{
|
||||
Now: time.Now().Unix() * 1000,
|
||||
// Servers: servers,
|
||||
})
|
||||
|
||||
c.HTML(http.StatusOK, "", gin.H{
|
||||
"Servers": string(serversBytes),
|
||||
"MonitorInfos": string(monitorInfos),
|
||||
})
|
||||
}
|
||||
|
||||
func (cp *commonPage) fm(c *gin.Context) {
|
||||
streamId := c.Param("id")
|
||||
if _, err := rpc.NezhaHandlerSingleton.GetStream(streamId); err != nil {
|
||||
// mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||
// Code: http.StatusForbidden,
|
||||
// Title: "无权访问",
|
||||
// Msg: "FM会话不存在",
|
||||
// Link: "/",
|
||||
// Btn: "返回首页",
|
||||
// }, true)
|
||||
return
|
||||
}
|
||||
defer rpc.NezhaHandlerSingleton.CloseStream(streamId)
|
||||
|
||||
wsConn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
|
||||
if err != nil {
|
||||
// mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||
// Code: http.StatusInternalServerError,
|
||||
// // Title: singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{
|
||||
// // MessageID: "NetworkError",
|
||||
// // }),
|
||||
// Msg: "Websocket协议切换失败",
|
||||
// Link: "/",
|
||||
// Btn: "返回首页",
|
||||
// }, true)
|
||||
return
|
||||
}
|
||||
defer wsConn.Close()
|
||||
conn := websocketx.NewConn(wsConn)
|
||||
|
||||
go func() {
|
||||
// PING 保活
|
||||
for {
|
||||
if err = conn.WriteMessage(websocket.PingMessage, []byte{}); err != nil {
|
||||
return
|
||||
}
|
||||
time.Sleep(time.Second * 10)
|
||||
}
|
||||
}()
|
||||
|
||||
if err = rpc.NezhaHandlerSingleton.UserConnected(streamId, conn); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
rpc.NezhaHandlerSingleton.StartStream(streamId, time.Second*10)
|
||||
}
|
||||
|
||||
func (cp *commonPage) createFM(c *gin.Context) {
|
||||
IdString := c.Query("id")
|
||||
if _, authorized := c.Get(model.CtxKeyAuthorizedUser); !authorized {
|
||||
// mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||
// Code: http.StatusForbidden,
|
||||
// Title: "无权访问",
|
||||
// Msg: "用户未登录",
|
||||
// Link: "/login",
|
||||
// Btn: "去登录",
|
||||
// }, true)
|
||||
return
|
||||
}
|
||||
|
||||
streamId, err := uuid.GenerateUUID()
|
||||
if err != nil {
|
||||
// mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||
// Code: http.StatusInternalServerError,
|
||||
// // Title: singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{
|
||||
// // MessageID: "SystemError",
|
||||
// // }),
|
||||
// Msg: "生成会话ID失败",
|
||||
// Link: "/server",
|
||||
// Btn: "返回重试",
|
||||
// }, true)
|
||||
return
|
||||
}
|
||||
|
||||
rpc.NezhaHandlerSingleton.CreateStream(streamId)
|
||||
|
||||
serverId, err := strconv.Atoi(IdString)
|
||||
if err != nil {
|
||||
// mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||
// Code: http.StatusForbidden,
|
||||
// Title: "请求失败",
|
||||
// Msg: "请求参数有误:" + err.Error(),
|
||||
// Link: "/server",
|
||||
// Btn: "返回重试",
|
||||
// }, true)
|
||||
return
|
||||
}
|
||||
|
||||
singleton.ServerLock.RLock()
|
||||
server := singleton.ServerList[uint64(serverId)]
|
||||
singleton.ServerLock.RUnlock()
|
||||
if server == nil {
|
||||
// mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||
// Code: http.StatusForbidden,
|
||||
// Title: "请求失败",
|
||||
// Msg: "服务器不存在或处于离线状态",
|
||||
// Link: "/server",
|
||||
// Btn: "返回重试",
|
||||
// }, true)
|
||||
return
|
||||
}
|
||||
|
||||
fmData, _ := utils.Json.Marshal(&model.TaskFM{
|
||||
StreamID: streamId,
|
||||
})
|
||||
if err := server.TaskStream.Send(&proto.Task{
|
||||
Type: model.TaskTypeFM,
|
||||
Data: string(fmData),
|
||||
}); err != nil {
|
||||
// mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||
// Code: http.StatusForbidden,
|
||||
// Title: "请求失败",
|
||||
// Msg: "Agent信令下发失败",
|
||||
// Link: "/server",
|
||||
// Btn: "返回重试",
|
||||
// }, true)
|
||||
return
|
||||
}
|
||||
|
||||
c.HTML(http.StatusOK, "dashboard-", gin.H{
|
||||
"SessionID": streamId,
|
||||
})
|
||||
}
|
@ -1,636 +0,0 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/jinzhu/copier"
|
||||
"golang.org/x/net/idna"
|
||||
|
||||
"github.com/naiba/nezha/model"
|
||||
"github.com/naiba/nezha/pkg/utils"
|
||||
"github.com/naiba/nezha/proto"
|
||||
"github.com/naiba/nezha/service/singleton"
|
||||
)
|
||||
|
||||
type memberAPI struct {
|
||||
r gin.IRouter
|
||||
}
|
||||
|
||||
func (ma *memberAPI) serve() {
|
||||
mr := ma.r.Group("")
|
||||
// mr.Use(mygin.Authorize(mygin.AuthorizeOption{
|
||||
// MemberOnly: true,
|
||||
// IsPage: false,
|
||||
// Msg: "访问此接口需要登录",
|
||||
// Btn: "点此登录",
|
||||
// Redirect: "/login",
|
||||
// }))
|
||||
mr.POST("/cron", ma.addOrEditCron)
|
||||
mr.GET("/cron/:id/manual", ma.manualTrigger)
|
||||
mr.POST("/force-update", ma.forceUpdate)
|
||||
mr.POST("/batch-update-server-group", ma.batchUpdateServerGroup)
|
||||
mr.POST("/notification", ma.addOrEditNotification)
|
||||
mr.POST("/ddns", ma.addOrEditDDNS)
|
||||
mr.POST("/nat", ma.addOrEditNAT)
|
||||
mr.POST("/alert-rule", ma.addOrEditAlertRule)
|
||||
mr.POST("/setting", ma.updateSetting)
|
||||
mr.DELETE("/:model/:id", ma.delete)
|
||||
mr.POST("/logout", ma.logout)
|
||||
}
|
||||
|
||||
func (ma *memberAPI) delete(c *gin.Context) {
|
||||
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
|
||||
if id < 1 {
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: "错误的 Server ID",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var err error
|
||||
switch c.Param("model") {
|
||||
|
||||
case "cron":
|
||||
err = singleton.DB.Unscoped().Delete(&model.Cron{}, "id = ?", id).Error
|
||||
if err == nil {
|
||||
singleton.CronLock.RLock()
|
||||
defer singleton.CronLock.RUnlock()
|
||||
cr := singleton.Crons[id]
|
||||
if cr != nil && cr.CronJobID != 0 {
|
||||
singleton.Cron.Remove(cr.CronJobID)
|
||||
}
|
||||
delete(singleton.Crons, id)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: fmt.Sprintf("数据库错误:%s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusOK,
|
||||
})
|
||||
}
|
||||
|
||||
type cronForm struct {
|
||||
ID uint64
|
||||
TaskType uint8 // 0:计划任务 1:触发任务
|
||||
Name string
|
||||
Scheduler string
|
||||
Command string
|
||||
ServersRaw string
|
||||
Cover uint8
|
||||
PushSuccessful string
|
||||
NotificationTag string
|
||||
}
|
||||
|
||||
func (ma *memberAPI) addOrEditCron(c *gin.Context) {
|
||||
var cf cronForm
|
||||
var cr model.Cron
|
||||
err := c.ShouldBindJSON(&cf)
|
||||
if err == nil {
|
||||
cr.TaskType = cf.TaskType
|
||||
cr.Name = cf.Name
|
||||
cr.Scheduler = cf.Scheduler
|
||||
cr.Command = cf.Command
|
||||
cr.ServersRaw = cf.ServersRaw
|
||||
cr.PushSuccessful = cf.PushSuccessful == "on"
|
||||
//cr.NotificationTag = cf.NotificationTag
|
||||
cr.ID = cf.ID
|
||||
cr.Cover = cf.Cover
|
||||
err = utils.Json.Unmarshal([]byte(cf.ServersRaw), &cr.Servers)
|
||||
}
|
||||
|
||||
// 计划任务类型不得使用触发服务器执行方式
|
||||
if cr.TaskType == model.CronTypeCronTask && cr.Cover == model.CronCoverAlertTrigger {
|
||||
err = errors.New("计划任务类型不得使用触发服务器执行方式")
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: fmt.Sprintf("请求错误:%s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
tx := singleton.DB.Begin()
|
||||
if err == nil {
|
||||
// 保证NotificationTag不为空
|
||||
//if cr.NotificationTag == "" {
|
||||
// cr.NotificationTag = "default"
|
||||
//}
|
||||
if cf.ID == 0 {
|
||||
err = tx.Create(&cr).Error
|
||||
} else {
|
||||
err = tx.Save(&cr).Error
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
err = tx.Commit().Error
|
||||
} else {
|
||||
tx.Rollback()
|
||||
}
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: fmt.Sprintf("请求错误:%s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
singleton.CronLock.Lock()
|
||||
defer singleton.CronLock.Unlock()
|
||||
crOld := singleton.Crons[cr.ID]
|
||||
if crOld != nil && crOld.CronJobID != 0 {
|
||||
singleton.Cron.Remove(crOld.CronJobID)
|
||||
}
|
||||
|
||||
delete(singleton.Crons, cr.ID)
|
||||
singleton.Crons[cr.ID] = &cr
|
||||
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusOK,
|
||||
})
|
||||
}
|
||||
|
||||
func (ma *memberAPI) manualTrigger(c *gin.Context) {
|
||||
var cr model.Cron
|
||||
if err := singleton.DB.First(&cr, "id = ?", c.Param("id")).Error; err != nil {
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
//singleton.ManualTrigger(cr)
|
||||
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusOK,
|
||||
})
|
||||
}
|
||||
|
||||
type BatchUpdateServerGroupRequest struct {
|
||||
Servers []uint64
|
||||
Group string
|
||||
}
|
||||
|
||||
func (ma *memberAPI) batchUpdateServerGroup(c *gin.Context) {
|
||||
var req BatchUpdateServerGroupRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if err := singleton.DB.Model(&model.Server{}).Where("id in (?)", req.Servers).Update("tag", req.Group).Error; err != nil {
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
singleton.ServerLock.Lock()
|
||||
|
||||
for i := 0; i < len(req.Servers); i++ {
|
||||
serverId := req.Servers[i]
|
||||
var s model.Server
|
||||
copier.Copy(&s, singleton.ServerList[serverId])
|
||||
// s.Tag = req.Group
|
||||
// // 如果修改了Ta
|
||||
// oldTag := singleton.ServerList[serverId].Tag
|
||||
// newTag := s.Tag
|
||||
// if newTag != oldTag {
|
||||
// index := -1
|
||||
// for i := 0; i < len(singleton.ServerTagToIDList[oldTag]); i++ {
|
||||
// if singleton.ServerTagToIDList[oldTag][i] == s.ID {
|
||||
// index = i
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// if index > -1 {
|
||||
// // 删除旧 Tag-ID 绑定关系
|
||||
// singleton.ServerTagToIDList[oldTag] = append(singleton.ServerTagToIDList[oldTag][:index], singleton.ServerTagToIDList[oldTag][index+1:]...)
|
||||
// if len(singleton.ServerTagToIDList[oldTag]) == 0 {
|
||||
// delete(singleton.ServerTagToIDList, oldTag)
|
||||
// }
|
||||
// }
|
||||
// // 设置新的 Tag-ID 绑定关系
|
||||
// singleton.ServerTagToIDList[newTag] = append(singleton.ServerTagToIDList[newTag], s.ID)
|
||||
// }
|
||||
singleton.ServerList[s.ID] = &s
|
||||
}
|
||||
|
||||
singleton.ServerLock.Unlock()
|
||||
|
||||
singleton.ReSortServer()
|
||||
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusOK,
|
||||
})
|
||||
}
|
||||
|
||||
func (ma *memberAPI) forceUpdate(c *gin.Context) {
|
||||
var forceUpdateServers []uint64
|
||||
if err := c.ShouldBindJSON(&forceUpdateServers); err != nil {
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var executeResult bytes.Buffer
|
||||
|
||||
for i := 0; i < len(forceUpdateServers); i++ {
|
||||
singleton.ServerLock.RLock()
|
||||
server := singleton.ServerList[forceUpdateServers[i]]
|
||||
singleton.ServerLock.RUnlock()
|
||||
if server != nil && server.TaskStream != nil {
|
||||
if err := server.TaskStream.Send(&proto.Task{
|
||||
Type: model.TaskTypeUpgrade,
|
||||
}); err != nil {
|
||||
executeResult.WriteString(fmt.Sprintf("%d 下发指令失败 %+v<br/>", forceUpdateServers[i], err))
|
||||
} else {
|
||||
executeResult.WriteString(fmt.Sprintf("%d 下发指令成功<br/>", forceUpdateServers[i]))
|
||||
}
|
||||
} else {
|
||||
executeResult.WriteString(fmt.Sprintf("%d 离线<br/>", forceUpdateServers[i]))
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusOK,
|
||||
Message: executeResult.String(),
|
||||
})
|
||||
}
|
||||
|
||||
type notificationForm struct {
|
||||
ID uint64
|
||||
Name string
|
||||
URL string
|
||||
RequestMethod int
|
||||
RequestType int
|
||||
RequestHeader string
|
||||
RequestBody string
|
||||
VerifySSL string
|
||||
SkipCheck string
|
||||
}
|
||||
|
||||
func (ma *memberAPI) addOrEditNotification(c *gin.Context) {
|
||||
var nf notificationForm
|
||||
var n model.Notification
|
||||
err := c.ShouldBindJSON(&nf)
|
||||
if err == nil {
|
||||
n.Name = nf.Name
|
||||
n.RequestMethod = nf.RequestMethod
|
||||
n.RequestType = nf.RequestType
|
||||
n.RequestHeader = nf.RequestHeader
|
||||
n.RequestBody = nf.RequestBody
|
||||
n.URL = nf.URL
|
||||
//verifySSL := nf.VerifySSL == "on"
|
||||
//n.VerifySSL = &verifySSL
|
||||
n.ID = nf.ID
|
||||
ns := model.NotificationServerBundle{
|
||||
Notification: &n,
|
||||
Server: nil,
|
||||
Loc: singleton.Loc,
|
||||
}
|
||||
// 勾选了跳过检查
|
||||
if nf.SkipCheck != "on" {
|
||||
err = ns.Send("这是测试消息")
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
if n.ID == 0 {
|
||||
err = singleton.DB.Create(&n).Error
|
||||
} else {
|
||||
err = singleton.DB.Save(&n).Error
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: fmt.Sprintf("请求错误:%s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
singleton.OnRefreshOrAddNotification(&n)
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusOK,
|
||||
})
|
||||
}
|
||||
|
||||
type ddnsForm struct {
|
||||
ID uint64
|
||||
MaxRetries uint64
|
||||
EnableIPv4 string
|
||||
EnableIPv6 string
|
||||
Name string
|
||||
Provider string
|
||||
DomainsRaw string
|
||||
AccessID string
|
||||
AccessSecret string
|
||||
WebhookURL string
|
||||
WebhookMethod uint8
|
||||
WebhookRequestType uint8
|
||||
WebhookRequestBody string
|
||||
WebhookHeaders string
|
||||
}
|
||||
|
||||
func (ma *memberAPI) addOrEditDDNS(c *gin.Context) {
|
||||
var df ddnsForm
|
||||
var p model.DDNSProfile
|
||||
err := c.ShouldBindJSON(&df)
|
||||
if err == nil {
|
||||
if df.MaxRetries < 1 || df.MaxRetries > 10 {
|
||||
err = errors.New("重试次数必须为大于 1 且不超过 10 的整数")
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
p.Name = df.Name
|
||||
p.ID = df.ID
|
||||
enableIPv4 := df.EnableIPv4 == "on"
|
||||
enableIPv6 := df.EnableIPv6 == "on"
|
||||
p.EnableIPv4 = &enableIPv4
|
||||
p.EnableIPv6 = &enableIPv6
|
||||
p.MaxRetries = df.MaxRetries
|
||||
p.Provider = df.Provider
|
||||
p.DomainsRaw = df.DomainsRaw
|
||||
p.Domains = strings.Split(p.DomainsRaw, ",")
|
||||
p.AccessID = df.AccessID
|
||||
p.AccessSecret = df.AccessSecret
|
||||
p.WebhookURL = df.WebhookURL
|
||||
p.WebhookMethod = df.WebhookMethod
|
||||
p.WebhookRequestType = df.WebhookRequestType
|
||||
p.WebhookRequestBody = df.WebhookRequestBody
|
||||
p.WebhookHeaders = df.WebhookHeaders
|
||||
|
||||
for n, domain := range p.Domains {
|
||||
// IDN to ASCII
|
||||
domainValid, domainErr := idna.Lookup.ToASCII(domain)
|
||||
if domainErr != nil {
|
||||
err = fmt.Errorf("域名 %s 解析错误: %v", domain, domainErr)
|
||||
break
|
||||
}
|
||||
p.Domains[n] = domainValid
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
if p.ID == 0 {
|
||||
err = singleton.DB.Create(&p).Error
|
||||
} else {
|
||||
err = singleton.DB.Save(&p).Error
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: fmt.Sprintf("请求错误:%s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
//singleton.OnDDNSUpdate()
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusOK,
|
||||
})
|
||||
}
|
||||
|
||||
type natForm struct {
|
||||
ID uint64
|
||||
Name string
|
||||
ServerID uint64
|
||||
Host string
|
||||
Domain string
|
||||
}
|
||||
|
||||
func (ma *memberAPI) addOrEditNAT(c *gin.Context) {
|
||||
var nf natForm
|
||||
var n model.NAT
|
||||
err := c.ShouldBindJSON(&nf)
|
||||
if err == nil {
|
||||
n.Name = nf.Name
|
||||
n.ID = nf.ID
|
||||
n.Domain = nf.Domain
|
||||
n.Host = nf.Host
|
||||
n.ServerID = nf.ServerID
|
||||
}
|
||||
if err == nil {
|
||||
if n.ID == 0 {
|
||||
err = singleton.DB.Create(&n).Error
|
||||
} else {
|
||||
err = singleton.DB.Save(&n).Error
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: fmt.Sprintf("请求错误:%s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
//singleton.OnNATUpdate()
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusOK,
|
||||
})
|
||||
}
|
||||
|
||||
type alertRuleForm struct {
|
||||
ID uint64
|
||||
Name string
|
||||
RulesRaw string
|
||||
FailTriggerTasksRaw string // 失败时触发的任务id
|
||||
RecoverTriggerTasksRaw string // 恢复时触发的任务id
|
||||
NotificationTag string
|
||||
TriggerMode int
|
||||
Enable string
|
||||
}
|
||||
|
||||
func (ma *memberAPI) addOrEditAlertRule(c *gin.Context) {
|
||||
var arf alertRuleForm
|
||||
var r model.AlertRule
|
||||
err := c.ShouldBindJSON(&arf)
|
||||
if err == nil {
|
||||
err = utils.Json.Unmarshal([]byte(arf.RulesRaw), &r.Rules)
|
||||
}
|
||||
if err == nil {
|
||||
if len(r.Rules) == 0 {
|
||||
err = errors.New("至少定义一条规则")
|
||||
} else {
|
||||
for i := 0; i < len(r.Rules); i++ {
|
||||
if !r.Rules[i].IsTransferDurationRule() {
|
||||
if r.Rules[i].Duration < 3 {
|
||||
err = errors.New("错误:Duration 至少为 3")
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if r.Rules[i].CycleInterval < 1 {
|
||||
err = errors.New("错误: cycle_interval 至少为 1")
|
||||
break
|
||||
}
|
||||
if r.Rules[i].CycleStart == nil {
|
||||
err = errors.New("错误: cycle_start 未设置")
|
||||
break
|
||||
}
|
||||
if r.Rules[i].CycleStart.After(time.Now()) {
|
||||
err = errors.New("错误: cycle_start 是个未来值")
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
r.Name = arf.Name
|
||||
r.RulesRaw = arf.RulesRaw
|
||||
r.FailTriggerTasksRaw = arf.FailTriggerTasksRaw
|
||||
r.RecoverTriggerTasksRaw = arf.RecoverTriggerTasksRaw
|
||||
//r.NotificationTag = arf.NotificationTag
|
||||
enable := arf.Enable == "on"
|
||||
r.TriggerMode = arf.TriggerMode
|
||||
r.Enable = &enable
|
||||
r.ID = arf.ID
|
||||
}
|
||||
if err == nil {
|
||||
err = utils.Json.Unmarshal([]byte(arf.FailTriggerTasksRaw), &r.FailTriggerTasks)
|
||||
}
|
||||
if err == nil {
|
||||
err = utils.Json.Unmarshal([]byte(arf.RecoverTriggerTasksRaw), &r.RecoverTriggerTasks)
|
||||
}
|
||||
//保证NotificationTag不为空
|
||||
if err == nil {
|
||||
//if r.NotificationTag == "" {
|
||||
// r.NotificationTag = "default"
|
||||
//}
|
||||
if r.ID == 0 {
|
||||
err = singleton.DB.Create(&r).Error
|
||||
} else {
|
||||
err = singleton.DB.Save(&r).Error
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: fmt.Sprintf("请求错误:%s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
//singleton.OnRefreshOrAddAlert(r)
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusOK,
|
||||
})
|
||||
}
|
||||
|
||||
type logoutForm struct {
|
||||
ID uint64
|
||||
}
|
||||
|
||||
func (ma *memberAPI) logout(c *gin.Context) {
|
||||
admin := c.MustGet(model.CtxKeyAuthorizedUser).(*model.User)
|
||||
var lf logoutForm
|
||||
if err := c.ShouldBindJSON(&lf); err != nil {
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: fmt.Sprintf("请求错误:%s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
if lf.ID != admin.ID {
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: fmt.Sprintf("请求错误:%s", "用户ID不匹配"),
|
||||
})
|
||||
return
|
||||
}
|
||||
singleton.DB.Model(admin).UpdateColumns(model.User{
|
||||
// Token: "",
|
||||
// TokenExpired: time.Now(),
|
||||
})
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusOK,
|
||||
})
|
||||
|
||||
// if oidcLogoutUrl := singleton.Conf.Oauth2.OidcLogoutURL; oidcLogoutUrl != "" {
|
||||
// // 重定向到 OIDC 退出登录地址。不知道为什么,这里的重定向不生效
|
||||
// c.Redirect(http.StatusOK, oidcLogoutUrl)
|
||||
// }
|
||||
}
|
||||
|
||||
type settingForm struct {
|
||||
SiteName string
|
||||
Language string
|
||||
CustomNameservers string
|
||||
IgnoredIPNotification string
|
||||
IPChangeNotificationTag string // IP变更提醒的通知组
|
||||
InstallHost string
|
||||
Cover uint8
|
||||
|
||||
EnableIPChangeNotification string
|
||||
EnablePlainIPInNotification string
|
||||
}
|
||||
|
||||
func (ma *memberAPI) updateSetting(c *gin.Context) {
|
||||
var sf settingForm
|
||||
if err := c.ShouldBind(&sf); err != nil {
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: fmt.Sprintf("请求错误:%s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// if _, yes := model.Themes[sf.Theme]; !yes {
|
||||
// c.JSON(http.StatusOK, model.Response{
|
||||
// Code: http.StatusBadRequest,
|
||||
// Message: fmt.Sprintf("前台主题不存在:%s", sf.Theme),
|
||||
// })
|
||||
// return
|
||||
// }
|
||||
|
||||
// if _, yes := model.DashboardThemes[sf.DashboardTheme]; !yes {
|
||||
// c.JSON(http.StatusOK, model.Response{
|
||||
// Code: http.StatusBadRequest,
|
||||
// Message: fmt.Sprintf("后台主题不存在:%s", sf.DashboardTheme),
|
||||
// })
|
||||
// return
|
||||
// }
|
||||
|
||||
/*
|
||||
singleton.Conf.Language = sf.Language
|
||||
singleton.Conf.EnableIPChangeNotification = sf.EnableIPChangeNotification == "on"
|
||||
singleton.Conf.EnablePlainIPInNotification = sf.EnablePlainIPInNotification == "on"
|
||||
singleton.Conf.Cover = sf.Cover
|
||||
singleton.Conf.InstallHost = sf.InstallHost
|
||||
singleton.Conf.IgnoredIPNotification = sf.IgnoredIPNotification
|
||||
singleton.Conf.IPChangeNotificationTag = sf.IPChangeNotificationTag
|
||||
singleton.Conf.SiteName = sf.SiteName
|
||||
singleton.Conf.DNSServers = sf.CustomNameservers
|
||||
// 保证NotificationTag不为空
|
||||
if singleton.Conf.IPChangeNotificationTag == "" {
|
||||
singleton.Conf.IPChangeNotificationTag = "default"
|
||||
}
|
||||
if err := singleton.Conf.Save(); err != nil {
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: fmt.Sprintf("请求错误:%s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
// 更新DNS服务器
|
||||
singleton.OnNameserverUpdate()
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusOK,
|
||||
})
|
||||
*/
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/naiba/nezha/model"
|
||||
"github.com/naiba/nezha/service/singleton"
|
||||
)
|
||||
|
||||
type memberPage struct {
|
||||
r *gin.Engine
|
||||
}
|
||||
|
||||
func (mp *memberPage) serve() {
|
||||
mr := mp.r.Group("")
|
||||
// mr.Use(mygin.Authorize(mygin.AuthorizeOption{
|
||||
// MemberOnly: true,
|
||||
// IsPage: true,
|
||||
// // Msg: singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "YouAreNotAuthorized"}),
|
||||
// // Btn: singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "Login"}),
|
||||
// Redirect: "/login",
|
||||
// }))
|
||||
mr.GET("/cron", mp.cron)
|
||||
mr.GET("/notification", mp.notification)
|
||||
mr.GET("/ddns", mp.ddns)
|
||||
mr.GET("/nat", mp.nat)
|
||||
mr.GET("/setting", mp.setting)
|
||||
}
|
||||
|
||||
func (mp *memberPage) cron(c *gin.Context) {
|
||||
var crons []model.Cron
|
||||
singleton.DB.Find(&crons)
|
||||
c.HTML(http.StatusOK, "dashboard-", gin.H{
|
||||
// "Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "ScheduledTasks"}),
|
||||
"Crons": crons,
|
||||
})
|
||||
}
|
||||
|
||||
func (mp *memberPage) notification(c *gin.Context) {
|
||||
var nf []model.Notification
|
||||
singleton.DB.Find(&nf)
|
||||
var ar []model.AlertRule
|
||||
singleton.DB.Find(&ar)
|
||||
c.HTML(http.StatusOK, "dashboard-", gin.H{
|
||||
// "Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "Notification"}),
|
||||
"Notifications": nf,
|
||||
"AlertRules": ar,
|
||||
})
|
||||
}
|
||||
|
||||
func (mp *memberPage) ddns(c *gin.Context) {
|
||||
var data []model.DDNSProfile
|
||||
singleton.DB.Find(&data)
|
||||
c.HTML(http.StatusOK, "dashboard-", gin.H{
|
||||
// "Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "DDNS"}),
|
||||
"DDNS": data,
|
||||
//"ProviderMap": model.ProviderMap,
|
||||
//"ProviderList": model.ProviderList,
|
||||
})
|
||||
}
|
||||
|
||||
func (mp *memberPage) nat(c *gin.Context) {
|
||||
var data []model.NAT
|
||||
singleton.DB.Find(&data)
|
||||
c.HTML(http.StatusOK, "dashboard-", gin.H{
|
||||
// "Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "NAT"}),
|
||||
"NAT": data,
|
||||
})
|
||||
}
|
||||
|
||||
func (mp *memberPage) setting(c *gin.Context) {
|
||||
c.HTML(http.StatusOK, "dashboard-", gin.H{
|
||||
// "Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "Settings"}),
|
||||
//"Languages": model.Languages,
|
||||
//"DashboardThemes": model.DashboardThemes,
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue
Block a user