admin_user.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. package service
  2. import (
  3. "context"
  4. "encoding/base64"
  5. "encoding/json"
  6. "entrance-grpc/iam"
  7. "gadmin/config"
  8. "gadmin/internal/admin/consts"
  9. "gadmin/internal/admin/forms"
  10. "gadmin/internal/gorm/model"
  11. "gadmin/internal/gorm/query"
  12. "gadmin/utility/serializer"
  13. "gadmin/utility/token"
  14. jsoniter "github.com/json-iterator/go"
  15. "time"
  16. "github.com/gin-gonic/gin"
  17. "github.com/sirupsen/logrus"
  18. "golang.org/x/crypto/bcrypt"
  19. )
  20. // User 管理员服务
  21. var User = NewsUser()
  22. type LoginStats struct {
  23. FailNum int
  24. BanTs int64
  25. }
  26. type sUser struct {
  27. BanIps map[string]*LoginStats
  28. }
  29. func NewsUser() *sUser {
  30. user := new(sUser)
  31. user.BanIps = make(map[string]*LoginStats)
  32. return user
  33. }
  34. // 一次登录,清空错误次数
  35. func (s *sUser) AddSucessNum(ip string) {
  36. delete(s.BanIps, ip)
  37. }
  38. // 增加错误登录次数,超过10次,不再进行密码验证
  39. func (s *sUser) AddFailNum(ip string) {
  40. stats, ok := s.BanIps[ip]
  41. if !ok {
  42. stats = new(LoginStats)
  43. s.BanIps[ip] = stats
  44. }
  45. if stats.BanTs > 0 {
  46. return
  47. }
  48. if stats.FailNum > 10 {
  49. curTs := time.Now().Unix()
  50. stats.BanTs = curTs
  51. // 清理错误登录
  52. for k, v := range s.BanIps {
  53. if v.BanTs+24*60*60 < curTs {
  54. delete(s.BanIps, k)
  55. }
  56. }
  57. return
  58. }
  59. stats.FailNum += 1
  60. }
  61. // 检查是否允许登录
  62. func (s *sUser) CheckLoginAllow(ip string) bool {
  63. stats, ok := s.BanIps[ip]
  64. if !ok {
  65. return true
  66. }
  67. cur := time.Now().Unix()
  68. if stats.BanTs+1*60*60 > cur {
  69. return false
  70. }
  71. stats.BanTs = 0
  72. stats.FailNum = 0
  73. return true
  74. }
  75. // GetUser 用ID获取用户
  76. //func (s *sUser) GetUser(ID interface{}) (u *model.AdminUser, err error) {
  77. // result := config.DB.First(&u, ID)
  78. // return u, result.Error
  79. //}
  80. // SetPassword 设置密码
  81. func (s *sUser) SetPassword(password string) (string, error) {
  82. bytes, err := bcrypt.GenerateFromPassword([]byte(password), consts.PassWordCost)
  83. if err != nil {
  84. return "", err
  85. }
  86. return string(bytes), nil
  87. }
  88. // CheckPassword 校验密码
  89. func (s *sUser) CheckPasswordRight(passwordDigest, password string) bool {
  90. err := bcrypt.CompareHashAndPassword([]byte(passwordDigest), []byte(password))
  91. return err == nil
  92. }
  93. func (s *sUser) Login(req forms.UserLoginReq, ip string) serializer.Response {
  94. var (
  95. u model.AdminUser
  96. )
  97. if ok := s.CheckLoginAllow(ip); !ok {
  98. return serializer.ParamErr("账号已被禁止登录", nil)
  99. }
  100. if err := config.AdminDB.Where("user_name = ?", req.UserName).First(&u).Error; err != nil {
  101. s.AddFailNum(ip)
  102. logrus.Warnf("sUser %v Login req error %v.", req.UserName, ip)
  103. return serializer.ParamErr("账号错误或不存在,请检查", nil)
  104. }
  105. //p, _ := s.SetPassword(req.Password)
  106. //fmt.Println("pass:", p)
  107. if u.Status != 1 {
  108. return serializer.ParamErr("账号已被禁用", nil)
  109. }
  110. if s.CheckPasswordRight(u.PasswordDigest, req.Password) == false {
  111. s.AddFailNum(ip)
  112. logrus.Warnf("sUser %v Login req error. ip: %v.", req.UserName, ip)
  113. return serializer.ParamErr("密码不正确,如忘记了密码请联系管理员!", nil)
  114. }
  115. s.AddSucessNum(ip)
  116. //if os.Getenv("GIN_MODE") == "release" && u.UserName == "mojun" {
  117. // return serializer.ParamErr("该账号只允许在测试服登录!", nil)
  118. //}
  119. t := token.GenerateTokenUsingUUID()
  120. // 记录登录token
  121. key := config.GetUserTokenKey(u.ID)
  122. config.TokenRedis.HSet(key, t, time.Now().Unix())
  123. config.TokenRedis.Expire(key, config.TokenExpireTime)
  124. tokenKey := config.GetTokenKey(t)
  125. user := &token.UserClaims{
  126. ID: u.ID,
  127. UserName: u.UserName,
  128. RoleId: int64(u.RoleID),
  129. Avatar: u.Avatar,
  130. Nickname: u.Nickname,
  131. AccessToken: t,
  132. }
  133. userStr, err := jsoniter.MarshalToString(user)
  134. if err != nil {
  135. return serializer.Err(1, "", err)
  136. }
  137. config.TokenRedis.Set(tokenKey, userStr, config.TokenExpireTime)
  138. return serializer.Suc(forms.UserLoginRes{
  139. ID: u.ID,
  140. UserName: u.UserName,
  141. Nickname: u.Nickname,
  142. Status: u.Status,
  143. Avatar: u.Avatar,
  144. Token: base64.URLEncoding.EncodeToString([]byte(t)),
  145. })
  146. //t, err := token.GenerateToken(&token.UserClaims{
  147. // ID: u.ID,
  148. // UserName: u.UserName,
  149. // RoleId: int64(u.RoleID),
  150. // Avatar: u.Avatar,
  151. // Nickname: u.Nickname,
  152. //})
  153. //if err != nil {
  154. // return serializer.ParamErr(err.Error(), nil)
  155. //}
  156. //return serializer.Suc(forms.UserLoginRes{
  157. // ID: u.ID,
  158. // UserName: u.UserName,
  159. // Nickname: u.Nickname,
  160. // Status: u.Status,
  161. // Avatar: u.Avatar,
  162. // Token: t,
  163. //})
  164. }
  165. func (s *sUser) List(ctx *gin.Context, req forms.AdminUserListReq) serializer.Response {
  166. var (
  167. q = query.Use(config.AdminDB).AdminUser
  168. r = query.Use(config.AdminDB).AdminRole
  169. m = q.WithContext(ctx)
  170. offset int64 = 0
  171. models forms.UserAccountListRes
  172. lists []*forms.AdminUserListModel
  173. )
  174. m = m.Order(q.ID.Desc())
  175. req.Page, req.PerPage, offset = forms.CalculatePage(req.Page, req.PerPage)
  176. count, err := m.Count()
  177. if err != nil {
  178. return serializer.Err(consts.CodeParamErr, "查询出错 count", err)
  179. }
  180. if count > 0 {
  181. if err = m.Limit(int(req.PerPage)).Offset(int(offset)).Scan(&lists); err != nil {
  182. return serializer.Err(consts.CodeParamErr, "查询出错 lists", err)
  183. }
  184. }
  185. for _, v := range lists {
  186. role, err := r.WithContext(ctx).Where(r.ID.Eq(v.RoleID)).First()
  187. v.RoleName = "未绑定角色"
  188. if role != nil && err == nil {
  189. v.RoleName = role.Name
  190. }
  191. }
  192. models.List = lists
  193. models.Page = req.Page
  194. models.PerPage = req.PerPage
  195. models.PageCount = (count + req.PerPage - 1) / req.PerPage
  196. return serializer.Suc(models)
  197. }
  198. func (s *sUser) Edit(ctx *gin.Context, req forms.AdminUserEditReq) serializer.Response {
  199. q := query.Use(config.AdminDB).AdminUser
  200. logrus.Warnf("sUser Edit req:%+v", req)
  201. if req.RoleID <= 0 {
  202. return serializer.ParamErr("角色不能为空", nil)
  203. }
  204. if req.UserName == "" {
  205. return serializer.ParamErr("用户名不能为空", nil)
  206. }
  207. // 修改
  208. if req.ID > 0 {
  209. update := &model.AdminUser{
  210. UserName: req.UserName,
  211. RoleID: int32(req.RoleID),
  212. Nickname: req.Nickname,
  213. Status: req.Status,
  214. UpdatedAt: time.Now(),
  215. }
  216. _, err := q.WithContext(ctx).Where(q.ID.Eq(req.ID)).Updates(update)
  217. if err != nil {
  218. return serializer.Err(consts.CodeParamErr, "更新出错", err)
  219. }
  220. // 维护redis token
  221. config.TokenRedis.Del(config.GetUserTokenKey(req.ID))
  222. return serializer.Suc(nil)
  223. }
  224. if req.Password == "" {
  225. return serializer.ParamErr("密码不能为空", nil)
  226. }
  227. // 加密密码
  228. password, err := s.SetPassword(req.Password)
  229. if err != nil {
  230. return serializer.Err(
  231. consts.CodeEncryptError,
  232. "密码加密失败",
  233. err,
  234. )
  235. }
  236. // 新增
  237. create := &model.AdminUser{
  238. UserName: req.UserName,
  239. RoleID: int32(req.RoleID),
  240. Nickname: req.Nickname,
  241. PasswordDigest: password,
  242. Status: req.Status,
  243. UpdatedAt: time.Now(),
  244. CreatedAt: time.Now(),
  245. }
  246. if err = query.Use(config.AdminDB).AdminUser.WithContext(ctx).Create(create); err != nil {
  247. return serializer.DBErr(err.Error(), err)
  248. }
  249. return serializer.Suc(nil)
  250. }
  251. func (s *sUser) ResetPassword(ctx *gin.Context, req forms.AdminUserResetPasswordReq) serializer.Response {
  252. q := query.Use(config.AdminDB).AdminUser
  253. logrus.Warnf("sUser ResetPassword req:%+v", req)
  254. if req.ID <= 0 {
  255. return serializer.ParamErr("用于ID不能为空", nil)
  256. }
  257. if req.Password == "" {
  258. return serializer.ParamErr("密码不能为空", nil)
  259. }
  260. // 加密密码
  261. password, err := s.SetPassword(req.Password)
  262. if err != nil {
  263. return serializer.Err(
  264. consts.CodeEncryptError,
  265. "密码加密失败",
  266. err,
  267. )
  268. }
  269. update := &model.AdminUser{
  270. PasswordDigest: password,
  271. UpdatedAt: time.Now(),
  272. }
  273. _, err = q.WithContext(ctx).Where(q.ID.Eq(req.ID)).Updates(update)
  274. if err != nil {
  275. return serializer.Err(consts.CodeParamErr, "更新出错", err)
  276. }
  277. // 维护redis token
  278. config.TokenRedis.Del(config.GetUserTokenKey(req.ID))
  279. return serializer.Suc(nil)
  280. }
  281. func (s *sUser) UpdatePassword(ctx *gin.Context, req forms.AdminUserUpdatePasswordReq) serializer.Response {
  282. q := query.Use(config.AdminDB).AdminUser
  283. logrus.Warnf("sUser UpdatePassword req:%+v", req)
  284. userId := token.GetUID(ctx)
  285. if userId <= 0 {
  286. return serializer.ParamErr("用户信息获取失败", nil)
  287. }
  288. models, err := q.WithContext(ctx).Where(q.ID.Eq(userId)).First()
  289. if err != nil {
  290. return serializer.ParamErr(err.Error(), err)
  291. }
  292. if models == nil {
  293. return serializer.ParamErr("用户不存在", nil)
  294. }
  295. if !s.CheckPasswordRight(models.PasswordDigest, req.OldPassword) {
  296. return serializer.ParamErr("老密码不正确", nil)
  297. }
  298. // 加密密码
  299. password, err := s.SetPassword(req.NewPassword)
  300. if err != nil {
  301. return serializer.Err(
  302. consts.CodeEncryptError,
  303. "密码加密失败",
  304. err,
  305. )
  306. }
  307. update := &model.AdminUser{
  308. PasswordDigest: password,
  309. UpdatedAt: time.Now(),
  310. }
  311. _, err = q.WithContext(ctx).Where(q.ID.Eq(userId)).Updates(update)
  312. if err != nil {
  313. return serializer.Err(consts.CodeParamErr, "更新出错", err)
  314. }
  315. // 修改token状态
  316. config.TokenRedis.Del(config.GetUserTokenKey(userId))
  317. return serializer.Suc(nil)
  318. }
  319. func (s *sUser) GetUserInfo(c *gin.Context) (*model.AdminUser, error) {
  320. q := query.Use(config.AdminDB).AdminUser
  321. userId := token.GetUID(c)
  322. if userId <= 0 {
  323. c.JSON(200, serializer.Err(consts.CodeNoPermission, "用户信息获取失败", nil))
  324. c.Abort()
  325. }
  326. return q.WithContext(c).Where(q.ID.Eq(userId)).First()
  327. }
  328. func (s *sUser) GetUserRoleId(c *gin.Context) int64 {
  329. info, err := s.GetUserInfo(c)
  330. if err != nil {
  331. return 0
  332. }
  333. if info == nil {
  334. return 0
  335. }
  336. return int64(info.RoleID)
  337. }
  338. func (s *sUser) GetUserByUnionID(unionID string) (*model.AdminUser, error) {
  339. q := query.Use(config.AdminDB).AdminUser
  340. return q.Where(q.FeishuUnionID.Eq(unionID)).First()
  341. }
  342. func (s *sUser) GetUserRolePermission(c *gin.Context) (bool, error) {
  343. // 只有超管拥有角色管理权限
  344. roleId, _ := c.Get("admin_role_id")
  345. return config.IsSuperRole(roleId.(int64)), nil
  346. //res, ok := c.Get("user")
  347. //if !ok {
  348. // c.JSON(200, serializer.CheckLogin())
  349. // c.Abort()
  350. //}
  351. //user := res.(*token.UserClaims)
  352. //if user.RoleId == 1 { // 超管拥有权限
  353. // return true, nil
  354. //}
  355. //// 查询玩家是否拥有权限管理页面的入口
  356. //pageQ := query.Use(config.AdminDB).AdminMenu
  357. //pageIds := make([]int32, 0)
  358. //err := pageQ.WithContext(c).Where(pageQ.Path.Eq("/permission")).Pluck(pageQ.ID, &pageIds)
  359. //if err != nil {
  360. // logrus.WithField("from", "AdminMenu Pluck").Error(err)
  361. // return false, err
  362. //}
  363. //rmq := query.Use(config.AdminDB).AdminRoleMenu
  364. //count, err := rmq.WithContext(c).Where(rmq.RoleID.Eq(int32(user.RoleId)), rmq.PageID.In(pageIds...)).Count()
  365. //if err != nil {
  366. // logrus.WithField("from", "AdminRoleMenu Count").Error(err)
  367. // return false, err
  368. //}
  369. //if count > 0 {
  370. // return true, nil
  371. //} else {
  372. // return false, nil
  373. //}
  374. }
  375. func (s *sUser) GetUserInfoByID(ctx context.Context, id int64) (*iam.AdminUserInfo, error) {
  376. var (
  377. q = query.Use(config.AdminDB).AdminUser
  378. m = q.WithContext(ctx)
  379. )
  380. user, err := m.Where(q.ID.Eq(id)).First()
  381. if err != nil {
  382. return nil, err
  383. }
  384. if user == nil {
  385. return nil, nil
  386. }
  387. return &iam.AdminUserInfo{
  388. ID: user.ID,
  389. RoleID: int64(user.RoleID),
  390. UserName: user.UserName,
  391. NickName: user.Nickname,
  392. Status: int64(user.Status),
  393. Avatar: user.Avatar,
  394. }, nil
  395. }
  396. func (s *sUser) BatchGetUsers(ctx context.Context, ids []int64) ([]*iam.AdminUserInfo, error) {
  397. var (
  398. q = query.Use(config.AdminDB).AdminUser
  399. m = q.WithContext(ctx)
  400. )
  401. users, err := m.Where(q.ID.In(ids...)).Find()
  402. if err != nil {
  403. return nil, err
  404. }
  405. var result []*iam.AdminUserInfo
  406. for _, v := range users {
  407. result = append(result, &iam.AdminUserInfo{
  408. ID: v.ID,
  409. RoleID: int64(v.RoleID),
  410. UserName: v.UserName,
  411. NickName: v.Nickname,
  412. Status: int64(v.Status),
  413. Avatar: v.Avatar,
  414. })
  415. }
  416. return result, nil
  417. }
  418. func (s *sUser) GetUserByNickName(ctx context.Context, nickName string) (*iam.AdminUserInfo, error) {
  419. var (
  420. q = query.Use(config.AdminDB).AdminUser
  421. m = q.WithContext(ctx)
  422. )
  423. user, err := m.Where(q.Nickname.Eq(nickName)).First()
  424. if err != nil {
  425. return nil, err
  426. }
  427. return &iam.AdminUserInfo{
  428. ID: user.ID,
  429. RoleID: int64(user.RoleID),
  430. UserName: user.UserName,
  431. NickName: user.Nickname,
  432. Status: int64(user.Status),
  433. Avatar: user.Avatar,
  434. }, nil
  435. }
  436. func (s *sUser) GetRoleSystems(ctx context.Context, roleId int64) ([]*iam.SystemInfo, error) {
  437. var (
  438. q = query.Use(config.AdminDB).AdminRole
  439. sq = query.Use(config.AdminDB).AdminSystem
  440. )
  441. systemModels := make([]*model.AdminSystem, 0)
  442. if config.IsSuperRole(roleId) {
  443. models, err := sq.Find()
  444. if err != nil {
  445. logrus.Error(err)
  446. return nil, err
  447. }
  448. systemModels = models
  449. } else {
  450. systems := ""
  451. if err := q.Where(q.ID.Eq(roleId)).Pluck(q.Systems, &systems); err != nil {
  452. return nil, err
  453. }
  454. if systems == "" {
  455. return []*iam.SystemInfo{}, nil
  456. }
  457. systemIds := make([]int32, 0)
  458. if err := json.Unmarshal([]byte(systems), &systemIds); err != nil {
  459. return nil, err
  460. }
  461. models, err := sq.Where(sq.ID.In(systemIds...)).Order(sq.ID).Find()
  462. if err != nil {
  463. logrus.Error(err)
  464. return nil, err
  465. }
  466. systemModels = models
  467. }
  468. services := make([]*iam.SystemInfo, 0)
  469. for _, v := range systemModels {
  470. services = append(services, &iam.SystemInfo{
  471. ID: int64(v.ID),
  472. Name: v.Name,
  473. Url: v.URL,
  474. })
  475. }
  476. return services, nil
  477. }
  478. func (s *sUser) Logout(accessToken string) error {
  479. tokenKey := config.GetTokenKey(accessToken)
  480. if config.TokenRedis.Exists(tokenKey).Val() == 0 {
  481. return nil
  482. }
  483. userStr := config.TokenRedis.Get(tokenKey).Val()
  484. user := new(token.UserClaims)
  485. if err := jsoniter.UnmarshalFromString(userStr, user); err != nil {
  486. logrus.Warningf("middleware jsoniter.UnmarshalFromString:%+v", err.Error())
  487. return err
  488. }
  489. if user.ID == 0 {
  490. config.TokenRedis.Del(tokenKey)
  491. return nil
  492. }
  493. key := config.GetUserTokenKey(user.ID)
  494. config.TokenRedis.HDel(key, accessToken)
  495. config.TokenRedis.Del(tokenKey)
  496. return nil
  497. }