| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- package user
- import (
- "errors"
- "testing"
- "perms-system-server/internal/consts"
- "perms-system-server/internal/loaders"
- userModel "perms-system-server/internal/model/user"
- "perms-system-server/internal/response"
- "perms-system-server/internal/svc"
- "perms-system-server/internal/testutil"
- "perms-system-server/internal/testutil/ctxhelper"
- "perms-system-server/internal/types"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- )
- // ---------------------------------------------------------------------------
- // 覆盖目标:审计 H-3 修复 —— "不能分配与自己同级(或更高)的角色"。
- // 修复前代码仅拦 `>` 严格高于,允许 MEMBER 调用者把同级角色分配给别人,继而下一次 BindRoles 时
- // 由于同级权限集相同,可用后续 upgrade 路径放大;修复后变为 `<=`(含同级)拦截。
- // 本文件作为"同级也必须 403"的契约锚点。
- // ---------------------------------------------------------------------------
- // TC-0813: H-3 —— MEMBER 调用者不能分配与自己同 permsLevel 的角色。
- func TestBindRoles_EqualPermsLevel_Rejected(t *testing.T) {
- svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
- conn := testutil.GetTestSqlConn()
- superCtx := ctxhelper.SuperAdminCtx()
- deptId, deptPath, cleanupDept := setupDeptForCaller(t, svcCtx)
- t.Cleanup(cleanupDept)
- productCode := "test_product"
- username := testutil.UniqueId()
- targetUserId := insertTestUserFull(t, superCtx, &userModel.SysUser{
- Username: username, Password: testutil.HashPassword("pass"),
- Nickname: "tgt_eq", DeptId: deptId,
- IsSuperAdmin: consts.IsSuperAdminNo, MustChangePassword: 2, Status: consts.StatusEnabled,
- })
- mId := insertTestMember(t, svcCtx, productCode, targetUserId)
- const callerLevel int64 = 50
- sameLevelRole := insertTestRoleWithLevel(t, svcCtx, productCode, consts.StatusEnabled, callerLevel)
- t.Cleanup(func() {
- testutil.CleanTableByField(superCtx, conn, "`sys_user_role`", "userId", targetUserId)
- testutil.CleanTable(superCtx, conn, "`sys_product_member`", mId)
- testutil.CleanTable(superCtx, conn, "`sys_user`", targetUserId)
- testutil.CleanTable(superCtx, conn, "`sys_role`", sameLevelRole)
- })
- ctx := ctxhelper.CustomCtx(&loaders.UserDetails{
- UserId: 999994,
- Username: "member_eq_level",
- IsSuperAdmin: false,
- MemberType: consts.MemberTypeMember,
- Status: consts.StatusEnabled,
- ProductCode: productCode,
- DeptId: deptId,
- DeptPath: deptPath,
- MinPermsLevel: callerLevel,
- })
- err := NewBindRolesLogic(ctx, svcCtx).BindRoles(&types.BindRolesReq{
- UserId: targetUserId,
- RoleIds: []int64{sameLevelRole},
- })
- require.Error(t, err, "H-3 防线:同级角色分配必须被拒绝(含同级)")
- var ce *response.CodeError
- require.True(t, errors.As(err, &ce))
- assert.Equal(t, 403, ce.Code())
- assert.Contains(t, ce.Error(), "不能分配权限级别高于自身的角色",
- "错误消息应当明确点出'含同级'的拦截语义")
- // 同时验证 DB 未产生任何 user-role 关系。
- rids, err := svcCtx.SysUserRoleModel.FindRoleIdsByUserIdForProduct(ctx, targetUserId, productCode)
- require.NoError(t, err)
- assert.Empty(t, rids, "被拒绝的 BindRoles 不得落地任何行")
- }
|