This commit is contained in:
2025-07-07 20:11:59 +08:00
parent ab0fdbc447
commit 06e3aa2eb3
2009 changed files with 193082 additions and 0 deletions

View File

@ -0,0 +1,996 @@
/*
* @desc:用户处理
* @company:云南奇讯科技有限公司
* @Author: yixiaohu<yxh669@qq.com>
* @Date: 2022/9/23 15:08
*/
package sysUser
import (
"context"
"fmt"
"reflect"
"github.com/gogf/gf/v2/container/gset"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/grand"
"github.com/mssola/user_agent"
"github.com/samber/lo"
"github.com/tiger1103/gfast/v3/api/v1/system"
commonService "github.com/tiger1103/gfast/v3/internal/app/common/service"
"github.com/tiger1103/gfast/v3/internal/app/system/consts"
"github.com/tiger1103/gfast/v3/internal/app/system/dao"
ct "github.com/tiger1103/gfast/v3/internal/app/system/logic/context"
"github.com/tiger1103/gfast/v3/internal/app/system/model"
"github.com/tiger1103/gfast/v3/internal/app/system/model/do"
"github.com/tiger1103/gfast/v3/internal/app/system/model/entity"
"github.com/tiger1103/gfast/v3/internal/app/system/service"
wxDao "github.com/tiger1103/gfast/v3/internal/app/wxApplet/dao"
logic "github.com/tiger1103/gfast/v3/internal/app/wxApplet/logic/busConstructionUser"
wxModel "github.com/tiger1103/gfast/v3/internal/app/wxApplet/model/do"
"github.com/tiger1103/gfast/v3/library/libUtils"
"github.com/tiger1103/gfast/v3/library/liberr"
)
func init() {
service.RegisterSysUser(New())
}
type sSysUser struct {
casBinUserPrefix string // CasBin 用户id前缀
}
func New() *sSysUser {
return &sSysUser{
casBinUserPrefix: "u_",
}
}
func (s *sSysUser) GetCasBinUserPrefix() string {
return s.casBinUserPrefix
}
func (s *sSysUser) NotCheckAuthAdminIds(ctx context.Context) *gset.Set {
ids := g.Cfg().MustGet(ctx, "system.notCheckAuthAdminIds")
if !g.IsNil(ids) {
return gset.NewFrom(ids)
}
return gset.New()
}
func (s *sSysUser) GetAdminUserByUsernamePassword(ctx context.Context, req *system.UserLoginReq) (user *model.LoginUserRes, err error) {
err = g.Try(ctx, func(ctx context.Context) {
user, err = s.GetUserByUsername(ctx, req.Username)
liberr.ErrIsNil(ctx, err)
liberr.ValueIsNil(user, "账号密码错误")
// 验证密码
if libUtils.EncryptPassword(req.Password, user.UserSalt) != user.UserPassword {
liberr.ErrIsNil(ctx, gerror.New("账号密码错误"))
}
// 账号状态
if user.UserStatus == 0 {
liberr.ErrIsNil(ctx, gerror.New("账号已被冻结"))
}
})
return
}
// GetUserByUsername 通过用户名获取用户信息
func (s *sSysUser) GetUserByUsername(ctx context.Context, userName string) (user *model.LoginUserRes, err error) {
err = g.Try(ctx, func(ctx context.Context) {
user = &model.LoginUserRes{}
query := g.Map{dao.SysUser.Columns().UserName: userName}
mobile, ok := ctx.Value("mobile").(string)
if ok {
query = g.Map{dao.SysUser.Columns().Mobile: mobile}
}
exist, err := dao.SysUser.Ctx(ctx).Where(query).Count()
liberr.ErrIsNil(ctx, err)
if exist == 0 {
liberr.ErrIsNil(ctx, gerror.New("账号或手机号不存在"))
}
err = dao.SysUser.Ctx(ctx).Fields(user).Where(query).Scan(user)
liberr.ErrIsNil(ctx, err, "账号密码错误")
})
return
}
// GetUserById 通过用户名获取用户信息
func (s *sSysUser) GetUserById(ctx context.Context, id uint64) (user *model.LoginUserRes, err error) {
err = g.Try(ctx, func(ctx context.Context) {
user = &model.LoginUserRes{}
err = dao.SysUser.Ctx(ctx).Fields(user).WherePri(id).Scan(user)
liberr.ErrIsNil(ctx, err, "获取用户信息失败")
})
return
}
// LoginLog 记录登录日志
func (s *sSysUser) LoginLog(ctx context.Context, params *model.LoginLogParams) {
ua := user_agent.New(params.UserAgent)
browser, _ := ua.Browser()
loginData := &do.SysLoginLog{
LoginName: params.Username,
Ipaddr: params.Ip,
LoginLocation: libUtils.GetCityByIp(params.Ip),
Browser: browser,
Os: ua.OS(),
Status: params.Status,
Msg: params.Msg,
LoginTime: gtime.Now(),
Module: params.Module,
}
_, err := dao.SysLoginLog.Ctx(ctx).Insert(loginData)
if err != nil {
g.Log().Error(ctx, err)
}
}
func (s *sSysUser) UpdateLoginInfo(ctx context.Context, id uint64, ip string) (err error) {
err = g.Try(ctx, func(ctx context.Context) {
_, err = dao.SysUser.Ctx(ctx).WherePri(id).Unscoped().Update(g.Map{
dao.SysUser.Columns().LastLoginIp: ip,
dao.SysUser.Columns().LastLoginTime: gtime.Now(),
})
liberr.ErrIsNil(ctx, err, "更新用户登录信息失败")
})
return
}
// GetAdminRules 获取用户菜单数据
func (s *sSysUser) GetAdminRules(ctx context.Context, userId uint64) (menuList []*model.UserMenus, permissions []string, err error) {
err = g.Try(ctx, func(ctx context.Context) {
// 是否超管
isSuperAdmin := false
// 获取无需验证权限的用户id
s.NotCheckAuthAdminIds(ctx).Iterator(func(v interface{}) bool {
if gconv.Uint64(v) == userId {
isSuperAdmin = true
return false
}
return true
})
// 获取用户菜单数据
allRoles, err := service.SysRole().GetRoleList(ctx)
liberr.ErrIsNil(ctx, err)
// 如果是来自 App 的登录请求
if isApp := ctx.Value("is_app"); isApp != nil {
// 将 allRoles 中 is_App 不等于 1 的数据过滤掉
allRoles = lo.Filter(allRoles, func(role *entity.SysRole, _ int) bool {
return role.IsApp == 1
})
}
roles, err := s.GetAdminRole(ctx, userId, allRoles)
liberr.ErrIsNil(ctx, err)
name := make([]string, len(roles))
roleIds := make([]uint, len(roles))
for k, v := range roles {
name[k] = v.Name
roleIds[k] = v.Id
}
// 获取菜单信息
if isSuperAdmin {
// 超管获取所有菜单
permissions = []string{"*/*/*"}
menuList, err = s.GetAllMenus(ctx)
liberr.ErrIsNil(ctx, err)
} else {
menuList, err = s.GetAdminMenusByRoleIds(ctx, roleIds)
liberr.ErrIsNil(ctx, err)
permissions, err = s.GetPermissions(ctx, roleIds)
liberr.ErrIsNil(ctx, err)
}
})
return
}
// GetAdminRole 获取用户角色
func (s *sSysUser) GetAdminRole(ctx context.Context, userId uint64, allRoleList []*entity.SysRole) (roles []*entity.SysRole, err error) {
var roleIds []uint
roleIds, err = s.GetAdminRoleIds(ctx, userId)
if err != nil {
return
}
roles = make([]*entity.SysRole, 0, len(allRoleList))
for _, v := range allRoleList {
for _, id := range roleIds {
if id == v.Id {
roles = append(roles, v)
}
}
if len(roles) == len(roleIds) {
break
}
}
return
}
// GetAdminRoleIds 获取用户角色ids
func (s *sSysUser) GetAdminRoleIds(ctx context.Context, userId uint64) (roleIds []uint, err error) {
enforcer, e := commonService.CasbinEnforcer(ctx)
if e != nil {
err = e
return
}
// 查询关联角色规则
groupPolicy := enforcer.GetFilteredGroupingPolicy(0, fmt.Sprintf("%s%d", s.casBinUserPrefix, userId))
if len(groupPolicy) > 0 {
roleIds = make([]uint, len(groupPolicy))
// 得到角色id的切片
for k, v := range groupPolicy {
roleIds[k] = gconv.Uint(v[1])
}
}
return
}
func (s *sSysUser) GetAllMenus(ctx context.Context) (menus []*model.UserMenus, err error) {
// 获取所有开启的菜单
var allMenus []*model.SysAuthRuleInfoRes
allMenus, err = service.SysAuthRule().GetIsMenuList(ctx)
if err != nil {
return
}
menus = make([]*model.UserMenus, len(allMenus))
for k, v := range allMenus {
var menu *model.UserMenu
menu = s.setMenuData(menu, v)
menus[k] = &model.UserMenus{UserMenu: menu}
}
menus = s.GetMenusTree(menus, 0)
return
}
func (s *sSysUser) GetAdminMenusByRoleIds(ctx context.Context, roleIds []uint) (menus []*model.UserMenus, err error) {
// 获取角色对应的菜单id
err = g.Try(ctx, func(ctx context.Context) {
enforcer, e := commonService.CasbinEnforcer(ctx)
liberr.ErrIsNil(ctx, e)
menuIds := map[int64]int64{}
for _, roleId := range roleIds {
// 查询当前权限
gp := enforcer.GetFilteredPolicy(0, gconv.String(roleId))
for _, p := range gp {
mid := gconv.Int64(p[1])
menuIds[mid] = mid
}
}
// 获取所有开启的菜单
allMenus, err := service.SysAuthRule().GetIsMenuList(ctx)
liberr.ErrIsNil(ctx, err)
menus = make([]*model.UserMenus, 0, len(allMenus))
for _, v := range allMenus {
if _, ok := menuIds[gconv.Int64(v.Id)]; gstr.Equal(v.Condition, "nocheck") || ok {
var roleMenu *model.UserMenu
roleMenu = s.setMenuData(roleMenu, v)
menus = append(menus, &model.UserMenus{UserMenu: roleMenu})
}
}
menus = s.GetMenusTree(menus, 0)
})
return
}
func (s *sSysUser) GetMenusTree(menus []*model.UserMenus, pid uint) []*model.UserMenus {
returnList := make([]*model.UserMenus, 0, len(menus))
for _, menu := range menus {
if menu.Pid == pid {
menu.Children = s.GetMenusTree(menus, menu.Id)
returnList = append(returnList, menu)
}
}
return returnList
}
func (s *sSysUser) setMenuData(menu *model.UserMenu, entity *model.SysAuthRuleInfoRes) *model.UserMenu {
menu = &model.UserMenu{
Id: entity.Id,
Pid: entity.Pid,
Name: gstr.CaseCamelLower(gstr.Replace(entity.Name, "/", "_")),
Component: entity.Component,
Path: entity.Path,
MenuMeta: &model.MenuMeta{
Icon: entity.Icon,
Title: entity.Title,
IsLink: "",
IsHide: entity.IsHide == 1,
IsKeepAlive: entity.IsCached == 1,
IsAffix: entity.IsAffix == 1,
IsIframe: entity.IsIframe == 1,
},
}
if menu.MenuMeta.IsIframe || entity.IsLink == 1 {
menu.MenuMeta.IsLink = entity.LinkUrl
}
return menu
}
func (s *sSysUser) GetPermissions(ctx context.Context, roleIds []uint) (userButtons []string, err error) {
err = g.Try(ctx, func(ctx context.Context) {
// 获取角色对应的菜单id
enforcer, err := commonService.CasbinEnforcer(ctx)
liberr.ErrIsNil(ctx, err)
menuIds := map[int64]int64{}
for _, roleId := range roleIds {
// 查询当前权限
gp := enforcer.GetFilteredPolicy(0, gconv.String(roleId))
for _, p := range gp {
mid := gconv.Int64(p[1])
menuIds[mid] = mid
}
}
// 获取所有开启的按钮
allButtons, err := service.SysAuthRule().GetIsButtonList(ctx)
liberr.ErrIsNil(ctx, err)
userButtons = make([]string, 0, len(allButtons))
for _, button := range allButtons {
if _, ok := menuIds[gconv.Int64(button.Id)]; gstr.Equal(button.Condition, "nocheck") || ok {
userButtons = append(userButtons, button.Name)
}
}
})
return
}
func fieldsEx() []string {
s := dao.SysUser.Columns()
return []string{
s.Id,
s.UserName,
s.Mobile,
s.UserNickname,
s.Birthday,
s.UserStatus,
s.UserEmail,
s.Sex,
s.Avatar,
s.DeptId,
s.Remark,
s.IsAdmin,
s.Address,
s.Describe,
s.LastLoginIp,
s.LastLoginTime,
s.CreatedAt,
s.UpdatedAt,
s.DeletedAt,
}
}
func inSlice(field string, excludes []string) bool {
for _, exclude := range excludes {
if exclude == field {
return true
}
}
return false
}
// List 用户列表
func (s *sSysUser) List(ctx context.Context, req *system.UserSearchReq) (total interface{}, userList []*entity.SysUser, err error) {
err = g.Try(ctx, func(ctx context.Context) {
m := dao.SysUser.Ctx(ctx)
if req.KeyWords != "" {
keyWords := "%" + req.KeyWords + "%"
m = m.Where("user_name like ? or user_nickname like ?", keyWords, keyWords)
}
if req.DeptId != "" {
deptIds, e := s.getSearchDeptIds(ctx, gconv.Uint64(req.DeptId))
liberr.ErrIsNil(ctx, e)
m = m.Where("dept_id in (?)", deptIds)
}
if req.Status != "" {
m = m.Where("user_status", gconv.Int(req.Status))
}
if req.Mobile != "" {
m = m.Where("mobile like ?", "%"+req.Mobile+"%")
}
if len(req.DateRange) > 0 {
m = m.Where("created_at >=? AND created_at <=?", req.DateRange[0], req.DateRange[1])
}
if req.RoleId > 0 {
m = m.As("a").LeftJoin("casbin_rule", "b", "b.v0 = CONCAT('u_',a.id )")
m = m.Where("v1 = ? and SUBSTR(v0,1,2) = 'u_'", req.RoleId)
}
if req.PageSize == 0 {
req.PageSize = consts.PageSize
}
if req.PageNum == 0 {
req.PageNum = 1
}
total, err = m.Count()
liberr.ErrIsNil(ctx, err, "获取用户数据失败")
// 排除password字段
if req.RoleId > 0 {
m = m.Fields(fieldsEx())
} else {
m = m.FieldsEx(dao.SysUser.Columns().UserPassword, dao.SysUser.Columns().UserSalt)
}
err = m.Page(req.PageNum, req.PageSize).Order("id asc").Scan(&userList)
liberr.ErrIsNil(ctx, err, "获取用户列表失败")
})
return
}
// GetUsersRoleDept 获取多个用户角色 部门信息
func (s *sSysUser) GetUsersRoleDept(ctx context.Context, userList []*entity.SysUser) (users []*model.SysUserRoleDeptRes, err error) {
err = g.Try(ctx, func(ctx context.Context) {
allRoles, e := service.SysRole().GetRoleList(ctx)
liberr.ErrIsNil(ctx, e)
depts, e := service.SysDept().GetFromCache(ctx)
liberr.ErrIsNil(ctx, e)
users = make([]*model.SysUserRoleDeptRes, len(userList))
for k, u := range userList {
var dept *entity.SysDept
users[k] = &model.SysUserRoleDeptRes{
SysUser: u,
}
for _, d := range depts {
if u.DeptId == uint64(d.DeptId) {
dept = d
}
}
users[k].Dept = dept
roles, e := s.GetAdminRole(ctx, u.Id, allRoles)
liberr.ErrIsNil(ctx, e)
for _, r := range roles {
users[k].RoleInfo = append(users[k].RoleInfo, &model.SysUserRoleInfoRes{RoleId: r.Id, Name: r.Name})
}
}
})
return
}
func (s *sSysUser) getSearchDeptIds(ctx context.Context, deptId uint64) (deptIds []uint64, err error) {
err = g.Try(ctx, func(ctx context.Context) {
deptAll, e := service.SysDept().GetFromCache(ctx)
liberr.ErrIsNil(ctx, e)
deptWithChildren := service.SysDept().FindSonByParentId(deptAll, deptId)
deptIds = make([]uint64, len(deptWithChildren))
for k, v := range deptWithChildren {
deptIds[k] = v.DeptId
}
deptIds = append(deptIds, deptId)
})
return
}
func (s *sSysUser) Add(ctx context.Context, req *system.UserAddReq) (err error) {
err = s.UserNameOrMobileExists(ctx, req.UserName, req.Mobile)
if err != nil {
return
}
req.UserSalt = grand.S(10)
req.Password = libUtils.EncryptPassword(req.Password, req.UserSalt)
err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
err = g.Try(ctx, func(ctx context.Context) {
// 1、新增用户信息
userId, e := dao.SysUser.Ctx(ctx).TX(tx).InsertAndGetId(do.SysUser{
UserName: req.UserName,
Mobile: req.Mobile,
UserNickname: req.NickName,
UserPassword: req.Password,
UserSalt: req.UserSalt,
UserStatus: req.Status,
UserEmail: req.Email,
Sex: req.Sex,
DeptId: req.DeptId,
Remark: req.Remark,
IsAdmin: req.IsAdmin,
IsData: req.IsData,
})
liberr.ErrIsNil(ctx, e, "添加用户失败")
e = s.addUserRole(ctx, req.RoleIds, userId)
liberr.ErrIsNil(ctx, e, "设置用户权限失败")
e = s.AddUserPost(ctx, tx, req.PostIds, userId)
liberr.ErrIsNil(ctx, e)
// 2、项目和用户进行关联
projectList := req.Project
name := ct.New().GetLoginUser(ctx).Id
for _, data := range projectList {
relevancy := wxModel.SysUserProjectRelevancy{
UserId: userId,
ProjectId: data,
CreateBy: name,
}
_, e = wxDao.SysUserProjectRelevancy.Ctx(ctx).Insert(relevancy)
liberr.ErrIsNil(ctx, e, "添加用户失败")
}
// 3、当前用户+项目id 得到对应权限进行保存
if len(req.Project) > 0 {
power := req.Power
for i := range power {
power[i].SysUserId = userId
}
_, err = g.DB().Model("document_power").Ctx(ctx).Insert(power)
if err != nil {
liberr.ErrIsNil(ctx, err, "添加用户失败")
}
}
liberr.ErrIsNil(ctx, err, "添加用户失败")
// 为该用户添加公司管理员的菜单角色
_, err = dao.AppUserRoles.Ctx(ctx).Insert(do.AppUserRoles{
UserId: userId,
RoleId: 8, // 公司管理员
MajorRole: 0, // 后台管理人员
})
liberr.ErrIsNil(ctx, err, "为用户添加公司管理员角色失败")
// 在微信小程序中添加用户
phone := req.Mobile
// 如果该用户已在小程序中存在,则不再添加
userExist, err := dao.BusConstructionUser.Ctx(ctx).Where(dao.BusConstructionUser.Columns().Phone, phone).Count()
liberr.ErrIsNil(ctx, err, "查询用户信息失败")
if userExist != 0 {
return
}
openID, err := libUtils.GetFakeOpenID()
liberr.ErrIsNil(ctx, err, "生成 OpenID 失败")
// 将用户信息插入到小程序的表中
busUserId, err := dao.BusConstructionUser.Ctx(ctx).TX(tx).Where(dao.BusConstructionUser.Columns().Phone, phone).
Data(do.BusConstructionUser{
Openid: openID, // OpenID
Phone: phone, // 手机号
ProjectRecord: 2,
WxOrPc: 3,
Subscription: 2,
}).InsertAndGetId()
liberr.ErrIsNil(ctx, err, "新增小程序用户失败")
err = logic.InitializationDataFunc(ctx, busUserId) // 为用户初始化实名数据
liberr.ErrIsNil(ctx, err, "为用户初始化身份证数据失败")
})
return err
})
return
}
func (s *sSysUser) Edit(ctx context.Context, req *system.UserEditReq) (err error) {
// err = s.UserNameOrMobileExists(ctx, "", req.Mobile, req.UserId)
// if err != nil {
// return
// }
err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
err = g.Try(ctx, func(ctx context.Context) {
_, err := dao.SysUser.Ctx(ctx).TX(tx).WherePri(req.UserId).Update(do.SysUser{
Mobile: req.Mobile,
UserNickname: req.NickName,
UserStatus: req.Status,
UserEmail: req.Email,
Sex: req.Sex,
DeptId: req.DeptId,
Remark: req.Remark,
IsAdmin: req.IsAdmin,
IsData: req.IsData,
})
liberr.ErrIsNil(ctx, err, "修改用户信息失败")
// 设置用户所属角色信息
err = s.EditUserRole(ctx, req.RoleIds, req.UserId)
liberr.ErrIsNil(ctx, err, "设置用户权限失败")
err = s.AddUserPost(ctx, tx, req.PostIds, req.UserId)
liberr.ErrIsNil(ctx, err)
// 2、项目和用户进行关联
// 删除数据
// if len(req.Project) > 0 {
_, err = wxDao.SysUserProjectRelevancy.Ctx(ctx).Where("user_id", req.UserId).Unscoped().Delete()
projectList := req.Project
name := ct.New().GetLoginUser(ctx).Id
for _, data := range projectList {
relevancy := wxModel.SysUserProjectRelevancy{
UserId: req.UserId,
ProjectId: data,
CreateBy: name,
}
_, err = wxDao.SysUserProjectRelevancy.Ctx(ctx).Insert(relevancy)
liberr.ErrIsNil(ctx, err, "修改用户信息失败")
}
//}
//3、当前用户+项目id 得到对应权限进行保存(修改的话,先删除再插入)
if len(req.Project) > 0 && len(req.Power) > 0 {
power := req.Power
// userId, _ := userEntity.LastInsertId()
_, err = g.DB().Model("document_power").Unscoped().Where("sys_user_id", power[0].SysUserId).Delete()
if err != nil {
liberr.ErrIsNil(ctx, err, "修改用户信息失败")
return
}
//for i := range power {
// power[i].SysUserId = userId
//}
_, err = g.DB().Model("document_power").Ctx(ctx).Insert(power)
if err != nil {
liberr.ErrIsNil(ctx, err, "修改用户信息失败")
}
}
})
return err
})
return
}
// AddUserPost 添加用户岗位信息
func (s *sSysUser) AddUserPost(ctx context.Context, tx gdb.TX, postIds []int64, userId int64) (err error) {
err = g.Try(ctx, func(ctx context.Context) {
// 删除旧岗位信息
_, err = dao.SysUserPost.Ctx(ctx).TX(tx).Where(dao.SysUserPost.Columns().UserId, userId).Delete()
liberr.ErrIsNil(ctx, err, "设置用户岗位失败")
if len(postIds) == 0 {
return
}
// 添加用户岗位信息
data := g.List{}
for _, v := range postIds {
data = append(data, g.Map{
dao.SysUserPost.Columns().UserId: userId,
dao.SysUserPost.Columns().PostId: v,
})
}
_, err = dao.SysUserPost.Ctx(ctx).TX(tx).Data(data).Insert()
liberr.ErrIsNil(ctx, err, "设置用户岗位失败")
})
return
}
// AddUserRole 添加用户角色信息
func (s *sSysUser) addUserRole(ctx context.Context, roleIds []int64, userId int64) (err error) {
err = g.Try(ctx, func(ctx context.Context) {
enforcer, e := commonService.CasbinEnforcer(ctx)
liberr.ErrIsNil(ctx, e)
for _, v := range roleIds {
_, e = enforcer.AddGroupingPolicy(fmt.Sprintf("%s%d", s.casBinUserPrefix, userId), gconv.String(v))
liberr.ErrIsNil(ctx, e)
}
})
return
}
// AddUserRole 添加用户角色信息
func (s *sSysUser) AddUserRole(ctx context.Context, roleIds []int64, userId int64) (err error) {
err = g.Try(ctx, func(ctx context.Context) {
enforcer, e := commonService.CasbinEnforcer(ctx)
liberr.ErrIsNil(ctx, e)
for _, v := range roleIds {
_, e = enforcer.AddGroupingPolicy(fmt.Sprintf("%s%d", s.casBinUserPrefix, userId), gconv.String(v))
liberr.ErrIsNil(ctx, e)
}
})
return
}
// EditUserRole 修改用户角色信息
func (s *sSysUser) EditUserRole(ctx context.Context, roleIds []int64, userId int64) (err error) {
err = g.Try(ctx, func(ctx context.Context) {
enforcer, e := commonService.CasbinEnforcer(ctx)
liberr.ErrIsNil(ctx, e)
// 删除用户旧角色信息
enforcer.RemoveFilteredGroupingPolicy(0, fmt.Sprintf("%s%d", s.casBinUserPrefix, userId))
for _, v := range roleIds {
_, err = enforcer.AddGroupingPolicy(fmt.Sprintf("%s%d", s.casBinUserPrefix, userId), gconv.String(v))
liberr.ErrIsNil(ctx, err)
}
})
return
}
func (s *sSysUser) UserNameOrMobileExists(ctx context.Context, userName, mobile string, id ...int64) error {
user := (*entity.SysUser)(nil)
err := g.Try(ctx, func(ctx context.Context) {
m := dao.SysUser.Ctx(ctx)
if len(id) > 0 {
m = m.Where(dao.SysUser.Columns().Id+" != ", id)
}
m = m.Where(fmt.Sprintf("%s='%s' OR %s='%s'",
dao.SysUser.Columns().UserName,
userName,
dao.SysUser.Columns().Mobile,
mobile))
err := m.Limit(1).Scan(&user)
liberr.ErrIsNil(ctx, err, "获取用户信息失败")
if user == nil {
return
}
if user.UserName == userName {
liberr.ErrIsNil(ctx, gerror.New("用户名已存在"))
}
if user.Mobile == mobile {
liberr.ErrIsNil(ctx, gerror.New("手机号已存在"))
}
})
return err
}
func (s *sSysUser) UserNameOrMobileData(ctx context.Context, userName, mobile string) (user *entity.SysUser, err error) {
user = new(entity.SysUser)
err = g.Try(ctx, func(ctx context.Context) {
m := dao.SysUser.Ctx(ctx)
m = m.Where(fmt.Sprintf("%s='%s' OR %s='%s'",
dao.SysUser.Columns().UserName,
userName,
dao.SysUser.Columns().Mobile,
mobile))
err := m.Limit(1).Scan(&user)
liberr.ErrIsNil(ctx, err, "获取用户信息失败")
})
return
}
// GetEditUser 获取编辑用户信息
func (s *sSysUser) GetEditUser(ctx context.Context, id uint64) (res *system.UserGetEditRes, err error) {
res = new(system.UserGetEditRes)
err = g.Try(ctx, func(ctx context.Context) {
// 获取用户信息
res.User, err = s.GetUserInfoById(ctx, id)
liberr.ErrIsNil(ctx, err)
// 获取已选择的角色信息
res.CheckedRoleIds, err = s.GetAdminRoleIds(ctx, id)
liberr.ErrIsNil(ctx, err)
res.CheckedPosts, err = s.GetUserPostIds(ctx, id)
liberr.ErrIsNil(ctx, err)
// 获取用户关联到的项目
var wxDataInfo []wxModel.SysUserProjectRelevancy
err := wxDao.SysUserProjectRelevancy.Ctx(ctx).As("a").
LeftJoin("sys_project as b on a.project_id = b.id").
Fields("a.*,b.project_name").
Where("a."+wxDao.SysUserProjectRelevancy.Columns().UserId, id).
WhereNull("a.source").
Scan(&wxDataInfo)
liberr.ErrIsNil(ctx, err)
res.WxList = wxDataInfo
// 获取到工程资料的权限
var pe []system.PowerEntity
err = g.DB().Model("document_power").Ctx(ctx).Where("sys_user_id", res.User.Id).Scan(&pe)
liberr.ErrIsNil(ctx, err)
res.PowerList = pe
})
return
}
// GetUserInfoById 通过Id获取用户信息
func (s *sSysUser) GetUserInfoById(ctx context.Context, id uint64, withPwd ...bool) (user *entity.SysUser, err error) {
err = g.Try(ctx, func(ctx context.Context) {
if len(withPwd) > 0 && withPwd[0] {
// 用户用户信息
err = dao.SysUser.Ctx(ctx).Where(dao.SysUser.Columns().Id, id).Scan(&user)
} else {
// 用户用户信息
err = dao.SysUser.Ctx(ctx).Where(dao.SysUser.Columns().Id, id).
FieldsEx(dao.SysUser.Columns().UserPassword, dao.SysUser.Columns().UserSalt).Scan(&user)
}
liberr.ErrIsNil(ctx, err, "获取用户数据失败")
})
return
}
// GetUserPostIds 获取用户岗位
func (s *sSysUser) GetUserPostIds(ctx context.Context, userId uint64) (postIds []int64, err error) {
err = g.Try(ctx, func(ctx context.Context) {
var list []*entity.SysUserPost
err = dao.SysUserPost.Ctx(ctx).Where(dao.SysUserPost.Columns().UserId, userId).Scan(&list)
liberr.ErrIsNil(ctx, err, "获取用户岗位信息失败")
postIds = make([]int64, 0)
for _, entity := range list {
postIds = append(postIds, entity.PostId)
}
})
return
}
// ResetUserPwd 重置用户密码
func (s *sSysUser) ResetUserPwd(ctx context.Context, req *system.UserResetPwdReq) (err error) {
salt := grand.S(10)
password := libUtils.EncryptPassword(req.Password, salt)
err = g.Try(ctx, func(ctx context.Context) {
_, err = dao.SysUser.Ctx(ctx).WherePri(req.Id).Update(g.Map{
dao.SysUser.Columns().UserSalt: salt,
dao.SysUser.Columns().UserPassword: password,
})
liberr.ErrIsNil(ctx, err, "重置用户密码失败")
})
return
}
func (s *sSysUser) ChangeUserStatus(ctx context.Context, req *system.UserStatusReq) (err error) {
err = g.Try(ctx, func(ctx context.Context) {
_, err = dao.SysUser.Ctx(ctx).WherePri(req.Id).Update(do.SysUser{UserStatus: req.UserStatus})
liberr.ErrIsNil(ctx, err, "设置用户状态失败")
})
return
}
// Delete 删除用户
func (s *sSysUser) Delete(ctx context.Context, ids []int) (err error) {
err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
err = g.Try(ctx, func(ctx context.Context) {
_, err = dao.SysUser.Ctx(ctx).TX(tx).Where(dao.SysUser.Columns().Id+" in(?)", ids).Delete()
liberr.ErrIsNil(ctx, err, "删除用户失败")
// 删除对应权限
enforcer, e := commonService.CasbinEnforcer(ctx)
liberr.ErrIsNil(ctx, e)
for _, v := range ids {
enforcer.RemoveFilteredGroupingPolicy(0, fmt.Sprintf("%s%d", s.casBinUserPrefix, v))
}
// 删除用户对应的岗位
_, err = dao.SysUserPost.Ctx(ctx).TX(tx).Delete(dao.SysUserPost.Columns().UserId+" in (?)", ids)
liberr.ErrIsNil(ctx, err, "删除用户的岗位失败")
// 删除用户工程资料权限
_, err = g.DB().Model("document_power").Ctx(ctx).TX(tx).Where("sys_user_id in(?)", ids).Delete()
liberr.ErrIsNil(ctx, err, "用户工程资料权限失败")
})
return err
})
return
}
// GetUsers 通过用户ids查询多个用户信息
func (s *sSysUser) GetUsers(ctx context.Context, ids []int) (users []*model.SysUserSimpleRes, err error) {
if len(ids) == 0 {
return
}
idsSet := gset.NewIntSetFrom(ids).Slice()
err = g.Try(ctx, func(ctx context.Context) {
err = dao.SysUser.Ctx(ctx).Where(dao.SysUser.Columns().Id+" in(?)", idsSet).
Order(dao.SysUser.Columns().Id + " ASC").Scan(&users)
})
return
}
// GetDataWhere 获取数据权限判断条件
func (s *sSysUser) GetDataWhere(ctx context.Context, userInfo *model.ContextUser, entityData interface{}) (where g.Map, err error) {
whereJustMe := g.Map{} // 本人数据权限
t := reflect.TypeOf(entityData)
for i := 0; i < t.Elem().NumField(); i++ {
if t.Elem().Field(i).Name == "CreatedBy" {
// 若存在用户id的字段则生成判断数据权限的条件
// 1、获取当前用户所属角色
allRoles := ([]*entity.SysRole)(nil)
allRoles, err = service.SysRole().GetRoleList(ctx)
if err != nil {
return nil, err
}
roles := ([]*entity.SysRole)(nil)
roles, err = s.GetAdminRole(ctx, userInfo.Id, allRoles)
if err != nil {
return nil, err
}
// 2获取角色对应数据权限
deptIdArr := gset.New()
for _, role := range roles {
switch role.DataScope {
case 1: // 全部数据权限
return
case 2: // 自定数据权限
var deptIds []int64
deptIds, err = service.SysRole().GetRoleDepts(ctx, gconv.Int64(role.Id))
if err != nil {
return
}
deptIdArr.Add(gconv.Interfaces(deptIds)...)
case 3: // 本部门数据权限
deptIdArr.Add(gconv.Int64(userInfo.DeptId))
case 4: // 本部门及以下数据权限
deptIdArr.Add(gconv.Int64(userInfo.DeptId))
// 获取正常状态部门数据
depts := ([]*entity.SysDept)(nil)
depts, err = service.SysDept().GetList(ctx, &system.DeptSearchReq{Status: "1"})
if err != nil {
return
}
var dList g.List
for _, d := range depts {
m := g.Map{
"id": d.DeptId,
"pid": d.ParentId,
"label": d.DeptName,
}
dList = append(dList, m)
}
l := libUtils.FindSonByParentId(dList, userInfo.DeptId, "pid", "id")
for _, li := range l {
deptIdArr.Add(gconv.Int64(li["id"]))
}
case 5: // 仅本人数据权限
whereJustMe = g.Map{"user.id": userInfo.Id}
}
}
if deptIdArr.Size() > 0 {
where = g.Map{"user.dept_id": deptIdArr.Slice()}
} else if len(whereJustMe) > 0 {
where = whereJustMe
}
}
}
return
}
// HasAccessByDataWhere 判断用户是否有数据权限
func (s *sSysUser) HasAccessByDataWhere(ctx context.Context, where g.Map, uid interface{}) bool {
err := g.Try(ctx, func(ctx context.Context) {
rec, err := dao.SysUser.Ctx(ctx).As("user").
Fields("user.id").
Where("user.id", uid).Where(where).One()
liberr.ErrIsNil(ctx, err)
if rec.IsEmpty() {
liberr.ErrIsNil(ctx, gerror.New("没有数据"))
}
})
return err == nil
}
// AccessRule 判断用户是否有某一菜单规则权限
func (s *sSysUser) AccessRule(ctx context.Context, userId uint64, rule string) bool {
// 获取无需验证权限的用户id
tagSuperAdmin := false
s.NotCheckAuthAdminIds(ctx).Iterator(func(v interface{}) bool {
if gconv.Uint64(v) == userId {
tagSuperAdmin = true
return false
}
return true
})
if tagSuperAdmin {
return true
}
menuList, err := service.SysAuthRule().GetMenuList(ctx)
if err != nil {
g.Log().Error(ctx, err)
return false
}
var menu *model.SysAuthRuleInfoRes
for _, m := range menuList {
ms := gstr.SubStr(m.Name, 0, gstr.Pos(m.Name, "?"))
if m.Name == rule || ms == rule {
menu = m
break
}
}
// 不存在的规则直接false
if menu == nil {
return false
}
enforcer, err := commonService.CasbinEnforcer(ctx)
if err != nil {
g.Log().Error(ctx, err)
return false
}
hasAccess, err := enforcer.Enforce(fmt.Sprintf("%s%d", service.SysUser().GetCasBinUserPrefix(), userId), gconv.String(menu.Id), "All")
if err != nil {
g.Log().Error(ctx, err)
return false
}
return hasAccess
}
// ProjectAll 获取当前用户下的所有项目
func ProjectAll(ctx context.Context) (ids string) {
// 1、获取当前登录用户
id := ct.New().GetLoginUser(ctx).Id
// 2、获取到当前项目下的所有详情
value, err := wxDao.SysUserProjectRelevancy.Ctx(ctx).
Where("user_id", id).
Fields("GROUP_CONCAT( `project_id` SEPARATOR ',' )").Value()
if err != nil {
return
}
return value.String()
}