package user import ( "errors" "testing" "time" productMemberModel "perms-system-server/internal/model/productmember" "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" ) // TC-0176: 含productCode func TestUserList_WithProductCode(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")) productCode := testutil.UniqueId() now := time.Now().Unix() memberRes, err := svcCtx.SysProductMemberModel.Insert(ctx, &productMemberModel.SysProductMember{ ProductCode: productCode, UserId: userId, MemberType: "ADMIN", Status: 1, CreateTime: now, UpdateTime: now, }) require.NoError(t, err) memberId, _ := memberRes.LastInsertId() t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_product_member`", memberId) testutil.CleanTable(ctx, conn, "`sys_user`", userId) }) logic := NewUserListLogic(ctx, svcCtx) resp, err := logic.UserList(&types.UserListReq{ ProductCode: productCode, Page: 1, PageSize: 100, }) require.NoError(t, err) require.NotNil(t, resp) assert.Greater(t, resp.Total, int64(0)) items := resp.List.([]types.UserItem) found := false for _, item := range items { if item.Id == userId { found = true assert.Equal(t, "ADMIN", item.MemberType) break } } assert.True(t, found, "should find the inserted user in the list") } // TC-0177: 不含productCode func TestUserList_WithoutProductCode(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 := NewUserListLogic(ctx, svcCtx) resp, err := logic.UserList(&types.UserListReq{ Page: 1, PageSize: 100, }) require.NoError(t, err) require.NotNil(t, resp) items := resp.List.([]types.UserItem) for _, item := range items { if item.Id == userId { assert.Equal(t, "", item.MemberType) return } } t.Fatal("should find inserted user in the list") } // TC-0178: pageSize超过上限 func TestUserList_PageSizeOver100_Capped(t *testing.T) { ctx := ctxhelper.SuperAdminCtx() svcCtx := svc.NewServiceContext(testutil.GetTestConfig()) logic := NewUserListLogic(ctx, svcCtx) resp, err := logic.UserList(&types.UserListReq{ Page: 1, PageSize: 200, }) require.NoError(t, err) require.NotNil(t, resp) items := resp.List.([]types.UserItem) assert.LessOrEqual(t, len(items), 100) } // TC-0179: 用户不在产品中 func TestUserList_PartialNonMember(t *testing.T) { ctx := ctxhelper.SuperAdminCtx() svcCtx := svc.NewServiceContext(testutil.GetTestConfig()) conn := testutil.GetTestSqlConn() now := time.Now().Unix() u1Name := testutil.UniqueId() u1Id := insertTestUser(t, ctx, u1Name, testutil.HashPassword("pass")) u2Name := testutil.UniqueId() u2Id := insertTestUser(t, ctx, u2Name, testutil.HashPassword("pass")) productCode := testutil.UniqueId() memberRes, err := svcCtx.SysProductMemberModel.Insert(ctx, &productMemberModel.SysProductMember{ ProductCode: productCode, UserId: u1Id, MemberType: "MEMBER", Status: 1, CreateTime: now, UpdateTime: now, }) require.NoError(t, err) memberId, _ := memberRes.LastInsertId() t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_product_member`", memberId) testutil.CleanTable(ctx, conn, "`sys_user`", u1Id, u2Id) }) logic := NewUserListLogic(ctx, svcCtx) resp, err := logic.UserList(&types.UserListReq{ ProductCode: productCode, Page: 1, PageSize: 100, }) require.NoError(t, err) require.NotNil(t, resp) items := resp.List.([]types.UserItem) for _, item := range items { if item.Id == u1Id { assert.Equal(t, "MEMBER", item.MemberType) } if item.Id == u2Id { assert.Equal(t, "", item.MemberType) } } } // TC-0205: 非超管用户仅能看到产品成员(#1修复验证) func TestUserList_NonSuperAdminOnlySeeProductMembers(t *testing.T) { svcCtx := svc.NewServiceContext(testutil.GetTestConfig()) conn := testutil.GetTestSqlConn() superCtx := ctxhelper.SuperAdminCtx() now := time.Now().Unix() productCode := testutil.UniqueId() memberName := testutil.UniqueId() memberId := insertTestUser(t, superCtx, memberName, testutil.HashPassword("pass")) nonMemberName := testutil.UniqueId() nonMemberId := insertTestUser(t, superCtx, nonMemberName, testutil.HashPassword("pass")) pmRes, err := svcCtx.SysProductMemberModel.Insert(superCtx, &productMemberModel.SysProductMember{ ProductCode: productCode, UserId: memberId, MemberType: "MEMBER", Status: 1, CreateTime: now, UpdateTime: now, }) require.NoError(t, err) pmId, _ := pmRes.LastInsertId() t.Cleanup(func() { testutil.CleanTable(superCtx, conn, "`sys_product_member`", pmId) testutil.CleanTable(superCtx, conn, "`sys_user`", memberId, nonMemberId) }) ctx := ctxhelper.AdminCtx(productCode) logic := NewUserListLogic(ctx, svcCtx) resp, err := logic.UserList(&types.UserListReq{ ProductCode: productCode, Page: 1, PageSize: 100, }) require.NoError(t, err) require.NotNil(t, resp) items := resp.List.([]types.UserItem) for _, item := range items { assert.NotEqual(t, nonMemberId, item.Id, "non-member user should NOT appear in product user list for non-super-admin (audit #1)") } } // TC-0206: 非超管不带productCode时返回403 func TestUserList_NonSuperAdminWithoutProductCode_Rejected(t *testing.T) { ctx := ctxhelper.AdminCtx("test_product") svcCtx := svc.NewServiceContext(testutil.GetTestConfig()) logic := NewUserListLogic(ctx, svcCtx) _, err := logic.UserList(&types.UserListReq{ Page: 1, PageSize: 10, }) 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-0207: 非超管访问其他产品数据被拒绝 func TestUserList_NonSuperAdminWrongProductCode_Rejected(t *testing.T) { ctx := ctxhelper.AdminCtx("product_a") svcCtx := svc.NewServiceContext(testutil.GetTestConfig()) logic := NewUserListLogic(ctx, svcCtx) _, err := logic.UserList(&types.UserListReq{ ProductCode: "product_b", Page: 1, PageSize: 10, }) 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(), "无权访问该产品的数据") }