nezha/pkg/mygin/auth.go
2024-02-24 23:21:33 +08:00

102 lines
2.5 KiB
Go

package mygin
import (
"net/http"
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/nicksnyder/go-i18n/v2/i18n"
"golang.org/x/crypto/bcrypt"
"github.com/naiba/nezha/model"
"github.com/naiba/nezha/service/singleton"
)
type AuthorizeOption struct {
GuestOnly bool
MemberOnly bool
ValidateViewPassword 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 = 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
}
// 验证查看密码
if opt.ValidateViewPassword && singleton.Conf.Site.ViewPassword != "" {
viewPassword, _ := c.Cookie(singleton.Conf.Site.CookieName + "-vp")
if err := bcrypt.CompareHashAndPassword([]byte(viewPassword), []byte(singleton.Conf.Site.ViewPassword)); err != nil {
c.HTML(http.StatusOK, GetPreferredTheme(c, "/viewpassword"), CommonEnvironment(c, gin.H{
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "VerifyPassword"}),
"CustomCode": singleton.Conf.Site.CustomCode,
}))
c.Abort()
return
}
c.Set(model.CtxKeyViewPasswordVerified, true)
}
}
}