< Summary - Jellyfin

Information
Class: Jellyfin.Server.Filters.SecurityRequirementsOperationFilter
Assembly: jellyfin
File(s): /srv/git/jellyfin/Jellyfin.Server/Filters/SecurityRequirementsOperationFilter.cs
Line coverage
100%
Covered lines: 40
Uncovered lines: 0
Coverable lines: 40
Total lines: 105
Line coverage: 100%
Branch coverage
96%
Covered branches: 29
Total branches: 30
Branch coverage: 96.6%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
.ctor(...)100%11100%
Apply(...)96.66%3030100%

File(s)

/srv/git/jellyfin/Jellyfin.Server/Filters/SecurityRequirementsOperationFilter.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using Jellyfin.Api.Auth.DefaultAuthorizationPolicy;
 5using Jellyfin.Api.Constants;
 6using Jellyfin.Extensions;
 7using Microsoft.AspNetCore.Authorization;
 8using Microsoft.OpenApi.Models;
 9using Swashbuckle.AspNetCore.SwaggerGen;
 10
 11namespace Jellyfin.Server.Filters;
 12
 13/// <summary>
 14/// Security requirement operation filter.
 15/// </summary>
 16public class SecurityRequirementsOperationFilter : IOperationFilter
 17{
 18    private const string DefaultAuthPolicy = "DefaultAuthorization";
 119    private static readonly Type _attributeType = typeof(AuthorizeAttribute);
 20
 21    private readonly IAuthorizationPolicyProvider _authorizationPolicyProvider;
 22
 23    /// <summary>
 24    /// Initializes a new instance of the <see cref="SecurityRequirementsOperationFilter"/> class.
 25    /// </summary>
 26    /// <param name="authorizationPolicyProvider">The authorization policy provider.</param>
 27    public SecurityRequirementsOperationFilter(IAuthorizationPolicyProvider authorizationPolicyProvider)
 28    {
 2129        _authorizationPolicyProvider = authorizationPolicyProvider;
 2130    }
 31
 32    /// <inheritdoc />
 33    public void Apply(OpenApiOperation operation, OperationFilterContext context)
 34    {
 38135        var requiredScopes = new List<string>();
 36
 38137        var requiresAuth = false;
 38        // Add all method scopes.
 108439        foreach (var authorizeAttribute in context.MethodInfo.GetCustomAttributes(_attributeType, true).Cast<AuthorizeAt
 40        {
 16141            requiresAuth = true;
 16142            var policy = authorizeAttribute.Policy ?? DefaultAuthPolicy;
 16143            if (!requiredScopes.Contains(policy, StringComparer.Ordinal))
 44            {
 16145                requiredScopes.Add(policy);
 46            }
 47        }
 48
 49        // Add controller scopes if any.
 38150        var controllerAttributes = context.MethodInfo.DeclaringType?.GetCustomAttributes(_attributeType, true).Cast<Auth
 38151        if (controllerAttributes is not null)
 52        {
 113653            foreach (var authorizeAttribute in controllerAttributes)
 54            {
 18755                requiresAuth = true;
 18756                var policy = authorizeAttribute.Policy ?? DefaultAuthPolicy;
 18757                if (!requiredScopes.Contains(policy, StringComparer.Ordinal))
 58                {
 18759                    requiredScopes.Add(policy);
 60                }
 61            }
 62        }
 63
 38164        if (!requiresAuth)
 65        {
 5966            return;
 67        }
 68
 32269        if (!operation.Responses.ContainsKey("401"))
 70        {
 31971            operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" });
 72        }
 73
 32274        if (!operation.Responses.ContainsKey("403"))
 75        {
 29776            operation.Responses.Add("403", new OpenApiResponse { Description = "Forbidden" });
 77        }
 78
 32279        var scheme = new OpenApiSecurityScheme
 32280        {
 32281            Reference = new OpenApiReference
 32282            {
 32283                Type = ReferenceType.SecurityScheme,
 32284                Id = AuthenticationSchemes.CustomAuthentication
 32285            },
 32286        };
 87
 88        // Add DefaultAuthorization scope to any endpoint that has a policy with a requirement that is a subset of Defau
 32289        if (!requiredScopes.Contains(DefaultAuthPolicy.AsSpan(), StringComparison.Ordinal))
 90        {
 53191            foreach (var scope in requiredScopes)
 92            {
 15893                var authorizationPolicy = _authorizationPolicyProvider.GetPolicyAsync(scope).GetAwaiter().GetResult();
 15894                if (authorizationPolicy is not null
 15895                    && authorizationPolicy.Requirements.Any(r => r is DefaultAuthorizationRequirement))
 96                {
 10197                    requiredScopes.Add(DefaultAuthPolicy);
 10198                    break;
 99                }
 100            }
 101        }
 102
 322103        operation.Security = [new OpenApiSecurityRequirement { [scheme] = requiredScopes }];
 322104    }
 105}