< Summary

Information
Class: Elsa.ExternalAuthentication.Services.DefaultUnlinkedIdentityPolicyRegistry
Assembly: Elsa.ExternalAuthentication
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.ExternalAuthentication/Services/ExtensionRegistries.cs
Line coverage
90%
Covered lines: 20
Uncovered lines: 2
Coverable lines: 22
Total lines: 111
Line coverage: 90.9%
Branch coverage
50%
Covered branches: 1
Total branches: 2
Branch coverage: 50%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)50%2290%
ListDescriptors()100%11100%
TryGet(...)100%11100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.ExternalAuthentication/Services/ExtensionRegistries.cs

#LineLine coverage
 1using Elsa.ExternalAuthentication.Contracts;
 2using Elsa.ExternalAuthentication.Models;
 3using Elsa.ExternalAuthentication.Options;
 4using Microsoft.Extensions.Options;
 5
 6namespace Elsa.ExternalAuthentication.Services;
 7
 8public sealed class DefaultUnlinkedIdentityPolicyRegistry : IUnlinkedIdentityPolicyRegistry
 9{
 10    private readonly IReadOnlyDictionary<string, IUnlinkedIdentityPolicy> _policies;
 11    private readonly IReadOnlyCollection<UnlinkedIdentityPolicyDescriptor> _descriptors;
 12
 213    public DefaultUnlinkedIdentityPolicyRegistry(
 214        IEnumerable<IUnlinkedIdentityPolicy> policies,
 215        IEnumerable<IExternalUserMatcher> matchers,
 216        ExtensionDescriptorValidator descriptorValidator,
 217        IOptions<ExternalAuthenticationOptions> options)
 18    {
 219        var matcherTypes = ExtensionRegistryBuilder.Create(
 220            matchers,
 021            matcher => matcher.Type,
 222            options.Value.AllowedExternalUserMatcherTypes,
 223            "external user matcher");
 224        _policies = ExtensionRegistryBuilder.Create(
 325            policies.Where(x => !string.Equals(x.Type, Policies.MatchExternalUserUnlinkedIdentityPolicy.PolicyType, Stri
 326            policy => policy.Type,
 227            options.Value.AllowedUnlinkedIdentityPolicyTypes,
 228            "unlinked identity policy");
 229        _descriptors = _policies.Values
 230            .Select(descriptorValidator.Validate)
 031            .OrderBy(x => x.Type, StringComparer.Ordinal)
 232            .ToArray();
 233    }
 34
 135    public IReadOnlyCollection<UnlinkedIdentityPolicyDescriptor> ListDescriptors() => _descriptors;
 236    public bool TryGet(string type, out IUnlinkedIdentityPolicy policy) => _policies.TryGetValue(type, out policy!);
 37}
 38
 39public sealed class DefaultPermissionGrantSourceRegistry : IPermissionGrantSourceRegistry
 40{
 41    private readonly IReadOnlyDictionary<string, IPermissionGrantSource> _sources;
 42    private readonly IReadOnlyCollection<PermissionGrantSourceDescriptor> _descriptors;
 43
 44    public DefaultPermissionGrantSourceRegistry(
 45        IEnumerable<IPermissionGrantSource> sources,
 46        ExtensionDescriptorValidator descriptorValidator,
 47        IOptions<ExternalAuthenticationOptions> options)
 48    {
 49        _sources = ExtensionRegistryBuilder.Create(
 50            sources,
 51            source => source.Type,
 52            options.Value.AllowedPermissionGrantSourceTypes,
 53            "permission grant source");
 54        _descriptors = _sources.Values
 55            .Select(descriptorValidator.Validate)
 56            .OrderBy(x => x.Type, StringComparer.Ordinal)
 57            .ToArray();
 58    }
 59
 60    public IReadOnlyCollection<PermissionGrantSourceDescriptor> ListDescriptors() => _descriptors;
 61    public bool TryGet(string type, out IPermissionGrantSource source) => _sources.TryGetValue(type, out source!);
 62}
 63
 64public sealed class DefaultExternalUserMatcherRegistry : IExternalUserMatcherRegistry
 65{
 66    private readonly IReadOnlyDictionary<string, IExternalUserMatcher> _matchers;
 67    private readonly IReadOnlyCollection<ExternalUserMatcherDescriptor> _descriptors;
 68
 69    public DefaultExternalUserMatcherRegistry(IEnumerable<IExternalUserMatcher> matchers, ExtensionDescriptorValidator d
 70    {
 71        _matchers = ExtensionRegistryBuilder.Create(matchers, matcher => matcher.Type, options.Value.AllowedExternalUser
 72        _descriptors = _matchers.Values.Select(descriptorValidator.Validate).OrderBy(x => x.Type, StringComparer.Ordinal
 73    }
 74
 75    public IReadOnlyCollection<ExternalUserMatcherDescriptor> ListDescriptors() => _descriptors;
 76    public bool TryGet(string type, out IExternalUserMatcher matcher) => _matchers.TryGetValue(type, out matcher!);
 77}
 78
 79internal static class ExtensionRegistryBuilder
 80{
 81    public static IReadOnlyDictionary<string, TExtension> Create<TExtension>(
 82        IEnumerable<TExtension> extensions,
 83        Func<TExtension, string> getType,
 84        IEnumerable<string> allowedTypes,
 85        string kind)
 86    {
 87        var installed = new Dictionary<string, TExtension>(StringComparer.Ordinal);
 88        foreach (var extension in extensions)
 89        {
 90            var type = getType(extension);
 91            if (string.IsNullOrWhiteSpace(type))
 92                throw new InvalidOperationException($"An installed {kind} has an empty type.");
 93            if (!installed.TryAdd(type, extension))
 94                throw new InvalidOperationException($"The installed {kind} type '{type}' is registered more than once.")
 95        }
 96
 97        var allowed = allowedTypes.ToHashSet(StringComparer.Ordinal);
 98        if (allowed.Count == 0)
 99            return installed;
 100
 101        foreach (var type in allowed)
 102        {
 103            if (!installed.ContainsKey(type))
 104                throw new InvalidOperationException($"The allowed {kind} type '{type}' is not installed.");
 105        }
 106
 107        return installed
 108            .Where(x => allowed.Contains(x.Key))
 109            .ToDictionary(x => x.Key, x => x.Value, StringComparer.Ordinal);
 110    }
 111}