@@ -0,0 +1,283 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"videoweb/pub/common"
|
||||
"videoweb/pub/common/errors"
|
||||
"videoweb/pub/common/ipaddr"
|
||||
"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/newenkey",
|
||||
"/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",
|
||||
"/wbapi",
|
||||
"/api/web/third/newpaycenter/recharge/callback",
|
||||
}
|
||||
)
|
||||
|
||||
// 读取角色信息
|
||||
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
|
||||
}
|
||||
|
||||
// 验证后台账号IP
|
||||
func authMwIP(ctx *gin.Context) (int, error) {
|
||||
|
||||
cIP := ipaddr.ResolveClientIP(ctx)
|
||||
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
|
||||
// 对指定 group 跳过
|
||||
if strings.HasPrefix(ctx.Request.URL.Path, "/mdps/mdcom/api/web") {
|
||||
ctx.Next()
|
||||
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)
|
||||
}
|
||||
|
||||
// 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 := ipaddr.ResolveClientIP(ctx)
|
||||
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)
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package auth
|
||||
|
||||
var LogList = []APIInfo{
|
||||
{"/api/web/acc/add", "账号-添加"},
|
||||
{"/api/web/acc/del", "账号-删除"},
|
||||
{"/api/web/acc/up", "账号-更新"},
|
||||
{"/api/web/acc/savestatus", "账号-保存状态"},
|
||||
{"/api/web/acc/uppwd", "账号-更新密码"},
|
||||
{"/api/web/login/acc", "登录-登录"},
|
||||
{"/api/web/login/slogin", "管理员sso登陆"},
|
||||
{"/api/web/role/add", "角色-添加"},
|
||||
{"/api/web/role/del", "角色-删除"},
|
||||
{"/api/web/role/up", "角色-更新"},
|
||||
{"/api/web/role/enable", "角色-使能"},
|
||||
{"/api/web/role/upauth", "角色-更新权限"},
|
||||
{"/api/web/syscfg/update", "修改系统配置"},
|
||||
{"/api/web/syscfg/appkey", "设置媒资库appKey"},
|
||||
{"/api/web/post/comment/del", "删除一个评论"},
|
||||
{"/api/web/post/comment/user/del", "删除一个用户所有评论"},
|
||||
{"/api/web/post/comment/replay", "回复评论"},
|
||||
{"/api/web/post/comment/reviewBatch", "批量审核评论"},
|
||||
{"/api/web/post/comment/review", "审核评论"},
|
||||
{"/api/web/ipblack/add", "IP黑名单-增加"},
|
||||
{"/api/web/ipblack/del", "IP黑名单-删除"},
|
||||
{"/api/web/announcement/add", "公告-增加"},
|
||||
{"/api/web/announcement/del", "公告-删除"},
|
||||
{"/api/web/announcement/update", "公告-更新"},
|
||||
{"/api/web/richtextcontent/add", "添加一个富文本内容"},
|
||||
{"/api/web/richtextcontent/del", "删除一个富文本内容"},
|
||||
{"/api/web/richtextcontent/update", "更新一个富文本内容"},
|
||||
{"/api/web/translationcategory/add", "添加一个导航分类"},
|
||||
{"/api/web/translationcategory/del", "删除一个导航分类"},
|
||||
{"/api/web/translationcategory/update", "更新一个导航分类"},
|
||||
{"/api/web/translation/add", "添加一个导航跳转信息"},
|
||||
{"/api/web/translation/del", "删除一个导航跳转信息"},
|
||||
{"/api/web/translation/update", "更新一个导航跳转信息"},
|
||||
{"/api/web/videocategory/add", "添加一个视频分类"},
|
||||
{"/api/web/videocategory/del", "删除一个视频分类"},
|
||||
{"/api/web/videocategory/update", "更新一个视频分类"},
|
||||
{"/api/web/videocreater/add", "添加一个视频作者"},
|
||||
{"/api/web/videocreater/del", "删除一个视频作者"},
|
||||
{"/api/web/videocreater/update", "更新一个视频作者"},
|
||||
{"/api/web/videotag/add", "添加一个标签管理"},
|
||||
{"/api/web/videotag/del", "删除一个标签管理"},
|
||||
{"/api/web/videotag/update", "更新一个标签管理"},
|
||||
{"/api/web/videoinfo/del", "删除一个视频管理"},
|
||||
{"/api/web/videoinfo/update", "更新一个视频管理"},
|
||||
{"/api/web/videoinfo/setFakeWatchTimes", "设置视频假观看次数"},
|
||||
{"/api/web/videoinfo/category/set", "视频-设置分类"},
|
||||
{"/api/web/videocollection/media/option", "修改合集里的视频列表"},
|
||||
{"/api/web/videocollection/media/rank", "修改合集里的视频排序"},
|
||||
{"/api/web/videoinfo/addcoll", "新增一个视频合集"},
|
||||
{"/api/web/actress/add", "添加一个女优信息"},
|
||||
{"/api/web/actress/del", "删除一个女优信息"},
|
||||
{"/api/web/actress/update", "更新一个女优信息"},
|
||||
{"/api/web/user/updatetype", "修改用户类型"},
|
||||
{"/api/web/user/giftcoin", "赠送/扣除用户金币"},
|
||||
{"/api/web/coin/recharge/add", "新增金币充值配置"},
|
||||
{"/api/web/coin/recharge/del", "删除金币充值配置"},
|
||||
{"/api/web/coin/recharge/update", "更新金币充值配置"},
|
||||
{"/api/web/merchant/list", "手动拉取商家列表"},
|
||||
{"/api/web/merchant/detail", "手动拉取商家详情"},
|
||||
{"/api/web/feedback/handle", "处理用户意见反馈"},
|
||||
{"/api/web/contactus/handle", "处理联系我们"},
|
||||
{"/api/web/home/banner/add", "首页banner-新增"},
|
||||
{"/api/web/home/banner/update", "首页banner-更新"},
|
||||
{"/api/web/home/banner/del", "首页banner-删除"},
|
||||
{"/api/web/home/config/add", "首页配置-新增"},
|
||||
{"/api/web/home/config/update", "首页配置-更新"},
|
||||
{"/api/web/home/config/del", "首页配置-删除"},
|
||||
// 短剧
|
||||
{"/api/web/playlet/add", "短剧-新增"},
|
||||
{"/api/web/playlet/update", "短剧-更新"},
|
||||
{"/api/web/playlet/status/set", "短剧-设置上下架"},
|
||||
{"/api/web/playlet/recommend/set", "短剧-设置推荐"},
|
||||
{"/api/web/playlet/featured/set", "短剧-设置爆剧"},
|
||||
{"/api/web/playlet/operate-type/set", "短剧-设置运营类型"},
|
||||
{"/api/web/playlet/banner/set", "短剧-设置banner展示"},
|
||||
{"/api/web/playlet/theme/set", "短剧-设置题材"},
|
||||
{"/api/web/playlet/theme/recommend/set", "短剧题材-设置推荐"},
|
||||
{"/api/web/playlet/tag/set", "短剧-设置标签"},
|
||||
{"/api/web/playlet/category/set", "短剧-设置分类"},
|
||||
{"/api/web/playlet/pay-type/set", "短剧-设置支付方式"},
|
||||
{"/api/web/playlet/watermark/reset", "短剧-重置水印"},
|
||||
{"/api/web/playlet/slug/sync", "短剧-同步历史slug"},
|
||||
{"/api/web/videoinfo/slug/sync", "视频-同步历史slug"},
|
||||
{"/api/web/playlet/chapter/add", "短剧剧集-新增"},
|
||||
{"/api/web/playlet/chapter/update", "短剧剧集-更新"},
|
||||
{"/api/web/playlet/chapter/del", "短剧剧集-删除"},
|
||||
{"/api/web/playlet/chapter/status/fill", "短剧剧集-回填上架状态"},
|
||||
{"/api/web/playlet/chapter/status/set", "短剧剧集-设置上架状态"},
|
||||
{"/api/web/playlet/chapter/pay-type/set", "短剧剧集-设置支付方式"},
|
||||
{"/api/web/playlet/chapter/sync", "短剧剧集-手动同步"},
|
||||
{"/api/web/playlet/theme/add", "短剧题材-新增"},
|
||||
{"/api/web/playlet/theme/update", "短剧题材-更新"},
|
||||
{"/api/web/playlet/theme/del", "短剧题材-删除"},
|
||||
{"/api/web/playlet/tag/add", "短剧标签-新增"},
|
||||
{"/api/web/playlet/tag/update", "短剧标签-更新"},
|
||||
{"/api/web/playlet/tag/del", "短剧标签-删除"},
|
||||
{"/api/web/resource/import", "短剧媒资-入库"},
|
||||
{"/api/web/card/order/district/sync", "充值订单-同步历史渠道码"},
|
||||
}
|
||||
Reference in New Issue
Block a user