< Summary

Information
Class: Elsa.ExternalAuthentication.Providers.ConfigurationIdentityProviderConnectionSource
Assembly: Elsa.ExternalAuthentication
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.ExternalAuthentication/Providers/ConfigurationIdentityProviderConnectionSource.cs
Line coverage
92%
Covered lines: 51
Uncovered lines: 4
Coverable lines: 55
Total lines: 90
Line coverage: 92.7%
Branch coverage
57%
Covered branches: 15
Total branches: 26
Branch coverage: 57.6%
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_Name()100%11100%
get_Ownership()100%11100%
GetSnapshotAsync(...)50%2275%
Materialize(...)66.66%121293.75%
IsInScope(...)50%44100%
CloneClaimProjection(...)50%66100%
CloneJson(...)50%22100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.ExternalAuthentication/Providers/ConfigurationIdentityProviderConnectionSource.cs

#LineLine coverage
 1using System.Text.Json;
 2using Elsa.ExternalAuthentication.Contracts;
 3using Elsa.ExternalAuthentication.Models;
 4using Elsa.ExternalAuthentication.Options;
 5using Elsa.ExternalAuthentication.Services;
 6using Microsoft.Extensions.Options;
 7
 8namespace Elsa.ExternalAuthentication.Providers;
 9
 10/// <summary>
 11/// Supplies deployment-owned connections from the current External Authentication options.
 12/// </summary>
 413public sealed class ConfigurationIdentityProviderConnectionSource(
 414    IOptionsMonitor<ExternalAuthenticationOptions> options,
 415    ConnectionRevisionCalculator revisionCalculator,
 416    IExternalAuthenticationAdapterRegistry adapters) : IIdentityProviderConnectionSource
 17{
 18    public const string SourceName = "configuration";
 19
 120    public string Name => SourceName;
 121    public ConnectionSourceOwnership Ownership => ConnectionSourceOwnership.Configuration;
 22
 23    public ValueTask<ConnectionSourceSnapshot> GetSnapshotAsync(ConnectionScope scope, CancellationToken cancellationTok
 24    {
 425        cancellationToken.ThrowIfCancellationRequested();
 26
 427        var connections = (options.CurrentValue.ConfigurationConnections ?? [])
 628            .Where(connection => IsInScope(connection.TenantId, scope))
 429            .Select(connection => Materialize(connection, scope))
 030            .OrderBy(connection => ConnectionRevisionCalculator.NormalizeKey(connection.Key), StringComparer.Ordinal)
 031            .ThenBy(connection => connection.Id, StringComparer.Ordinal)
 432            .ToArray();
 33
 334        return ValueTask.FromResult(new ConnectionSourceSnapshot(scope, revisionCalculator.CalculateSourceVersion(scope,
 35    }
 36
 37    private IdentityProviderConnection Materialize(IdentityProviderConnection configuredConnection, ConnectionScope scop
 38    {
 439        if (adapters.TryGet(configuredConnection.AdapterType, out var adapter))
 140            AdapterSettingsSecretFieldGuard.ThrowIfContainsDeclaredSecret(configuredConnection.AdapterSettings, adapter.
 41
 342        var connection = new IdentityProviderConnection
 343        {
 344            Id = string.IsNullOrWhiteSpace(configuredConnection.Id)
 345                ? ConnectionRevisionCalculator.CalculateConfigurationConnectionId(scope, configuredConnection.Key)
 346                : configuredConnection.Id,
 347            TenantId = scope.TenantId,
 348            Key = ConnectionRevisionCalculator.NormalizeKey(configuredConnection.Key),
 349            AdapterType = configuredConnection.AdapterType,
 350            AdapterSettingsVersion = configuredConnection.AdapterSettingsVersion,
 351            AdapterSettings = CloneJson(configuredConnection.AdapterSettings),
 052            SecretBindings = configuredConnection.SecretBindings?.ToDictionary(x => x.Key, x => x.Value, StringComparer.
 353            DisplayName = configuredConnection.DisplayName,
 354            IconId = configuredConnection.IconId,
 355            DisplayOrder = configuredConnection.DisplayOrder,
 356            IsPreferred = configuredConnection.IsPreferred,
 357            IsEnabled = configuredConnection.IsEnabled,
 358            OverridesConfigurationConnection = false,
 359            ArchivedAt = configuredConnection.ArchivedAt,
 360            UnlinkedPolicy = configuredConnection.UnlinkedPolicy is { } policy ? new PolicySelection(policy.Type, policy
 361            PermissionGrantSources = (configuredConnection.PermissionGrantSources ?? [])
 062                .Select(x => new GrantSourceSelection(x.Type, x.SettingsVersion, CloneJson(x.Settings), x.Order))
 363                .ToArray(),
 364            ClaimProjection = CloneClaimProjection(configuredConnection.ClaimProjection),
 365            UpstreamLogoutMode = configuredConnection.UpstreamLogoutMode,
 366            Revision = 1,
 367            CreatedAt = DateTimeOffset.UnixEpoch,
 368            UpdatedAt = DateTimeOffset.UnixEpoch
 369        };
 70
 371        connection.MaterialRevision = revisionCalculator.CalculateMaterialRevision(connection);
 372        return connection;
 73    }
 74
 75    private static bool IsInScope(string? tenantId, ConnectionScope scope) =>
 676        scope == ConnectionScope.Host && (string.IsNullOrWhiteSpace(tenantId) || string.Equals(tenantId, ConnectionScope
 77
 78    private static ClaimProjection CloneClaimProjection(ClaimProjection? projection)
 79    {
 380        projection ??= ClaimProjection.Empty;
 381        return new ClaimProjection(
 382            new HashSet<string>(projection.AllowedClaimTypes ?? new HashSet<string>(), StringComparer.Ordinal),
 383            new HashSet<string>(projection.RedactedClaimTypes ?? new HashSet<string>(), StringComparer.Ordinal),
 384            projection.MaximumClaimCount,
 385            projection.MaximumValueLength,
 386            projection.MaximumTotalBytes);
 87    }
 88
 389    private static JsonElement CloneJson(JsonElement value) => value.ValueKind == JsonValueKind.Undefined ? default : va
 90}