refactor: remove pages, combine grpc http port

This commit is contained in:
naiba
2024-10-20 11:47:45 +08:00
parent 4fc0aad7a0
commit 606e10ca0a
20 changed files with 368 additions and 761 deletions

View File

@@ -1,82 +0,0 @@
package mygin
import (
"net/http"
"strings"
"github.com/gin-gonic/gin"
"github.com/naiba/nezha/model"
"github.com/naiba/nezha/service/singleton"
)
type AuthorizeOption struct {
GuestOnly bool
MemberOnly bool
IsPage bool
AllowAPI bool
Msg string
Redirect string
Btn string
}
func Authorize(opt AuthorizeOption) func(*gin.Context) {
return func(c *gin.Context) {
var code = http.StatusForbidden
if opt.GuestOnly {
code = http.StatusBadRequest
}
commonErr := ErrInfo{
Title: "访问受限",
Code: code,
Msg: opt.Msg,
Link: opt.Redirect,
Btn: opt.Btn,
}
var isLogin bool
// 用户鉴权
token, _ := c.Cookie(singleton.Conf.Site.CookieName)
token = strings.TrimSpace(token)
if token != "" {
var u model.User
if err := singleton.DB.Where("token = ?", token).First(&u).Error; err == nil {
isLogin = true // u.TokenExpired.After(time.Now())
}
if isLogin {
c.Set(model.CtxKeyAuthorizedUser, &u)
}
}
// API鉴权
if opt.AllowAPI {
apiToken := c.GetHeader("Authorization")
if apiToken != "" {
var u model.User
singleton.ApiLock.RLock()
if _, ok := singleton.ApiTokenList[apiToken]; ok {
err := singleton.DB.First(&u).Where("id = ?", singleton.ApiTokenList[apiToken].UserID).Error
isLogin = err == nil
}
singleton.ApiLock.RUnlock()
if isLogin {
c.Set(model.CtxKeyAuthorizedUser, &u)
c.Set("isAPI", true)
}
}
}
// 已登录且只能游客访问
if isLogin && opt.GuestOnly {
ShowErrorPage(c, commonErr, opt.IsPage)
return
}
// 未登录且需要登录
if !isLogin && opt.MemberOnly {
ShowErrorPage(c, commonErr, opt.IsPage)
return
}
}
}

View File

@@ -1,36 +0,0 @@
package mygin
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/naiba/nezha/model"
"github.com/naiba/nezha/service/singleton"
)
type ErrInfo struct {
Code int
Title string
Msg string
Link string
Btn string
}
func ShowErrorPage(c *gin.Context, i ErrInfo, isPage bool) {
if isPage {
c.HTML(i.Code, "dashboard-"+singleton.Conf.Site.DashboardTheme+"/error", CommonEnvironment(c, gin.H{
"Code": i.Code,
"Title": i.Title,
"Msg": i.Msg,
"Link": i.Link,
"Btn": i.Btn,
}))
} else {
c.JSON(http.StatusOK, model.Response{
Code: i.Code,
Message: i.Msg,
})
}
c.Abort()
}

View File

@@ -1,52 +0,0 @@
package mygin
import (
"fmt"
"strings"
"github.com/gin-gonic/gin"
"github.com/naiba/nezha/model"
"github.com/naiba/nezha/service/singleton"
)
var adminPage = map[string]bool{
"/server": true,
"/monitor": true,
"/setting": true,
"/notification": true,
"/ddns": true,
"/nat": true,
"/cron": true,
"/api": true,
}
func CommonEnvironment(c *gin.Context, data map[string]interface{}) gin.H {
data["MatchedPath"] = c.MustGet("MatchedPath")
data["Version"] = singleton.Version
data["Conf"] = singleton.Conf
data["Themes"] = model.Themes
data["CustomCode"] = singleton.Conf.Site.CustomCode
data["CustomCodeDashboard"] = singleton.Conf.Site.CustomCodeDashboard
// 是否是管理页面
data["IsAdminPage"] = adminPage[data["MatchedPath"].(string)]
// 站点标题
if t, has := data["Title"]; !has {
data["Title"] = singleton.Conf.Site.Brand
} else {
data["Title"] = fmt.Sprintf("%s - %s", t, singleton.Conf.Site.Brand)
}
u, ok := c.Get(model.CtxKeyAuthorizedUser)
if ok {
data["Admin"] = u
}
return data
}
func RecordPath(c *gin.Context) {
url := c.Request.URL.String()
for _, p := range c.Params {
url = strings.Replace(url, p.Value, ":"+p.Key, 1)
}
c.Set("MatchedPath", url)
}

View File

@@ -1,30 +0,0 @@
package mygin
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/naiba/nezha/model"
"github.com/naiba/nezha/pkg/utils"
"github.com/naiba/nezha/service/singleton"
)
func PreferredTheme(c *gin.Context) {
// 采用前端传入的主题
if theme, err := c.Cookie("preferred_theme"); err == nil {
if _, has := model.Themes[theme]; has {
// 检验自定义主题
if theme == "custom" && singleton.Conf.Site.Theme != "custom" && !utils.IsFileExists("resource/template/theme-custom/home.html") {
return
}
c.Set(model.CtxKeyPreferredTheme, theme)
}
}
}
func GetPreferredTheme(c *gin.Context, path string) string {
if theme, has := c.Get(model.CtxKeyPreferredTheme); has {
return fmt.Sprintf("theme-%s%s", theme, path)
}
return fmt.Sprintf("theme-%s%s", singleton.Conf.Site.Theme, path)
}

View File

@@ -1,50 +0,0 @@
package mygin
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/naiba/nezha/model"
"github.com/naiba/nezha/service/singleton"
"golang.org/x/crypto/bcrypt"
)
type ValidateViewPasswordOption struct {
IsPage bool
AbortWhenFail bool
}
func ValidateViewPassword(opt ValidateViewPasswordOption) gin.HandlerFunc {
return func(c *gin.Context) {
if singleton.Conf.Site.ViewPassword == "" {
return
}
_, authorized := c.Get(model.CtxKeyAuthorizedUser)
if authorized {
return
}
viewPassword, err := c.Cookie(singleton.Conf.Site.CookieName + "-vp")
if err == nil {
err = bcrypt.CompareHashAndPassword([]byte(viewPassword), []byte(singleton.Conf.Site.ViewPassword))
}
if err == nil {
c.Set(model.CtxKeyViewPasswordVerified, true)
return
}
if !opt.AbortWhenFail {
return
}
if opt.IsPage {
c.HTML(http.StatusOK, GetPreferredTheme(c, "/viewpassword"), CommonEnvironment(c, gin.H{
// "Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "VerifyPassword"}),
}))
} else {
c.JSON(http.StatusOK, model.Response{
Code: http.StatusForbidden,
Message: "访问受限",
})
}
c.Abort()
}
}

View File

@@ -1,33 +0,0 @@
package utils
import (
"embed"
"io/fs"
"os"
)
// HybridFS combines embed.FS and os.DirFS.
type HybridFS struct {
embedFS, dir fs.FS
}
func NewHybridFS(embed embed.FS, subDir string, localDir string) (*HybridFS, error) {
subFS, err := fs.Sub(embed, subDir)
if err != nil {
return nil, err
}
return &HybridFS{
embedFS: subFS,
dir: os.DirFS(localDir),
}, nil
}
func (hfs *HybridFS) Open(name string) (fs.File, error) {
// Ensure embed files are not replaced
if file, err := hfs.embedFS.Open(name); err == nil {
return file, nil
}
return hfs.dir.Open(name)
}