using System.Collections.Immutable; using System.Security.Claims; using System.Text.RegularExpressions; namespace Abstractions; public partial class Invoker { public const string TenantAuthorityPrefix = "tenant-authority"; public const string AppAuthorityPrefix = "app-authority"; public const string AuthoritySeparator = ":"; public const string SubType = "sub"; public required long SubjectId { get; init; } public required IReadOnlyDictionary> TenantAuthorityDictionary { get; init; } public required IReadOnlyDictionary> AppAuthorityDictionary { get; init; } public required bool IsAuthenticated { get; init; } [GeneratedRegex("(?" + TenantAuthorityPrefix + ")" + AuthoritySeparator + @"(?[a-zA-Z0-9]+)")] private static partial Regex TenantAuthorityRegex(); [GeneratedRegex("(?" + AppAuthorityPrefix + ")" + AuthoritySeparator + @"(?[a-zA-Z0-9]+)")] private static partial Regex AppAuthorityRegex(); public static implicit operator Invoker(ClaimsPrincipal claimsPrincipal) { var sub = claimsPrincipal.Claims.Where(x => x.Type == SubType).Select(x => (long?)long.Parse(x.Value)).SingleOrDefault(); return new Invoker { SubjectId = sub.GetValueOrDefault(), TenantAuthorityDictionary = claimsPrincipal.Claims .Where(x => TenantAuthorityRegex().IsMatch(x.Type)) .ToImmutableDictionary( x => TenantAuthorityRegex().Match(x.Type).Groups["id"].Value, x => claimsPrincipal.Claims.Where(y => y.Type == x.Type).Select(y => y.Value).ToHashSet() ), AppAuthorityDictionary = claimsPrincipal.Claims .Where(x => AppAuthorityRegex().IsMatch(x.Type)) .ToImmutableDictionary( x => AppAuthorityRegex().Match(x.Type).Groups["id"].Value, x => claimsPrincipal.Claims.Where(y => y.Type == x.Type).Select(y => y.Value).ToHashSet() ), IsAuthenticated = claimsPrincipal.Identity.IsAuthenticated }; } }