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") }