< Summary

Information
Class: Elsa.ExternalAuthentication.Services.DefaultExternalUserMatcherRegistry
Assembly: Elsa.ExternalAuthentication
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.ExternalAuthentication/Services/ExtensionRegistries.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 6
Coverable lines: 6
Total lines: 111
Line coverage: 0%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
ListDescriptors()100%210%
TryGet(...)100%210%

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
 13    public DefaultUnlinkedIdentityPolicyRegistry(
 14        IEnumerable<IUnlinkedIdentityPolicy> policies,
 15        IEnumerable<IExternalUserMatcher> matchers,
 16        ExtensionDescriptorValidator descriptorValidator,
 17        IOptions<ExternalAuthenticationOptions> options)
 18    {
 19        var matcherTypes = ExtensionRegistryBuilder.Create(
 20            matchers,
 21            matcher => matcher.Type,
 22            options.Value.AllowedExternalUserMatcherTypes,
 23            "external user matcher");
 24        _policies = ExtensionRegistryBuilder.Create(
 25            policies.Where(x => !string.Equals(x.Type, Policies.MatchExternalUserUnlinkedIdentityPolicy.PolicyType, Stri
 26            policy => policy.Type,
 27            options.Value.AllowedUnlinkedIdentityPolicyTypes,
 28            "unlinked identity policy");
 29        _descriptors = _policies.Values
 30            .Select(descriptorValidator.Validate)
 31            .OrderBy(x => x.Type, StringComparer.Ordinal)
 32            .ToArray();
 33    }
 34
 35    public IReadOnlyCollection<UnlinkedIdentityPolicyDescriptor> ListDescriptors() => _descriptors;
 36    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
 069    public DefaultExternalUserMatcherRegistry(IEnumerable<IExternalUserMatcher> matchers, ExtensionDescriptorValidator d
 70    {
 071        _matchers = ExtensionRegistryBuilder.Create(matchers, matcher => matcher.Type, options.Value.AllowedExternalUser
 072        _descriptors = _matchers.Values.Select(descriptorValidator.Validate).OrderBy(x => x.Type, StringComparer.Ordinal
 073    }
 74
 075    public IReadOnlyCollection<ExternalUserMatcherDescriptor> ListDescriptors() => _descriptors;
 076    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}