< 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    {
 2029        _authorizationPolicyProvider = authorizationPolicyProvider;
 2030    }
 31
 32    /// <inheritdoc />
 33    public void Apply(OpenApiOperation operation, OperationFilterContext context)
 34    {
 38435        var requiredScopes = new List<string>();
 36
 38437        var requiresAuth = false;
 38        // Add all method scopes.
 109439        foreach (var authorizeAttribute in context.MethodInfo.GetCustomAttributes(_attributeType, true).Cast<AuthorizeAt
 40        {
 16341            requiresAuth = true;
 16342            var policy = authorizeAttribute.Policy ?? DefaultAuthPolicy;
 16343            if (!requiredScopes.Contains(policy, StringComparer.Ordinal))
 44            {
 16345                requiredScopes.Add(policy);
 46            }
 47        }
 48
 49        // Add controller scopes if any.
 38450        var controllerAttributes = context.MethodInfo.DeclaringType?.GetCustomAttributes(_attributeType, true).Cast<Auth
 38451        if (controllerAttributes is not null)
 52        {
 114853            foreach (var authorizeAttribute in controllerAttributes)
 54            {
 19055                requiresAuth = true;
 19056                var policy = authorizeAttribute.Policy ?? DefaultAuthPolicy;
 19057                if (!requiredScopes.Contains(policy, StringComparer.Ordinal))
 58                {
 19059                    requiredScopes.Add(policy);
 60                }
 61            }
 62        }
 63
 38464        if (!requiresAuth)
 65        {
 5966            return;
 67        }
 68
 32569        if (!operation.Responses.ContainsKey("401"))
 70        {
 32271            operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" });
 72        }
 73
 32574        if (!operation.Responses.ContainsKey("403"))
 75        {
 29976            operation.Responses.Add("403", new OpenApiResponse { Description = "Forbidden" });
 77        }
 78
 32579        var scheme = new OpenApiSecurityScheme
 32580        {
 32581            Reference = new OpenApiReference
 32582            {
 32583                Type = ReferenceType.SecurityScheme,
 32584                Id = AuthenticationSchemes.CustomAuthentication
 32585            },
 32586        };
 87
 88        // Add DefaultAuthorization scope to any endpoint that has a policy with a requirement that is a subset of Defau
 32589        if (!requiredScopes.Contains(DefaultAuthPolicy.AsSpan(), StringComparison.Ordinal))
 90        {
 53891            foreach (var scope in requiredScopes)
 92            {
 16093                var authorizationPolicy = _authorizationPolicyProvider.GetPolicyAsync(scope).GetAwaiter().GetResult();
 16094                if (authorizationPolicy is not null
 16095                    && authorizationPolicy.Requirements.Any(r => r is DefaultAuthorizationRequirement))
 96                {
 10297                    requiredScopes.Add(DefaultAuthPolicy);
 10298                    break;
 99                }
 100            }
 101        }
 102
 325103        operation.Security = [new OpenApiSecurityRequirement { [scheme] = requiredScopes }];
 325104    }
 105}