271 lines
8.1 KiB
Go
271 lines
8.1 KiB
Go
|
/*
|
|||
|
* @desc:中间件
|
|||
|
* @company:云南奇讯科技有限公司
|
|||
|
* @Author: yixiaohu<yxh669@qq.com>
|
|||
|
* @Date: 2022/9/23 15:05
|
|||
|
*/
|
|||
|
|
|||
|
package middleware
|
|||
|
|
|||
|
import (
|
|||
|
"fmt"
|
|||
|
"github.com/gogf/gf/v2/frame/g"
|
|||
|
"github.com/gogf/gf/v2/net/ghttp"
|
|||
|
"github.com/gogf/gf/v2/os/gctx"
|
|||
|
"github.com/gogf/gf/v2/text/gstr"
|
|||
|
"github.com/gogf/gf/v2/util/gconv"
|
|||
|
"github.com/tiger1103/gfast-token/gftoken"
|
|||
|
"github.com/tiger1103/gfast/v3/api/wxApplet/wxApplet"
|
|||
|
commonService "github.com/tiger1103/gfast/v3/internal/app/common/service"
|
|||
|
"github.com/tiger1103/gfast/v3/internal/app/system/dao"
|
|||
|
"github.com/tiger1103/gfast/v3/internal/app/system/model"
|
|||
|
"github.com/tiger1103/gfast/v3/internal/app/system/service"
|
|||
|
"github.com/tiger1103/gfast/v3/library/libResponse"
|
|||
|
"strings"
|
|||
|
)
|
|||
|
|
|||
|
func init() {
|
|||
|
service.RegisterMiddleware(New())
|
|||
|
}
|
|||
|
|
|||
|
func New() *sMiddleware {
|
|||
|
return &sMiddleware{}
|
|||
|
}
|
|||
|
|
|||
|
type sMiddleware struct{}
|
|||
|
|
|||
|
// Ctx 自定义上下文对象
|
|||
|
func (s *sMiddleware) Ctx(r *ghttp.Request) {
|
|||
|
ctx := r.GetCtx()
|
|||
|
// 初始化登录用户信息
|
|||
|
data, err := service.GfToken().ParseToken(r)
|
|||
|
if err != nil {
|
|||
|
// 执行下一步请求逻辑
|
|||
|
r.Middleware.Next()
|
|||
|
}
|
|||
|
if data != nil {
|
|||
|
context := new(model.Context)
|
|||
|
err = gconv.Struct(data.Data, &context.User)
|
|||
|
if err != nil {
|
|||
|
g.Log().Error(ctx, err)
|
|||
|
// 执行下一步请求逻辑
|
|||
|
r.Middleware.Next()
|
|||
|
}
|
|||
|
service.Context().Init(r, context)
|
|||
|
}
|
|||
|
// 执行下一步请求逻辑
|
|||
|
r.Middleware.Next()
|
|||
|
}
|
|||
|
|
|||
|
// Auth 权限判断处理中间件
|
|||
|
func (s *sMiddleware) Auth(r *ghttp.Request) {
|
|||
|
ctx := r.GetCtx()
|
|||
|
//获取登陆用户id
|
|||
|
adminId := service.Context().GetUserId(ctx)
|
|||
|
accessParams := r.Get("accessParams").Strings()
|
|||
|
accessParamsStr := ""
|
|||
|
if len(accessParams) > 0 && accessParams[0] != "undefined" {
|
|||
|
accessParamsStr = "?" + gstr.Join(accessParams, "&")
|
|||
|
}
|
|||
|
url := gstr.TrimLeft(r.Request.URL.Path, "/") + accessParamsStr
|
|||
|
/*if r.Method != "GET" && adminId != 1 && url!="api/v1/system/login" {
|
|||
|
libResponse.FailJson(true, r, "对不起!演示系统,不能删改数据!")
|
|||
|
}*/
|
|||
|
//获取无需验证权限的用户id
|
|||
|
tagSuperAdmin := false
|
|||
|
service.SysUser().NotCheckAuthAdminIds(ctx).Iterator(func(v interface{}) bool {
|
|||
|
if gconv.Uint64(v) == adminId {
|
|||
|
tagSuperAdmin = true
|
|||
|
return false
|
|||
|
}
|
|||
|
return true
|
|||
|
})
|
|||
|
if tagSuperAdmin {
|
|||
|
r.Middleware.Next()
|
|||
|
//不要再往后面执行
|
|||
|
return
|
|||
|
}
|
|||
|
//获取地址对应的菜单id
|
|||
|
menuList, err := service.SysAuthRule().GetMenuList(ctx)
|
|||
|
if err != nil {
|
|||
|
g.Log().Error(ctx, err)
|
|||
|
libResponse.FailJson(true, r, "请求数据失败")
|
|||
|
}
|
|||
|
var menu *model.SysAuthRuleInfoRes
|
|||
|
for _, m := range menuList {
|
|||
|
ms := gstr.SubStr(m.Name, 0, gstr.Pos(m.Name, "?"))
|
|||
|
if m.Name == url || ms == url {
|
|||
|
menu = m
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
//只验证存在数据库中的规则
|
|||
|
if menu != nil {
|
|||
|
//若是不登录能访问的接口则不判断权限
|
|||
|
excludePaths := g.Cfg().MustGet(ctx, "gfToken.excludePaths").Strings()
|
|||
|
for _, p := range excludePaths {
|
|||
|
if gstr.Equal(menu.Name, gstr.TrimLeft(p, "/")) {
|
|||
|
r.Middleware.Next()
|
|||
|
return
|
|||
|
}
|
|||
|
}
|
|||
|
//若存在不需要验证的条件则跳过
|
|||
|
if gstr.Equal(menu.Condition, "nocheck") {
|
|||
|
r.Middleware.Next()
|
|||
|
return
|
|||
|
}
|
|||
|
menuId := menu.Id
|
|||
|
//菜单没存数据库不验证权限
|
|||
|
if menuId != 0 {
|
|||
|
//判断权限操作
|
|||
|
enforcer, err := commonService.CasbinEnforcer(ctx)
|
|||
|
if err != nil {
|
|||
|
g.Log().Error(ctx, err)
|
|||
|
libResponse.FailJson(true, r, "获取权限失败")
|
|||
|
}
|
|||
|
hasAccess := false
|
|||
|
hasAccess, err = enforcer.Enforce(fmt.Sprintf("%s%d", service.SysUser().GetCasBinUserPrefix(), adminId), gconv.String(menuId), "All")
|
|||
|
if err != nil {
|
|||
|
g.Log().Error(ctx, err)
|
|||
|
libResponse.FailJson(true, r, "判断权限失败")
|
|||
|
}
|
|||
|
if !hasAccess {
|
|||
|
libResponse.FailJson(true, r, "没有访问权限")
|
|||
|
}
|
|||
|
}
|
|||
|
} else if menu == nil && accessParamsStr != "" {
|
|||
|
libResponse.FailJson(true, r, "没有访问权限")
|
|||
|
}
|
|||
|
r.Middleware.Next()
|
|||
|
}
|
|||
|
|
|||
|
// Blacklist 黑名单 阻挡小程序的黑名单用户登录
|
|||
|
func (s *sMiddleware) Blacklist(r *ghttp.Request) {
|
|||
|
ctx := gctx.New()
|
|||
|
//1、判断是否是小程序请求来的数据
|
|||
|
userAgent := strings.ToLower(r.Header.Get("User-Agent"))
|
|||
|
if strings.Contains(userAgent, "micromessenger") {
|
|||
|
//2、解析token 拿到openid
|
|||
|
var user *wxApplet.BusConstructionUserAddReq
|
|||
|
datatoken, err := service.GfToken().ParseToken(r)
|
|||
|
if err != nil {
|
|||
|
libResponse.FailJson(true, r, "解析token错误!")
|
|||
|
}
|
|||
|
if datatoken != nil {
|
|||
|
err = gconv.Struct(datatoken.Data, &user)
|
|||
|
if err != nil {
|
|||
|
libResponse.FailJson(true, r, "获取用户信息错误!")
|
|||
|
}
|
|||
|
}
|
|||
|
//3、查询数据库黑名单
|
|||
|
count, err := dao.BusConstructionBlacklist.Ctx(ctx).Where("openid", user.Openid).Count()
|
|||
|
if err != nil {
|
|||
|
libResponse.FailJson(true, r, "系统错误,请联系管理员!")
|
|||
|
}
|
|||
|
if count > 0 {
|
|||
|
gfToken := gftoken.NewGfToken()
|
|||
|
token := gfToken.GetRequestToken(r)
|
|||
|
service.GfToken().RemoveToken(ctx, token)
|
|||
|
libResponse.FailJson(true, r, "登录异常,请联系管理员!")
|
|||
|
} else {
|
|||
|
//4、匹配黑名单用户 随后放行
|
|||
|
r.Middleware.Next()
|
|||
|
}
|
|||
|
} else {
|
|||
|
r.Middleware.Next()
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
var engineeringData = "/zm/api/v1/system/documentData/newFolder," + //新建文件夹
|
|||
|
"/zm/api/v1/system/documentData/add," + //导入
|
|||
|
"/zm/api/v1/system/documentData/edit" + //重命名
|
|||
|
"/zm/api/v1/system/documentData/compressedDownload" + //下载
|
|||
|
"/zm/api/v1/system/documentData/get" + //查看
|
|||
|
"/zm/api/v1/system/documentData/complaintBoxAdd" + //保存
|
|||
|
"/zm/api/v1/system/documentData/delete" + //删除
|
|||
|
"/zm/api/v1/system/documentData/onlineImport" + //模板批量导入
|
|||
|
"/zm/api/v1/system/documentData/onlineMobile" + //资料在线移动
|
|||
|
"/zm/api/v1/system/documentData/dataFileQuery" + //所有资料查询
|
|||
|
"/zm/api/v1/system/document/templateRecycleBin" + //模板回收站
|
|||
|
"/zm/api/v1/system/documentData/dataRecyclingStation" + //资料回收站
|
|||
|
"/zm/api/v1/system/documentData/uniFileDownload" //下载
|
|||
|
|
|||
|
// EngineeringDataPermission 工程资料权限校验(资料-回收站)
|
|||
|
func (s *sMiddleware) EngineeringDataPermission(r *ghttp.Request) {
|
|||
|
ctx := r.GetCtx()
|
|||
|
userId := service.Context().GetUserId(ctx)
|
|||
|
//0、把admin用户给排除掉
|
|||
|
if userId == 1 {
|
|||
|
r.Middleware.Next()
|
|||
|
return
|
|||
|
}
|
|||
|
projectId := r.Get("projectId").String()
|
|||
|
//1、看看有哪些API需要调用权限
|
|||
|
path := r.Request.URL.Path
|
|||
|
authorityJudgment := strings.Split(engineeringData, ",")
|
|||
|
for _, pathApi := range authorityJudgment {
|
|||
|
//2、根据用户id去数据库查询工程资料的权限是否开启(1有权 2无权)
|
|||
|
if pathApi == path {
|
|||
|
if projectId == "" {
|
|||
|
libResponse.FailJson(true, r, "当前操作暂无项目id!")
|
|||
|
}
|
|||
|
sql := g.DB().Model("document_power").
|
|||
|
Where("sys_user_id", userId).
|
|||
|
Where("project_id", projectId)
|
|||
|
if strings.Contains(path, "/zm/api/v1/system/document/allList") || strings.Contains(path, "/zm/api/v1/system/documentData/allList") {
|
|||
|
sql = sql.Where("type = 3")
|
|||
|
} else if strings.Contains(path, "/zm/api/v1/system/documentData/") {
|
|||
|
sql = sql.Where("type = 2")
|
|||
|
} else {
|
|||
|
libResponse.FailJson(true, r, "系统错误,请联系管理员!")
|
|||
|
}
|
|||
|
//3、判断具体是什么权限
|
|||
|
fetch := fieldFetch(path, authorityJudgment)
|
|||
|
count, err := sql.Where(fetch, "1").Count()
|
|||
|
if err != nil {
|
|||
|
libResponse.FailJson(true, r, "系统错误,请联系管理员!")
|
|||
|
}
|
|||
|
if count > 0 {
|
|||
|
r.Middleware.Next()
|
|||
|
} else {
|
|||
|
libResponse.FailJson(true, r, "当前操作暂无权限!")
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
r.Middleware.Next()
|
|||
|
}
|
|||
|
|
|||
|
// fieldFetch 根据数据匹配 返回需要查询的字段
|
|||
|
func fieldFetch(path string, authorityJudgment []string) string {
|
|||
|
switch path {
|
|||
|
case authorityJudgment[0]:
|
|||
|
return "v1"
|
|||
|
case authorityJudgment[1]:
|
|||
|
return "v2"
|
|||
|
case authorityJudgment[2]:
|
|||
|
return "v3"
|
|||
|
case authorityJudgment[3]:
|
|||
|
return "v4"
|
|||
|
case authorityJudgment[4]:
|
|||
|
return "v5"
|
|||
|
case authorityJudgment[5]:
|
|||
|
return "v6"
|
|||
|
case authorityJudgment[6]:
|
|||
|
return "v7"
|
|||
|
case authorityJudgment[7]:
|
|||
|
return "v8"
|
|||
|
case authorityJudgment[8]:
|
|||
|
return "v9"
|
|||
|
case authorityJudgment[9]:
|
|||
|
return "v10"
|
|||
|
case authorityJudgment[10]:
|
|||
|
return "v11"
|
|||
|
case authorityJudgment[11]:
|
|||
|
return "v12"
|
|||
|
case authorityJudgment[12]:
|
|||
|
return "v4"
|
|||
|
default:
|
|||
|
return ""
|
|||
|
}
|
|||
|
}
|