mirror of
https://github.com/Buriburizaem0n/nezha_domains.git
synced 2026-02-05 13:10:07 +00:00
refactor: remove pages, combine grpc http port
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
Reference in New Issue
Block a user