300 lines
6.7 KiB
Go
300 lines
6.7 KiB
Go
package auth
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"strings"
|
|
"sync"
|
|
"videoweb/pub/common"
|
|
"videoweb/pub/common/errors"
|
|
"videoweb/pub/common/log"
|
|
"videoweb/pub/common/srvdef"
|
|
"videoweb/pub/common/utils"
|
|
"videoweb/pub/models/mwacc"
|
|
"videoweb/pub/models/oplog"
|
|
"videoweb/web/webg"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
)
|
|
|
|
var (
|
|
RoleApiMenus = map[int64][]string{} // 角色Api
|
|
mutex sync.RWMutex
|
|
)
|
|
|
|
var (
|
|
tokener = utils.NewTokenRedis()
|
|
)
|
|
|
|
const (
|
|
AccId = "ACC_ID"
|
|
roleAuthAdrr = "/web/role/getauth"
|
|
)
|
|
|
|
type APIInfo struct {
|
|
Api string
|
|
Desc string
|
|
}
|
|
|
|
var (
|
|
// 白名单,不需要验证token的api
|
|
whiteList = []string{
|
|
"/swagger",
|
|
"/api/web/file/uploadImg",
|
|
"/api/web/file/uploadImgs",
|
|
"/api/web/media/videoBody",
|
|
"/api/web/media/videoOk",
|
|
"/api/web/m3u8",
|
|
"/api/web/uploader/m3u8",
|
|
"/api/web/enkey",
|
|
"/api/web/login/acc",
|
|
"/api/web/login/bind",
|
|
"/api/web/login/slogin",
|
|
"/api/web/stat/media/list",
|
|
"/api/web/stat/analytics",
|
|
"/api/web/stat/daily/analytics",
|
|
"/api/web/sync/video/list",
|
|
"/api/web/sync/videocollection/list",
|
|
"/api/web/sync/category/list",
|
|
"/api/web/sync/creator/list",
|
|
"/api/web/sync/tag/list",
|
|
"/api/web/contentexcel",
|
|
"/api/web/videoinfo/fillZeroFakeFlow",
|
|
"/wbapi",
|
|
"/api/web/seopush/indexnow/bulk",
|
|
}
|
|
)
|
|
|
|
// 读取角色信息
|
|
func GetRoleApiMenus(ctx context.Context, accid int64) (roles []string, err error) {
|
|
mutex.RLock()
|
|
roles, ok := RoleApiMenus[accid]
|
|
mutex.RUnlock()
|
|
if !ok {
|
|
accInfo, dataErr := mwacc.FindOneAccByFilter(nil, bson.M{mwacc.FN.MwAcc.Id: accid})
|
|
if dataErr != nil || accInfo.Id == 0 {
|
|
return roles, dataErr
|
|
}
|
|
|
|
roleInfo, roleErr := mwacc.FindOneRoleByFilter(ctx, bson.M{mwacc.FN.MwRole.Id: accInfo.RoleId})
|
|
|
|
if roleErr != nil || roleInfo.Id == 0 {
|
|
return roles, roleErr
|
|
}
|
|
|
|
if roleInfo.Name == "超级管理员" {
|
|
return nil, nil
|
|
}
|
|
|
|
mutex.Lock()
|
|
RoleApiMenus[accid] = roleInfo.ApiMenus
|
|
mutex.Unlock()
|
|
roles = roleInfo.ApiMenus
|
|
}
|
|
return
|
|
}
|
|
|
|
// 是否角色api
|
|
func HasRoleApi(path string, apis []string) bool {
|
|
apimap := make(map[string]struct{})
|
|
for _, v := range apis {
|
|
apimap[v] = struct{}{}
|
|
}
|
|
_, ok := apimap[path]
|
|
return ok
|
|
}
|
|
|
|
// 角色权限
|
|
func handleRoles(ctx *gin.Context) (int, error) {
|
|
path := ctx.Request.URL.Path
|
|
if strings.HasPrefix(path, roleAuthAdrr) {
|
|
return 0, nil
|
|
}
|
|
|
|
accid := ctx.GetInt(AccId)
|
|
apis, err := GetRoleApiMenus(ctx, int64(accid))
|
|
if err != nil {
|
|
return int(errors.RoleErr), err
|
|
}
|
|
if apis == nil {
|
|
return 0, nil
|
|
}
|
|
has := HasRoleApi(path, apis)
|
|
if !has {
|
|
return int(errors.RoleErr), srvdef.New(srvdef.RoleErr, (srvdef.RoleErr).Msg(), "")
|
|
}
|
|
return 0, nil
|
|
}
|
|
|
|
// 楼风经纪人权限
|
|
func handleLouFengBossRoles(ctx *gin.Context) (int, error) {
|
|
path := ctx.Request.URL.Path
|
|
if strings.HasPrefix(path, roleAuthAdrr) {
|
|
return 0, nil
|
|
}
|
|
|
|
accid := ctx.GetInt64(AccId)
|
|
accInfo, dataErr := mwacc.FindOneAccByFilter(nil, bson.M{mwacc.FN.MwAcc.Id: accid})
|
|
if dataErr != nil || accInfo.Id == 0 {
|
|
return int(errors.RoleErr), dataErr
|
|
}
|
|
|
|
return 0, nil
|
|
}
|
|
|
|
// 验证后台账号IP
|
|
func authMwIP(ctx *gin.Context) (int, error) {
|
|
|
|
cIP := ctx.ClientIP()
|
|
accid := ctx.GetInt64(AccId)
|
|
accInfo, dataErr := mwacc.FindOneAccByFilter(nil, bson.M{mwacc.FN.MwAcc.Id: accid})
|
|
if dataErr != nil || accInfo.Id == 0 {
|
|
return int(errors.RoleErr), dataErr
|
|
}
|
|
if len(accInfo.LimitIP) != 0 {
|
|
for _, v := range accInfo.LimitIP {
|
|
if v == cIP {
|
|
return 0, nil
|
|
}
|
|
}
|
|
return int(errors.LimitIPErr), dataErr
|
|
} else {
|
|
return int(errors.LimitIPErr), dataErr
|
|
}
|
|
|
|
// return 0, nil
|
|
}
|
|
|
|
// 验证
|
|
func Auth(ctx *gin.Context) {
|
|
//for test
|
|
//ctx.Set(AccId, int64(1000))
|
|
//return
|
|
p := ctx.Request.URL.Path
|
|
if strings.Contains(p, "swagger") {
|
|
return
|
|
}
|
|
for _, w := range whiteList {
|
|
if strings.HasPrefix(ctx.Request.URL.Path, w) {
|
|
return
|
|
}
|
|
}
|
|
if v, ok := common.ApiSetMaps[p]; ok {
|
|
fmt.Println(v.IsWhite)
|
|
if v.IsWhite {
|
|
return
|
|
}
|
|
}
|
|
|
|
doToken := func() (int, error) {
|
|
checkToken := ctx.Request.Header.Get("Authorization")
|
|
// 去掉Bearer,如果有
|
|
checkToken = utils.StripBearerPrefixFromTokenString(checkToken)
|
|
|
|
if checkToken == "" {
|
|
return http.StatusUnauthorized, srvdef.New(srvdef.NoToken, (srvdef.NoToken).Msg(), "")
|
|
}
|
|
|
|
has, err := mwacc.CheckToken(ctx, checkToken)
|
|
if err != nil {
|
|
return http.StatusUnauthorized, err
|
|
}
|
|
if !has {
|
|
return http.StatusUnauthorized, srvdef.New(srvdef.ReLogin, (srvdef.ReLogin).Msg(), "")
|
|
}
|
|
|
|
userId, _, err := utils.ParseUserToken(checkToken, webg.Conf.JwtKey)
|
|
if err != nil {
|
|
return http.StatusUnauthorized, srvdef.New(srvdef.InvalidToken, (srvdef.InvalidToken).Msg(), "")
|
|
}
|
|
// log.Info("Auth test", log.Any("checkToken", checkToken), log.Any("userId", userId))
|
|
ctx.Set(AccId, userId)
|
|
return 0, nil
|
|
}
|
|
|
|
statusCode, err := doToken()
|
|
if err != nil || statusCode != 0 {
|
|
ctx.AbortWithStatusJSON(statusCode, err)
|
|
return
|
|
}
|
|
|
|
roleCode, err := handleRoles(ctx)
|
|
if err != nil || roleCode != 0 {
|
|
ctx.AbortWithStatusJSON(http.StatusForbidden, err)
|
|
}
|
|
|
|
roleCode1, err1 := handleLouFengBossRoles(ctx)
|
|
if err1 != nil || roleCode1 != 0 {
|
|
ctx.AbortWithStatusJSON(http.StatusForbidden, err)
|
|
}
|
|
|
|
// authIPCode, err2 := authMwIP(ctx)
|
|
// if err2 != nil || authIPCode != 0 {
|
|
// ctx.AbortWithStatusJSON(http.StatusForbidden, err)
|
|
// }
|
|
}
|
|
|
|
// func userAgentHandler(ctx *gin.Context) {
|
|
// userAgent := ctx.Request.Header.Get("User-Agent")
|
|
// if userAgent != "" {
|
|
// fields := strings.Fields(userAgent)
|
|
// curVersion := fields[len(fields)-1]
|
|
// if strings.HasPrefix(curVersion, "version:") {
|
|
// versionNum := strings.Split(curVersion, ":")[1]
|
|
// ctx.Set("VERSION", versionNum)
|
|
// } else {
|
|
// ctx.Set("VERSION", "")
|
|
// }
|
|
// }
|
|
// if strings.Contains(userAgent, "Android") {
|
|
// ctx.Set("SYSTEM", "android")
|
|
// }
|
|
// if strings.Contains(userAgent, "iPhone") {
|
|
// ctx.Set("SYSTEM", "ios")
|
|
// }
|
|
|
|
// // 增加 不签名,不加密 开关
|
|
// }
|
|
|
|
// 操作日志
|
|
func OperateLog(ctx *gin.Context) {
|
|
desc := ""
|
|
find := false
|
|
for _, w := range LogList {
|
|
if ctx.Request.URL.Path == w.Api {
|
|
find = true
|
|
desc = w.Desc
|
|
}
|
|
}
|
|
if !find {
|
|
ctx.Next()
|
|
return
|
|
}
|
|
|
|
accId := ctx.GetInt64(AccId)
|
|
rawData, err := ctx.GetRawData()
|
|
ip := ctx.ClientIP()
|
|
if err != nil {
|
|
ctx.AbortWithStatusJSON(400, err)
|
|
}
|
|
|
|
log.Info("OperateLog Test", log.Any("vmap.Path", ctx.Request.URL.Path))
|
|
|
|
err = oplog.AddLog(ctx, ctx.Request.URL.Path, desc, accId, string(rawData), ip)
|
|
if err != nil {
|
|
ctx.AbortWithStatusJSON(int(errors.OperateLog), err)
|
|
return
|
|
}
|
|
|
|
ctx.Request.Body = ioutil.NopCloser(bytes.NewBuffer(rawData)) // 将取出来的执行条件放回ctx中
|
|
ctx.Next()
|
|
}
|
|
|
|
func GetAccount(ctx *gin.Context) int64 {
|
|
return ctx.GetInt64(AccId)
|
|
}
|