init: web_hgcg_server 初始化提交

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-10-27 16:44:55 +08:00
co-authored by Claude Opus 4.7
commit 189556e702
627 changed files with 126228 additions and 0 deletions
+283
View File
@@ -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)
}
+85
View File
@@ -0,0 +1,85 @@
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/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/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", "充值订单-同步历史渠道码"},
}