using System.Net; using PnvPanel.IntegrationTests.TestSupport; using Xunit; using static PnvPanel.IntegrationTests.TestSupport.AuthTestHelper; namespace PnvPanel.IntegrationTests.Activation; [Collection(IntegrationTestCollection.Name)] public class ActivationFlowTests(PnvPanelWebApplicationFactory factory) { private sealed record ActivationRequestResponse( Guid Id, string? Comment, DateTimeOffset CreatedAt ); [Fact] public async Task RequestThenAdminApprove_ActivatesUser() { using var userClient = factory.CreateClient(); var userName = $"dave_{Guid.NewGuid():N}"[..20]; var (userId, userToken) = await RegisterAndLoginAsync(userClient, userName, "P@ssw0rd123"); userClient.UseBearerToken(userToken); var requestResponse = await userClient.PostJsonAsync( "/api/activation/request", new { comment = "Please activate me" } ); Assert.Equal(HttpStatusCode.OK, requestResponse.StatusCode); var request = await requestResponse.ReadAsAsync(); Assert.NotNull(request); using var adminClient = factory.CreateClient(); var adminToken = await LoginAsAdminAsync(adminClient); adminClient.UseBearerToken(adminToken); var approveResponse = await adminClient.PostAsync( $"/api/admin/activation-requests/{request!.Id}/approve", content: null ); Assert.Equal(HttpStatusCode.NoContent, approveResponse.StatusCode); var meResponse = await userClient.GetAsync("/api/auth/me"); var me = await meResponse.ReadAsAsync(); Assert.True(me!.IsActivated); Assert.Equal(userId, me.Id); } [Fact] public async Task RequestThenAdminReject_KeepsUserNotActivated() { using var userClient = factory.CreateClient(); var userName = $"erin_{Guid.NewGuid():N}"[..20]; var (_, userToken) = await RegisterAndLoginAsync(userClient, userName, "P@ssw0rd123"); userClient.UseBearerToken(userToken); var requestResponse = await userClient.PostJsonAsync( "/api/activation/request", new { comment = "Erin, a friend of the admin" } ); var request = await requestResponse.ReadAsAsync(); using var adminClient = factory.CreateClient(); var adminToken = await LoginAsAdminAsync(adminClient); adminClient.UseBearerToken(adminToken); var rejectResponse = await adminClient.PostJsonAsync( $"/api/admin/activation-requests/{request!.Id}/reject", new { reason = "not enough info" } ); Assert.Equal(HttpStatusCode.NoContent, rejectResponse.StatusCode); var meResponse = await userClient.GetAsync("/api/auth/me"); var me = await meResponse.ReadAsAsync(); Assert.False(me!.IsActivated); } [Fact] public async Task Request_WhenAlreadyPending_ReturnsConflict() { using var userClient = factory.CreateClient(); var userName = $"frank_{Guid.NewGuid():N}"[..20]; var (_, userToken) = await RegisterAndLoginAsync(userClient, userName, "P@ssw0rd123"); userClient.UseBearerToken(userToken); var first = await userClient.PostJsonAsync( "/api/activation/request", new { comment = "Frank, a colleague of the admin" } ); Assert.Equal(HttpStatusCode.OK, first.StatusCode); var second = await userClient.PostJsonAsync( "/api/activation/request", new { comment = "Frank, a colleague of the admin" } ); Assert.Equal(HttpStatusCode.Conflict, second.StatusCode); } [Fact] public async Task Request_WhenCommentEmpty_ReturnsBadRequest() { using var userClient = factory.CreateClient(); var userName = $"gina_{Guid.NewGuid():N}"[..20]; var (_, userToken) = await RegisterAndLoginAsync(userClient, userName, "P@ssw0rd123"); userClient.UseBearerToken(userToken); var response = await userClient.PostJsonAsync( "/api/activation/request", new { comment = (string?)null } ); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } }