< Summary

Information
Class: OzonOrdersWeb.Authorization.PermissionClaimsTransformation
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Authorization/PermissionClaimsTransformation.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 36
Coverable lines: 36
Total lines: 88
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 22
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
TransformAsync()0%342180%
EnsureLegacyUserRole(...)0%2040%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Authorization/PermissionClaimsTransformation.cs

#LineLine coverage
 1using System.Security.Claims;
 2using Microsoft.AspNetCore.Authentication;
 3using Microsoft.Extensions.Logging;
 4using Services.Authorization.Dtos;
 5using Services.Authorization.Services;
 6using Claim = System.Security.Claims.Claim;
 7
 8namespace OzonOrdersWeb.Authorization;
 9
 10/// <summary>
 11/// ClaimsTransformation: при каждом запросе обогащает ClaimsPrincipal именами прикладных ролей (AppRoleNames)
 12/// и отметкой SuperAdmin. Это позволяет использовать стандартные [Authorize(Roles=...)] для быстрых проверок
 13/// и видеть роли в claims сессии.
 14/// </summary>
 15public sealed class PermissionClaimsTransformation : IClaimsTransformation
 16{
 17    public const string AppRoleClaimType = "app_role";
 18    public const string SuperAdminClaimType = "app_is_super_admin";
 19
 20    private readonly IPermissionService _permissions;
 21    private readonly ILogger<PermissionClaimsTransformation> _logger;
 22
 023    public PermissionClaimsTransformation(
 024        IPermissionService permissions,
 025        ILogger<PermissionClaimsTransformation> logger)
 26    {
 027        _permissions = permissions;
 028        _logger = logger;
 029    }
 30
 31    public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
 32    {
 033        if (principal.Identity?.IsAuthenticated != true) return principal;
 34
 035        var userId = principal.FindFirst(ClaimTypes.NameIdentifier)?.Value;
 036        if (string.IsNullOrWhiteSpace(userId)) return principal;
 37
 38        UserPermissionsBundle bundle;
 39        try
 40        {
 041            bundle = await _permissions.GetUserPermissionsAsync(userId);
 042        }
 043        catch (Exception ex)
 44        {
 045            _logger.LogWarning(
 046                ex,
 047                "Не удалось загрузить права для claims (userId={UserId}), запрос продолжится с Identity-ролями",
 048                userId);
 049            return EnsureLegacyUserRole(principal);
 50        }
 51
 052        var identity = new ClaimsIdentity();
 053        foreach (var roleName in bundle.RoleNames)
 54        {
 055            identity.AddClaim(new Claim(AppRoleClaimType, roleName));
 056            identity.AddClaim(new Claim(ClaimTypes.Role, roleName));
 57        }
 058        if (bundle.IsSuperAdmin)
 59        {
 060            identity.AddClaim(new Claim(SuperAdminClaimType, "true"));
 61            // Обратная совместимость с существующими [Authorize(Roles="Admin")]
 062            if (!principal.IsInRole("Admin"))
 063                identity.AddClaim(new Claim(ClaimTypes.Role, "Admin"));
 64        }
 065        else if (bundle.RoleNames.Count > 0 && !principal.IsInRole("User"))
 66        {
 67            // Обратная совместимость: legacy-контроллеры защищены [Authorize(Roles="User,Admin")].
 68            // Любой пользователь с прикладной ролью должен проходить проверку "User".
 069            identity.AddClaim(new Claim(ClaimTypes.Role, "User"));
 70        }
 71
 072        principal.AddIdentity(identity);
 073        return principal;
 074    }
 75
 76    private static ClaimsPrincipal EnsureLegacyUserRole(ClaimsPrincipal principal)
 77    {
 078        if (principal.IsInRole("User") || principal.IsInRole("Admin"))
 79        {
 080            return principal;
 81        }
 82
 083        var identity = new ClaimsIdentity();
 084        identity.AddClaim(new Claim(ClaimTypes.Role, "User"));
 085        principal.AddIdentity(identity);
 086        return principal;
 87    }
 88}