package user import ( "context" "errors" "testing" "time" permModel "perms-system-server/internal/model/perm" "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" ) type userPermRow struct { Id int64 `db:"id"` UserId int64 `db:"userId"` PermId int64 `db:"permId"` Effect string `db:"effect"` } func findUserPerms(t *testing.T, ctx context.Context, userId int64) []userPermRow { t.Helper() conn := testutil.GetTestSqlConn() var rows []userPermRow require.NoError(t, conn.QueryRowsCtx(ctx, &rows, "SELECT `id`,`userId`,`permId`,`effect` FROM `sys_user_perm` WHERE `userId`=?", userId)) return rows } func insertTestPerm(t *testing.T, svcCtx *svc.ServiceContext, productCode string) int64 { t.Helper() now := time.Now().Unix() res, err := svcCtx.SysPermModel.Insert(ctxhelper.SuperAdminCtx(), &permModel.SysPerm{ ProductCode: productCode, Name: "perm_" + testutil.UniqueId(), Code: "code_" + testutil.UniqueId(), Status: 1, CreateTime: now, UpdateTime: now, }) require.NoError(t, err) id, _ := res.LastInsertId() return id } // TC-0192: 正常ALLOW func TestSetUserPerms_Allow(t *testing.T) { ctx := ctxhelper.SuperAdminCtx() svcCtx := svc.NewServiceContext(testutil.GetTestConfig()) conn := testutil.GetTestSqlConn() username := testutil.UniqueId() userId := insertTestUser(t, ctx, username, testutil.HashPassword("pass")) mId := insertTestMember(t, svcCtx, "test_product", userId) p1 := insertTestPerm(t, svcCtx, "test_product") p2 := insertTestPerm(t, svcCtx, "test_product") t.Cleanup(func() { testutil.CleanTableByField(ctx, conn, "`sys_user_perm`", "userId", userId) testutil.CleanTable(ctx, conn, "`sys_product_member`", mId) testutil.CleanTable(ctx, conn, "`sys_user`", userId) testutil.CleanTable(ctx, conn, "`sys_perm`", p1, p2) }) logic := NewSetUserPermsLogic(ctx, svcCtx) err := logic.SetUserPerms(&types.SetPermsReq{ UserId: userId, Perms: []types.UserPermItem{ {PermId: p1, Effect: "ALLOW"}, {PermId: p2, Effect: "ALLOW"}, }, }) require.NoError(t, err) perms := findUserPerms(t, ctx, userId) assert.Len(t, perms, 2) for _, p := range perms { assert.Equal(t, "ALLOW", p.Effect) } } // TC-0194: DENY权限 func TestSetUserPerms_Deny(t *testing.T) { ctx := ctxhelper.SuperAdminCtx() svcCtx := svc.NewServiceContext(testutil.GetTestConfig()) conn := testutil.GetTestSqlConn() username := testutil.UniqueId() userId := insertTestUser(t, ctx, username, testutil.HashPassword("pass")) mId := insertTestMember(t, svcCtx, "test_product", userId) p1 := insertTestPerm(t, svcCtx, "test_product") t.Cleanup(func() { testutil.CleanTableByField(ctx, conn, "`sys_user_perm`", "userId", userId) testutil.CleanTable(ctx, conn, "`sys_product_member`", mId) testutil.CleanTable(ctx, conn, "`sys_user`", userId) testutil.CleanTable(ctx, conn, "`sys_perm`", p1) }) logic := NewSetUserPermsLogic(ctx, svcCtx) err := logic.SetUserPerms(&types.SetPermsReq{ UserId: userId, Perms: []types.UserPermItem{ {PermId: p1, Effect: "DENY"}, }, }) require.NoError(t, err) perms := findUserPerms(t, ctx, userId) require.Len(t, perms, 1) assert.Equal(t, "DENY", perms[0].Effect) assert.Equal(t, p1, perms[0].PermId) } // TC-0193: 用户不存在 func TestSetUserPerms_UserNotFound(t *testing.T) { ctx := ctxhelper.SuperAdminCtx() svcCtx := svc.NewServiceContext(testutil.GetTestConfig()) logic := NewSetUserPermsLogic(ctx, svcCtx) err := logic.SetUserPerms(&types.SetPermsReq{ UserId: 999999999, Perms: []types.UserPermItem{ {PermId: 1, Effect: "ALLOW"}, }, }) require.Error(t, err) var codeErr *response.CodeError require.True(t, errors.As(err, &codeErr)) assert.Equal(t, 404, codeErr.Code()) assert.Equal(t, "用户不存在", codeErr.Error()) } // TC-0195: 清空权限 func TestSetUserPerms_EmptyPerms_ClearsAll(t *testing.T) { ctx := ctxhelper.SuperAdminCtx() svcCtx := svc.NewServiceContext(testutil.GetTestConfig()) conn := testutil.GetTestSqlConn() username := testutil.UniqueId() userId := insertTestUser(t, ctx, username, testutil.HashPassword("pass")) mId := insertTestMember(t, svcCtx, "test_product", userId) p1 := insertTestPerm(t, svcCtx, "test_product") t.Cleanup(func() { testutil.CleanTableByField(ctx, conn, "`sys_user_perm`", "userId", userId) testutil.CleanTable(ctx, conn, "`sys_product_member`", mId) testutil.CleanTable(ctx, conn, "`sys_user`", userId) testutil.CleanTable(ctx, conn, "`sys_perm`", p1) }) logic := NewSetUserPermsLogic(ctx, svcCtx) err := logic.SetUserPerms(&types.SetPermsReq{ UserId: userId, Perms: []types.UserPermItem{ {PermId: p1, Effect: "ALLOW"}, }, }) require.NoError(t, err) err = logic.SetUserPerms(&types.SetPermsReq{ UserId: userId, Perms: []types.UserPermItem{}, }) require.NoError(t, err) perms := findUserPerms(t, ctx, userId) assert.Empty(t, perms) } // TC-0196: 无效Effect值 func TestSetUserPerms_InvalidEffect(t *testing.T) { ctx := ctxhelper.SuperAdminCtx() svcCtx := svc.NewServiceContext(testutil.GetTestConfig()) conn := testutil.GetTestSqlConn() username := testutil.UniqueId() userId := insertTestUser(t, ctx, username, testutil.HashPassword("pass")) mId := insertTestMember(t, svcCtx, "test_product", userId) t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_product_member`", mId) testutil.CleanTable(ctx, conn, "`sys_user`", userId) }) logic := NewSetUserPermsLogic(ctx, svcCtx) err := logic.SetUserPerms(&types.SetPermsReq{ UserId: userId, Perms: []types.UserPermItem{ {PermId: 1, Effect: "INVALID"}, }, }) require.Error(t, err) var codeErr *response.CodeError require.True(t, errors.As(err, &codeErr)) assert.Equal(t, 400, codeErr.Code()) assert.Contains(t, codeErr.Error(), "effect值无效") } // TC-0197: PermId不存在 func TestSetUserPerms_PermNotExists(t *testing.T) { ctx := ctxhelper.SuperAdminCtx() svcCtx := svc.NewServiceContext(testutil.GetTestConfig()) conn := testutil.GetTestSqlConn() username := testutil.UniqueId() userId := insertTestUser(t, ctx, username, testutil.HashPassword("pass")) mId := insertTestMember(t, svcCtx, "test_product", userId) t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_product_member`", mId) testutil.CleanTable(ctx, conn, "`sys_user`", userId) }) logic := NewSetUserPermsLogic(ctx, svcCtx) err := logic.SetUserPerms(&types.SetPermsReq{ UserId: userId, Perms: []types.UserPermItem{ {PermId: 999999999, Effect: "ALLOW"}, }, }) require.Error(t, err) var codeErr *response.CodeError require.True(t, errors.As(err, &codeErr)) assert.Equal(t, 400, codeErr.Code()) assert.Contains(t, codeErr.Error(), "无效的权限ID") } // TC-0198: 权限不属于当前产品 func TestSetUserPerms_PermBelongsToOtherProduct(t *testing.T) { ctx := ctxhelper.SuperAdminCtx() svcCtx := svc.NewServiceContext(testutil.GetTestConfig()) conn := testutil.GetTestSqlConn() username := testutil.UniqueId() userId := insertTestUser(t, ctx, username, testutil.HashPassword("pass")) mId := insertTestMember(t, svcCtx, "test_product", userId) otherPerm := insertTestPerm(t, svcCtx, "other_product") t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_product_member`", mId) testutil.CleanTable(ctx, conn, "`sys_user`", userId) testutil.CleanTable(ctx, conn, "`sys_perm`", otherPerm) }) logic := NewSetUserPermsLogic(ctx, svcCtx) err := logic.SetUserPerms(&types.SetPermsReq{ UserId: userId, Perms: []types.UserPermItem{ {PermId: otherPerm, Effect: "ALLOW"}, }, }) require.Error(t, err) var codeErr *response.CodeError require.True(t, errors.As(err, &codeErr)) assert.Equal(t, 400, codeErr.Code()) assert.Contains(t, codeErr.Error(), "其他产品的权限") } // TC-0210: 同一权限ID同时为ALLOW和DENY被拒绝 func TestSetUserPerms_ConflictingEffects(t *testing.T) { ctx := ctxhelper.SuperAdminCtx() svcCtx := svc.NewServiceContext(testutil.GetTestConfig()) conn := testutil.GetTestSqlConn() username := testutil.UniqueId() userId := insertTestUser(t, ctx, username, testutil.HashPassword("pass")) mId := insertTestMember(t, svcCtx, "test_product", userId) p1 := insertTestPerm(t, svcCtx, "test_product") t.Cleanup(func() { testutil.CleanTableByField(ctx, conn, "`sys_user_perm`", "userId", userId) testutil.CleanTable(ctx, conn, "`sys_product_member`", mId) testutil.CleanTable(ctx, conn, "`sys_user`", userId) testutil.CleanTable(ctx, conn, "`sys_perm`", p1) }) logic := NewSetUserPermsLogic(ctx, svcCtx) err := logic.SetUserPerms(&types.SetPermsReq{ UserId: userId, Perms: []types.UserPermItem{ {PermId: p1, Effect: "ALLOW"}, {PermId: p1, Effect: "DENY"}, }, }) require.Error(t, err) var codeErr *response.CodeError require.True(t, errors.As(err, &codeErr)) assert.Equal(t, 400, codeErr.Code()) assert.Contains(t, codeErr.Error(), "同一权限ID不能同时为 ALLOW 和 DENY") } // TC-0211: 重复的权限ID相同Effect被去重 func TestSetUserPerms_DuplicatePermDedup(t *testing.T) { ctx := ctxhelper.SuperAdminCtx() svcCtx := svc.NewServiceContext(testutil.GetTestConfig()) conn := testutil.GetTestSqlConn() username := testutil.UniqueId() userId := insertTestUser(t, ctx, username, testutil.HashPassword("pass")) mId := insertTestMember(t, svcCtx, "test_product", userId) p1 := insertTestPerm(t, svcCtx, "test_product") t.Cleanup(func() { testutil.CleanTableByField(ctx, conn, "`sys_user_perm`", "userId", userId) testutil.CleanTable(ctx, conn, "`sys_product_member`", mId) testutil.CleanTable(ctx, conn, "`sys_user`", userId) testutil.CleanTable(ctx, conn, "`sys_perm`", p1) }) logic := NewSetUserPermsLogic(ctx, svcCtx) err := logic.SetUserPerms(&types.SetPermsReq{ UserId: userId, Perms: []types.UserPermItem{ {PermId: p1, Effect: "ALLOW"}, {PermId: p1, Effect: "ALLOW"}, }, }) require.NoError(t, err) perms := findUserPerms(t, ctx, userId) assert.Len(t, perms, 1, "重复的权限ID应被去重,只插入一条") assert.Equal(t, "ALLOW", perms[0].Effect) } // TC-0212: 已禁用的权限不能被设置 func TestSetUserPerms_DisabledPermRejected(t *testing.T) { ctx := ctxhelper.SuperAdminCtx() svcCtx := svc.NewServiceContext(testutil.GetTestConfig()) conn := testutil.GetTestSqlConn() username := testutil.UniqueId() userId := insertTestUser(t, ctx, username, testutil.HashPassword("pass")) mId := insertTestMember(t, svcCtx, "test_product", userId) now := time.Now().Unix() res, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{ ProductCode: "test_product", Name: "disabled_perm_" + testutil.UniqueId(), Code: "disabled_" + testutil.UniqueId(), Status: 2, CreateTime: now, UpdateTime: now, }) require.NoError(t, err) disabledPermId, _ := res.LastInsertId() t.Cleanup(func() { testutil.CleanTableByField(ctx, conn, "`sys_user_perm`", "userId", userId) testutil.CleanTable(ctx, conn, "`sys_product_member`", mId) testutil.CleanTable(ctx, conn, "`sys_user`", userId) testutil.CleanTable(ctx, conn, "`sys_perm`", disabledPermId) }) logic := NewSetUserPermsLogic(ctx, svcCtx) err = logic.SetUserPerms(&types.SetPermsReq{ UserId: userId, Perms: []types.UserPermItem{ {PermId: disabledPermId, Effect: "ALLOW"}, }, }) require.Error(t, err) var codeErr *response.CodeError require.True(t, errors.As(err, &codeErr)) assert.Equal(t, 400, codeErr.Code()) assert.Contains(t, codeErr.Error(), "已被禁用") } // TC-0199: 目标用户不是当前产品成员时拒绝设置权限(L-5修复验证) func TestSetUserPerms_NonMemberRejected(t *testing.T) { ctx := ctxhelper.SuperAdminCtx() svcCtx := svc.NewServiceContext(testutil.GetTestConfig()) conn := testutil.GetTestSqlConn() username := testutil.UniqueId() userId := insertTestUser(t, ctx, username, testutil.HashPassword("pass")) t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_user`", userId) }) logic := NewSetUserPermsLogic(ctx, svcCtx) err := logic.SetUserPerms(&types.SetPermsReq{ UserId: userId, Perms: []types.UserPermItem{}, }) require.Error(t, err) var codeErr2 *response.CodeError require.True(t, errors.As(err, &codeErr2)) assert.Equal(t, 400, codeErr2.Code()) assert.Contains(t, codeErr2.Error(), "不是当前产品的成员") }