| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- package user
- import (
- "context"
- "errors"
- "math"
- "testing"
- "time"
- "perms-system-server/internal/consts"
- "perms-system-server/internal/loaders"
- "perms-system-server/internal/middleware"
- permModel "perms-system-server/internal/model/perm"
- productModel "perms-system-server/internal/model/product"
- "perms-system-server/internal/response"
- "perms-system-server/internal/svc"
- "perms-system-server/internal/testutil"
- "perms-system-server/internal/types"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- )
- // TC-0743: H-A 修复回归 —— 普通 MEMBER 不得通过 SetUserPerms 给自己授予任何权限
- // (RequireProductAdminFor 前置校验必须拦截)。
- func TestSetUserPerms_MemberCannotSelfEscalate(t *testing.T) {
- svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
- conn := testutil.GetTestSqlConn()
- now := time.Now().Unix()
- bootstrap := context.Background()
- code := testutil.UniqueId()
- pRes, err := svcCtx.SysProductModel.Insert(bootstrap, &productModel.SysProduct{
- Code: code, Name: "p_" + code, AppKey: code + "_k", AppSecret: "s",
- Status: consts.StatusEnabled, CreateTime: now, UpdateTime: now,
- })
- require.NoError(t, err)
- pId, _ := pRes.LastInsertId()
- username := testutil.UniqueId()
- userId := insertTestUser(t, bootstrap, username, testutil.HashPassword("pw"))
- mId := insertTestMember(t, svcCtx, code, userId)
- permRes, err := svcCtx.SysPermModel.Insert(bootstrap, &permModel.SysPerm{
- ProductCode: code, Name: "escalate_p", Code: "esc_" + testutil.UniqueId(),
- Status: consts.StatusEnabled, CreateTime: now, UpdateTime: now,
- })
- require.NoError(t, err)
- permId, _ := permRes.LastInsertId()
- t.Cleanup(func() {
- testutil.CleanTableByField(bootstrap, conn, "`sys_user_perm`", "userId", userId)
- testutil.CleanTable(bootstrap, conn, "`sys_product_member`", mId)
- testutil.CleanTable(bootstrap, conn, "`sys_perm`", permId)
- testutil.CleanTable(bootstrap, conn, "`sys_user`", userId)
- testutil.CleanTable(bootstrap, conn, "`sys_product`", pId)
- })
- // caller = 目标用户本人,MemberType=MEMBER(非 ADMIN)
- callerCtx := middleware.WithUserDetails(context.Background(), &loaders.UserDetails{
- UserId: userId, Username: username,
- IsSuperAdmin: false,
- MemberType: consts.MemberTypeMember,
- Status: consts.StatusEnabled,
- ProductCode: code,
- DeptId: 1,
- DeptPath: "/1/",
- MinPermsLevel: math.MaxInt64,
- })
- err = NewSetUserPermsLogic(callerCtx, svcCtx).SetUserPerms(&types.SetPermsReq{
- UserId: userId, // 给自己
- Perms: []types.UserPermItem{{PermId: permId, Effect: consts.PermEffectAllow}},
- })
- require.Error(t, err, "MEMBER 不得自我授权")
- var ce *response.CodeError
- require.True(t, errors.As(err, &ce))
- assert.Equal(t, 403, ce.Code())
- assert.Contains(t, ce.Error(), "仅超级管理员或该产品的管理员可执行此操作")
- // 二次确认:没有任何 user_perm 记录被写入
- rows := findUserPerms(t, bootstrap, userId)
- assert.Len(t, rows, 0, "被拒绝的 SetUserPerms 不得在 DB 残留任何个性化权限")
- }
- // TC-0744: H-A 修复回归 —— DEVELOPER 调用者(非 ADMIN)同样被拦截,即便目标不是自己。
- func TestSetUserPerms_DeveloperCallerRejected(t *testing.T) {
- svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
- conn := testutil.GetTestSqlConn()
- bootstrap := context.Background()
- now := time.Now().Unix()
- code := testutil.UniqueId()
- pRes, err := svcCtx.SysProductModel.Insert(bootstrap, &productModel.SysProduct{
- Code: code, Name: "p_" + code, AppKey: code + "_k", AppSecret: "s",
- Status: consts.StatusEnabled, CreateTime: now, UpdateTime: now,
- })
- require.NoError(t, err)
- pId, _ := pRes.LastInsertId()
- targetUsername := "target_" + testutil.UniqueId()
- targetId := insertTestUser(t, bootstrap, targetUsername, testutil.HashPassword("pw"))
- mId := insertTestMember(t, svcCtx, code, targetId)
- t.Cleanup(func() {
- testutil.CleanTable(bootstrap, conn, "`sys_product_member`", mId)
- testutil.CleanTable(bootstrap, conn, "`sys_user`", targetId)
- testutil.CleanTable(bootstrap, conn, "`sys_product`", pId)
- })
- devCtx := middleware.WithUserDetails(context.Background(), &loaders.UserDetails{
- UserId: 777777, Username: "dev_caller",
- MemberType: consts.MemberTypeDeveloper, Status: consts.StatusEnabled,
- ProductCode: code, DeptId: 1, DeptPath: "/1/", MinPermsLevel: math.MaxInt64,
- })
- err = NewSetUserPermsLogic(devCtx, svcCtx).SetUserPerms(&types.SetPermsReq{
- UserId: targetId, Perms: []types.UserPermItem{},
- })
- require.Error(t, err)
- var ce *response.CodeError
- require.True(t, errors.As(err, &ce))
- assert.Equal(t, 403, ce.Code())
- assert.Contains(t, ce.Error(), "仅超级管理员或该产品的管理员可执行此操作")
- }
- // TC-0745: H-A 正向回归 —— 同产品 ADMIN 操作合法 MEMBER 目标(非自己)依旧放行。
- func TestSetUserPerms_ProductAdminStillWorks(t *testing.T) {
- svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
- conn := testutil.GetTestSqlConn()
- bootstrap := context.Background()
- now := time.Now().Unix()
- code := testutil.UniqueId()
- pRes, err := svcCtx.SysProductModel.Insert(bootstrap, &productModel.SysProduct{
- Code: code, Name: "p_" + code, AppKey: code + "_k", AppSecret: "s",
- Status: consts.StatusEnabled, CreateTime: now, UpdateTime: now,
- })
- require.NoError(t, err)
- pId, _ := pRes.LastInsertId()
- targetId := insertTestUser(t, bootstrap, "tgt_"+testutil.UniqueId(), testutil.HashPassword("pw"))
- mId := insertTestMember(t, svcCtx, code, targetId)
- permRes, err := svcCtx.SysPermModel.Insert(bootstrap, &permModel.SysPerm{
- ProductCode: code, Name: "ok_p", Code: "ok_" + testutil.UniqueId(),
- Status: consts.StatusEnabled, CreateTime: now, UpdateTime: now,
- })
- require.NoError(t, err)
- permId, _ := permRes.LastInsertId()
- t.Cleanup(func() {
- testutil.CleanTableByField(bootstrap, conn, "`sys_user_perm`", "userId", targetId)
- testutil.CleanTable(bootstrap, conn, "`sys_product_member`", mId)
- testutil.CleanTable(bootstrap, conn, "`sys_perm`", permId)
- testutil.CleanTable(bootstrap, conn, "`sys_user`", targetId)
- testutil.CleanTable(bootstrap, conn, "`sys_product`", pId)
- })
- adminCtx := middleware.WithUserDetails(context.Background(), &loaders.UserDetails{
- UserId: 999999, Username: "admin_caller",
- MemberType: consts.MemberTypeAdmin, Status: consts.StatusEnabled,
- ProductCode: code, DeptId: 1, DeptPath: "/1/", MinPermsLevel: math.MaxInt64,
- })
- err = NewSetUserPermsLogic(adminCtx, svcCtx).SetUserPerms(&types.SetPermsReq{
- UserId: targetId,
- Perms: []types.UserPermItem{{PermId: permId, Effect: consts.PermEffectAllow}},
- })
- require.NoError(t, err, "产品 ADMIN 正常路径必须放行")
- rows := findUserPerms(t, bootstrap, targetId)
- assert.Len(t, rows, 1, "ADMIN 授权后 DB 应有 1 条 user_perm")
- }
|