sys_user.go 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  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/model"
  21. "github.com/tiger1103/gfast/v3/internal/app/system/model/entity"
  22. "github.com/tiger1103/gfast/v3/internal/app/system/service/internal/dao"
  23. "github.com/tiger1103/gfast/v3/internal/app/system/service/internal/do"
  24. "github.com/tiger1103/gfast/v3/library/libUtils"
  25. "github.com/tiger1103/gfast/v3/library/liberr"
  26. )
  27. type IUser interface {
  28. GetAdminUserByUsernamePassword(ctx context.Context, req *system.UserLoginReq) (user *model.LoginUserRes, err error)
  29. LoginLog(ctx context.Context, params *model.LoginLogParams)
  30. UpdateLoginInfo(ctx context.Context, id uint64, ip string) (err error)
  31. NotCheckAuthAdminIds(ctx context.Context) *gset.Set
  32. GetAdminRules(ctx context.Context, userId uint64) (menuList []*model.UserMenus, permissions []string, err error)
  33. }
  34. type userImpl struct{}
  35. var (
  36. notCheckAuthAdminIds *gset.Set //无需验证权限的用户id
  37. user = userImpl{}
  38. )
  39. func User() IUser {
  40. return IUser(&user)
  41. }
  42. func (s *userImpl) NotCheckAuthAdminIds(ctx context.Context) *gset.Set {
  43. ids := g.Cfg().MustGet(ctx, "system.notCheckAuthAdminIds")
  44. if !g.IsNil(ids) {
  45. notCheckAuthAdminIds = gset.NewFrom(ids)
  46. }
  47. return notCheckAuthAdminIds
  48. }
  49. func (s *userImpl) GetAdminUserByUsernamePassword(ctx context.Context, req *system.UserLoginReq) (user *model.LoginUserRes, err error) {
  50. err = g.Try(func() {
  51. user, err = s.GetUserByUsername(ctx, req.Username)
  52. liberr.ErrIsNil(ctx, err)
  53. liberr.ValueIsNil(user, "账号密码错误")
  54. //验证密码
  55. if libUtils.EncryptPassword(req.Password, user.UserSalt) != user.UserPassword {
  56. liberr.ErrIsNil(ctx, gerror.New("账号密码错误"))
  57. }
  58. //账号状态
  59. if user.UserStatus == 0 {
  60. liberr.ErrIsNil(ctx, gerror.New("账号已被冻结"))
  61. }
  62. })
  63. return
  64. }
  65. // GetUserByUsername 通过用户名获取用户信息
  66. func (s *userImpl) GetUserByUsername(ctx context.Context, userName string) (user *model.LoginUserRes, err error) {
  67. err = g.Try(func() {
  68. user = &model.LoginUserRes{}
  69. err = dao.SysUser.Ctx(ctx).Fields(user).Where(dao.SysUser.Columns().UserName, userName).Scan(user)
  70. liberr.ErrIsNil(ctx, err, "账号密码错误")
  71. })
  72. return
  73. }
  74. // LoginLog 记录登录日志
  75. func (s *userImpl) LoginLog(ctx context.Context, params *model.LoginLogParams) {
  76. ua := user_agent.New(params.UserAgent)
  77. browser, _ := ua.Browser()
  78. loginData := &do.SysLoginLog{
  79. LoginName: params.Username,
  80. Ipaddr: params.Ip,
  81. LoginLocation: libUtils.GetCityByIp(params.Ip),
  82. Browser: browser,
  83. Os: ua.OS(),
  84. Status: params.Status,
  85. Msg: params.Msg,
  86. LoginTime: gtime.Now(),
  87. Module: params.Module,
  88. }
  89. _, err := dao.SysLoginLog.Ctx(ctx).Insert(loginData)
  90. if err != nil {
  91. g.Log().Error(ctx, err)
  92. }
  93. }
  94. func (s *userImpl) UpdateLoginInfo(ctx context.Context, id uint64, ip string) (err error) {
  95. g.Try(func() {
  96. _, err = dao.SysUser.Ctx(ctx).WherePri(id).Update(g.Map{
  97. dao.SysUser.Columns().LastLoginIp: ip,
  98. dao.SysUser.Columns().LastLoginTime: gtime.Now(),
  99. })
  100. liberr.ErrIsNil(ctx, err, "更新用户登录信息失败")
  101. })
  102. return
  103. }
  104. // GetAdminRules 获取用户菜单数据
  105. func (s *userImpl) GetAdminRules(ctx context.Context, userId uint64) (menuList []*model.UserMenus, permissions []string, err error) {
  106. err = g.Try(func() {
  107. //是否超管
  108. isSuperAdmin := false
  109. //获取无需验证权限的用户id
  110. s.NotCheckAuthAdminIds(ctx).Iterator(func(v interface{}) bool {
  111. if gconv.Uint64(v) == userId {
  112. isSuperAdmin = true
  113. return false
  114. }
  115. return true
  116. })
  117. //获取用户菜单数据
  118. allRoles, err := Role().GetRoleList(ctx)
  119. liberr.ErrIsNil(ctx, err)
  120. roles, err := s.GetAdminRole(ctx, userId, allRoles)
  121. liberr.ErrIsNil(ctx, err)
  122. name := make([]string, len(roles))
  123. roleIds := make([]uint, len(roles))
  124. for k, v := range roles {
  125. name[k] = v.Name
  126. roleIds[k] = v.Id
  127. }
  128. //获取菜单信息
  129. if isSuperAdmin {
  130. //超管获取所有菜单
  131. permissions = []string{"*/*/*"}
  132. menuList, err = s.GetAllMenus(ctx)
  133. liberr.ErrIsNil(ctx, err)
  134. } else {
  135. menuList, err = s.GetAdminMenusByRoleIds(ctx, roleIds)
  136. liberr.ErrIsNil(ctx, err)
  137. permissions, err = s.GetPermissions(ctx, roleIds)
  138. liberr.ErrIsNil(ctx, err)
  139. }
  140. })
  141. return
  142. }
  143. // GetAdminRole 获取用户角色
  144. func (s *userImpl) GetAdminRole(ctx context.Context, userId uint64, allRoleList []*entity.SysRole) (roles []*entity.SysRole, err error) {
  145. var roleIds []uint
  146. roleIds, err = s.GetAdminRoleIds(ctx, userId)
  147. if err != nil {
  148. return
  149. }
  150. roles = make([]*entity.SysRole, 0, len(allRoleList))
  151. for _, v := range allRoleList {
  152. for _, id := range roleIds {
  153. if id == v.Id {
  154. roles = append(roles, v)
  155. }
  156. }
  157. if len(roles) == len(roleIds) {
  158. break
  159. }
  160. }
  161. return
  162. }
  163. // GetAdminRoleIds 获取用户角色ids
  164. func (s *userImpl) GetAdminRoleIds(ctx context.Context, userId uint64) (roleIds []uint, err error) {
  165. enforcer, e := service.CasbinEnforcer(ctx)
  166. if e != nil {
  167. err = e
  168. return
  169. }
  170. //查询关联角色规则
  171. groupPolicy := enforcer.GetFilteredGroupingPolicy(0, gconv.String(userId))
  172. if len(groupPolicy) > 0 {
  173. roleIds = make([]uint, len(groupPolicy))
  174. //得到角色id的切片
  175. for k, v := range groupPolicy {
  176. roleIds[k] = gconv.Uint(v[1])
  177. }
  178. }
  179. return
  180. }
  181. func (s *userImpl) GetAllMenus(ctx context.Context) (menus []*model.UserMenus, err error) {
  182. //获取所有开启的菜单
  183. var allMenus []*model.SysAuthRuleInfoRes
  184. allMenus, err = Rule().GetIsMenuStatusList(ctx)
  185. if err != nil {
  186. return
  187. }
  188. menus = make([]*model.UserMenus, len(allMenus))
  189. for k, v := range allMenus {
  190. var menu *model.UserMenu
  191. menu = s.setMenuData(menu, v)
  192. menus[k] = &model.UserMenus{UserMenu: menu}
  193. }
  194. menus = s.GetMenusTree(menus, 0)
  195. return
  196. }
  197. func (s *userImpl) GetAdminMenusByRoleIds(ctx context.Context, roleIds []uint) (menus []*model.UserMenus, err error) {
  198. //获取角色对应的菜单id
  199. err = g.Try(func() {
  200. enforcer, e := service.CasbinEnforcer(ctx)
  201. liberr.ErrIsNil(ctx, e)
  202. menuIds := map[int64]int64{}
  203. for _, roleId := range roleIds {
  204. //查询当前权限
  205. gp := enforcer.GetFilteredPolicy(0, fmt.Sprintf("%d", roleId))
  206. for _, p := range gp {
  207. mid := gconv.Int64(p[1])
  208. menuIds[mid] = mid
  209. }
  210. }
  211. //获取所有开启的菜单
  212. allMenus, err := Rule().GetIsMenuStatusList(ctx)
  213. liberr.ErrIsNil(ctx, err)
  214. menus = make([]*model.UserMenus, 0, len(allMenus))
  215. for _, v := range allMenus {
  216. if _, ok := menuIds[gconv.Int64(v.Id)]; gstr.Equal(v.Condition, "nocheck") || ok {
  217. var roleMenu *model.UserMenu
  218. roleMenu = s.setMenuData(roleMenu, v)
  219. menus = append(menus, &model.UserMenus{UserMenu: roleMenu})
  220. }
  221. }
  222. menus = s.GetMenusTree(menus, 0)
  223. })
  224. return
  225. }
  226. func (s *userImpl) GetMenusTree(menus []*model.UserMenus, pid uint) []*model.UserMenus {
  227. returnList := make([]*model.UserMenus, 0, len(menus))
  228. for _, menu := range menus {
  229. if menu.Pid == pid {
  230. menu.Children = s.GetMenusTree(menus, menu.Id)
  231. returnList = append(returnList, menu)
  232. }
  233. }
  234. return returnList
  235. }
  236. func (s *userImpl) setMenuData(menu *model.UserMenu, entity *model.SysAuthRuleInfoRes) *model.UserMenu {
  237. menu = &model.UserMenu{
  238. Id: entity.Id,
  239. Pid: entity.Pid,
  240. Index: entity.Name,
  241. Name: gstr.UcFirst(entity.Path),
  242. MenuName: entity.Title,
  243. MenuMeta: &model.MenuMeta{
  244. Icon: entity.Icon,
  245. Title: entity.Title,
  246. IsLink: "",
  247. IsHide: false,
  248. IsKeepAlive: false,
  249. IsAffix: false,
  250. IsIframe: false,
  251. },
  252. }
  253. if entity.MenuType != 0 {
  254. menu.Component = entity.Component
  255. menu.Path = entity.Path
  256. } else {
  257. menu.Component = "Layout"
  258. menu.Path = "/" + entity.Path
  259. }
  260. if entity.AlwaysShow == 1 {
  261. menu.MenuMeta.IsHide = false
  262. } else {
  263. menu.MenuMeta.IsHide = true
  264. }
  265. if entity.AlwaysShow == 1 && entity.MenuType == 0 {
  266. menu.MenuMeta.IsHide = true
  267. } else {
  268. menu.MenuMeta.IsHide = false
  269. }
  270. return menu
  271. }
  272. func (s *userImpl) GetPermissions(ctx context.Context, roleIds []uint) (userButtons []string, err error) {
  273. err = g.Try(func() {
  274. //获取角色对应的菜单id
  275. enforcer, err := service.CasbinEnforcer(ctx)
  276. liberr.ErrIsNil(ctx, err)
  277. menuIds := map[int64]int64{}
  278. for _, roleId := range roleIds {
  279. //查询当前权限
  280. gp := enforcer.GetFilteredPolicy(0, gconv.String(roleId))
  281. for _, p := range gp {
  282. mid := gconv.Int64(p[1])
  283. menuIds[mid] = mid
  284. }
  285. }
  286. //获取所有开启的按钮
  287. allButtons, err := Rule().GetIsButtonStatusList(ctx)
  288. liberr.ErrIsNil(ctx, err)
  289. userButtons = make([]string, 0, len(allButtons))
  290. for _, button := range allButtons {
  291. if _, ok := menuIds[gconv.Int64(button.Id)]; gstr.Equal(button.Condition, "nocheck") || ok {
  292. userButtons = append(userButtons, button.Name)
  293. }
  294. }
  295. })
  296. return
  297. }