admin_user.go 12 KB

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