using System.Net; using System.Net.Http.Json; using ItWorx.KnowledgeHub.Contracts.Admin; using ItWorx.KnowledgeHub.Contracts.Identity; using ItWorx.KnowledgeHub.IntegrationTests.Infrastructure; namespace ItWorx.KnowledgeHub.IntegrationTests.Auth; /// /// Backs the accessible owner picker (docs/adr/ADR-029-v2-r5-final-hardening.md, brief /// Phase 7), replacing manual `OwnerId`/GUID entry. Any Reader may search, results are /// scoped to the current workspace's enabled members only, and a disabled account is /// never disclosed. /// [Collection(PostgresTestGroup.Name)] public sealed class WorkspaceMemberSearchTests(PostgresContainerFixture postgres) : OwnerSetupTestBase(postgres) { [Fact] public async Task A_reader_can_search_workspace_members_by_name_or_email() { using var owner = Factory.CreateClient(); await SetupHelper.LoginAsync(owner, OwnerEmail, OwnerPassword); var createResponse = await SetupHelper.PostWithCsrfAsync( owner, "/api/v1/admin/users", new CreateUserRequest("Zoekbare Collega", "zoekbare-collega@itworx.test", "reader-strong-password", "Reader")); Assert.Equal(HttpStatusCode.OK, createResponse.StatusCode); using var reader = Factory.CreateClient(); await SetupHelper.LoginAsync(reader, "zoekbare-collega@itworx.test", "reader-strong-password"); var byName = await reader.GetFromJsonAsync("/api/v1/workspace/members?q=Zoekbare"); Assert.NotNull(byName); Assert.Contains(byName.Items, item => item.Email == "zoekbare-collega@itworx.test"); var byEmail = await reader.GetFromJsonAsync( "/api/v1/workspace/members?q=zoekbare-collega@itworx.test"); Assert.NotNull(byEmail); Assert.Contains(byEmail.Items, item => item.DisplayName == "Zoekbare Collega"); var noMatch = await reader.GetFromJsonAsync( "/api/v1/workspace/members?q=geen-enkele-overeenkomst-xyz"); Assert.NotNull(noMatch); Assert.Empty(noMatch.Items); } [Fact] public async Task An_empty_query_returns_an_initial_list_rather_than_an_error() { using var owner = Factory.CreateClient(); await SetupHelper.LoginAsync(owner, OwnerEmail, OwnerPassword); var response = await owner.GetFromJsonAsync("/api/v1/workspace/members"); Assert.NotNull(response); Assert.Contains(response.Items, item => item.Email == OwnerEmail); } [Fact] public async Task A_disabled_account_is_never_returned() { using var owner = Factory.CreateClient(); await SetupHelper.LoginAsync(owner, OwnerEmail, OwnerPassword); var createResponse = await SetupHelper.PostWithCsrfAsync( owner, "/api/v1/admin/users", new CreateUserRequest("Uitgeschakelde Collega", "uitgeschakeld@itworx.test", "reader-strong-password", "Reader")); Assert.Equal(HttpStatusCode.OK, createResponse.StatusCode); var created = await createResponse.Content.ReadFromJsonAsync(); Assert.NotNull(created); var disableResponse = await SetupHelper.PatchWithCsrfAsync( owner, $"/api/v1/admin/users/{created.Id}", new { enabled = false }); Assert.Equal(HttpStatusCode.OK, disableResponse.StatusCode); var result = await owner.GetFromJsonAsync("/api/v1/workspace/members?q=Uitgeschakelde"); Assert.NotNull(result); Assert.Empty(result.Items); } [Fact] public async Task An_unauthenticated_caller_is_rejected() { using var client = Factory.CreateClient(); var response = await client.GetAsync("/api/v1/workspace/members"); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); } }