using System.Threading.Tasks; using Jellyfin.Api.Constants; using MediaBrowser.Common.Api; using MediaBrowser.Controller.Configuration; using MediaBrowser.Model.Configuration; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Logging; namespace Jellyfin.Api.Auth.ConditionalAuthorizationHandler; /// /// Authorization handler for conditionally requiring elevated access to specific routes. /// public class ConditionalAuthorizationHandler : AuthorizationHandler { private readonly IServerConfigurationManager _configurationManager; private readonly ILogger _logger; /// /// Initializes a new instance of the class. /// /// Instance of the interface. /// Instance of the interface. public ConditionalAuthorizationHandler(IServerConfigurationManager configurationManager, ILogger logger) { _configurationManager = configurationManager; _logger = logger; } /// protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ConditionalAuthorizationRequirement requirement) { var experimentalConfiguration = (ExperimentalConfiguration)_configurationManager.GetConfiguration("experimental"); var requiresElevation = requirement.PolicyName == Policies.ElevatePlugin || requirement.PolicyName == Policies.ElevateConfiguration; var conditionalAuthorization = requirement.PolicyName switch { Policies.ElevatePlugin => experimentalConfiguration.ElevatePluginRoutes, Policies.ElevateConfiguration => experimentalConfiguration.ElevateConfigurationRoutes, Policies.AuthenticateAudio => experimentalConfiguration.AuthenticateAudioRoutes, Policies.AuthenticateVideo => experimentalConfiguration.AuthenticateVideoRoutes, _ => true }; if (conditionalAuthorization && requiresElevation && !context.User.IsInRole(UserRoles.Administrator)) { _logger.LogWarning("administrator access currently required for this route due to {PolicyName} setting", requirement.PolicyName); context.Fail(); } else if (conditionalAuthorization && !requiresElevation && !context.User.Identity!.IsAuthenticated) { _logger.LogWarning("authentication currently required for this route due to {PolicyName} setting", requirement.PolicyName); context.Fail(); } else { context.Succeed(requirement); } return Task.CompletedTask; } }