|
- using System.Security.Claims;
- using System.Text.Json;
-
- namespace Campaign_Tracker.Server.Authorization;
-
- public static class ApplicationRole
- {
- public const string ClientServices = "ClientServices";
- public const string Production = "Production";
- public const string Transportation = "Transportation";
- public const string Support = "Support";
- public const string Admin = "Admin";
-
- private static readonly IReadOnlyDictionary<string, string> Aliases =
- new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
- {
- ["client-services"] = ClientServices,
- ["clientservices"] = ClientServices,
- ["production-lead"] = Production,
- ["production"] = Production,
- ["transportation"] = Transportation,
- ["support-analyst"] = Support,
- ["support"] = Support,
- ["operations-admin"] = Admin,
- ["admin"] = Admin,
- };
-
- public static string? Normalize(string role)
- {
- return Aliases.TryGetValue(role, out var normalized) ? normalized : null;
- }
-
- public static string[] NormalizeMany(IEnumerable<string> roles)
- {
- return roles
- .Select(Normalize)
- .OfType<string>()
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .ToArray();
- }
-
- public static bool HasAny(IEnumerable<string> roles, params string[] requiredRoles)
- {
- var normalizedRoles = NormalizeMany(roles);
- return normalizedRoles.Contains(Admin, StringComparer.OrdinalIgnoreCase) ||
- normalizedRoles.Intersect(requiredRoles, StringComparer.OrdinalIgnoreCase).Any();
- }
-
- public static IEnumerable<string> ExtractKeycloakRoles(IEnumerable<Claim> claims, string clientId)
- {
- foreach (var claim in claims)
- {
- if (claim.Type == ClaimTypes.Role || claim.Type == "roles")
- {
- yield return claim.Value;
- continue;
- }
-
- if (claim.Type == "realm_access")
- {
- foreach (var role in ExtractRolesFromJson(claim.Value))
- {
- yield return role;
- }
- continue;
- }
-
- if (claim.Type == "resource_access")
- {
- foreach (var role in ExtractResourceRolesFromJson(claim.Value, clientId))
- {
- yield return role;
- }
- }
- }
- }
-
- private static IEnumerable<string> ExtractRolesFromJson(string json)
- {
- using var document = ParseJsonOrDefault(json);
- if (document is null ||
- !document.RootElement.TryGetProperty("roles", out var roles) ||
- roles.ValueKind != JsonValueKind.Array)
- {
- yield break;
- }
-
- foreach (var role in roles.EnumerateArray())
- {
- if (role.ValueKind == JsonValueKind.String)
- {
- yield return role.GetString()!;
- }
- }
- }
-
- private static IEnumerable<string> ExtractResourceRolesFromJson(string json, string clientId)
- {
- using var document = ParseJsonOrDefault(json);
- if (document is null ||
- !document.RootElement.TryGetProperty(clientId, out var clientAccess))
- {
- yield break;
- }
-
- foreach (var role in ExtractRolesFromJson(clientAccess.GetRawText()))
- {
- yield return role;
- }
- }
-
- private static JsonDocument? ParseJsonOrDefault(string json)
- {
- try
- {
- return JsonDocument.Parse(json);
- }
- catch (JsonException)
- {
- return null;
- }
- }
- }
|