fix(admin): 收紧 isSuper、plan-prices RBAC 与封禁状态机

避免 roles.write 绕过全部 can();定价读写挂 membership.plans 权限;去掉快捷封禁双路径并让 ban/unban 走 lifecycle。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
jackyu66git
2026-08-13 01:56:00 +08:00
co-authored by Cursor
parent 62cd8c45dd
commit 0d50c0ee73
10 changed files with 44 additions and 64 deletions
+4 -28
View File
@@ -39,38 +39,14 @@ func (s *Service) RequireSuper(ctx context.Context, adminID uuid.UUID) error {
return nil
}
// BanUser sets users.status=banned.
// BanUser transitions user status to banned via the lifecycle state machine.
func (s *Service) BanUser(ctx context.Context, adminID, userID uuid.UUID) error {
ok, err := s.Repo.UserExists(ctx, userID)
if err != nil {
return err
}
if !ok {
return ErrUserNotFound
}
meta, _ := json.Marshal(map[string]any{"status": "banned"})
err = s.Repo.SetUserStatusWithAudit(ctx, adminID, userID, "banned", "user.ban", meta)
if errors.Is(err, repository.ErrUserStatusNotFound) {
return ErrUserNotFound
}
return err
return s.TransitionUserStatus(ctx, adminID, userID, "banned", "admin ban")
}
// UnbanUser sets users.status=active.
// UnbanUser transitions user status to active via the lifecycle state machine.
func (s *Service) UnbanUser(ctx context.Context, adminID, userID uuid.UUID) error {
ok, err := s.Repo.UserExists(ctx, userID)
if err != nil {
return err
}
if !ok {
return ErrUserNotFound
}
meta, _ := json.Marshal(map[string]any{"status": "active"})
err = s.Repo.SetUserStatusWithAudit(ctx, adminID, userID, "active", "user.unban", meta)
if errors.Is(err, repository.ErrUserStatusNotFound) {
return ErrUserNotFound
}
return err
return s.TransitionUserStatus(ctx, adminID, userID, "active", "admin unban")
}
// ListAdmins returns admin accounts (super only caller).