Implement rate limiting and enhance authentication flow
- 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.
This commit is contained in:
@@ -8,13 +8,13 @@ namespace PnvPanel.IntegrationTests.Admin;
|
||||
[Collection(IntegrationTestCollection.Name)]
|
||||
public class NodeInboundCrudTests(PnvPanelWebApplicationFactory factory)
|
||||
{
|
||||
private sealed record NodeResponse(Guid Id, string Name, string BaseAddress, string Username, string? Location, int Status, bool IsEnabled);
|
||||
private sealed record NodeResponse(Guid Id, string Name, string BaseAddress, string Username, string? Location, string Status, bool IsEnabled);
|
||||
|
||||
private sealed record InboundResponse(
|
||||
Guid Id, Guid NodeId, string RemoteInboundId, int Protocol, string Remark, int Port,
|
||||
Guid Id, Guid NodeId, string RemoteInboundId, string Protocol, string Remark, int Port,
|
||||
bool IsPublished, string? DisplayName, int? MaxClients, IReadOnlyList<Guid> AllowedRoleIds);
|
||||
|
||||
private sealed record SyncNodeResponse(int InboundsSynced, int Status);
|
||||
private sealed record SyncNodeResponse(int InboundsSynced, string Status);
|
||||
|
||||
[Fact]
|
||||
public async Task RegisterSyncListPublish_FullNodeInboundLifecycle_Succeeds()
|
||||
|
||||
@@ -77,7 +77,7 @@ public class AuthFlowTests(PnvPanelWebApplicationFactory factory)
|
||||
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" });
|
||||
var second = await client.PostJsonAsync("/api/auth/register", new { userName, password = "AnotherPass123!" });
|
||||
|
||||
Assert.Equal(HttpStatusCode.Conflict, second.StatusCode);
|
||||
}
|
||||
|
||||
@@ -15,12 +15,14 @@ public class ConfigQuotaTests(PnvPanelWebApplicationFactory factory)
|
||||
|
||||
private sealed record NodeResponse(Guid Id, string Name);
|
||||
|
||||
private sealed record SyncNodeResponse(int InboundsSynced, int Status);
|
||||
private sealed record SyncNodeResponse(int InboundsSynced, string Status);
|
||||
|
||||
private sealed record InboundResponse(Guid Id, Guid NodeId, string RemoteInboundId, int Protocol, string Remark, int Port, bool IsPublished);
|
||||
private sealed record InboundResponse(Guid Id, Guid NodeId, string RemoteInboundId, string Protocol, string Remark, int Port, bool IsPublished);
|
||||
|
||||
private sealed record ActivationRequestResponse(Guid Id, string? Comment, DateTimeOffset CreatedAt);
|
||||
|
||||
private sealed record MyConfigsResponse(List<object> Configs, int MaxConfigs);
|
||||
|
||||
/// <summary>
|
||||
/// Доказывает, что pg_advisory_xact_lock в CreateVpnConfigCommandHandler реально защищает
|
||||
/// от гонки: при параллельных запросах ровно Quota проходят, остальные — 409 QuotaExceeded.
|
||||
@@ -98,7 +100,7 @@ public class ConfigQuotaTests(PnvPanelWebApplicationFactory factory)
|
||||
Assert.Equal(ConcurrentAttempts - Quota, quotaExceeded);
|
||||
|
||||
var myConfigsResponse = await userClient.GetAsync("/api/configs");
|
||||
var myConfigs = await myConfigsResponse.ReadAsAsync<List<object>>();
|
||||
Assert.Equal(Quota, myConfigs!.Count);
|
||||
var myConfigs = await myConfigsResponse.ReadAsAsync<MyConfigsResponse>();
|
||||
Assert.Equal(Quota, myConfigs!.Configs.Count);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-1
@@ -27,7 +27,10 @@ public sealed class PnvPanelWebApplicationFactory : WebApplicationFactory<Progra
|
||||
.WithPassword("pnvpanel")
|
||||
.Build();
|
||||
|
||||
public async Task InitializeAsync() => await _postgres.StartAsync();
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
await _postgres.StartAsync();
|
||||
}
|
||||
|
||||
async Task IAsyncLifetime.DisposeAsync()
|
||||
{
|
||||
@@ -48,6 +51,9 @@ public sealed class PnvPanelWebApplicationFactory : WebApplicationFactory<Progra
|
||||
["AdminSeed:Password"] = AdminPassword,
|
||||
// Пусто — TelegramBotHostedService при пустом токене не стартует (см. Api/Telegram/TelegramBotHostedService.cs).
|
||||
["Telegram:BotToken"] = "",
|
||||
// Весь collection делит один TestServer/host — все запросы идут от одного "клиента",
|
||||
// дефолтный лимит 20/мин быстро исчерпывается. Поднимаем для тестового окружения.
|
||||
["RateLimiting:AuthPermitLimit"] = "10000",
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user