updateRoleAudit_test.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package role
  2. import (
  3. "errors"
  4. "testing"
  5. "time"
  6. roleModel "perms-system-server/internal/model/role"
  7. "perms-system-server/internal/response"
  8. "perms-system-server/internal/svc"
  9. "perms-system-server/internal/testutil"
  10. "perms-system-server/internal/testutil/ctxhelper"
  11. "perms-system-server/internal/types"
  12. "github.com/stretchr/testify/assert"
  13. "github.com/stretchr/testify/require"
  14. )
  15. // TC-0730: 修复:非超管 admin 不能把角色权限**提升**(数字越小 = 权限越高)
  16. // 修复前的源码注释写作"不能降低 PermsLevel",与实际代码 `req.PermsLevel < role.PermsLevel → 403`
  17. // 的语义相反(数字越小 = 权限越高,`<` 拦截的是"提升"); 把 Error msg 与注释一并修正,
  18. // 测试随之把断言从"不能降低"改为"不能提升",钉死 R12 后的语义契约。
  19. func TestUpdateRole_NonSuperAdminCannotPromoteLevel(t *testing.T) {
  20. ctx := ctxhelper.SuperAdminCtx()
  21. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  22. conn := testutil.GetTestSqlConn()
  23. now := time.Now().Unix()
  24. pc := testutil.UniqueId()
  25. pid := mustInsertEnabledProduct(t, ctx, svcCtx, pc)
  26. roleRes, err := svcCtx.SysRoleModel.Insert(ctx, &roleModel.SysRole{
  27. ProductCode: pc, Name: testutil.UniqueId(),
  28. Status: 1, PermsLevel: 100, CreateTime: now, UpdateTime: now,
  29. })
  30. require.NoError(t, err)
  31. roleId, _ := roleRes.LastInsertId()
  32. t.Cleanup(func() {
  33. testutil.CleanTable(ctx, conn, "`sys_role`", roleId)
  34. testutil.CleanTable(ctx, conn, "`sys_product`", pid)
  35. })
  36. adminCtx := ctxhelper.AdminCtx(pc)
  37. // 100 → 10:数字变小 = 权限提升,修复后应被拒
  38. err = NewUpdateRoleLogic(adminCtx, svcCtx).UpdateRole(&types.UpdateRoleReq{
  39. Id: roleId, Name: "high", Remark: "promote attempt", PermsLevel: 10,
  40. })
  41. require.Error(t, err)
  42. var ce *response.CodeError
  43. require.True(t, errors.As(err, &ce))
  44. assert.Equal(t, 403, ce.Code())
  45. assert.Contains(t, ce.Error(), "不能提升角色的权限级别",
  46. "错误消息必须与代码语义一致;历史上这里写作'不能降低',方向反向,"+
  47. "本断言锁死 R12 修复后的正向消息,不允许回退")
  48. persisted, err := svcCtx.SysRoleModel.FindOne(ctx, roleId)
  49. require.NoError(t, err)
  50. assert.Equal(t, int64(100), persisted.PermsLevel, "PermsLevel 必须保持不变")
  51. }
  52. // TC-0731: 修复:非超管 admin 可以保持或提升 PermsLevel
  53. func TestUpdateRole_NonSuperAdminCanRaiseOrKeepLevel(t *testing.T) {
  54. ctx := ctxhelper.SuperAdminCtx()
  55. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  56. conn := testutil.GetTestSqlConn()
  57. now := time.Now().Unix()
  58. pc := testutil.UniqueId()
  59. pid := mustInsertEnabledProduct(t, ctx, svcCtx, pc)
  60. roleRes, err := svcCtx.SysRoleModel.Insert(ctx, &roleModel.SysRole{
  61. ProductCode: pc, Name: testutil.UniqueId(),
  62. Status: 1, PermsLevel: 100, CreateTime: now, UpdateTime: now,
  63. })
  64. require.NoError(t, err)
  65. roleId, _ := roleRes.LastInsertId()
  66. t.Cleanup(func() {
  67. testutil.CleanTable(ctx, conn, "`sys_role`", roleId)
  68. testutil.CleanTable(ctx, conn, "`sys_product`", pid)
  69. })
  70. adminCtx := ctxhelper.AdminCtx(pc)
  71. require.NoError(t, NewUpdateRoleLogic(adminCtx, svcCtx).UpdateRole(&types.UpdateRoleReq{
  72. Id: roleId, Name: "keep", Remark: "keep level", PermsLevel: 100,
  73. }), "PermsLevel 保持不变应允许")
  74. require.NoError(t, NewUpdateRoleLogic(adminCtx, svcCtx).UpdateRole(&types.UpdateRoleReq{
  75. Id: roleId, Name: "raise", Remark: "raise level", PermsLevel: 500,
  76. }), "PermsLevel 提升应允许")
  77. persisted, err := svcCtx.SysRoleModel.FindOne(ctx, roleId)
  78. require.NoError(t, err)
  79. assert.Equal(t, int64(500), persisted.PermsLevel)
  80. }
  81. // TC-0732: :超管可以任意降低 PermsLevel
  82. func TestUpdateRole_SuperAdminCanDemoteLevel(t *testing.T) {
  83. ctx := ctxhelper.SuperAdminCtx()
  84. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  85. conn := testutil.GetTestSqlConn()
  86. now := time.Now().Unix()
  87. pc := testutil.UniqueId()
  88. pid := mustInsertEnabledProduct(t, ctx, svcCtx, pc)
  89. roleRes, err := svcCtx.SysRoleModel.Insert(ctx, &roleModel.SysRole{
  90. ProductCode: pc, Name: testutil.UniqueId(),
  91. Status: 1, PermsLevel: 500, CreateTime: now, UpdateTime: now,
  92. })
  93. require.NoError(t, err)
  94. roleId, _ := roleRes.LastInsertId()
  95. t.Cleanup(func() {
  96. testutil.CleanTable(ctx, conn, "`sys_role`", roleId)
  97. testutil.CleanTable(ctx, conn, "`sys_product`", pid)
  98. })
  99. require.NoError(t, NewUpdateRoleLogic(ctx, svcCtx).UpdateRole(&types.UpdateRoleReq{
  100. Id: roleId, Name: "down", Remark: "superadmin demote", PermsLevel: 10,
  101. }))
  102. persisted, err := svcCtx.SysRoleModel.FindOne(ctx, roleId)
  103. require.NoError(t, err)
  104. assert.Equal(t, int64(10), persisted.PermsLevel)
  105. }
  106. // TC-0733: :边界 PermsLevel 校验
  107. func TestUpdateRole_PermsLevelBoundary(t *testing.T) {
  108. ctx := ctxhelper.SuperAdminCtx()
  109. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  110. conn := testutil.GetTestSqlConn()
  111. now := time.Now().Unix()
  112. pc := testutil.UniqueId()
  113. pid := mustInsertEnabledProduct(t, ctx, svcCtx, pc)
  114. roleRes, err := svcCtx.SysRoleModel.Insert(ctx, &roleModel.SysRole{
  115. ProductCode: pc, Name: testutil.UniqueId(),
  116. Status: 1, PermsLevel: 50, CreateTime: now, UpdateTime: now,
  117. })
  118. require.NoError(t, err)
  119. roleId, _ := roleRes.LastInsertId()
  120. t.Cleanup(func() {
  121. testutil.CleanTable(ctx, conn, "`sys_role`", roleId)
  122. testutil.CleanTable(ctx, conn, "`sys_product`", pid)
  123. })
  124. for _, level := range []int64{0, -1, 1000, 10000} {
  125. err := NewUpdateRoleLogic(ctx, svcCtx).UpdateRole(&types.UpdateRoleReq{
  126. Id: roleId, Name: "b", PermsLevel: level,
  127. })
  128. require.Error(t, err, "PermsLevel=%d 应当被拒", level)
  129. var ce *response.CodeError
  130. require.True(t, errors.As(err, &ce))
  131. assert.Equal(t, 400, ce.Code())
  132. }
  133. }