2019-12-08 03:59:58 -05:00
|
|
|
package controller
|
|
|
|
|
|
|
|
import (
|
2021-01-31 00:37:43 -05:00
|
|
|
"errors"
|
|
|
|
"fmt"
|
2019-12-08 03:59:58 -05:00
|
|
|
"net/http"
|
2019-12-10 04:57:57 -05:00
|
|
|
"time"
|
2019-12-08 03:59:58 -05:00
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
2019-12-10 04:57:57 -05:00
|
|
|
"github.com/gorilla/websocket"
|
2021-01-31 00:37:43 -05:00
|
|
|
"golang.org/x/crypto/bcrypt"
|
2019-12-08 03:59:58 -05:00
|
|
|
|
2020-11-10 21:07:45 -05:00
|
|
|
"github.com/naiba/nezha/model"
|
|
|
|
"github.com/naiba/nezha/pkg/mygin"
|
|
|
|
"github.com/naiba/nezha/service/dao"
|
2019-12-08 03:59:58 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
type commonPage struct {
|
|
|
|
r *gin.Engine
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cp *commonPage) serve() {
|
|
|
|
cr := cp.r.Group("")
|
|
|
|
cr.Use(mygin.Authorize(mygin.AuthorizeOption{}))
|
2021-01-31 00:37:43 -05:00
|
|
|
cr.POST("/view-password", cp.issueViewPassword)
|
|
|
|
cr.Use(cp.checkViewPassword) // 前端查看密码鉴权
|
2019-12-08 03:59:58 -05:00
|
|
|
cr.GET("/", cp.home)
|
2021-01-15 11:45:49 -05:00
|
|
|
cr.GET("/service", cp.service)
|
2019-12-10 04:57:57 -05:00
|
|
|
cr.GET("/ws", cp.ws)
|
2019-12-08 03:59:58 -05:00
|
|
|
}
|
|
|
|
|
2021-01-31 00:37:43 -05:00
|
|
|
type viewPasswordForm struct {
|
|
|
|
Password string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *commonPage) issueViewPassword(c *gin.Context) {
|
|
|
|
var vpf viewPasswordForm
|
|
|
|
err := c.ShouldBind(&vpf)
|
|
|
|
var hash []byte
|
|
|
|
if err == nil && vpf.Password != dao.Conf.Site.ViewPassword {
|
|
|
|
err = errors.New("查看密码错误")
|
|
|
|
}
|
|
|
|
if err == nil {
|
|
|
|
hash, err = bcrypt.GenerateFromPassword([]byte(vpf.Password), bcrypt.DefaultCost)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
mygin.ShowErrorPage(c, mygin.ErrInfo{
|
2021-08-10 08:13:17 -04:00
|
|
|
Code: http.StatusOK,
|
2021-01-31 00:37:43 -05:00
|
|
|
Title: "出现错误",
|
|
|
|
Msg: fmt.Sprintf("请求错误:%s", err),
|
|
|
|
}, true)
|
|
|
|
c.Abort()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
c.SetCookie(dao.Conf.Site.CookieName+"-vp", string(hash), 60*60*24, "", "", false, false)
|
|
|
|
c.Redirect(http.StatusFound, c.Request.Referer())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *commonPage) checkViewPassword(c *gin.Context) {
|
|
|
|
if dao.Conf.Site.ViewPassword == "" {
|
|
|
|
c.Next()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if _, authorized := c.Get(model.CtxKeyAuthorizedUser); authorized {
|
|
|
|
c.Next()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// 验证查看密码
|
|
|
|
viewPassword, _ := c.Cookie(dao.Conf.Site.CookieName + "-vp")
|
|
|
|
if err := bcrypt.CompareHashAndPassword([]byte(viewPassword), []byte(dao.Conf.Site.ViewPassword)); err != nil {
|
|
|
|
c.HTML(http.StatusOK, "theme-"+dao.Conf.Site.Theme+"/viewpassword", mygin.CommonEnvironment(c, gin.H{
|
|
|
|
"Title": "验证查看密码",
|
|
|
|
"CustomCode": dao.Conf.Site.CustomCode,
|
|
|
|
}))
|
|
|
|
c.Abort()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
c.Next()
|
|
|
|
}
|
|
|
|
|
2021-01-15 11:45:49 -05:00
|
|
|
func (p *commonPage) service(c *gin.Context) {
|
2021-01-15 22:42:12 -05:00
|
|
|
c.HTML(http.StatusOK, "theme-"+dao.Conf.Site.Theme+"/service", mygin.CommonEnvironment(c, gin.H{
|
2021-01-17 20:45:15 -05:00
|
|
|
"Title": "服务状态",
|
2021-07-17 01:53:13 -04:00
|
|
|
"Services": dao.ServiceSentinelShared.LoadStats(),
|
2021-01-17 20:45:15 -05:00
|
|
|
"CustomCode": dao.Conf.Site.CustomCode,
|
2021-01-15 22:42:12 -05:00
|
|
|
}))
|
2021-01-15 11:45:49 -05:00
|
|
|
}
|
|
|
|
|
2019-12-08 03:59:58 -05:00
|
|
|
func (cp *commonPage) home(c *gin.Context) {
|
2021-01-17 09:18:36 -05:00
|
|
|
dao.SortedServerLock.RLock()
|
|
|
|
defer dao.SortedServerLock.RUnlock()
|
2021-01-15 22:42:12 -05:00
|
|
|
|
|
|
|
c.HTML(http.StatusOK, "theme-"+dao.Conf.Site.Theme+"/home", mygin.CommonEnvironment(c, gin.H{
|
2021-01-08 08:04:50 -05:00
|
|
|
"Servers": dao.SortedServerList,
|
2020-12-23 20:54:17 -05:00
|
|
|
"CustomCode": dao.Conf.Site.CustomCode,
|
2021-01-15 22:42:12 -05:00
|
|
|
}))
|
2019-12-08 03:59:58 -05:00
|
|
|
}
|
2019-12-10 04:57:57 -05:00
|
|
|
|
|
|
|
var upgrader = websocket.Upgrader{}
|
|
|
|
|
2021-07-15 23:14:07 -04:00
|
|
|
type Data struct {
|
|
|
|
Now int64 `json:"now,omitempty"`
|
|
|
|
Servers []*model.Server `json:"servers,omitempty"`
|
|
|
|
}
|
|
|
|
|
2019-12-10 04:57:57 -05:00
|
|
|
func (cp *commonPage) ws(c *gin.Context) {
|
|
|
|
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
|
|
|
|
if err != nil {
|
|
|
|
mygin.ShowErrorPage(c, mygin.ErrInfo{
|
|
|
|
Code: http.StatusInternalServerError,
|
|
|
|
Title: "网络错误",
|
|
|
|
Msg: "Websocket协议切换失败",
|
|
|
|
Link: "/",
|
|
|
|
Btn: "返回首页",
|
|
|
|
}, true)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
defer conn.Close()
|
2021-04-03 12:22:50 -04:00
|
|
|
count := 0
|
2020-12-19 10:27:59 -05:00
|
|
|
for {
|
2021-01-17 09:18:36 -05:00
|
|
|
dao.SortedServerLock.RLock()
|
2021-07-15 23:14:07 -04:00
|
|
|
err = conn.WriteJSON(Data{
|
|
|
|
Now: time.Now().Unix() * 1000,
|
|
|
|
Servers: dao.SortedServerList,
|
|
|
|
})
|
2021-01-17 09:18:36 -05:00
|
|
|
dao.SortedServerLock.RUnlock()
|
2020-12-19 10:27:59 -05:00
|
|
|
if err != nil {
|
|
|
|
break
|
2019-12-10 04:57:57 -05:00
|
|
|
}
|
2021-04-03 12:22:50 -04:00
|
|
|
count += 1
|
|
|
|
if count%4 == 0 {
|
2021-04-03 13:01:04 -04:00
|
|
|
err = conn.WriteMessage(websocket.PingMessage, []byte{})
|
|
|
|
if err != nil {
|
|
|
|
break
|
|
|
|
}
|
2021-04-03 12:22:50 -04:00
|
|
|
}
|
2020-12-19 10:27:59 -05:00
|
|
|
time.Sleep(time.Second * 2)
|
|
|
|
}
|
2019-12-10 04:57:57 -05:00
|
|
|
}
|