- Added rate limiting configuration for authentication endpoints, allowing customizable request limits via environment variables. - Updated authentication flow to utilize HttpRequest for cookie management, ensuring secure handling of refresh tokens. - Introduced a new endpoint to retrieve user subscription details. - Enhanced the handling of Telegram bot token validation to prevent errors with empty tokens. - Updated the application to serialize enums as strings for better documentation and compatibility with TypeScript. - Improved test coverage for new features and adjustments in command handlers.
85 lines
3.7 KiB
C#
85 lines
3.7 KiB
C#
using System.Net;
|
|
using System.Net.Http.Json;
|
|
using PnvPanel.IntegrationTests.TestSupport;
|
|
using Xunit;
|
|
|
|
namespace PnvPanel.IntegrationTests.Auth;
|
|
|
|
[Collection(IntegrationTestCollection.Name)]
|
|
public class AuthFlowTests(PnvPanelWebApplicationFactory factory)
|
|
{
|
|
private sealed record RegisterResponse(Guid Id, string UserName);
|
|
|
|
private sealed record CurrentUserResponse(Guid Id, string UserName, string Role, bool IsActivated, bool TelegramLinked);
|
|
|
|
private sealed record LoginResponse(string AccessToken, DateTimeOffset ExpiresAt, CurrentUserResponse User);
|
|
|
|
[Fact]
|
|
public async Task RegisterLoginMeRefreshLogout_FullFlow_Succeeds()
|
|
{
|
|
using var client = factory.CreateClient();
|
|
var userName = $"alice_{Guid.NewGuid():N}"[..20];
|
|
const string password = "P@ssw0rd123";
|
|
|
|
var registerResponse = await client.PostJsonAsync("/api/auth/register", new { userName, password });
|
|
Assert.Equal(HttpStatusCode.OK, registerResponse.StatusCode);
|
|
var registered = await registerResponse.ReadAsAsync<RegisterResponse>();
|
|
Assert.NotNull(registered);
|
|
Assert.Equal(userName, registered!.UserName);
|
|
|
|
var loginResponse = await client.PostJsonAsync("/api/auth/login", new { userName, password });
|
|
Assert.Equal(HttpStatusCode.OK, loginResponse.StatusCode);
|
|
var login = await loginResponse.ReadAsAsync<LoginResponse>();
|
|
Assert.NotNull(login);
|
|
Assert.False(login!.User.IsActivated);
|
|
Assert.False(login.User.TelegramLinked);
|
|
Assert.Equal("user", login.User.Role);
|
|
|
|
client.UseBearerToken(login.AccessToken);
|
|
var meResponse = await client.GetAsync("/api/auth/me");
|
|
Assert.Equal(HttpStatusCode.OK, meResponse.StatusCode);
|
|
var me = await meResponse.ReadAsAsync<CurrentUserResponse>();
|
|
Assert.Equal(userName, me!.UserName);
|
|
|
|
var refreshResponse = await client.PostAsync("/api/auth/refresh", content: null);
|
|
Assert.Equal(HttpStatusCode.OK, refreshResponse.StatusCode);
|
|
var refreshed = await refreshResponse.ReadAsAsync<LoginResponse>();
|
|
Assert.NotNull(refreshed);
|
|
Assert.NotEqual(login.AccessToken, refreshed!.AccessToken);
|
|
|
|
var logoutResponse = await client.PostAsync("/api/auth/logout", content: null);
|
|
Assert.Equal(HttpStatusCode.NoContent, logoutResponse.StatusCode);
|
|
|
|
// Использованный refresh-токен отозван при logout — повторный refresh должен провалиться.
|
|
var refreshAfterLogout = await client.PostAsync("/api/auth/refresh", content: null);
|
|
Assert.Equal(HttpStatusCode.Unauthorized, refreshAfterLogout.StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Login_WithWrongPassword_ReturnsUnauthorized()
|
|
{
|
|
using var client = factory.CreateClient();
|
|
var userName = $"bob_{Guid.NewGuid():N}"[..20];
|
|
|
|
await client.PostJsonAsync("/api/auth/register", new { userName, password = "CorrectPassword123" });
|
|
|
|
var loginResponse = await client.PostJsonAsync("/api/auth/login", new { userName, password = "WrongPassword123" });
|
|
|
|
Assert.Equal(HttpStatusCode.Unauthorized, loginResponse.StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Register_WithDuplicateUserName_ReturnsConflict()
|
|
{
|
|
using var client = factory.CreateClient();
|
|
var userName = $"carol_{Guid.NewGuid():N}"[..20];
|
|
|
|
var first = await client.PostJsonAsync("/api/auth/register", new { userName, password = "P@ssw0rd123" });
|
|
Assert.Equal(HttpStatusCode.OK, first.StatusCode);
|
|
|
|
var second = await client.PostJsonAsync("/api/auth/register", new { userName, password = "AnotherPass123!" });
|
|
|
|
Assert.Equal(HttpStatusCode.Conflict, second.StatusCode);
|
|
}
|
|
}
|