< Summary

Information
Class: Elsa.ExternalAuthentication.Options.ConfigureExternalAuthenticationRateLimiterOptions
Assembly: Elsa.ExternalAuthentication
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.ExternalAuthentication/Options/ConfigureExternalAuthenticationRateLimiterOptions.cs
Line coverage
70%
Covered lines: 24
Uncovered lines: 10
Coverable lines: 34
Total lines: 55
Line coverage: 70.5%
Branch coverage
0%
Covered branches: 0
Total branches: 10
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
Configure(...)100%1170.58%
AddPolicy(...)0%22100%
GetPartitionKey(...)0%7280%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.ExternalAuthentication/Options/ConfigureExternalAuthenticationRateLimiterOptions.cs

#LineLine coverage
 1using System.Threading.RateLimiting;
 2using Elsa.ExternalAuthentication.Constants;
 3using Microsoft.AspNetCore.Http;
 4using Microsoft.AspNetCore.RateLimiting;
 5using Microsoft.Extensions.Options;
 6
 7namespace Elsa.ExternalAuthentication.Options;
 8
 19public sealed class ConfigureExternalAuthenticationRateLimiterOptions(IOptions<ExternalAuthenticationOptions> externalAu
 10{
 11    public void Configure(RateLimiterOptions options)
 12    {
 113        var rateLimits = externalAuthenticationOptions.Value.RateLimits;
 114        AddPolicy(options, ExternalAuthenticationRateLimitPolicyNames.Discovery, rateLimits.Discovery, rateLimits.Partit
 115        AddPolicy(options, ExternalAuthenticationRateLimitPolicyNames.ExternalInitiation, rateLimits.ExternalInitiation,
 116        AddPolicy(options, ExternalAuthenticationRateLimitPolicyNames.LocalInitiation, rateLimits.LocalInitiation, rateL
 117        AddPolicy(options, ExternalAuthenticationRateLimitPolicyNames.ProviderCallback, rateLimits.ProviderCallback, rat
 118        AddPolicy(options, ExternalAuthenticationRateLimitPolicyNames.TokenExchange, rateLimits.TokenExchange, rateLimit
 19
 120        var previousOnRejected = options.OnRejected;
 121        options.OnRejected = async (context, cancellationToken) =>
 122        {
 023            context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;
 024            if (context.Lease.TryGetMetadata(MetadataName.RetryAfter, out var retryAfter))
 025                context.HttpContext.Response.Headers.RetryAfter = Math.Ceiling(retryAfter.TotalSeconds).ToString(System.
 126
 027            if (previousOnRejected != null)
 028                await previousOnRejected(context, cancellationToken);
 129        };
 130    }
 31
 32    private static void AddPolicy(RateLimiterOptions options, string name, RateLimitRule rule, ExternalAuthenticationRat
 33    {
 534        options.AddPolicy(name, context => RateLimitPartition.GetFixedWindowLimiter(
 535            GetPartitionKey(context, partitionStrategy),
 536            _ => new FixedWindowRateLimiterOptions
 537            {
 538                PermitLimit = rule.PermitLimit,
 539                Window = rule.Window,
 540                QueueLimit = 0,
 541                QueueProcessingOrder = QueueProcessingOrder.OldestFirst,
 542                AutoReplenishment = true
 543            }));
 544    }
 45
 46    private static string GetPartitionKey(HttpContext context, ExternalAuthenticationRateLimitPartitionStrategy partitio
 47    {
 048        var remoteIp = context.Connection.RemoteIpAddress?.ToString() ?? "unknown";
 049        if (partitionStrategy != ExternalAuthenticationRateLimitPartitionStrategy.ClientIdAndRemoteIp)
 050            return remoteIp;
 51
 052        var clientId = context.Request.Query["client_id"].FirstOrDefault();
 053        return string.IsNullOrWhiteSpace(clientId) ? remoteIp : $"{remoteIp}:{clientId}";
 54    }
 55}