| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- package role
- import (
- "errors"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- permModel "perms-system-server/internal/model/perm"
- roleModel "perms-system-server/internal/model/role"
- "perms-system-server/internal/model/roleperm"
- "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"
- "testing"
- "time"
- )
- func TestRoleDetail_Normal(t *testing.T) {
- ctx := ctxhelper.SuperAdminCtx()
- svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
- conn := testutil.GetTestSqlConn()
- now := time.Now().Unix()
- pc := testutil.UniqueId()
- roleRes, err := svcCtx.SysRoleModel.Insert(ctx, &roleModel.SysRole{
- ProductCode: pc, Name: testutil.UniqueId(), Remark: "detail test",
- Status: 1, PermsLevel: 1, CreateTime: now, UpdateTime: now,
- })
- require.NoError(t, err)
- roleId, _ := roleRes.LastInsertId()
- p1Res, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{
- ProductCode: pc, Name: testutil.UniqueId(), Code: testutil.UniqueId(),
- Status: 1, CreateTime: now, UpdateTime: now,
- })
- require.NoError(t, err)
- p1Id, _ := p1Res.LastInsertId()
- p2Res, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{
- ProductCode: pc, Name: testutil.UniqueId(), Code: testutil.UniqueId(),
- Status: 1, CreateTime: now, UpdateTime: now,
- })
- require.NoError(t, err)
- p2Id, _ := p2Res.LastInsertId()
- rp1Res, err := svcCtx.SysRolePermModel.Insert(ctx, &roleperm.SysRolePerm{
- RoleId: roleId, PermId: p1Id, CreateTime: now, UpdateTime: now,
- })
- require.NoError(t, err)
- rp1Id, _ := rp1Res.LastInsertId()
- rp2Res, err := svcCtx.SysRolePermModel.Insert(ctx, &roleperm.SysRolePerm{
- RoleId: roleId, PermId: p2Id, CreateTime: now, UpdateTime: now,
- })
- require.NoError(t, err)
- rp2Id, _ := rp2Res.LastInsertId()
- t.Cleanup(func() {
- testutil.CleanTable(ctx, conn, "`sys_role_perm`", rp1Id, rp2Id)
- testutil.CleanTable(ctx, conn, "`sys_perm`", p1Id, p2Id)
- testutil.CleanTable(ctx, conn, "`sys_role`", roleId)
- })
- logic := NewRoleDetailLogic(ctx, svcCtx)
- resp, err := logic.RoleDetail(&types.RoleDetailReq{Id: roleId})
- require.NoError(t, err)
- assert.Equal(t, roleId, resp.Id)
- assert.Equal(t, pc, resp.ProductCode)
- assert.Equal(t, "detail test", resp.Remark)
- assert.ElementsMatch(t, []int64{p1Id, p2Id}, resp.PermIds)
- }
- // TC-0125: 不存在
- func TestRoleDetail_NotFound(t *testing.T) {
- ctx := ctxhelper.SuperAdminCtx()
- svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
- logic := NewRoleDetailLogic(ctx, svcCtx)
- resp, err := logic.RoleDetail(&types.RoleDetailReq{Id: 999999999})
- assert.Nil(t, resp)
- require.Error(t, err)
- var ce *response.CodeError
- require.True(t, errors.As(err, &ce))
- assert.Equal(t, 404, ce.Code())
- assert.Equal(t, "角色不存在", ce.Error())
- }
- func TestRoleDetail_MN3_CrossProductReturns404NotFound(t *testing.T) {
- ctx := ctxhelper.SuperAdminCtx()
- svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
- conn := testutil.GetTestSqlConn()
- now := time.Now().Unix()
- // 插入别的产品("test_product2")下的 role
- otherProduct := "mn3_other_" + testutil.UniqueId()
- roleRes, err := svcCtx.SysRoleModel.Insert(ctx, &roleModel.SysRole{
- ProductCode: otherProduct, Name: "mn3_role_" + testutil.UniqueId(),
- Remark: "mn3", Status: 1, PermsLevel: 1, CreateTime: now, UpdateTime: now,
- })
- require.NoError(t, err)
- roleId, _ := roleRes.LastInsertId()
- t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_role`", roleId) })
- // Admin 身份在 "test_product" 下访问 "mn3_other_*" 的 roleId
- adminCtx := ctxhelper.AdminCtx("test_product")
- resp, err := NewRoleDetailLogic(adminCtx, svcCtx).RoleDetail(&types.RoleDetailReq{Id: roleId})
- assert.Nil(t, resp)
- require.Error(t, err)
- var ce *response.CodeError
- require.True(t, errors.As(err, &ce))
- assert.Equal(t, 404, ce.Code(),
- "跨产品访问必须 404,不得以 403 暴露存在性")
- assert.Equal(t, "角色不存在", ce.Error(),
- "响应文案必须与 'id 真实不存在' 完全一致,彻底关闭枚举 oracle")
- }
- // TC-1001: 对照 —— "id 不存在" 的响应必须与 "跨产品访问" 完全一致(code 与 body)。
- func TestRoleDetail_MN3_NotFoundAndCrossProduct_Indistinguishable(t *testing.T) {
- svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
- conn := testutil.GetTestSqlConn()
- ctx := ctxhelper.SuperAdminCtx()
- now := time.Now().Unix()
- // 预埋一条别的产品的角色
- otherProduct := "mn3_cmp_" + testutil.UniqueId()
- roleRes, err := svcCtx.SysRoleModel.Insert(ctx, &roleModel.SysRole{
- ProductCode: otherProduct, Name: "mn3cmp_" + testutil.UniqueId(),
- Remark: "", Status: 1, PermsLevel: 1, CreateTime: now, UpdateTime: now,
- })
- require.NoError(t, err)
- existingId, _ := roleRes.LastInsertId()
- t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_role`", existingId) })
- adminCtx := ctxhelper.AdminCtx("test_product")
- // (A) 跨产品访问真实存在的 id
- _, errCross := NewRoleDetailLogic(adminCtx, svcCtx).RoleDetail(&types.RoleDetailReq{Id: existingId})
- require.Error(t, errCross)
- var ceA *response.CodeError
- require.True(t, errors.As(errCross, &ceA))
- // (B) 访问一个肯定不存在的 id(id 选在 existingId + 很大偏移,规避数据库递增到该值)
- _, errAbsent := NewRoleDetailLogic(adminCtx, svcCtx).RoleDetail(
- &types.RoleDetailReq{Id: existingId + 999_999_999},
- )
- require.Error(t, errAbsent)
- var ceB *response.CodeError
- require.True(t, errors.As(errAbsent, &ceB))
- // 响应码与文案必须完全一致,不给任何侧信道
- assert.Equal(t, ceB.Code(), ceA.Code(),
- "跨产品 vs id 不存在必须返回相同 code")
- assert.Equal(t, ceB.Error(), ceA.Error(),
- "跨产品 vs id 不存在必须返回相同 body")
- }
- // TC-1002: 超管跨产品仍然可以正常访问(/运维路径不能被误伤)。
- func TestRoleDetail_MN3_SuperAdminCanStillAccessCrossProduct(t *testing.T) {
- ctx := ctxhelper.SuperAdminCtx()
- svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
- conn := testutil.GetTestSqlConn()
- now := time.Now().Unix()
- otherProduct := "mn3_sa_" + testutil.UniqueId()
- roleRes, err := svcCtx.SysRoleModel.Insert(ctx, &roleModel.SysRole{
- ProductCode: otherProduct, Name: "mn3sa_" + testutil.UniqueId(),
- Remark: "sa_cross", Status: 1, PermsLevel: 1, CreateTime: now, UpdateTime: now,
- })
- require.NoError(t, err)
- roleId, _ := roleRes.LastInsertId()
- permRes, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{
- ProductCode: otherProduct, Name: "mn3sa_p_" + testutil.UniqueId(), Code: testutil.UniqueId(),
- Status: 1, CreateTime: now, UpdateTime: now,
- })
- require.NoError(t, err)
- permId, _ := permRes.LastInsertId()
- rpRes, err := svcCtx.SysRolePermModel.Insert(ctx, &roleperm.SysRolePerm{
- RoleId: roleId, PermId: permId, CreateTime: now, UpdateTime: now,
- })
- require.NoError(t, err)
- rpId, _ := rpRes.LastInsertId()
- t.Cleanup(func() {
- testutil.CleanTable(ctx, conn, "`sys_role_perm`", rpId)
- testutil.CleanTable(ctx, conn, "`sys_perm`", permId)
- testutil.CleanTable(ctx, conn, "`sys_role`", roleId)
- })
- // 超管在 "test_product" 当前身份,但跨产品访问 "mn3_sa_*" 的 role,应允许
- resp, err := NewRoleDetailLogic(ctx, svcCtx).RoleDetail(&types.RoleDetailReq{Id: roleId})
- require.NoError(t, err, "超管必须能跨产品查看 role,支撑/运维路径")
- require.NotNil(t, resp)
- assert.Equal(t, roleId, resp.Id)
- assert.Equal(t, otherProduct, resp.ProductCode)
- assert.Contains(t, resp.PermIds, permId)
- }
|