< Summary

Information
Class: OzonOrdersWeb.Authorization.AuthRateLimiterPolicy
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Authorization/AuthRateLimiterPolicy.cs
Line coverage
96%
Covered lines: 26
Uncovered lines: 1
Coverable lines: 27
Total lines: 49
Line coverage: 96.2%
Branch coverage
77%
Covered branches: 14
Total branches: 18
Branch coverage: 77.7%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
get_OnRejected()100%210%
GetPartition(...)77.77%1818100%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Authorization/AuthRateLimiterPolicy.cs

#LineLine coverage
 1using System.Threading.RateLimiting;
 2using Microsoft.AspNetCore.Http;
 3using Microsoft.AspNetCore.RateLimiting;
 4using Microsoft.Extensions.Options;
 5using Services.Authorization;
 6
 7namespace OzonOrdersWeb.Authorization;
 8
 9/// <summary>
 10/// Политика ограничения частоты запросов для страницы логина и эндпоинтов аутентификации.
 11/// Разделяет учет попыток отправки форм (POST) для защиты от брут-форса паролей и
 12/// комфортный лимит открытия/чтения страниц (GET/HEAD/OPTIONS), исключая блокировку легитимных пользователей (регрессия
 13/// </summary>
 214public sealed class AuthRateLimiterPolicy(IOptions<AppAuthorizationOptions> options) : IRateLimiterPolicy<string>
 15{
 016    public Func<OnRejectedContext, CancellationToken, ValueTask>? OnRejected => null;
 17
 18    public RateLimitPartition<string> GetPartition(HttpContext httpContext)
 19    {
 4620        var opts = options.Value;
 4621        var ip = httpContext.Connection.RemoteIpAddress?.ToString() ?? "anonymous";
 4622        var isMutating = HttpMethods.IsPost(httpContext.Request.Method)
 4623                         || HttpMethods.IsPut(httpContext.Request.Method)
 4624                         || HttpMethods.IsPatch(httpContext.Request.Method)
 4625                         || HttpMethods.IsDelete(httpContext.Request.Method);
 26
 4627        var limit = isMutating
 4628            ? Math.Clamp(opts.AuthPostRateLimitPerMinute, 5, 1_000)
 4629            : Math.Clamp(opts.AuthGetRateLimitPerMinute, 30, 10_000);
 30
 4631        var partitionKey = $"{ip}:{(isMutating ? "post" : "get")}:{limit}";
 32
 4633        return RateLimitPartition.GetFixedWindowLimiter(partitionKey, static key =>
 4634        {
 335            var lastColon = key.LastIndexOf(':');
 336            var parsedLimit = lastColon >= 0 && int.TryParse(key.AsSpan(lastColon + 1), out var parsed)
 337                ? parsed
 338                : 20;
 4639
 340            return new FixedWindowRateLimiterOptions
 341            {
 342                PermitLimit = parsedLimit,
 343                Window = TimeSpan.FromMinutes(1),
 344                AutoReplenishment = true,
 345                QueueLimit = 0,
 346            };
 4647        });
 48    }
 49}