sys_user.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /*
  2. * @desc:用户处理
  3. * @company:云南奇讯科技有限公司
  4. * @Author: yixiaohu
  5. * @Date: 2022/3/7 9:50
  6. */
  7. package service
  8. import (
  9. "context"
  10. "fmt"
  11. "github.com/gogf/gf/v2/container/gset"
  12. "github.com/gogf/gf/v2/errors/gerror"
  13. "github.com/gogf/gf/v2/frame/g"
  14. "github.com/gogf/gf/v2/os/gtime"
  15. "github.com/gogf/gf/v2/text/gstr"
  16. "github.com/gogf/gf/v2/util/gconv"
  17. "github.com/mssola/user_agent"
  18. "github.com/tiger1103/gfast/v3/api/v1/system"
  19. "github.com/tiger1103/gfast/v3/internal/app/common/service"
  20. "github.com/tiger1103/gfast/v3/internal/app/system/consts"
  21. "github.com/tiger1103/gfast/v3/internal/app/system/model"
  22. "github.com/tiger1103/gfast/v3/internal/app/system/model/entity"
  23. "github.com/tiger1103/gfast/v3/internal/app/system/service/internal/dao"
  24. "github.com/tiger1103/gfast/v3/internal/app/system/service/internal/do"
  25. "github.com/tiger1103/gfast/v3/library/libUtils"
  26. "github.com/tiger1103/gfast/v3/library/liberr"
  27. )
  28. type IUser interface {
  29. GetAdminUserByUsernamePassword(ctx context.Context, req *system.UserLoginReq) (user *model.LoginUserRes, err error)
  30. LoginLog(ctx context.Context, params *model.LoginLogParams)
  31. UpdateLoginInfo(ctx context.Context, id uint64, ip string) (err error)
  32. NotCheckAuthAdminIds(ctx context.Context) *gset.Set
  33. GetAdminRules(ctx context.Context, userId uint64) (menuList []*model.UserMenus, permissions []string, err error)
  34. List(ctx context.Context, req *system.UserSearchReq) (total int, userList []*entity.SysUser, err error)
  35. GetUsersRoleDept(ctx context.Context, userList []*entity.SysUser) (users []*model.SysUserRoleDeptRes, err error)
  36. }
  37. type userImpl struct{}
  38. var (
  39. notCheckAuthAdminIds *gset.Set //无需验证权限的用户id
  40. userService = userImpl{}
  41. )
  42. func User() IUser {
  43. return IUser(&userService)
  44. }
  45. func (s *userImpl) NotCheckAuthAdminIds(ctx context.Context) *gset.Set {
  46. ids := g.Cfg().MustGet(ctx, "system.notCheckAuthAdminIds")
  47. if !g.IsNil(ids) {
  48. notCheckAuthAdminIds = gset.NewFrom(ids)
  49. }
  50. return notCheckAuthAdminIds
  51. }
  52. func (s *userImpl) GetAdminUserByUsernamePassword(ctx context.Context, req *system.UserLoginReq) (user *model.LoginUserRes, err error) {
  53. err = g.Try(func() {
  54. user, err = s.GetUserByUsername(ctx, req.Username)
  55. liberr.ErrIsNil(ctx, err)
  56. liberr.ValueIsNil(user, "账号密码错误")
  57. //验证密码
  58. if libUtils.EncryptPassword(req.Password, user.UserSalt) != user.UserPassword {
  59. liberr.ErrIsNil(ctx, gerror.New("账号密码错误"))
  60. }
  61. //账号状态
  62. if user.UserStatus == 0 {
  63. liberr.ErrIsNil(ctx, gerror.New("账号已被冻结"))
  64. }
  65. })
  66. return
  67. }
  68. // GetUserByUsername 通过用户名获取用户信息
  69. func (s *userImpl) GetUserByUsername(ctx context.Context, userName string) (user *model.LoginUserRes, err error) {
  70. err = g.Try(func() {
  71. user = &model.LoginUserRes{}
  72. err = dao.SysUser.Ctx(ctx).Fields(user).Where(dao.SysUser.Columns().UserName, userName).Scan(user)
  73. liberr.ErrIsNil(ctx, err, "账号密码错误")
  74. })
  75. return
  76. }
  77. // LoginLog 记录登录日志
  78. func (s *userImpl) LoginLog(ctx context.Context, params *model.LoginLogParams) {
  79. ua := user_agent.New(params.UserAgent)
  80. browser, _ := ua.Browser()
  81. loginData := &do.SysLoginLog{
  82. LoginName: params.Username,
  83. Ipaddr: params.Ip,
  84. LoginLocation: libUtils.GetCityByIp(params.Ip),
  85. Browser: browser,
  86. Os: ua.OS(),
  87. Status: params.Status,
  88. Msg: params.Msg,
  89. LoginTime: gtime.Now(),
  90. Module: params.Module,
  91. }
  92. _, err := dao.SysLoginLog.Ctx(ctx).Insert(loginData)
  93. if err != nil {
  94. g.Log().Error(ctx, err)
  95. }
  96. }
  97. func (s *userImpl) UpdateLoginInfo(ctx context.Context, id uint64, ip string) (err error) {
  98. g.Try(func() {
  99. _, err = dao.SysUser.Ctx(ctx).WherePri(id).Update(g.Map{
  100. dao.SysUser.Columns().LastLoginIp: ip,
  101. dao.SysUser.Columns().LastLoginTime: gtime.Now(),
  102. })
  103. liberr.ErrIsNil(ctx, err, "更新用户登录信息失败")
  104. })
  105. return
  106. }
  107. // GetAdminRules 获取用户菜单数据
  108. func (s *userImpl) GetAdminRules(ctx context.Context, userId uint64) (menuList []*model.UserMenus, permissions []string, err error) {
  109. err = g.Try(func() {
  110. //是否超管
  111. isSuperAdmin := false
  112. //获取无需验证权限的用户id
  113. s.NotCheckAuthAdminIds(ctx).Iterator(func(v interface{}) bool {
  114. if gconv.Uint64(v) == userId {
  115. isSuperAdmin = true
  116. return false
  117. }
  118. return true
  119. })
  120. //获取用户菜单数据
  121. allRoles, err := Role().GetRoleList(ctx)
  122. liberr.ErrIsNil(ctx, err)
  123. roles, err := s.GetAdminRole(ctx, userId, allRoles)
  124. liberr.ErrIsNil(ctx, err)
  125. name := make([]string, len(roles))
  126. roleIds := make([]uint, len(roles))
  127. for k, v := range roles {
  128. name[k] = v.Name
  129. roleIds[k] = v.Id
  130. }
  131. //获取菜单信息
  132. if isSuperAdmin {
  133. //超管获取所有菜单
  134. permissions = []string{"*/*/*"}
  135. menuList, err = s.GetAllMenus(ctx)
  136. liberr.ErrIsNil(ctx, err)
  137. } else {
  138. menuList, err = s.GetAdminMenusByRoleIds(ctx, roleIds)
  139. liberr.ErrIsNil(ctx, err)
  140. permissions, err = s.GetPermissions(ctx, roleIds)
  141. liberr.ErrIsNil(ctx, err)
  142. }
  143. })
  144. return
  145. }
  146. // GetAdminRole 获取用户角色
  147. func (s *userImpl) GetAdminRole(ctx context.Context, userId uint64, allRoleList []*entity.SysRole) (roles []*entity.SysRole, err error) {
  148. var roleIds []uint
  149. roleIds, err = s.GetAdminRoleIds(ctx, userId)
  150. if err != nil {
  151. return
  152. }
  153. roles = make([]*entity.SysRole, 0, len(allRoleList))
  154. for _, v := range allRoleList {
  155. for _, id := range roleIds {
  156. if id == v.Id {
  157. roles = append(roles, v)
  158. }
  159. }
  160. if len(roles) == len(roleIds) {
  161. break
  162. }
  163. }
  164. return
  165. }
  166. // GetAdminRoleIds 获取用户角色ids
  167. func (s *userImpl) GetAdminRoleIds(ctx context.Context, userId uint64) (roleIds []uint, err error) {
  168. enforcer, e := service.CasbinEnforcer(ctx)
  169. if e != nil {
  170. err = e
  171. return
  172. }
  173. //查询关联角色规则
  174. groupPolicy := enforcer.GetFilteredGroupingPolicy(0, gconv.String(userId))
  175. if len(groupPolicy) > 0 {
  176. roleIds = make([]uint, len(groupPolicy))
  177. //得到角色id的切片
  178. for k, v := range groupPolicy {
  179. roleIds[k] = gconv.Uint(v[1])
  180. }
  181. }
  182. return
  183. }
  184. func (s *userImpl) GetAllMenus(ctx context.Context) (menus []*model.UserMenus, err error) {
  185. //获取所有开启的菜单
  186. var allMenus []*model.SysAuthRuleInfoRes
  187. allMenus, err = Rule().GetIsMenuList(ctx)
  188. if err != nil {
  189. return
  190. }
  191. menus = make([]*model.UserMenus, len(allMenus))
  192. for k, v := range allMenus {
  193. var menu *model.UserMenu
  194. menu = s.setMenuData(menu, v)
  195. menus[k] = &model.UserMenus{UserMenu: menu}
  196. }
  197. menus = s.GetMenusTree(menus, 0)
  198. return
  199. }
  200. func (s *userImpl) GetAdminMenusByRoleIds(ctx context.Context, roleIds []uint) (menus []*model.UserMenus, err error) {
  201. //获取角色对应的菜单id
  202. err = g.Try(func() {
  203. enforcer, e := service.CasbinEnforcer(ctx)
  204. liberr.ErrIsNil(ctx, e)
  205. menuIds := map[int64]int64{}
  206. for _, roleId := range roleIds {
  207. //查询当前权限
  208. gp := enforcer.GetFilteredPolicy(0, fmt.Sprintf("%d", roleId))
  209. for _, p := range gp {
  210. mid := gconv.Int64(p[1])
  211. menuIds[mid] = mid
  212. }
  213. }
  214. //获取所有开启的菜单
  215. allMenus, err := Rule().GetIsMenuList(ctx)
  216. liberr.ErrIsNil(ctx, err)
  217. menus = make([]*model.UserMenus, 0, len(allMenus))
  218. for _, v := range allMenus {
  219. if _, ok := menuIds[gconv.Int64(v.Id)]; gstr.Equal(v.Condition, "nocheck") || ok {
  220. var roleMenu *model.UserMenu
  221. roleMenu = s.setMenuData(roleMenu, v)
  222. menus = append(menus, &model.UserMenus{UserMenu: roleMenu})
  223. }
  224. }
  225. menus = s.GetMenusTree(menus, 0)
  226. })
  227. return
  228. }
  229. func (s *userImpl) GetMenusTree(menus []*model.UserMenus, pid uint) []*model.UserMenus {
  230. returnList := make([]*model.UserMenus, 0, len(menus))
  231. for _, menu := range menus {
  232. if menu.Pid == pid {
  233. menu.Children = s.GetMenusTree(menus, menu.Id)
  234. returnList = append(returnList, menu)
  235. }
  236. }
  237. return returnList
  238. }
  239. func (s *userImpl) setMenuData(menu *model.UserMenu, entity *model.SysAuthRuleInfoRes) *model.UserMenu {
  240. menu = &model.UserMenu{
  241. Id: entity.Id,
  242. Pid: entity.Pid,
  243. Name: gstr.CaseCamelLower(gstr.Replace(entity.Name, "/", "_")),
  244. Component: entity.Component,
  245. Path: entity.Path,
  246. MenuMeta: &model.MenuMeta{
  247. Icon: entity.Icon,
  248. Title: entity.Title,
  249. IsLink: "",
  250. IsHide: entity.IsHide == 1,
  251. IsKeepAlive: entity.IsCached == 1,
  252. IsAffix: entity.IsAffix == 1,
  253. IsIframe: entity.IsIframe == 1,
  254. },
  255. }
  256. if menu.MenuMeta.IsIframe || entity.IsLink == 1 {
  257. menu.MenuMeta.IsLink = entity.LinkUrl
  258. }
  259. return menu
  260. }
  261. func (s *userImpl) GetPermissions(ctx context.Context, roleIds []uint) (userButtons []string, err error) {
  262. err = g.Try(func() {
  263. //获取角色对应的菜单id
  264. enforcer, err := service.CasbinEnforcer(ctx)
  265. liberr.ErrIsNil(ctx, err)
  266. menuIds := map[int64]int64{}
  267. for _, roleId := range roleIds {
  268. //查询当前权限
  269. gp := enforcer.GetFilteredPolicy(0, gconv.String(roleId))
  270. for _, p := range gp {
  271. mid := gconv.Int64(p[1])
  272. menuIds[mid] = mid
  273. }
  274. }
  275. //获取所有开启的按钮
  276. allButtons, err := Rule().GetIsButtonList(ctx)
  277. liberr.ErrIsNil(ctx, err)
  278. userButtons = make([]string, 0, len(allButtons))
  279. for _, button := range allButtons {
  280. if _, ok := menuIds[gconv.Int64(button.Id)]; gstr.Equal(button.Condition, "nocheck") || ok {
  281. userButtons = append(userButtons, button.Name)
  282. }
  283. }
  284. })
  285. return
  286. }
  287. // List 用户列表
  288. func (s *userImpl) List(ctx context.Context, req *system.UserSearchReq) (total int, userList []*entity.SysUser, err error) {
  289. err = g.Try(func() {
  290. m := dao.SysUser.Ctx(ctx)
  291. if req.KeyWords != "" {
  292. keyWords := "%" + req.KeyWords + "%"
  293. m = m.Where("user_name like ? or user_nickname like ?", keyWords, keyWords)
  294. }
  295. if len(req.DeptIds) != 0 {
  296. m = m.Where("dept_id in (?)", req.DeptIds)
  297. }
  298. if req.Status != "" {
  299. m = m.Where("user_status", gconv.Int(req.Status))
  300. }
  301. if req.Mobile != "" {
  302. m = m.Where("mobile like ?", "%"+req.Mobile+"%")
  303. }
  304. if req.BeginTime != "" {
  305. m = m.Where("created_at >=?", req.BeginTime)
  306. }
  307. if req.EndTime != "" {
  308. m = m.Where("created_at <=?", req.EndTime)
  309. }
  310. if req.PageSize == 0 {
  311. req.PageSize = consts.PageSize
  312. }
  313. if req.PageNum == 0 {
  314. req.PageNum = 1
  315. }
  316. total, err = m.Count()
  317. liberr.ErrIsNil(ctx, err, "获取用户数据失败")
  318. err = m.FieldsEx(dao.SysUser.Columns().UserPassword, dao.SysUser.Columns().UserSalt).
  319. Page(req.PageNum, req.PageSize).Order("id asc").Scan(&userList)
  320. liberr.ErrIsNil(ctx, err, "获取用户列表失败")
  321. })
  322. return
  323. }
  324. // GetUsersRoleDept 获取多个用户角色 部门信息
  325. func (s *userImpl) GetUsersRoleDept(ctx context.Context, userList []*entity.SysUser) (users []*model.SysUserRoleDeptRes, err error) {
  326. err = g.Try(func() {
  327. allRoles, e := Role().GetRoleList(ctx)
  328. liberr.ErrIsNil(ctx, e)
  329. depts, e := Dept().GetFromCache(ctx)
  330. liberr.ErrIsNil(ctx, e)
  331. users = make([]*model.SysUserRoleDeptRes, len(userList))
  332. for k, u := range userList {
  333. var dept *entity.SysDept
  334. users[k] = &model.SysUserRoleDeptRes{
  335. SysUser: u,
  336. }
  337. for _, d := range depts {
  338. if u.DeptId == uint64(d.DeptId) {
  339. dept = d
  340. }
  341. }
  342. users[k].Dept = dept
  343. roles, e := s.GetAdminRole(ctx, u.Id, allRoles)
  344. liberr.ErrIsNil(ctx, e)
  345. for _, r := range roles {
  346. users[k].RoleInfo = append(users[k].RoleInfo, &struct {
  347. RoleId uint `json:"roleId"`
  348. Name string `json:"name"`
  349. }{RoleId: r.Id, Name: r.Name})
  350. }
  351. }
  352. })
  353. return
  354. }