Implement rate limiting and enhance authentication flow
CI / Backend (build + test) (push) Successful in 1m17s
CI / Frontend (lint + typecheck + build) (push) Successful in 35s

- 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:
Leonid Pershin
2026-07-02 12:40:23 +03:00
parent ed07221ca5
commit 8067be3c35
106 changed files with 8823 additions and 172 deletions
@@ -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);
}
}