removeMemberLogic.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. package member
  2. import (
  3. "context"
  4. "perms-system-server/internal/consts"
  5. "perms-system-server/internal/loaders"
  6. authHelper "perms-system-server/internal/logic/auth"
  7. "perms-system-server/internal/response"
  8. "perms-system-server/internal/svc"
  9. "perms-system-server/internal/types"
  10. "github.com/zeromicro/go-zero/core/logx"
  11. "github.com/zeromicro/go-zero/core/stores/sqlx"
  12. )
  13. type RemoveMemberLogic struct {
  14. logx.Logger
  15. ctx context.Context
  16. svcCtx *svc.ServiceContext
  17. }
  18. func NewRemoveMemberLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RemoveMemberLogic {
  19. return &RemoveMemberLogic{
  20. Logger: logx.WithContext(ctx),
  21. ctx: ctx,
  22. svcCtx: svcCtx,
  23. }
  24. }
  25. // RemoveMember 移除产品成员。在事务内同时清理该用户在产品下的角色和个性化权限绑定后移除成员记录。不能移除产品的最后一个 ADMIN。
  26. func (l *RemoveMemberLogic) RemoveMember(req *types.RemoveMemberReq) error {
  27. member, err := l.svcCtx.SysProductMemberModel.FindOne(l.ctx, req.Id)
  28. if err != nil {
  29. return response.ErrNotFound("成员不存在")
  30. }
  31. if err := authHelper.CheckManageAccess(l.ctx, l.svcCtx, member.UserId, member.ProductCode); err != nil {
  32. return err
  33. }
  34. if err := l.svcCtx.SysProductMemberModel.TransactCtx(l.ctx, func(ctx context.Context, session sqlx.Session) error {
  35. locked, err := l.svcCtx.SysProductMemberModel.FindOneForUpdateTx(ctx, session, req.Id)
  36. if err != nil {
  37. return response.ErrNotFound("成员不存在")
  38. }
  39. if locked.MemberType == consts.MemberTypeAdmin && locked.Status == consts.StatusEnabled {
  40. // 使用 CountOtherActiveAdminsTx 排除目标自己,返回 0 即目标为最后一个 active admin,
  41. // 不再依赖"count<=1 包含自己"的反向推理(见审计 L-5)。
  42. otherAdminCount, err := l.svcCtx.SysProductMemberModel.CountOtherActiveAdminsTx(ctx, session, member.ProductCode, locked.Id)
  43. if err != nil {
  44. return err
  45. }
  46. if otherAdminCount == 0 {
  47. return response.ErrBadRequest("不能移除该产品的最后一个管理员")
  48. }
  49. }
  50. if err := l.svcCtx.SysUserRoleModel.DeleteByUserIdForProductTx(ctx, session, member.UserId, member.ProductCode); err != nil {
  51. return err
  52. }
  53. if err := l.svcCtx.SysUserPermModel.DeleteByUserIdForProductTx(ctx, session, member.UserId, member.ProductCode); err != nil {
  54. return err
  55. }
  56. return l.svcCtx.SysProductMemberModel.DeleteWithTx(ctx, session, req.Id)
  57. }); err != nil {
  58. return err
  59. }
  60. // 审计 L-R13-5 方案 A:移除成员后 UD 里仍有旧 MemberType / Roles / Perms,必须立刻失效;
  61. // 断连也不能让"已移除"的会话继续活 5 分钟。
  62. cleanCtx, cancel := loaders.DetachCacheCleanCtx(l.ctx)
  63. defer cancel()
  64. l.svcCtx.UserDetailsLoader.Del(cleanCtx, member.UserId, member.ProductCode)
  65. return nil
  66. }