diff --git a/Jellyfin.Api/Auth/AnonymousLanAccessPolicy/AnonymousLanAccessHandler.cs b/Jellyfin.Api/Auth/AnonymousLanAccessPolicy/AnonymousLanAccessHandler.cs
index d4b1ffb060..741b88ea95 100644
--- a/Jellyfin.Api/Auth/AnonymousLanAccessPolicy/AnonymousLanAccessHandler.cs
+++ b/Jellyfin.Api/Auth/AnonymousLanAccessPolicy/AnonymousLanAccessHandler.cs
@@ -1,4 +1,5 @@
using System.Threading.Tasks;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
@@ -29,7 +30,7 @@ namespace Jellyfin.Api.Auth.AnonymousLanAccessPolicy
///
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AnonymousLanAccessRequirement requirement)
{
- var ip = _httpContextAccessor.HttpContext?.Connection.RemoteIpAddress;
+ var ip = _httpContextAccessor.HttpContext?.GetNormalizedRemoteIp();
// Loopback will be on LAN, so we can accept null.
if (ip is null || _networkManager.IsInLocalNetwork(ip))
diff --git a/Jellyfin.Api/Auth/BaseAuthorizationHandler.cs b/Jellyfin.Api/Auth/BaseAuthorizationHandler.cs
deleted file mode 100644
index 8e5e66d64a..0000000000
--- a/Jellyfin.Api/Auth/BaseAuthorizationHandler.cs
+++ /dev/null
@@ -1,113 +0,0 @@
-using System.Security.Claims;
-using Jellyfin.Api.Extensions;
-using Jellyfin.Api.Helpers;
-using Jellyfin.Data.Enums;
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Library;
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Http;
-
-namespace Jellyfin.Api.Auth
-{
- ///
- /// Base authorization handler.
- ///
- /// Type of Authorization Requirement.
- public abstract class BaseAuthorizationHandler : AuthorizationHandler
- where T : IAuthorizationRequirement
- {
- private readonly IUserManager _userManager;
- private readonly INetworkManager _networkManager;
- private readonly IHttpContextAccessor _httpContextAccessor;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Instance of the interface.
- /// Instance of the interface.
- /// Instance of the interface.
- protected BaseAuthorizationHandler(
- IUserManager userManager,
- INetworkManager networkManager,
- IHttpContextAccessor httpContextAccessor)
- {
- _userManager = userManager;
- _networkManager = networkManager;
- _httpContextAccessor = httpContextAccessor;
- }
-
- ///
- /// Validate authenticated claims.
- ///
- /// Request claims.
- /// Whether to ignore parental control.
- /// Whether access is to be allowed locally only.
- /// Whether validation requires download permission.
- /// Validated claim status.
- protected bool ValidateClaims(
- ClaimsPrincipal claimsPrincipal,
- bool ignoreSchedule = false,
- bool localAccessOnly = false,
- bool requiredDownloadPermission = false)
- {
- // ApiKey is currently global admin, always allow.
- var isApiKey = claimsPrincipal.GetIsApiKey();
- if (isApiKey)
- {
- return true;
- }
-
- // Ensure claim has userId.
- var userId = claimsPrincipal.GetUserId();
- if (userId.Equals(default))
- {
- return false;
- }
-
- // Ensure userId links to a valid user.
- var user = _userManager.GetUserById(userId);
- if (user is null)
- {
- return false;
- }
-
- // Ensure user is not disabled.
- if (user.HasPermission(PermissionKind.IsDisabled))
- {
- return false;
- }
-
- var isInLocalNetwork = _httpContextAccessor.HttpContext is not null
- && _networkManager.IsInLocalNetwork(_httpContextAccessor.HttpContext.GetNormalizedRemoteIp());
-
- // User cannot access remotely and user is remote
- if (!user.HasPermission(PermissionKind.EnableRemoteAccess) && !isInLocalNetwork)
- {
- return false;
- }
-
- if (localAccessOnly && !isInLocalNetwork)
- {
- return false;
- }
-
- // User attempting to access out of parental control hours.
- if (!ignoreSchedule
- && !user.HasPermission(PermissionKind.IsAdministrator)
- && !user.IsParentalScheduleAllowed())
- {
- return false;
- }
-
- // User attempting to download without permission.
- if (requiredDownloadPermission
- && !user.HasPermission(PermissionKind.EnableContentDownloading))
- {
- return false;
- }
-
- return true;
- }
- }
-}
diff --git a/Jellyfin.Api/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandler.cs b/Jellyfin.Api/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandler.cs
index be77b7a4e4..7489e2a35c 100644
--- a/Jellyfin.Api/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandler.cs
+++ b/Jellyfin.Api/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandler.cs
@@ -1,4 +1,8 @@
using System.Threading.Tasks;
+using Jellyfin.Api.Constants;
+using Jellyfin.Api.Extensions;
+using Jellyfin.Data.Enums;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Library;
using Microsoft.AspNetCore.Authorization;
@@ -9,8 +13,12 @@ namespace Jellyfin.Api.Auth.DefaultAuthorizationPolicy
///
/// Default authorization handler.
///
- public class DefaultAuthorizationHandler : BaseAuthorizationHandler
+ public class DefaultAuthorizationHandler : AuthorizationHandler
{
+ private readonly IUserManager _userManager;
+ private readonly INetworkManager _networkManager;
+ private readonly IHttpContextAccessor _httpContextAccessor;
+
///
/// Initializes a new instance of the class.
///
@@ -21,21 +29,50 @@ namespace Jellyfin.Api.Auth.DefaultAuthorizationPolicy
IUserManager userManager,
INetworkManager networkManager,
IHttpContextAccessor httpContextAccessor)
- : base(userManager, networkManager, httpContextAccessor)
{
+ _userManager = userManager;
+ _networkManager = networkManager;
+ _httpContextAccessor = httpContextAccessor;
}
///
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, DefaultAuthorizationRequirement requirement)
{
- var validated = ValidateClaims(context.User);
- if (validated)
+ // Admins can do everything
+ if (context.User.GetIsApiKey() || context.User.IsInRole(UserRoles.Administrator))
{
context.Succeed(requirement);
+ return Task.CompletedTask;
}
- else
+
+ var userId = context.User.GetUserId();
+ // This likely only happens during the wizard, so skip the default checks and let any other handlers do it
+ if (userId.Equals(default))
+ {
+ return Task.CompletedTask;
+ }
+
+ var isInLocalNetwork = _httpContextAccessor.HttpContext is not null
+ && _networkManager.IsInLocalNetwork(_httpContextAccessor.HttpContext.GetNormalizedRemoteIp());
+ var user = _userManager.GetUserById(userId);
+ // User cannot access remotely and user is remote
+ if (!isInLocalNetwork && !user.HasPermission(PermissionKind.EnableRemoteAccess))
{
context.Fail();
+ return Task.CompletedTask;
+ }
+
+ // It's not great to have this check, but parental schedule must usually be honored except in a few rare cases
+ if (requirement.ValidateParentalSchedule && !user.IsParentalScheduleAllowed())
+ {
+ context.Fail();
+ return Task.CompletedTask;
+ }
+
+ // Only succeed if the requirement isn't a subclass as any subclassed requirement will handle success in its own handler
+ if (requirement.GetType() == typeof(DefaultAuthorizationRequirement))
+ {
+ context.Succeed(requirement);
}
return Task.CompletedTask;
diff --git a/Jellyfin.Api/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationRequirement.cs b/Jellyfin.Api/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationRequirement.cs
index 7cea00b694..0846e7515a 100644
--- a/Jellyfin.Api/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationRequirement.cs
+++ b/Jellyfin.Api/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationRequirement.cs
@@ -7,5 +7,18 @@ namespace Jellyfin.Api.Auth.DefaultAuthorizationPolicy
///
public class DefaultAuthorizationRequirement : IAuthorizationRequirement
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// A value indicating whether to validate parental schedule.
+ public DefaultAuthorizationRequirement(bool validateParentalSchedule = true)
+ {
+ ValidateParentalSchedule = validateParentalSchedule;
+ }
+
+ ///
+ /// Gets a value indicating whether to ignore parental schedule.
+ ///
+ public bool ValidateParentalSchedule { get; init; }
}
}
diff --git a/Jellyfin.Api/Auth/DownloadPolicy/DownloadHandler.cs b/Jellyfin.Api/Auth/DownloadPolicy/DownloadHandler.cs
deleted file mode 100644
index b61680ab1a..0000000000
--- a/Jellyfin.Api/Auth/DownloadPolicy/DownloadHandler.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-using System.Threading.Tasks;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Library;
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Http;
-
-namespace Jellyfin.Api.Auth.DownloadPolicy
-{
- ///
- /// Download authorization handler.
- ///
- public class DownloadHandler : BaseAuthorizationHandler
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// Instance of the interface.
- /// Instance of the interface.
- /// Instance of the interface.
- public DownloadHandler(
- IUserManager userManager,
- INetworkManager networkManager,
- IHttpContextAccessor httpContextAccessor)
- : base(userManager, networkManager, httpContextAccessor)
- {
- }
-
- ///
- protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, DownloadRequirement requirement)
- {
- var validated = ValidateClaims(context.User);
- if (validated)
- {
- context.Succeed(requirement);
- }
- else
- {
- context.Fail();
- }
-
- return Task.CompletedTask;
- }
- }
-}
diff --git a/Jellyfin.Api/Auth/DownloadPolicy/DownloadRequirement.cs b/Jellyfin.Api/Auth/DownloadPolicy/DownloadRequirement.cs
deleted file mode 100644
index b0a72a9dec..0000000000
--- a/Jellyfin.Api/Auth/DownloadPolicy/DownloadRequirement.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using Microsoft.AspNetCore.Authorization;
-
-namespace Jellyfin.Api.Auth.DownloadPolicy
-{
- ///
- /// The download permission requirement.
- ///
- public class DownloadRequirement : IAuthorizationRequirement
- {
- }
-}
diff --git a/Jellyfin.Api/Auth/FirstTimeOrIgnoreParentalControlSetupPolicy/FirstTimeOrIgnoreParentalControlSetupHandler.cs b/Jellyfin.Api/Auth/FirstTimeOrIgnoreParentalControlSetupPolicy/FirstTimeOrIgnoreParentalControlSetupHandler.cs
deleted file mode 100644
index 31482a930f..0000000000
--- a/Jellyfin.Api/Auth/FirstTimeOrIgnoreParentalControlSetupPolicy/FirstTimeOrIgnoreParentalControlSetupHandler.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-using System.Threading.Tasks;
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Library;
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Http;
-
-namespace Jellyfin.Api.Auth.FirstTimeOrIgnoreParentalControlSetupPolicy
-{
- ///
- /// Ignore parental control schedule and allow before startup wizard has been completed.
- ///
- public class FirstTimeOrIgnoreParentalControlSetupHandler : BaseAuthorizationHandler
- {
- private readonly IConfigurationManager _configurationManager;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Instance of the interface.
- /// Instance of the interface.
- /// Instance of the interface.
- /// Instance of the interface.
- public FirstTimeOrIgnoreParentalControlSetupHandler(
- IUserManager userManager,
- INetworkManager networkManager,
- IHttpContextAccessor httpContextAccessor,
- IConfigurationManager configurationManager)
- : base(userManager, networkManager, httpContextAccessor)
- {
- _configurationManager = configurationManager;
- }
-
- ///
- protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FirstTimeOrIgnoreParentalControlSetupRequirement requirement)
- {
- if (!_configurationManager.CommonConfiguration.IsStartupWizardCompleted)
- {
- context.Succeed(requirement);
- return Task.CompletedTask;
- }
-
- var validated = ValidateClaims(context.User, ignoreSchedule: true);
- if (validated)
- {
- context.Succeed(requirement);
- }
- else
- {
- context.Fail();
- }
-
- return Task.CompletedTask;
- }
- }
-}
diff --git a/Jellyfin.Api/Auth/FirstTimeOrIgnoreParentalControlSetupPolicy/FirstTimeOrIgnoreParentalControlSetupRequirement.cs b/Jellyfin.Api/Auth/FirstTimeOrIgnoreParentalControlSetupPolicy/FirstTimeOrIgnoreParentalControlSetupRequirement.cs
deleted file mode 100644
index 00aaec334b..0000000000
--- a/Jellyfin.Api/Auth/FirstTimeOrIgnoreParentalControlSetupPolicy/FirstTimeOrIgnoreParentalControlSetupRequirement.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using Microsoft.AspNetCore.Authorization;
-
-namespace Jellyfin.Api.Auth.FirstTimeOrIgnoreParentalControlSetupPolicy
-{
- ///
- /// First time setup or ignore parental controls requirement.
- ///
- public class FirstTimeOrIgnoreParentalControlSetupRequirement : IAuthorizationRequirement
- {
- }
-}
diff --git a/Jellyfin.Api/Auth/FirstTimeSetupOrDefaultPolicy/FirstTimeSetupOrDefaultRequirement.cs b/Jellyfin.Api/Auth/FirstTimeSetupOrDefaultPolicy/FirstTimeSetupOrDefaultRequirement.cs
deleted file mode 100644
index f7366bd7a9..0000000000
--- a/Jellyfin.Api/Auth/FirstTimeSetupOrDefaultPolicy/FirstTimeSetupOrDefaultRequirement.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using Microsoft.AspNetCore.Authorization;
-
-namespace Jellyfin.Api.Auth.FirstTimeSetupOrDefaultPolicy
-{
- ///
- /// The authorization requirement, requiring incomplete first time setup or default privileges, for the authorization handler.
- ///
- public class FirstTimeSetupOrDefaultRequirement : IAuthorizationRequirement
- {
- }
-}
diff --git a/Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandler.cs b/Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandler.cs
deleted file mode 100644
index 90b76ee99a..0000000000
--- a/Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandler.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-using System.Threading.Tasks;
-using Jellyfin.Api.Constants;
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Library;
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Http;
-
-namespace Jellyfin.Api.Auth.FirstTimeSetupOrElevatedPolicy
-{
- ///
- /// Authorization handler for requiring first time setup or elevated privileges.
- ///
- public class FirstTimeSetupOrElevatedHandler : BaseAuthorizationHandler
- {
- private readonly IConfigurationManager _configurationManager;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Instance of the interface.
- /// Instance of the interface.
- /// Instance of the interface.
- /// Instance of the interface.
- public FirstTimeSetupOrElevatedHandler(
- IConfigurationManager configurationManager,
- IUserManager userManager,
- INetworkManager networkManager,
- IHttpContextAccessor httpContextAccessor)
- : base(userManager, networkManager, httpContextAccessor)
- {
- _configurationManager = configurationManager;
- }
-
- ///
- protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FirstTimeSetupOrElevatedRequirement requirement)
- {
- if (!_configurationManager.CommonConfiguration.IsStartupWizardCompleted)
- {
- context.Succeed(requirement);
- return Task.CompletedTask;
- }
-
- var validated = ValidateClaims(context.User);
- if (validated && context.User.IsInRole(UserRoles.Administrator))
- {
- context.Succeed(requirement);
- }
- else
- {
- context.Fail();
- }
-
- return Task.CompletedTask;
- }
- }
-}
diff --git a/Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedRequirement.cs b/Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedRequirement.cs
deleted file mode 100644
index 51ba637b60..0000000000
--- a/Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedRequirement.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using Microsoft.AspNetCore.Authorization;
-
-namespace Jellyfin.Api.Auth.FirstTimeSetupOrElevatedPolicy
-{
- ///
- /// The authorization requirement, requiring incomplete first time setup or elevated privileges, for the authorization handler.
- ///
- public class FirstTimeSetupOrElevatedRequirement : IAuthorizationRequirement
- {
- }
-}
diff --git a/Jellyfin.Api/Auth/FirstTimeSetupOrDefaultPolicy/FirstTimeSetupOrDefaultHandler.cs b/Jellyfin.Api/Auth/FirstTimeSetupPolicy/FirstTimeSetupHandler.cs
similarity index 58%
rename from Jellyfin.Api/Auth/FirstTimeSetupOrDefaultPolicy/FirstTimeSetupOrDefaultHandler.cs
rename to Jellyfin.Api/Auth/FirstTimeSetupPolicy/FirstTimeSetupHandler.cs
index dd0bd4ec2f..302e052a7c 100644
--- a/Jellyfin.Api/Auth/FirstTimeSetupOrDefaultPolicy/FirstTimeSetupOrDefaultHandler.cs
+++ b/Jellyfin.Api/Auth/FirstTimeSetupPolicy/FirstTimeSetupHandler.cs
@@ -1,38 +1,35 @@
using System.Threading.Tasks;
+using Jellyfin.Api.Constants;
+using Jellyfin.Api.Extensions;
using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Library;
using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Http;
-namespace Jellyfin.Api.Auth.FirstTimeSetupOrDefaultPolicy
+namespace Jellyfin.Api.Auth.FirstTimeSetupPolicy
{
///
/// Authorization handler for requiring first time setup or default privileges.
///
- public class FirstTimeSetupOrDefaultHandler : BaseAuthorizationHandler
+ public class FirstTimeSetupHandler : AuthorizationHandler
{
private readonly IConfigurationManager _configurationManager;
+ private readonly IUserManager _userManager;
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// Instance of the interface.
/// Instance of the interface.
- /// Instance of the interface.
- /// Instance of the interface.
- public FirstTimeSetupOrDefaultHandler(
+ public FirstTimeSetupHandler(
IConfigurationManager configurationManager,
- IUserManager userManager,
- INetworkManager networkManager,
- IHttpContextAccessor httpContextAccessor)
- : base(userManager, networkManager, httpContextAccessor)
+ IUserManager userManager)
{
_configurationManager = configurationManager;
+ _userManager = userManager;
}
///
- protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FirstTimeSetupOrDefaultRequirement requirement)
+ protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FirstTimeSetupRequirement requirement)
{
if (!_configurationManager.CommonConfiguration.IsStartupWizardCompleted)
{
@@ -40,14 +37,22 @@ namespace Jellyfin.Api.Auth.FirstTimeSetupOrDefaultPolicy
return Task.CompletedTask;
}
- var validated = ValidateClaims(context.User);
- if (validated)
+ if (requirement.RequireAdmin && !context.User.IsInRole(UserRoles.Administrator))
+ {
+ context.Fail();
+ return Task.CompletedTask;
+ }
+
+ if (!requirement.ValidateParentalSchedule)
{
context.Succeed(requirement);
+ return Task.CompletedTask;
}
- else
+
+ var user = _userManager.GetUserById(context.User.GetUserId());
+ if (user.IsParentalScheduleAllowed())
{
- context.Fail();
+ context.Succeed(requirement);
}
return Task.CompletedTask;
diff --git a/Jellyfin.Api/Auth/FirstTimeSetupPolicy/FirstTimeSetupRequirement.cs b/Jellyfin.Api/Auth/FirstTimeSetupPolicy/FirstTimeSetupRequirement.cs
new file mode 100644
index 0000000000..8b7a94954e
--- /dev/null
+++ b/Jellyfin.Api/Auth/FirstTimeSetupPolicy/FirstTimeSetupRequirement.cs
@@ -0,0 +1,26 @@
+using Jellyfin.Api.Auth.DefaultAuthorizationPolicy;
+
+namespace Jellyfin.Api.Auth.FirstTimeSetupPolicy
+{
+ ///
+ /// The authorization requirement, requiring incomplete first time setup or default privileges, for the authorization handler.
+ ///
+ public class FirstTimeSetupRequirement : DefaultAuthorizationRequirement
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// A value indicating whether to ignore parental schedule.
+ /// A value indicating whether administrator role is required.
+ public FirstTimeSetupRequirement(bool validateParentalSchedule = false, bool requireAdmin = true)
+ {
+ ValidateParentalSchedule = validateParentalSchedule;
+ RequireAdmin = requireAdmin;
+ }
+
+ ///
+ /// Gets a value indicating whether administrator role is required.
+ ///
+ public bool RequireAdmin { get; }
+ }
+}
diff --git a/Jellyfin.Api/Auth/IgnoreParentalControlPolicy/IgnoreParentalControlHandler.cs b/Jellyfin.Api/Auth/IgnoreParentalControlPolicy/IgnoreParentalControlHandler.cs
deleted file mode 100644
index a7623556a9..0000000000
--- a/Jellyfin.Api/Auth/IgnoreParentalControlPolicy/IgnoreParentalControlHandler.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-using System.Threading.Tasks;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Library;
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Http;
-
-namespace Jellyfin.Api.Auth.IgnoreParentalControlPolicy
-{
- ///
- /// Escape schedule controls handler.
- ///
- public class IgnoreParentalControlHandler : BaseAuthorizationHandler
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// Instance of the interface.
- /// Instance of the interface.
- /// Instance of the interface.
- public IgnoreParentalControlHandler(
- IUserManager userManager,
- INetworkManager networkManager,
- IHttpContextAccessor httpContextAccessor)
- : base(userManager, networkManager, httpContextAccessor)
- {
- }
-
- ///
- protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IgnoreParentalControlRequirement requirement)
- {
- var validated = ValidateClaims(context.User, ignoreSchedule: true);
- if (validated)
- {
- context.Succeed(requirement);
- }
- else
- {
- context.Fail();
- }
-
- return Task.CompletedTask;
- }
- }
-}
diff --git a/Jellyfin.Api/Auth/IgnoreParentalControlPolicy/IgnoreParentalControlRequirement.cs b/Jellyfin.Api/Auth/IgnoreParentalControlPolicy/IgnoreParentalControlRequirement.cs
deleted file mode 100644
index cdad74270e..0000000000
--- a/Jellyfin.Api/Auth/IgnoreParentalControlPolicy/IgnoreParentalControlRequirement.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using Microsoft.AspNetCore.Authorization;
-
-namespace Jellyfin.Api.Auth.IgnoreParentalControlPolicy
-{
- ///
- /// Escape schedule controls requirement.
- ///
- public class IgnoreParentalControlRequirement : IAuthorizationRequirement
- {
- }
-}
diff --git a/Jellyfin.Api/Auth/LocalAccessOrRequiresElevationPolicy/LocalAccessOrRequiresElevationHandler.cs b/Jellyfin.Api/Auth/LocalAccessOrRequiresElevationPolicy/LocalAccessOrRequiresElevationHandler.cs
deleted file mode 100644
index 14722aa57e..0000000000
--- a/Jellyfin.Api/Auth/LocalAccessOrRequiresElevationPolicy/LocalAccessOrRequiresElevationHandler.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using System.Threading.Tasks;
-using Jellyfin.Api.Constants;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Library;
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Http;
-
-namespace Jellyfin.Api.Auth.LocalAccessOrRequiresElevationPolicy
-{
- ///
- /// Local access or require elevated privileges handler.
- ///
- public class LocalAccessOrRequiresElevationHandler : BaseAuthorizationHandler
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// Instance of the interface.
- /// Instance of the interface.
- /// Instance of the interface.
- public LocalAccessOrRequiresElevationHandler(
- IUserManager userManager,
- INetworkManager networkManager,
- IHttpContextAccessor httpContextAccessor)
- : base(userManager, networkManager, httpContextAccessor)
- {
- }
-
- ///
- protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, LocalAccessOrRequiresElevationRequirement requirement)
- {
- var validated = ValidateClaims(context.User, localAccessOnly: true);
- if (validated || context.User.IsInRole(UserRoles.Administrator))
- {
- context.Succeed(requirement);
- }
- else
- {
- context.Fail();
- }
-
- return Task.CompletedTask;
- }
- }
-}
diff --git a/Jellyfin.Api/Auth/LocalAccessOrRequiresElevationPolicy/LocalAccessOrRequiresElevationRequirement.cs b/Jellyfin.Api/Auth/LocalAccessOrRequiresElevationPolicy/LocalAccessOrRequiresElevationRequirement.cs
deleted file mode 100644
index d9c64d01c4..0000000000
--- a/Jellyfin.Api/Auth/LocalAccessOrRequiresElevationPolicy/LocalAccessOrRequiresElevationRequirement.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using Microsoft.AspNetCore.Authorization;
-
-namespace Jellyfin.Api.Auth.LocalAccessOrRequiresElevationPolicy
-{
- ///
- /// The local access or elevated privileges authorization requirement.
- ///
- public class LocalAccessOrRequiresElevationRequirement : IAuthorizationRequirement
- {
- }
-}
diff --git a/Jellyfin.Api/Auth/LocalAccessPolicy/LocalAccessHandler.cs b/Jellyfin.Api/Auth/LocalAccessPolicy/LocalAccessHandler.cs
deleted file mode 100644
index d772ec5542..0000000000
--- a/Jellyfin.Api/Auth/LocalAccessPolicy/LocalAccessHandler.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-using System.Threading.Tasks;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Library;
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Http;
-
-namespace Jellyfin.Api.Auth.LocalAccessPolicy
-{
- ///
- /// Local access handler.
- ///
- public class LocalAccessHandler : BaseAuthorizationHandler
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// Instance of the interface.
- /// Instance of the interface.
- /// Instance of the interface.
- public LocalAccessHandler(
- IUserManager userManager,
- INetworkManager networkManager,
- IHttpContextAccessor httpContextAccessor)
- : base(userManager, networkManager, httpContextAccessor)
- {
- }
-
- ///
- protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, LocalAccessRequirement requirement)
- {
- var validated = ValidateClaims(context.User, localAccessOnly: true);
- if (validated)
- {
- context.Succeed(requirement);
- }
- else
- {
- context.Fail();
- }
-
- return Task.CompletedTask;
- }
- }
-}
diff --git a/Jellyfin.Api/Auth/LocalAccessPolicy/LocalAccessRequirement.cs b/Jellyfin.Api/Auth/LocalAccessPolicy/LocalAccessRequirement.cs
deleted file mode 100644
index 761127fa40..0000000000
--- a/Jellyfin.Api/Auth/LocalAccessPolicy/LocalAccessRequirement.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using Microsoft.AspNetCore.Authorization;
-
-namespace Jellyfin.Api.Auth.LocalAccessPolicy
-{
- ///
- /// The local access authorization requirement.
- ///
- public class LocalAccessRequirement : IAuthorizationRequirement
- {
- }
-}
diff --git a/Jellyfin.Api/Auth/RequiresElevationPolicy/RequiresElevationHandler.cs b/Jellyfin.Api/Auth/RequiresElevationPolicy/RequiresElevationHandler.cs
deleted file mode 100644
index b235c4b63b..0000000000
--- a/Jellyfin.Api/Auth/RequiresElevationPolicy/RequiresElevationHandler.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using System.Threading.Tasks;
-using Jellyfin.Api.Constants;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Library;
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Http;
-
-namespace Jellyfin.Api.Auth.RequiresElevationPolicy
-{
- ///
- /// Authorization handler for requiring elevated privileges.
- ///
- public class RequiresElevationHandler : BaseAuthorizationHandler
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// Instance of the interface.
- /// Instance of the interface.
- /// Instance of the interface.
- public RequiresElevationHandler(
- IUserManager userManager,
- INetworkManager networkManager,
- IHttpContextAccessor httpContextAccessor)
- : base(userManager, networkManager, httpContextAccessor)
- {
- }
-
- ///
- protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RequiresElevationRequirement requirement)
- {
- var validated = ValidateClaims(context.User);
- if (validated && context.User.IsInRole(UserRoles.Administrator))
- {
- context.Succeed(requirement);
- }
- else
- {
- context.Fail();
- }
-
- return Task.CompletedTask;
- }
- }
-}
diff --git a/Jellyfin.Api/Auth/RequiresElevationPolicy/RequiresElevationRequirement.cs b/Jellyfin.Api/Auth/RequiresElevationPolicy/RequiresElevationRequirement.cs
deleted file mode 100644
index cfff1cc0c5..0000000000
--- a/Jellyfin.Api/Auth/RequiresElevationPolicy/RequiresElevationRequirement.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using Microsoft.AspNetCore.Authorization;
-
-namespace Jellyfin.Api.Auth.RequiresElevationPolicy
-{
- ///
- /// The authorization requirement for requiring elevated privileges in the authorization handler.
- ///
- public class RequiresElevationRequirement : IAuthorizationRequirement
- {
- }
-}
diff --git a/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs b/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs
index cdd7d8a52b..5c1029b383 100644
--- a/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs
+++ b/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs
@@ -1,19 +1,16 @@
using System.Threading.Tasks;
using Jellyfin.Api.Extensions;
-using Jellyfin.Api.Helpers;
using Jellyfin.Data.Enums;
-using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.SyncPlay;
using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Http;
namespace Jellyfin.Api.Auth.SyncPlayAccessPolicy
{
///
/// Default authorization handler.
///
- public class SyncPlayAccessHandler : BaseAuthorizationHandler
+ public class SyncPlayAccessHandler : AuthorizationHandler
{
private readonly ISyncPlayManager _syncPlayManager;
private readonly IUserManager _userManager;
@@ -23,14 +20,9 @@ namespace Jellyfin.Api.Auth.SyncPlayAccessPolicy
///
/// Instance of the interface.
/// Instance of the interface.
- /// Instance of the interface.
- /// Instance of the interface.
public SyncPlayAccessHandler(
ISyncPlayManager syncPlayManager,
- IUserManager userManager,
- INetworkManager networkManager,
- IHttpContextAccessor httpContextAccessor)
- : base(userManager, networkManager, httpContextAccessor)
+ IUserManager userManager)
{
_syncPlayManager = syncPlayManager;
_userManager = userManager;
@@ -39,27 +31,16 @@ namespace Jellyfin.Api.Auth.SyncPlayAccessPolicy
///
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, SyncPlayAccessRequirement requirement)
{
- if (!ValidateClaims(context.User))
- {
- context.Fail();
- return Task.CompletedTask;
- }
-
var userId = context.User.GetUserId();
var user = _userManager.GetUserById(userId);
if (requirement.RequiredAccess == SyncPlayAccessRequirementType.HasAccess)
{
- if (user.SyncPlayAccess == SyncPlayUserAccessType.CreateAndJoinGroups
- || user.SyncPlayAccess == SyncPlayUserAccessType.JoinGroups
+ if (user.SyncPlayAccess is SyncPlayUserAccessType.CreateAndJoinGroups or SyncPlayUserAccessType.JoinGroups
|| _syncPlayManager.IsUserActive(userId))
{
context.Succeed(requirement);
}
- else
- {
- context.Fail();
- }
}
else if (requirement.RequiredAccess == SyncPlayAccessRequirementType.CreateGroup)
{
@@ -67,10 +48,6 @@ namespace Jellyfin.Api.Auth.SyncPlayAccessPolicy
{
context.Succeed(requirement);
}
- else
- {
- context.Fail();
- }
}
else if (requirement.RequiredAccess == SyncPlayAccessRequirementType.JoinGroup)
{
@@ -79,10 +56,6 @@ namespace Jellyfin.Api.Auth.SyncPlayAccessPolicy
{
context.Succeed(requirement);
}
- else
- {
- context.Fail();
- }
}
else if (requirement.RequiredAccess == SyncPlayAccessRequirementType.IsInGroup)
{
@@ -90,14 +63,6 @@ namespace Jellyfin.Api.Auth.SyncPlayAccessPolicy
{
context.Succeed(requirement);
}
- else
- {
- context.Fail();
- }
- }
- else
- {
- context.Fail();
}
return Task.CompletedTask;
diff --git a/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessRequirement.cs b/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessRequirement.cs
index 6fab4c0ad8..220b223b39 100644
--- a/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessRequirement.cs
+++ b/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessRequirement.cs
@@ -1,12 +1,12 @@
-using Jellyfin.Data.Enums;
-using Microsoft.AspNetCore.Authorization;
+using Jellyfin.Api.Auth.DefaultAuthorizationPolicy;
+using Jellyfin.Data.Enums;
namespace Jellyfin.Api.Auth.SyncPlayAccessPolicy
{
///
/// The default authorization requirement.
///
- public class SyncPlayAccessRequirement : IAuthorizationRequirement
+ public class SyncPlayAccessRequirement : DefaultAuthorizationRequirement
{
///
/// Initializes a new instance of the class.
diff --git a/Jellyfin.Api/Auth/UserPermissionPolicy/UserPermissionHandler.cs b/Jellyfin.Api/Auth/UserPermissionPolicy/UserPermissionHandler.cs
new file mode 100644
index 0000000000..c3de7be328
--- /dev/null
+++ b/Jellyfin.Api/Auth/UserPermissionPolicy/UserPermissionHandler.cs
@@ -0,0 +1,37 @@
+using System.Threading.Tasks;
+using Jellyfin.Api.Auth.DownloadPolicy;
+using Jellyfin.Api.Extensions;
+using MediaBrowser.Controller.Library;
+using Microsoft.AspNetCore.Authorization;
+
+namespace Jellyfin.Api.Auth.UserPermissionPolicy
+{
+ ///
+ /// Download authorization handler.
+ ///
+ public class UserPermissionHandler : AuthorizationHandler
+ {
+ private readonly IUserManager _userManager;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Instance of the interface.
+ public UserPermissionHandler(IUserManager userManager)
+ {
+ _userManager = userManager;
+ }
+
+ ///
+ protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, UserPermissionRequirement requirement)
+ {
+ var user = _userManager.GetUserById(context.User.GetUserId());
+ if (user.HasPermission(requirement.RequiredPermission))
+ {
+ context.Succeed(requirement);
+ }
+
+ return Task.CompletedTask;
+ }
+ }
+}
diff --git a/Jellyfin.Api/Auth/UserPermissionPolicy/UserPermissionRequirement.cs b/Jellyfin.Api/Auth/UserPermissionPolicy/UserPermissionRequirement.cs
new file mode 100644
index 0000000000..195a611992
--- /dev/null
+++ b/Jellyfin.Api/Auth/UserPermissionPolicy/UserPermissionRequirement.cs
@@ -0,0 +1,26 @@
+using Jellyfin.Api.Auth.DefaultAuthorizationPolicy;
+using Jellyfin.Data.Enums;
+
+namespace Jellyfin.Api.Auth.DownloadPolicy
+{
+ ///
+ /// The user permission requirement.
+ ///
+ public class UserPermissionRequirement : DefaultAuthorizationRequirement
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The required .
+ /// Whether to validate the user's parental schedule.
+ public UserPermissionRequirement(PermissionKind requiredPermission, bool validateParentalSchedule = true) : base(validateParentalSchedule)
+ {
+ RequiredPermission = requiredPermission;
+ }
+
+ ///
+ /// Gets the required user permission.
+ ///
+ public PermissionKind RequiredPermission { get; }
+ }
+}
diff --git a/Jellyfin.Api/Constants/Policies.cs b/Jellyfin.Api/Constants/Policies.cs
index 5a5a2bf466..adc95e57b2 100644
--- a/Jellyfin.Api/Constants/Policies.cs
+++ b/Jellyfin.Api/Constants/Policies.cs
@@ -5,11 +5,6 @@ namespace Jellyfin.Api.Constants;
///
public static class Policies
{
- ///
- /// Policy name for default authorization.
- ///
- public const string DefaultAuthorization = "DefaultAuthorization";
-
///
/// Policy name for requiring first time setup or elevated privileges.
///
diff --git a/Jellyfin.Api/Controllers/ArtistsController.cs b/Jellyfin.Api/Controllers/ArtistsController.cs
index 069e7311b8..11933fd97f 100644
--- a/Jellyfin.Api/Controllers/ArtistsController.cs
+++ b/Jellyfin.Api/Controllers/ArtistsController.cs
@@ -1,7 +1,6 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
@@ -23,7 +22,7 @@ namespace Jellyfin.Api.Controllers;
/// The artists controller.
///
[Route("Artists")]
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class ArtistsController : BaseJellyfinApiController
{
private readonly ILibraryManager _libraryManager;
diff --git a/Jellyfin.Api/Controllers/ChannelsController.cs b/Jellyfin.Api/Controllers/ChannelsController.cs
index 573b7069c5..42f072f669 100644
--- a/Jellyfin.Api/Controllers/ChannelsController.cs
+++ b/Jellyfin.Api/Controllers/ChannelsController.cs
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Threading;
using System.Threading.Tasks;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Enums;
@@ -23,7 +22,7 @@ namespace Jellyfin.Api.Controllers;
///
/// Channels Controller.
///
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class ChannelsController : BaseJellyfinApiController
{
private readonly IChannelManager _channelManager;
diff --git a/Jellyfin.Api/Controllers/ClientLogController.cs b/Jellyfin.Api/Controllers/ClientLogController.cs
index 21c31bc936..2c5dbacbbe 100644
--- a/Jellyfin.Api/Controllers/ClientLogController.cs
+++ b/Jellyfin.Api/Controllers/ClientLogController.cs
@@ -1,7 +1,6 @@
using System.Net.Mime;
using System.Threading.Tasks;
using Jellyfin.Api.Attributes;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Models.ClientLogDtos;
using MediaBrowser.Controller.ClientEvent;
@@ -15,7 +14,7 @@ namespace Jellyfin.Api.Controllers;
///
/// Client log controller.
///
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class ClientLogController : BaseJellyfinApiController
{
private const int MaxDocumentSize = 1_000_000;
diff --git a/Jellyfin.Api/Controllers/CollectionController.cs b/Jellyfin.Api/Controllers/CollectionController.cs
index 5a4a9bf079..f9f9be7ce4 100644
--- a/Jellyfin.Api/Controllers/CollectionController.cs
+++ b/Jellyfin.Api/Controllers/CollectionController.cs
@@ -1,7 +1,6 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.ModelBinders;
using MediaBrowser.Controller.Collections;
@@ -17,7 +16,7 @@ namespace Jellyfin.Api.Controllers;
/// The collection controller.
///
[Route("Collections")]
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class CollectionController : BaseJellyfinApiController
{
private readonly ICollectionManager _collectionManager;
diff --git a/Jellyfin.Api/Controllers/ConfigurationController.cs b/Jellyfin.Api/Controllers/ConfigurationController.cs
index d53d7cefd0..9007dfc410 100644
--- a/Jellyfin.Api/Controllers/ConfigurationController.cs
+++ b/Jellyfin.Api/Controllers/ConfigurationController.cs
@@ -19,7 +19,7 @@ namespace Jellyfin.Api.Controllers;
/// Configuration Controller.
///
[Route("System")]
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class ConfigurationController : BaseJellyfinApiController
{
private readonly IServerConfigurationManager _configurationManager;
diff --git a/Jellyfin.Api/Controllers/DashboardController.cs b/Jellyfin.Api/Controllers/DashboardController.cs
index f7e978bad0..076084c7a3 100644
--- a/Jellyfin.Api/Controllers/DashboardController.cs
+++ b/Jellyfin.Api/Controllers/DashboardController.cs
@@ -4,7 +4,6 @@ using System.IO;
using System.Linq;
using System.Net.Mime;
using Jellyfin.Api.Attributes;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Models;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Model.Net;
@@ -48,7 +47,7 @@ public class DashboardController : BaseJellyfinApiController
[HttpGet("web/ConfigurationPages")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
public ActionResult> GetConfigurationPages(
[FromQuery] bool? enableInMainMenu)
{
diff --git a/Jellyfin.Api/Controllers/DisplayPreferencesController.cs b/Jellyfin.Api/Controllers/DisplayPreferencesController.cs
index 49d87a3621..6f0006832b 100644
--- a/Jellyfin.Api/Controllers/DisplayPreferencesController.cs
+++ b/Jellyfin.Api/Controllers/DisplayPreferencesController.cs
@@ -3,7 +3,6 @@ using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
-using Jellyfin.Api.Constants;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Extensions;
@@ -19,7 +18,7 @@ namespace Jellyfin.Api.Controllers;
///
/// Display Preferences Controller.
///
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class DisplayPreferencesController : BaseJellyfinApiController
{
private readonly IDisplayPreferencesManager _displayPreferencesManager;
diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs
index b68849171f..4d8b4de24f 100644
--- a/Jellyfin.Api/Controllers/DynamicHlsController.cs
+++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs
@@ -9,7 +9,6 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Api.Attributes;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.Models.PlaybackDtos;
using Jellyfin.Api.Models.StreamingDtos;
@@ -36,7 +35,7 @@ namespace Jellyfin.Api.Controllers;
/// Dynamic hls controller.
///
[Route("")]
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class DynamicHlsController : BaseJellyfinApiController
{
private const string DefaultVodEncoderPreset = "veryfast";
diff --git a/Jellyfin.Api/Controllers/FilterController.cs b/Jellyfin.Api/Controllers/FilterController.cs
index 2378aada5f..dd64ff9034 100644
--- a/Jellyfin.Api/Controllers/FilterController.cs
+++ b/Jellyfin.Api/Controllers/FilterController.cs
@@ -1,6 +1,5 @@
using System;
using System.Linq;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Dto;
@@ -18,7 +17,7 @@ namespace Jellyfin.Api.Controllers;
/// Filters controller.
///
[Route("")]
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class FilterController : BaseJellyfinApiController
{
private readonly ILibraryManager _libraryManager;
diff --git a/Jellyfin.Api/Controllers/GenresController.cs b/Jellyfin.Api/Controllers/GenresController.cs
index 28ebe20475..711fb4aef1 100644
--- a/Jellyfin.Api/Controllers/GenresController.cs
+++ b/Jellyfin.Api/Controllers/GenresController.cs
@@ -1,7 +1,6 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
@@ -23,7 +22,7 @@ namespace Jellyfin.Api.Controllers;
///
/// The genres controller.
///
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class GenresController : BaseJellyfinApiController
{
private readonly IUserManager _userManager;
@@ -132,7 +131,7 @@ public class GenresController : BaseJellyfinApiController
QueryResult<(BaseItem, ItemCounts)> result;
if (parentItem is ICollectionFolder parentCollectionFolder
&& (string.Equals(parentCollectionFolder.CollectionType, CollectionType.Music, StringComparison.Ordinal)
- || string.Equals(parentCollectionFolder.CollectionType, CollectionType.MusicVideos, StringComparison.Ordinal)))
+ || string.Equals(parentCollectionFolder.CollectionType, CollectionType.MusicVideos, StringComparison.Ordinal)))
{
result = _libraryManager.GetMusicGenres(query);
}
diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs
index 085115e1c8..d7cec865e1 100644
--- a/Jellyfin.Api/Controllers/HlsSegmentController.cs
+++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs
@@ -4,7 +4,6 @@ using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Threading.Tasks;
using Jellyfin.Api.Attributes;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Helpers;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Configuration;
@@ -80,7 +79,7 @@ public class HlsSegmentController : BaseJellyfinApiController
/// Hls video playlist returned.
/// A containing the playlist.
[HttpGet("Videos/{itemId}/hls/{playlistId}/stream.m3u8")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesPlaylistFile]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "itemId", Justification = "Required for ServiceStack")]
@@ -106,7 +105,7 @@ public class HlsSegmentController : BaseJellyfinApiController
/// Encoding stopped successfully.
/// A indicating success.
[HttpDelete("Videos/ActiveEncodings")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult StopEncodingProcess(
[FromQuery, Required] string deviceId,
diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs
index cc824c65ab..b2adb6a2d6 100644
--- a/Jellyfin.Api/Controllers/ImageController.cs
+++ b/Jellyfin.Api/Controllers/ImageController.cs
@@ -88,7 +88,7 @@ public class ImageController : BaseJellyfinApiController
/// User does not have permission to delete the image.
/// A .
[HttpPost("Users/{userId}/Images/{imageType}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[AcceptsImageFile]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
@@ -137,7 +137,7 @@ public class ImageController : BaseJellyfinApiController
/// User does not have permission to delete the image.
/// A .
[HttpPost("Users/{userId}/Images/{imageType}/{index}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[AcceptsImageFile]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
@@ -186,7 +186,7 @@ public class ImageController : BaseJellyfinApiController
/// User does not have permission to delete the image.
/// A .
[HttpDelete("Users/{userId}/Images/{imageType}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "imageType", Justification = "Imported from ServiceStack")]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
@@ -230,7 +230,7 @@ public class ImageController : BaseJellyfinApiController
/// User does not have permission to delete the image.
/// A .
[HttpDelete("Users/{userId}/Images/{imageType}/{index}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "imageType", Justification = "Imported from ServiceStack")]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
@@ -432,7 +432,7 @@ public class ImageController : BaseJellyfinApiController
/// Item not found.
/// The list of image infos on success, or if item not found.
[HttpGet("Items/{itemId}/Images")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task>> GetItemImageInfos([FromRoute, Required] Guid itemId)
@@ -1930,10 +1930,10 @@ public class ImageController : BaseJellyfinApiController
}
var responseHeaders = new Dictionary
- {
- { "transferMode.dlna.org", "Interactive" },
- { "realTimeInfo.dlna.org", "DLNA.ORG_TLAG=*" }
- };
+ {
+ { "transferMode.dlna.org", "Interactive" },
+ { "realTimeInfo.dlna.org", "DLNA.ORG_TLAG=*" }
+ };
if (!imageInfo.IsLocalFile && item is not null)
{
diff --git a/Jellyfin.Api/Controllers/InstantMixController.cs b/Jellyfin.Api/Controllers/InstantMixController.cs
index 89592bade4..43f09b49a2 100644
--- a/Jellyfin.Api/Controllers/InstantMixController.cs
+++ b/Jellyfin.Api/Controllers/InstantMixController.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Entities;
@@ -22,7 +21,7 @@ namespace Jellyfin.Api.Controllers;
/// The instant mix controller.
///
[Route("")]
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class InstantMixController : BaseJellyfinApiController
{
private readonly IUserManager _userManager;
diff --git a/Jellyfin.Api/Controllers/ItemLookupController.cs b/Jellyfin.Api/Controllers/ItemLookupController.cs
index c2ce4e67e5..b030e74dda 100644
--- a/Jellyfin.Api/Controllers/ItemLookupController.cs
+++ b/Jellyfin.Api/Controllers/ItemLookupController.cs
@@ -23,7 +23,7 @@ namespace Jellyfin.Api.Controllers;
/// Item lookup controller.
///
[Route("")]
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class ItemLookupController : BaseJellyfinApiController
{
private readonly IProviderManager _providerManager;
diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs
index 134974dbe0..97922d5dbc 100644
--- a/Jellyfin.Api/Controllers/ItemsController.cs
+++ b/Jellyfin.Api/Controllers/ItemsController.cs
@@ -1,7 +1,6 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
@@ -25,7 +24,7 @@ namespace Jellyfin.Api.Controllers;
/// The items controller.
///
[Route("")]
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class ItemsController : BaseJellyfinApiController
{
private readonly IUserManager _userManager;
diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs
index 830f84849e..e1ad87412e 100644
--- a/Jellyfin.Api/Controllers/LibraryController.cs
+++ b/Jellyfin.Api/Controllers/LibraryController.cs
@@ -95,7 +95,7 @@ public class LibraryController : BaseJellyfinApiController
/// Item not found.
/// A with the original file.
[HttpGet("Items/{itemId}/File")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesFile("video/*", "audio/*")]
@@ -116,7 +116,7 @@ public class LibraryController : BaseJellyfinApiController
/// Critic reviews returned.
/// The list of critic reviews.
[HttpGet("Items/{itemId}/CriticReviews")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[Obsolete("This endpoint is obsolete.")]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult> GetCriticReviews()
@@ -134,7 +134,7 @@ public class LibraryController : BaseJellyfinApiController
/// Item not found.
/// The item theme songs.
[HttpGet("Items/{itemId}/ThemeSongs")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult GetThemeSongs(
@@ -200,7 +200,7 @@ public class LibraryController : BaseJellyfinApiController
/// Item not found.
/// The item theme videos.
[HttpGet("Items/{itemId}/ThemeVideos")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult GetThemeVideos(
@@ -266,7 +266,7 @@ public class LibraryController : BaseJellyfinApiController
/// Item not found.
/// The item theme videos.
[HttpGet("Items/{itemId}/ThemeMedia")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult GetThemeMedia(
[FromRoute, Required] Guid itemId,
@@ -321,7 +321,7 @@ public class LibraryController : BaseJellyfinApiController
/// Unauthorized access.
/// A .
[HttpDelete("Items/{itemId}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public ActionResult DeleteItem(Guid itemId)
@@ -350,7 +350,7 @@ public class LibraryController : BaseJellyfinApiController
/// Unauthorized access.
/// A .
[HttpDelete("Items")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public ActionResult DeleteItems([FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid[] ids)
@@ -392,7 +392,7 @@ public class LibraryController : BaseJellyfinApiController
/// Item counts returned.
/// Item counts.
[HttpGet("Items/Counts")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult GetItemCounts(
[FromQuery] Guid? userId,
@@ -426,7 +426,7 @@ public class LibraryController : BaseJellyfinApiController
/// Item not found.
/// Item parents.
[HttpGet("Items/{itemId}/Ancestors")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult> GetAncestors([FromRoute, Required] Guid itemId, [FromQuery] Guid? userId)
@@ -509,7 +509,7 @@ public class LibraryController : BaseJellyfinApiController
/// A .
[HttpPost("Library/Series/Added", Name = "PostAddedSeries")]
[HttpPost("Library/Series/Updated")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult PostUpdatedSeries([FromQuery] string? tvdbId)
{
@@ -539,7 +539,7 @@ public class LibraryController : BaseJellyfinApiController
/// A .
[HttpPost("Library/Movies/Added", Name = "PostAddedMovies")]
[HttpPost("Library/Movies/Updated")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult PostUpdatedMovies([FromQuery] string? tmdbId, [FromQuery] string? imdbId)
{
@@ -580,7 +580,7 @@ public class LibraryController : BaseJellyfinApiController
/// Report success.
/// A .
[HttpPost("Library/Media/Updated")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult PostUpdatedMedia([FromBody, Required] MediaUpdateInfoDto dto)
{
@@ -657,7 +657,7 @@ public class LibraryController : BaseJellyfinApiController
[HttpGet("Shows/{itemId}/Similar", Name = "GetSimilarShows")]
[HttpGet("Movies/{itemId}/Similar", Name = "GetSimilarMovies")]
[HttpGet("Trailers/{itemId}/Similar", Name = "GetSimilarTrailers")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult> GetSimilarItems(
[FromRoute, Required] Guid itemId,
@@ -802,32 +802,32 @@ public class LibraryController : BaseJellyfinApiController
Type = type,
MetadataFetchers = plugins
- .Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))
- .SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.MetadataFetcher))
- .Select(i => new LibraryOptionInfoDto
- {
- Name = i.Name,
- DefaultEnabled = IsMetadataFetcherEnabledByDefault(i.Name, type, isNewLibrary)
- })
- .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
- .ToArray(),
+ .Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))
+ .SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.MetadataFetcher))
+ .Select(i => new LibraryOptionInfoDto
+ {
+ Name = i.Name,
+ DefaultEnabled = IsMetadataFetcherEnabledByDefault(i.Name, type, isNewLibrary)
+ })
+ .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
+ .ToArray(),
ImageFetchers = plugins
- .Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))
- .SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.ImageFetcher))
- .Select(i => new LibraryOptionInfoDto
- {
- Name = i.Name,
- DefaultEnabled = IsImageFetcherEnabledByDefault(i.Name, type, isNewLibrary)
- })
- .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
- .ToArray(),
+ .Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))
+ .SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.ImageFetcher))
+ .Select(i => new LibraryOptionInfoDto
+ {
+ Name = i.Name,
+ DefaultEnabled = IsImageFetcherEnabledByDefault(i.Name, type, isNewLibrary)
+ })
+ .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
+ .ToArray(),
SupportedImageTypes = plugins
- .Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))
- .SelectMany(i => i.SupportedImageTypes ?? Array.Empty())
- .Distinct()
- .ToArray(),
+ .Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))
+ .SelectMany(i => i.SupportedImageTypes ?? Array.Empty())
+ .Distinct()
+ .ToArray(),
DefaultImageOptions = defaultImageOptions ?? Array.Empty()
});
@@ -920,13 +920,13 @@ public class LibraryController : BaseJellyfinApiController
if (string.Equals(name, "TheMovieDb", StringComparison.OrdinalIgnoreCase))
{
return !(string.Equals(type, "Season", StringComparison.OrdinalIgnoreCase)
- || string.Equals(type, "Episode", StringComparison.OrdinalIgnoreCase)
- || string.Equals(type, "MusicVideo", StringComparison.OrdinalIgnoreCase));
+ || string.Equals(type, "Episode", StringComparison.OrdinalIgnoreCase)
+ || string.Equals(type, "MusicVideo", StringComparison.OrdinalIgnoreCase));
}
return string.Equals(name, "TheTVDB", StringComparison.OrdinalIgnoreCase)
- || string.Equals(name, "TheAudioDB", StringComparison.OrdinalIgnoreCase)
- || string.Equals(name, "MusicBrainz", StringComparison.OrdinalIgnoreCase);
+ || string.Equals(name, "TheAudioDB", StringComparison.OrdinalIgnoreCase)
+ || string.Equals(name, "MusicBrainz", StringComparison.OrdinalIgnoreCase);
}
var metadataOptions = _serverConfigurationManager.Configuration.MetadataOptions
@@ -934,7 +934,7 @@ public class LibraryController : BaseJellyfinApiController
.ToArray();
return metadataOptions.Length == 0
- || metadataOptions.Any(i => !i.DisabledMetadataFetchers.Contains(name, StringComparison.OrdinalIgnoreCase));
+ || metadataOptions.Any(i => !i.DisabledMetadataFetchers.Contains(name, StringComparison.OrdinalIgnoreCase));
}
private bool IsImageFetcherEnabledByDefault(string name, string type, bool isNewLibrary)
diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs
index 21b4243464..c1f5d74cd9 100644
--- a/Jellyfin.Api/Controllers/LiveTvController.cs
+++ b/Jellyfin.Api/Controllers/LiveTvController.cs
@@ -10,7 +10,6 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Api.Attributes;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
@@ -95,7 +94,7 @@ public class LiveTvController : BaseJellyfinApiController
///
[HttpGet("Info")]
[ProducesResponseType(StatusCodes.Status200OK)]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
public ActionResult GetLiveTvInfo()
{
return _liveTvManager.GetLiveTvInfo(CancellationToken.None);
@@ -131,7 +130,7 @@ public class LiveTvController : BaseJellyfinApiController
///
[HttpGet("Channels")]
[ProducesResponseType(StatusCodes.Status200OK)]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
public ActionResult> GetLiveTvChannels(
[FromQuery] ChannelType? type,
[FromQuery] Guid? userId,
@@ -210,7 +209,7 @@ public class LiveTvController : BaseJellyfinApiController
/// An containing the live tv channel.
[HttpGet("Channels/{channelId}")]
[ProducesResponseType(StatusCodes.Status200OK)]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
public ActionResult GetChannel([FromRoute, Required] Guid channelId, [FromQuery] Guid? userId)
{
var user = userId is null || userId.Value.Equals(default)
@@ -251,7 +250,7 @@ public class LiveTvController : BaseJellyfinApiController
/// An containing the live tv recordings.
[HttpGet("Recordings")]
[ProducesResponseType(StatusCodes.Status200OK)]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
public ActionResult> GetRecordings(
[FromQuery] string? channelId,
[FromQuery] Guid? userId,
@@ -322,7 +321,7 @@ public class LiveTvController : BaseJellyfinApiController
/// An containing the live tv recordings.
[HttpGet("Recordings/Series")]
[ProducesResponseType(StatusCodes.Status200OK)]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[Obsolete("This endpoint is obsolete.")]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "channelId", Justification = "Imported from ServiceStack")]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Imported from ServiceStack")]
@@ -365,7 +364,7 @@ public class LiveTvController : BaseJellyfinApiController
/// An containing the recording groups.
[HttpGet("Recordings/Groups")]
[ProducesResponseType(StatusCodes.Status200OK)]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[Obsolete("This endpoint is obsolete.")]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Imported from ServiceStack")]
public ActionResult> GetRecordingGroups([FromQuery] Guid? userId)
@@ -381,7 +380,7 @@ public class LiveTvController : BaseJellyfinApiController
/// An containing the recording folders.
[HttpGet("Recordings/Folders")]
[ProducesResponseType(StatusCodes.Status200OK)]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
public ActionResult> GetRecordingFolders([FromQuery] Guid? userId)
{
var user = userId is null || userId.Value.Equals(default)
@@ -403,7 +402,7 @@ public class LiveTvController : BaseJellyfinApiController
/// An containing the live tv recording.
[HttpGet("Recordings/{recordingId}")]
[ProducesResponseType(StatusCodes.Status200OK)]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
public ActionResult GetRecording([FromRoute, Required] Guid recordingId, [FromQuery] Guid? userId)
{
var user = userId is null || userId.Value.Equals(default)
@@ -425,7 +424,7 @@ public class LiveTvController : BaseJellyfinApiController
/// A .
[HttpPost("Tuners/{tunerId}/Reset")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
public async Task ResetTuner([FromRoute, Required] string tunerId)
{
await AssertUserCanManageLiveTv().ConfigureAwait(false);
@@ -443,7 +442,7 @@ public class LiveTvController : BaseJellyfinApiController
///
[HttpGet("Timers/{timerId}")]
[ProducesResponseType(StatusCodes.Status200OK)]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
public async Task> GetTimer([FromRoute, Required] string timerId)
{
return await _liveTvManager.GetTimer(timerId, CancellationToken.None).ConfigureAwait(false);
@@ -459,7 +458,7 @@ public class LiveTvController : BaseJellyfinApiController
///
[HttpGet("Timers/Defaults")]
[ProducesResponseType(StatusCodes.Status200OK)]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
public async Task> GetDefaultTimer([FromQuery] string? programId)
{
return string.IsNullOrEmpty(programId)
@@ -479,7 +478,7 @@ public class LiveTvController : BaseJellyfinApiController
///
[HttpGet("Timers")]
[ProducesResponseType(StatusCodes.Status200OK)]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
public async Task>> GetTimers(
[FromQuery] string? channelId,
[FromQuery] string? seriesTimerId,
@@ -533,7 +532,7 @@ public class LiveTvController : BaseJellyfinApiController
///
[HttpGet("Programs")]
[ProducesResponseType(StatusCodes.Status200OK)]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
public async Task>> GetLiveTvPrograms(
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid[] channelIds,
[FromQuery] Guid? userId,
@@ -616,7 +615,7 @@ public class LiveTvController : BaseJellyfinApiController
///
[HttpPost("Programs")]
[ProducesResponseType(StatusCodes.Status200OK)]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
public async Task>> GetPrograms([FromBody] GetProgramsDto body)
{
var user = body.UserId.Equals(default) ? null : _userManager.GetUserById(body.UserId);
@@ -682,7 +681,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Recommended epgs returned.
/// A containing the queryresult of recommended epgs.
[HttpGet("Programs/Recommended")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task>> GetRecommendedPrograms(
[FromQuery] Guid? userId,
@@ -734,7 +733,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Program returned.
/// An containing the livetv program.
[HttpGet("Programs/{programId}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task> GetProgram(
[FromRoute, Required] string programId,
@@ -755,7 +754,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Item not found.
/// A on success, or a if item not found.
[HttpDelete("Recordings/{recordingId}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task DeleteRecording([FromRoute, Required] Guid recordingId)
@@ -783,7 +782,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Timer deleted.
/// A .
[HttpDelete("Timers/{timerId}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task CancelTimer([FromRoute, Required] string timerId)
{
@@ -800,7 +799,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Timer updated.
/// A .
[HttpPost("Timers/{timerId}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "timerId", Justification = "Imported from ServiceStack")]
public async Task UpdateTimer([FromRoute, Required] string timerId, [FromBody] TimerInfoDto timerInfo)
@@ -817,7 +816,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Timer created.
/// A .
[HttpPost("Timers")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task CreateTimer([FromBody] TimerInfoDto timerInfo)
{
@@ -834,7 +833,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Series timer not found.
/// A on success, or a if timer not found.
[HttpGet("SeriesTimers/{timerId}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task> GetSeriesTimer([FromRoute, Required] string timerId)
@@ -856,7 +855,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Timers returned.
/// An of live tv series timers.
[HttpGet("SeriesTimers")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task>> GetSeriesTimers([FromQuery] string? sortBy, [FromQuery] SortOrder? sortOrder)
{
@@ -876,7 +875,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Timer cancelled.
/// A .
[HttpDelete("SeriesTimers/{timerId}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task CancelSeriesTimer([FromRoute, Required] string timerId)
{
@@ -893,7 +892,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Series timer updated.
/// A .
[HttpPost("SeriesTimers/{timerId}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "timerId", Justification = "Imported from ServiceStack")]
public async Task UpdateSeriesTimer([FromRoute, Required] string timerId, [FromBody] SeriesTimerInfoDto seriesTimerInfo)
@@ -910,7 +909,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Series timer info created.
/// A .
[HttpPost("SeriesTimers")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task CreateSeriesTimer([FromBody] SeriesTimerInfoDto seriesTimerInfo)
{
@@ -925,7 +924,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Group id.
/// A .
[HttpGet("Recordings/Groups/{groupId}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[Obsolete("This endpoint is obsolete.")]
public ActionResult GetRecordingGroup([FromRoute, Required] Guid groupId)
@@ -939,7 +938,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Guid info returned.
/// An containing the guide info.
[HttpGet("GuideInfo")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult GetGuideInfo()
{
@@ -953,7 +952,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Created tuner host returned.
/// A containing the created tuner host.
[HttpPost("TunerHosts")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task> AddTunerHost([FromBody] TunerHostInfo tunerHostInfo)
{
@@ -967,7 +966,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Tuner host deleted.
/// A .
[HttpDelete("TunerHosts")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult DeleteTunerHost([FromQuery] string? id)
{
@@ -983,7 +982,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Default listings provider info returned.
/// An containing the default listings provider info.
[HttpGet("ListingProviders/Default")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult GetDefaultListingProvider()
{
@@ -1000,7 +999,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Created listings provider returned.
/// A containing the created listings provider.
[HttpPost("ListingProviders")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[SuppressMessage("Microsoft.Performance", "CA5350:RemoveSha1", MessageId = "AddListingProvider", Justification = "Imported from ServiceStack")]
public async Task> AddListingProvider(
@@ -1026,7 +1025,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Listing provider deleted.
/// A .
[HttpDelete("ListingProviders")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult DeleteListingProvider([FromQuery] string? id)
{
@@ -1044,7 +1043,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Available lineups returned.
/// A containing the available lineups.
[HttpGet("ListingProviders/Lineups")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task>> GetLineups(
[FromQuery] string? id,
@@ -1061,7 +1060,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Available countries returned.
/// A containing the available countries.
[HttpGet("ListingProviders/SchedulesDirect/Countries")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesFile(MediaTypeNames.Application.Json)]
public async Task GetSchedulesDirectCountries()
@@ -1082,7 +1081,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Channel mapping options returned.
/// An containing the channel mapping options.
[HttpGet("ChannelMappingOptions")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task> GetChannelMappingOptions([FromQuery] string? providerId)
{
@@ -1120,7 +1119,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Created channel mapping returned.
/// An containing the created channel mapping.
[HttpPost("ChannelMappings")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task> SetChannelMapping([FromBody, Required] SetChannelMappingDto setChannelMappingDto)
{
@@ -1133,7 +1132,7 @@ public class LiveTvController : BaseJellyfinApiController
/// Tuner host types returned.
/// An containing the tuner host types.
[HttpGet("TunerHosts/Types")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult> GetTunerHostTypes()
{
@@ -1148,7 +1147,7 @@ public class LiveTvController : BaseJellyfinApiController
/// An containing the tuners.
[HttpGet("Tuners/Discvover", Name = "DiscvoverTuners")]
[HttpGet("Tuners/Discover")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task>> DiscoverTuners([FromQuery] bool newDevicesOnly = false)
{
diff --git a/Jellyfin.Api/Controllers/MediaInfoController.cs b/Jellyfin.Api/Controllers/MediaInfoController.cs
index eee7df3af8..ea10dd771f 100644
--- a/Jellyfin.Api/Controllers/MediaInfoController.cs
+++ b/Jellyfin.Api/Controllers/MediaInfoController.cs
@@ -5,7 +5,6 @@ using System.Linq;
using System.Net.Mime;
using System.Threading.Tasks;
using Jellyfin.Api.Attributes;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.Models.MediaInfoDtos;
@@ -25,7 +24,7 @@ namespace Jellyfin.Api.Controllers;
/// The media info controller.
///
[Route("")]
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class MediaInfoController : BaseJellyfinApiController
{
private readonly IMediaSourceManager _mediaSourceManager;
diff --git a/Jellyfin.Api/Controllers/MoviesController.cs b/Jellyfin.Api/Controllers/MoviesController.cs
index 4c30dd2b37..a9336f6d24 100644
--- a/Jellyfin.Api/Controllers/MoviesController.cs
+++ b/Jellyfin.Api/Controllers/MoviesController.cs
@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Entities;
@@ -23,7 +22,7 @@ namespace Jellyfin.Api.Controllers;
///
/// Movies controller.
///
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class MoviesController : BaseJellyfinApiController
{
private readonly IUserManager _userManager;
diff --git a/Jellyfin.Api/Controllers/MusicGenresController.cs b/Jellyfin.Api/Controllers/MusicGenresController.cs
index 302f138ebc..da1a6e832c 100644
--- a/Jellyfin.Api/Controllers/MusicGenresController.cs
+++ b/Jellyfin.Api/Controllers/MusicGenresController.cs
@@ -1,7 +1,6 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
@@ -23,7 +22,7 @@ namespace Jellyfin.Api.Controllers;
///
/// The music genres controller.
///
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class MusicGenresController : BaseJellyfinApiController
{
private readonly ILibraryManager _libraryManager;
diff --git a/Jellyfin.Api/Controllers/PackageController.cs b/Jellyfin.Api/Controllers/PackageController.cs
index 3cb3caadb3..0ba5e995fb 100644
--- a/Jellyfin.Api/Controllers/PackageController.cs
+++ b/Jellyfin.Api/Controllers/PackageController.cs
@@ -17,7 +17,7 @@ namespace Jellyfin.Api.Controllers;
/// Package Controller.
///
[Route("")]
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class PackageController : BaseJellyfinApiController
{
private readonly IInstallationManager _installationManager;
diff --git a/Jellyfin.Api/Controllers/PersonsController.cs b/Jellyfin.Api/Controllers/PersonsController.cs
index 9fb6da5276..5310f50b13 100644
--- a/Jellyfin.Api/Controllers/PersonsController.cs
+++ b/Jellyfin.Api/Controllers/PersonsController.cs
@@ -1,7 +1,6 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Entities;
@@ -20,7 +19,7 @@ namespace Jellyfin.Api.Controllers;
///
/// Persons controller.
///
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class PersonsController : BaseJellyfinApiController
{
private readonly ILibraryManager _libraryManager;
diff --git a/Jellyfin.Api/Controllers/PlaylistsController.cs b/Jellyfin.Api/Controllers/PlaylistsController.cs
index 11e5893017..79c0d3c7b2 100644
--- a/Jellyfin.Api/Controllers/PlaylistsController.cs
+++ b/Jellyfin.Api/Controllers/PlaylistsController.cs
@@ -4,7 +4,6 @@ using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Jellyfin.Api.Attributes;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Api.Models.PlaylistDtos;
@@ -25,7 +24,7 @@ namespace Jellyfin.Api.Controllers;
///
/// Playlists controller.
///
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class PlaylistsController : BaseJellyfinApiController
{
private readonly IPlaylistManager _playlistManager;
diff --git a/Jellyfin.Api/Controllers/PlaystateController.cs b/Jellyfin.Api/Controllers/PlaystateController.cs
index 18d6ebf1e0..11f3ddbb0a 100644
--- a/Jellyfin.Api/Controllers/PlaystateController.cs
+++ b/Jellyfin.Api/Controllers/PlaystateController.cs
@@ -2,7 +2,6 @@ using System;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
@@ -23,7 +22,7 @@ namespace Jellyfin.Api.Controllers;
/// Playstate controller.
///
[Route("")]
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class PlaystateController : BaseJellyfinApiController
{
private readonly IUserManager _userManager;
diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs
index 5a037d7a6b..4726cf0663 100644
--- a/Jellyfin.Api/Controllers/PluginsController.cs
+++ b/Jellyfin.Api/Controllers/PluginsController.cs
@@ -21,7 +21,7 @@ namespace Jellyfin.Api.Controllers;
///
/// Plugins controller.
///
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class PluginsController : BaseJellyfinApiController
{
private readonly IInstallationManager _installationManager;
diff --git a/Jellyfin.Api/Controllers/QuickConnectController.cs b/Jellyfin.Api/Controllers/QuickConnectController.cs
index a58e85b2b2..503b9d3729 100644
--- a/Jellyfin.Api/Controllers/QuickConnectController.cs
+++ b/Jellyfin.Api/Controllers/QuickConnectController.cs
@@ -111,7 +111,7 @@ public class QuickConnectController : BaseJellyfinApiController
/// Unknown user id.
/// Boolean indicating if the authorization was successful.
[HttpPost("Authorize")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task> AuthorizeQuickConnect([FromQuery, Required] string code, [FromQuery] Guid? userId = null)
diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs
index 445c5594f8..5c77db2407 100644
--- a/Jellyfin.Api/Controllers/RemoteImageController.cs
+++ b/Jellyfin.Api/Controllers/RemoteImageController.cs
@@ -56,7 +56,7 @@ public class RemoteImageController : BaseJellyfinApiController
/// Item not found.
/// Remote Image Result.
[HttpGet("Items/{itemId}/RemoteImages")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task> GetRemoteImages(
@@ -121,7 +121,7 @@ public class RemoteImageController : BaseJellyfinApiController
/// Item not found.
/// List of remote image providers.
[HttpGet("Items/{itemId}/RemoteImages/Providers")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult> GetRemoteImageProviders([FromRoute, Required] Guid itemId)
diff --git a/Jellyfin.Api/Controllers/SearchController.cs b/Jellyfin.Api/Controllers/SearchController.cs
index 46b4920cad..a25b43345a 100644
--- a/Jellyfin.Api/Controllers/SearchController.cs
+++ b/Jellyfin.Api/Controllers/SearchController.cs
@@ -3,7 +3,6 @@ using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Linq;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
@@ -26,7 +25,7 @@ namespace Jellyfin.Api.Controllers;
/// Search controller.
///
[Route("Search/Hints")]
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class SearchController : BaseJellyfinApiController
{
private readonly ISearchEngine _searchEngine;
diff --git a/Jellyfin.Api/Controllers/SessionController.cs b/Jellyfin.Api/Controllers/SessionController.cs
index ef33644785..bae8e0a490 100644
--- a/Jellyfin.Api/Controllers/SessionController.cs
+++ b/Jellyfin.Api/Controllers/SessionController.cs
@@ -56,7 +56,7 @@ public class SessionController : BaseJellyfinApiController
/// List of sessions returned.
/// An with the available sessions.
[HttpGet("Sessions")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult> GetSessions(
[FromQuery] Guid? controllableByUserId,
@@ -119,7 +119,7 @@ public class SessionController : BaseJellyfinApiController
/// Instruction sent to session.
/// A .
[HttpPost("Sessions/{sessionId}/Viewing")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task DisplayContent(
[FromRoute, Required] string sessionId,
@@ -158,7 +158,7 @@ public class SessionController : BaseJellyfinApiController
/// Instruction sent to session.
/// A .
[HttpPost("Sessions/{sessionId}/Playing")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task Play(
[FromRoute, Required] string sessionId,
@@ -201,7 +201,7 @@ public class SessionController : BaseJellyfinApiController
/// Playstate command sent to session.
/// A .
[HttpPost("Sessions/{sessionId}/Playing/{command}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task SendPlaystateCommand(
[FromRoute, Required] string sessionId,
@@ -232,7 +232,7 @@ public class SessionController : BaseJellyfinApiController
/// System command sent to session.
/// A .
[HttpPost("Sessions/{sessionId}/System/{command}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task SendSystemCommand(
[FromRoute, Required] string sessionId,
@@ -258,7 +258,7 @@ public class SessionController : BaseJellyfinApiController
/// General command sent to session.
/// A .
[HttpPost("Sessions/{sessionId}/Command/{command}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task SendGeneralCommand(
[FromRoute, Required] string sessionId,
@@ -286,7 +286,7 @@ public class SessionController : BaseJellyfinApiController
/// Full general command sent to session.
/// A .
[HttpPost("Sessions/{sessionId}/Command")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task SendFullGeneralCommand(
[FromRoute, Required] string sessionId,
@@ -316,7 +316,7 @@ public class SessionController : BaseJellyfinApiController
/// Message sent.
/// A .
[HttpPost("Sessions/{sessionId}/Message")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task SendMessageCommand(
[FromRoute, Required] string sessionId,
@@ -345,7 +345,7 @@ public class SessionController : BaseJellyfinApiController
/// User added to session.
/// A .
[HttpPost("Sessions/{sessionId}/User/{userId}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult AddUserToSession(
[FromRoute, Required] string sessionId,
@@ -363,7 +363,7 @@ public class SessionController : BaseJellyfinApiController
/// User removed from session.
/// A .
[HttpDelete("Sessions/{sessionId}/User/{userId}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult RemoveUserFromSession(
[FromRoute, Required] string sessionId,
@@ -385,7 +385,7 @@ public class SessionController : BaseJellyfinApiController
/// Capabilities posted.
/// A .
[HttpPost("Sessions/Capabilities")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task PostCapabilities(
[FromQuery] string? id,
@@ -419,7 +419,7 @@ public class SessionController : BaseJellyfinApiController
/// Capabilities updated.
/// A .
[HttpPost("Sessions/Capabilities/Full")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task PostFullCapabilities(
[FromQuery] string? id,
@@ -443,7 +443,7 @@ public class SessionController : BaseJellyfinApiController
/// Session reported to server.
/// A .
[HttpPost("Sessions/Viewing")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task ReportViewing(
[FromQuery] string? sessionId,
@@ -461,7 +461,7 @@ public class SessionController : BaseJellyfinApiController
/// Session end reported to server.
/// A .
[HttpPost("Sessions/Logout")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task ReportSessionEnded()
{
diff --git a/Jellyfin.Api/Controllers/StudiosController.cs b/Jellyfin.Api/Controllers/StudiosController.cs
index 799be2ae86..21965e956d 100644
--- a/Jellyfin.Api/Controllers/StudiosController.cs
+++ b/Jellyfin.Api/Controllers/StudiosController.cs
@@ -1,6 +1,5 @@
using System;
using System.ComponentModel.DataAnnotations;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
@@ -21,7 +20,7 @@ namespace Jellyfin.Api.Controllers;
///
/// Studios controller.
///
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class StudiosController : BaseJellyfinApiController
{
private readonly ILibraryManager _libraryManager;
diff --git a/Jellyfin.Api/Controllers/SubtitleController.cs b/Jellyfin.Api/Controllers/SubtitleController.cs
index fd0a71f9e3..e384213380 100644
--- a/Jellyfin.Api/Controllers/SubtitleController.cs
+++ b/Jellyfin.Api/Controllers/SubtitleController.cs
@@ -114,7 +114,7 @@ public class SubtitleController : BaseJellyfinApiController
/// Subtitles retrieved.
/// An array of .
[HttpGet("Items/{itemId}/RemoteSearch/Subtitles/{language}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task>> SearchRemoteSubtitles(
[FromRoute, Required] Guid itemId,
@@ -134,7 +134,7 @@ public class SubtitleController : BaseJellyfinApiController
/// Subtitle downloaded.
/// A .
[HttpPost("Items/{itemId}/RemoteSearch/Subtitles/{subtitleId}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task DownloadRemoteSubtitles(
[FromRoute, Required] Guid itemId,
@@ -164,7 +164,7 @@ public class SubtitleController : BaseJellyfinApiController
/// File returned.
/// A with the subtitle file.
[HttpGet("Providers/Subtitles/Subtitles/{id}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[Produces(MediaTypeNames.Application.Octet)]
[ProducesFile("text/*")]
@@ -322,7 +322,7 @@ public class SubtitleController : BaseJellyfinApiController
/// Subtitle playlist retrieved.
/// A with the HLS subtitle playlist.
[HttpGet("Videos/{itemId}/{mediaSourceId}/Subtitles/{index}/subtitles.m3u8")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesPlaylistFile]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")]
@@ -463,7 +463,7 @@ public class SubtitleController : BaseJellyfinApiController
/// Information retrieved.
/// An array of with the available font files.
[HttpGet("FallbackFont/Fonts")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
public IEnumerable GetFallbackFontList()
{
@@ -514,7 +514,7 @@ public class SubtitleController : BaseJellyfinApiController
/// Fallback font file retrieved.
/// The fallback font file.
[HttpGet("FallbackFont/Fonts/{name}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesFile("font/*")]
public ActionResult GetFallbackFont([FromRoute, Required] string name)
diff --git a/Jellyfin.Api/Controllers/SuggestionsController.cs b/Jellyfin.Api/Controllers/SuggestionsController.cs
index c5c429757a..5b808f257c 100644
--- a/Jellyfin.Api/Controllers/SuggestionsController.cs
+++ b/Jellyfin.Api/Controllers/SuggestionsController.cs
@@ -1,6 +1,5 @@
using System;
using System.ComponentModel.DataAnnotations;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Enums;
@@ -19,7 +18,7 @@ namespace Jellyfin.Api.Controllers;
/// The suggestions controller.
///
[Route("")]
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class SuggestionsController : BaseJellyfinApiController
{
private readonly IDtoService _dtoService;
diff --git a/Jellyfin.Api/Controllers/SystemController.cs b/Jellyfin.Api/Controllers/SystemController.cs
index b0b2e2d6d8..4ab705f40a 100644
--- a/Jellyfin.Api/Controllers/SystemController.cs
+++ b/Jellyfin.Api/Controllers/SystemController.cs
@@ -172,7 +172,7 @@ public class SystemController : BaseJellyfinApiController
/// Information retrieved.
/// with information about the endpoint.
[HttpGet("Endpoint")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult GetEndpointInfo()
{
@@ -210,7 +210,7 @@ public class SystemController : BaseJellyfinApiController
/// Information retrieved.
/// An with the WakeOnLan infos.
[HttpGet("WakeOnLanInfo")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[Obsolete("This endpoint is obsolete.")]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult> GetWakeOnLanInfo()
diff --git a/Jellyfin.Api/Controllers/TrailersController.cs b/Jellyfin.Api/Controllers/TrailersController.cs
index 115efcd8f3..b5b6406206 100644
--- a/Jellyfin.Api/Controllers/TrailersController.cs
+++ b/Jellyfin.Api/Controllers/TrailersController.cs
@@ -1,5 +1,4 @@
using System;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Enums;
using MediaBrowser.Model.Dto;
@@ -14,7 +13,7 @@ namespace Jellyfin.Api.Controllers;
///
/// The trailers controller.
///
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class TrailersController : BaseJellyfinApiController
{
private readonly ItemsController _itemsController;
diff --git a/Jellyfin.Api/Controllers/TvShowsController.cs b/Jellyfin.Api/Controllers/TvShowsController.cs
index 2be32095e3..b0760f97c7 100644
--- a/Jellyfin.Api/Controllers/TvShowsController.cs
+++ b/Jellyfin.Api/Controllers/TvShowsController.cs
@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Enums;
@@ -25,7 +24,7 @@ namespace Jellyfin.Api.Controllers;
/// The tv shows controller.
///
[Route("Shows")]
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class TvShowsController : BaseJellyfinApiController
{
private readonly IUserManager _userManager;
diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs
index 6946caa2ba..3455215979 100644
--- a/Jellyfin.Api/Controllers/UniversalAudioController.cs
+++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs
@@ -5,7 +5,6 @@ using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Jellyfin.Api.Attributes;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
@@ -82,7 +81,7 @@ public class UniversalAudioController : BaseJellyfinApiController
/// A containing the audio file.
[HttpGet("Audio/{itemId}/universal")]
[HttpHead("Audio/{itemId}/universal", Name = "HeadUniversalAudioStream")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status302Found)]
[ProducesAudioFile]
diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs
index 7f184f31e7..d9ea96f2d7 100644
--- a/Jellyfin.Api/Controllers/UserController.cs
+++ b/Jellyfin.Api/Controllers/UserController.cs
@@ -81,7 +81,7 @@ public class UserController : BaseJellyfinApiController
/// Users returned.
/// An containing the users.
[HttpGet]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult> GetUsers(
[FromQuery] bool? isHidden,
@@ -251,7 +251,7 @@ public class UserController : BaseJellyfinApiController
/// User not found.
/// A indicating success or a or a on failure.
[HttpPost("{userId}/Password")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
@@ -312,7 +312,7 @@ public class UserController : BaseJellyfinApiController
/// User not found.
/// A indicating success or a or a on failure.
[HttpPost("{userId}/EasyPassword")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
@@ -354,7 +354,7 @@ public class UserController : BaseJellyfinApiController
/// User update forbidden.
/// A indicating success or a or a on failure.
[HttpPost("{userId}")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
@@ -440,7 +440,7 @@ public class UserController : BaseJellyfinApiController
/// User configuration update forbidden.
/// A indicating success.
[HttpPost("{userId}/Configuration")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task UpdateUserConfiguration(
@@ -526,7 +526,7 @@ public class UserController : BaseJellyfinApiController
/// Token is not owned by a user.
/// A for the authenticated user.
[HttpGet("Me")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult GetCurrentUser()
diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs
index 556cf38945..93312b817f 100644
--- a/Jellyfin.Api/Controllers/UserLibraryController.cs
+++ b/Jellyfin.Api/Controllers/UserLibraryController.cs
@@ -4,7 +4,6 @@ using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Enums;
@@ -28,7 +27,7 @@ namespace Jellyfin.Api.Controllers;
/// User library controller.
///
[Route("")]
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class UserLibraryController : BaseJellyfinApiController
{
private readonly IUserManager _userManager;
diff --git a/Jellyfin.Api/Controllers/UserViewsController.cs b/Jellyfin.Api/Controllers/UserViewsController.cs
index aa7ba8891b..838b432340 100644
--- a/Jellyfin.Api/Controllers/UserViewsController.cs
+++ b/Jellyfin.Api/Controllers/UserViewsController.cs
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Linq;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Api.Models.UserViewDtos;
@@ -23,7 +22,7 @@ namespace Jellyfin.Api.Controllers;
/// User views controller.
///
[Route("")]
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class UserViewsController : BaseJellyfinApiController
{
private readonly IUserManager _userManager;
diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs
index 01a319879a..9299991966 100644
--- a/Jellyfin.Api/Controllers/VideosController.cs
+++ b/Jellyfin.Api/Controllers/VideosController.cs
@@ -100,7 +100,7 @@ public class VideosController : BaseJellyfinApiController
/// Additional parts returned.
/// A with the parts.
[HttpGet("{itemId}/AdditionalParts")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult> GetAdditionalPart([FromRoute, Required] Guid itemId, [FromQuery] Guid? userId)
{
diff --git a/Jellyfin.Api/Controllers/YearsController.cs b/Jellyfin.Api/Controllers/YearsController.cs
index 2e5fdc1464..def37cb971 100644
--- a/Jellyfin.Api/Controllers/YearsController.cs
+++ b/Jellyfin.Api/Controllers/YearsController.cs
@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
@@ -24,7 +23,7 @@ namespace Jellyfin.Api.Controllers;
///
/// Years controller.
///
-[Authorize(Policy = Policies.DefaultAuthorization)]
+[Authorize]
public class YearsController : BaseJellyfinApiController
{
private readonly ILibraryManager _libraryManager;
diff --git a/Jellyfin.Api/Middleware/LanFilteringMiddleware.cs b/Jellyfin.Api/Middleware/LanFilteringMiddleware.cs
index 7b05351e32..9c2194fafd 100644
--- a/Jellyfin.Api/Middleware/LanFilteringMiddleware.cs
+++ b/Jellyfin.Api/Middleware/LanFilteringMiddleware.cs
@@ -1,6 +1,6 @@
-using System.Net;
using System.Threading.Tasks;
using Jellyfin.Networking.Configuration;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using Microsoft.AspNetCore.Http;
@@ -32,9 +32,14 @@ public class LanFilteringMiddleware
/// The async task.
public async Task Invoke(HttpContext httpContext, INetworkManager networkManager, IServerConfigurationManager serverConfigurationManager)
{
- var host = httpContext.Connection.RemoteIpAddress ?? IPAddress.Loopback;
+ if (serverConfigurationManager.GetNetworkConfiguration().EnableRemoteAccess)
+ {
+ await _next(httpContext).ConfigureAwait(false);
+ return;
+ }
- if (!networkManager.IsInLocalNetwork(host) && !serverConfigurationManager.GetNetworkConfiguration().EnableRemoteAccess)
+ var host = httpContext.GetNormalizedRemoteIp();
+ if (!networkManager.IsInLocalNetwork(host))
{
return;
}
diff --git a/Jellyfin.Data/DayOfWeekHelper.cs b/Jellyfin.Data/DayOfWeekHelper.cs
index b7ba30180e..d1ce8185f2 100644
--- a/Jellyfin.Data/DayOfWeekHelper.cs
+++ b/Jellyfin.Data/DayOfWeekHelper.cs
@@ -17,5 +17,16 @@ namespace Jellyfin.Data
_ => new[] { (DayOfWeek)day }
};
}
+
+ public static bool Contains(this DynamicDayOfWeek dynamicDayOfWeek, DayOfWeek dayOfWeek)
+ {
+ return dynamicDayOfWeek switch
+ {
+ DynamicDayOfWeek.Everyday => true,
+ DynamicDayOfWeek.Weekday => dayOfWeek is > DayOfWeek.Sunday and <= DayOfWeek.Friday,
+ DynamicDayOfWeek.Weekend => dayOfWeek is DayOfWeek.Saturday or DayOfWeek.Sunday,
+ _ => (DayOfWeek)dynamicDayOfWeek == dayOfWeek
+ };
+ }
}
}
diff --git a/Jellyfin.Data/Entities/User.cs b/Jellyfin.Data/Entities/User.cs
index eb59e70f3b..4ce581749f 100644
--- a/Jellyfin.Data/Entities/User.cs
+++ b/Jellyfin.Data/Entities/User.cs
@@ -525,8 +525,9 @@ namespace Jellyfin.Data.Entities
{
var localTime = date.ToLocalTime();
var hour = localTime.TimeOfDay.TotalHours;
+ var currentDayOfWeek = localTime.DayOfWeek;
- return DayOfWeekHelper.GetDaysOfWeek(schedule.DayOfWeek).Contains(localTime.DayOfWeek)
+ return schedule.DayOfWeek.Contains(currentDayOfWeek)
&& hour >= schedule.StartHour
&& hour <= schedule.EndHour;
}
diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs
index e9af1cf83c..e2dcaf5f5c 100644
--- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs
+++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs
@@ -5,19 +5,15 @@ using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
+using System.Security.Claims;
using Emby.Server.Implementations;
using Jellyfin.Api.Auth;
using Jellyfin.Api.Auth.AnonymousLanAccessPolicy;
using Jellyfin.Api.Auth.DefaultAuthorizationPolicy;
using Jellyfin.Api.Auth.DownloadPolicy;
-using Jellyfin.Api.Auth.FirstTimeOrIgnoreParentalControlSetupPolicy;
-using Jellyfin.Api.Auth.FirstTimeSetupOrDefaultPolicy;
-using Jellyfin.Api.Auth.FirstTimeSetupOrElevatedPolicy;
-using Jellyfin.Api.Auth.IgnoreParentalControlPolicy;
-using Jellyfin.Api.Auth.LocalAccessOrRequiresElevationPolicy;
-using Jellyfin.Api.Auth.LocalAccessPolicy;
-using Jellyfin.Api.Auth.RequiresElevationPolicy;
+using Jellyfin.Api.Auth.FirstTimeSetupPolicy;
using Jellyfin.Api.Auth.SyncPlayAccessPolicy;
+using Jellyfin.Api.Auth.UserPermissionPolicy;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Controllers;
using Jellyfin.Api.Formatters;
@@ -56,117 +52,34 @@ namespace Jellyfin.Server.Extensions
/// The updated service collection.
public static IServiceCollection AddJellyfinApiAuthorization(this IServiceCollection serviceCollection)
{
+ // The default handler must be first so that it is evaluated first
serviceCollection.AddSingleton();
- serviceCollection.AddSingleton();
- serviceCollection.AddSingleton();
- serviceCollection.AddSingleton();
- serviceCollection.AddSingleton();
- serviceCollection.AddSingleton();
- serviceCollection.AddSingleton();
+ serviceCollection.AddSingleton();
+ serviceCollection.AddSingleton();
serviceCollection.AddSingleton();
- serviceCollection.AddSingleton();
- serviceCollection.AddSingleton();
serviceCollection.AddSingleton();
+
return serviceCollection.AddAuthorizationCore(options =>
{
- options.AddPolicy(
- Policies.DefaultAuthorization,
- policy =>
- {
- policy.AddAuthenticationSchemes(AuthenticationSchemes.CustomAuthentication);
- policy.AddRequirements(new DefaultAuthorizationRequirement());
- });
- options.AddPolicy(
- Policies.Download,
- policy =>
- {
- policy.AddAuthenticationSchemes(AuthenticationSchemes.CustomAuthentication);
- policy.AddRequirements(new DownloadRequirement());
- });
- options.AddPolicy(
- Policies.FirstTimeSetupOrDefault,
- policy =>
- {
- policy.AddAuthenticationSchemes(AuthenticationSchemes.CustomAuthentication);
- policy.AddRequirements(new FirstTimeSetupOrDefaultRequirement());
- });
- options.AddPolicy(
- Policies.FirstTimeSetupOrElevated,
- policy =>
- {
- policy.AddAuthenticationSchemes(AuthenticationSchemes.CustomAuthentication);
- policy.AddRequirements(new FirstTimeSetupOrElevatedRequirement());
- });
- options.AddPolicy(
- Policies.IgnoreParentalControl,
- policy =>
- {
- policy.AddAuthenticationSchemes(AuthenticationSchemes.CustomAuthentication);
- policy.AddRequirements(new IgnoreParentalControlRequirement());
- });
- options.AddPolicy(
- Policies.FirstTimeSetupOrIgnoreParentalControl,
- policy =>
- {
- policy.AddAuthenticationSchemes(AuthenticationSchemes.CustomAuthentication);
- policy.AddRequirements(new FirstTimeOrIgnoreParentalControlSetupRequirement());
- });
- options.AddPolicy(
- Policies.LocalAccessOnly,
- policy =>
- {
- policy.AddAuthenticationSchemes(AuthenticationSchemes.CustomAuthentication);
- policy.AddRequirements(new LocalAccessRequirement());
- });
- options.AddPolicy(
- Policies.LocalAccessOrRequiresElevation,
- policy =>
- {
- policy.AddAuthenticationSchemes(AuthenticationSchemes.CustomAuthentication);
- policy.AddRequirements(new LocalAccessOrRequiresElevationRequirement());
- });
+ options.DefaultPolicy = new AuthorizationPolicyBuilder()
+ .AddAuthenticationSchemes(AuthenticationSchemes.CustomAuthentication)
+ .RequireAuthenticatedUser()
+ .Build();
+
+ options.AddPolicy(Policies.Download, new UserPermissionRequirement(PermissionKind.EnableContentDownloading));
+ options.AddPolicy(Policies.FirstTimeSetupOrDefault, new FirstTimeSetupRequirement());
+ options.AddPolicy(Policies.FirstTimeSetupOrElevated, new FirstTimeSetupRequirement(requireAdmin: true));
+ options.AddPolicy(Policies.FirstTimeSetupOrIgnoreParentalControl, new FirstTimeSetupRequirement(validateParentalSchedule: false));
+ options.AddPolicy(Policies.IgnoreParentalControl, new DefaultAuthorizationRequirement(validateParentalSchedule: false));
+ options.AddPolicy(Policies.SyncPlayHasAccess, new SyncPlayAccessRequirement(SyncPlayAccessRequirementType.HasAccess));
+ options.AddPolicy(Policies.SyncPlayCreateGroup, new SyncPlayAccessRequirement(SyncPlayAccessRequirementType.CreateGroup));
+ options.AddPolicy(Policies.SyncPlayJoinGroup, new SyncPlayAccessRequirement(SyncPlayAccessRequirementType.JoinGroup));
+ options.AddPolicy(Policies.SyncPlayIsInGroup, new SyncPlayAccessRequirement(SyncPlayAccessRequirementType.IsInGroup));
+ options.AddPolicy(Policies.AnonymousLanAccessPolicy, new AnonymousLanAccessRequirement());
options.AddPolicy(
Policies.RequiresElevation,
- policy =>
- {
- policy.AddAuthenticationSchemes(AuthenticationSchemes.CustomAuthentication);
- policy.AddRequirements(new RequiresElevationRequirement());
- });
- options.AddPolicy(
- Policies.SyncPlayHasAccess,
- policy =>
- {
- policy.AddAuthenticationSchemes(AuthenticationSchemes.CustomAuthentication);
- policy.AddRequirements(new SyncPlayAccessRequirement(SyncPlayAccessRequirementType.HasAccess));
- });
- options.AddPolicy(
- Policies.SyncPlayCreateGroup,
- policy =>
- {
- policy.AddAuthenticationSchemes(AuthenticationSchemes.CustomAuthentication);
- policy.AddRequirements(new SyncPlayAccessRequirement(SyncPlayAccessRequirementType.CreateGroup));
- });
- options.AddPolicy(
- Policies.SyncPlayJoinGroup,
- policy =>
- {
- policy.AddAuthenticationSchemes(AuthenticationSchemes.CustomAuthentication);
- policy.AddRequirements(new SyncPlayAccessRequirement(SyncPlayAccessRequirementType.JoinGroup));
- });
- options.AddPolicy(
- Policies.SyncPlayIsInGroup,
- policy =>
- {
- policy.AddAuthenticationSchemes(AuthenticationSchemes.CustomAuthentication);
- policy.AddRequirements(new SyncPlayAccessRequirement(SyncPlayAccessRequirementType.IsInGroup));
- });
- options.AddPolicy(
- Policies.AnonymousLanAccessPolicy,
- policy =>
- {
- policy.AddAuthenticationSchemes(AuthenticationSchemes.CustomAuthentication);
- policy.AddRequirements(new AnonymousLanAccessRequirement());
- });
+ policy => policy.AddAuthenticationSchemes(AuthenticationSchemes.CustomAuthentication)
+ .RequireClaim(ClaimTypes.Role, UserRoles.Administrator));
});
}
@@ -334,6 +247,14 @@ namespace Jellyfin.Server.Extensions
});
}
+ private static void AddPolicy(this AuthorizationOptions authorizationOptions, string policyName, IAuthorizationRequirement authorizationRequirement)
+ {
+ authorizationOptions.AddPolicy(policyName, policy =>
+ {
+ policy.AddAuthenticationSchemes(AuthenticationSchemes.CustomAuthentication).AddRequirements(authorizationRequirement);
+ });
+ }
+
///
/// Sets up the proxy configuration based on the addresses in .
///
diff --git a/tests/Jellyfin.Api.Tests/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandlerTests.cs b/tests/Jellyfin.Api.Tests/Auth/FirstTimeSetupPolicy/FirstTimeSetupHandlerTests.cs
similarity index 80%
rename from tests/Jellyfin.Api.Tests/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandlerTests.cs
rename to tests/Jellyfin.Api.Tests/Auth/FirstTimeSetupPolicy/FirstTimeSetupHandlerTests.cs
index ee42216e46..6669a6689c 100644
--- a/tests/Jellyfin.Api.Tests/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandlerTests.cs
+++ b/tests/Jellyfin.Api.Tests/Auth/FirstTimeSetupPolicy/FirstTimeSetupHandlerTests.cs
@@ -2,7 +2,8 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using AutoFixture;
using AutoFixture.AutoMoq;
-using Jellyfin.Api.Auth.FirstTimeSetupOrElevatedPolicy;
+using Jellyfin.Api.Auth.DefaultAuthorizationPolicy;
+using Jellyfin.Api.Auth.FirstTimeSetupPolicy;
using Jellyfin.Api.Constants;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Library;
@@ -11,25 +12,25 @@ using Microsoft.AspNetCore.Http;
using Moq;
using Xunit;
-namespace Jellyfin.Api.Tests.Auth.FirstTimeSetupOrElevatedPolicy
+namespace Jellyfin.Api.Tests.Auth.FirstTimeSetupPolicy
{
- public class FirstTimeSetupOrElevatedHandlerTests
+ public class FirstTimeSetupHandlerTests
{
private readonly Mock _configurationManagerMock;
private readonly List _requirements;
- private readonly FirstTimeSetupOrElevatedHandler _sut;
+ private readonly FirstTimeSetupHandler _firstTimeSetupHandler;
private readonly Mock _userManagerMock;
private readonly Mock _httpContextAccessor;
- public FirstTimeSetupOrElevatedHandlerTests()
+ public FirstTimeSetupHandlerTests()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
_configurationManagerMock = fixture.Freeze>();
- _requirements = new List { new FirstTimeSetupOrElevatedRequirement() };
+ _requirements = new List { new FirstTimeSetupRequirement() };
_userManagerMock = fixture.Freeze>();
_httpContextAccessor = fixture.Freeze>();
- _sut = fixture.Create();
+ _firstTimeSetupHandler = fixture.Create();
}
[Theory]
@@ -46,7 +47,7 @@ namespace Jellyfin.Api.Tests.Auth.FirstTimeSetupOrElevatedPolicy
var context = new AuthorizationHandlerContext(_requirements, claims, null);
- await _sut.HandleAsync(context);
+ await _firstTimeSetupHandler.HandleAsync(context);
Assert.True(context.HasSucceeded);
}
@@ -64,7 +65,7 @@ namespace Jellyfin.Api.Tests.Auth.FirstTimeSetupOrElevatedPolicy
var context = new AuthorizationHandlerContext(_requirements, claims, null);
- await _sut.HandleAsync(context);
+ await _firstTimeSetupHandler.HandleAsync(context);
Assert.Equal(shouldSucceed, context.HasSucceeded);
}
}
diff --git a/tests/Jellyfin.Api.Tests/Auth/IgnoreSchedulePolicy/IgnoreScheduleHandlerTests.cs b/tests/Jellyfin.Api.Tests/Auth/IgnoreSchedulePolicy/IgnoreScheduleHandlerTests.cs
index 7150c90bb8..9cf8f85483 100644
--- a/tests/Jellyfin.Api.Tests/Auth/IgnoreSchedulePolicy/IgnoreScheduleHandlerTests.cs
+++ b/tests/Jellyfin.Api.Tests/Auth/IgnoreSchedulePolicy/IgnoreScheduleHandlerTests.cs
@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using AutoFixture;
using AutoFixture.AutoMoq;
-using Jellyfin.Api.Auth.IgnoreParentalControlPolicy;
+using Jellyfin.Api.Auth.DefaultAuthorizationPolicy;
using Jellyfin.Api.Constants;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
@@ -20,7 +20,7 @@ namespace Jellyfin.Api.Tests.Auth.IgnoreSchedulePolicy
{
private readonly Mock _configurationManagerMock;
private readonly List _requirements;
- private readonly IgnoreParentalControlHandler _sut;
+ private readonly DefaultAuthorizationHandler _sut;
private readonly Mock _userManagerMock;
private readonly Mock _httpContextAccessor;
@@ -33,11 +33,11 @@ namespace Jellyfin.Api.Tests.Auth.IgnoreSchedulePolicy
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
_configurationManagerMock = fixture.Freeze>();
- _requirements = new List { new IgnoreParentalControlRequirement() };
+ _requirements = new List { new DefaultAuthorizationRequirement(validateParentalSchedule: false) };
_userManagerMock = fixture.Freeze>();
_httpContextAccessor = fixture.Freeze>();
- _sut = fixture.Create();
+ _sut = fixture.Create();
}
[Theory]
diff --git a/tests/Jellyfin.Api.Tests/Auth/LocalAccessPolicy/LocalAccessHandlerTests.cs b/tests/Jellyfin.Api.Tests/Auth/LocalAccessPolicy/LocalAccessHandlerTests.cs
deleted file mode 100644
index 5b3d784ffa..0000000000
--- a/tests/Jellyfin.Api.Tests/Auth/LocalAccessPolicy/LocalAccessHandlerTests.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-using System.Collections.Generic;
-using System.Net;
-using System.Threading.Tasks;
-using AutoFixture;
-using AutoFixture.AutoMoq;
-using Jellyfin.Api.Auth.LocalAccessPolicy;
-using Jellyfin.Api.Constants;
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Library;
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Http;
-using Moq;
-using Xunit;
-
-namespace Jellyfin.Api.Tests.Auth.LocalAccessPolicy
-{
- public class LocalAccessHandlerTests
- {
- private readonly Mock _configurationManagerMock;
- private readonly List _requirements;
- private readonly LocalAccessHandler _sut;
- private readonly Mock _userManagerMock;
- private readonly Mock _httpContextAccessor;
- private readonly Mock _networkManagerMock;
-
- public LocalAccessHandlerTests()
- {
- var fixture = new Fixture().Customize(new AutoMoqCustomization());
- _configurationManagerMock = fixture.Freeze>();
- _requirements = new List { new LocalAccessRequirement() };
- _userManagerMock = fixture.Freeze>();
- _httpContextAccessor = fixture.Freeze>();
- _networkManagerMock = fixture.Freeze>();
-
- _sut = fixture.Create();
- }
-
- [Theory]
- [InlineData(true, true)]
- [InlineData(false, false)]
- public async Task LocalAccessOnly(bool isInLocalNetwork, bool shouldSucceed)
- {
- _networkManagerMock
- .Setup(n => n.IsInLocalNetwork(It.IsAny()))
- .Returns(isInLocalNetwork);
-
- TestHelpers.SetupConfigurationManager(_configurationManagerMock, true);
- var claims = TestHelpers.SetupUser(
- _userManagerMock,
- _httpContextAccessor,
- UserRoles.User);
-
- var context = new AuthorizationHandlerContext(_requirements, claims, null);
- await _sut.HandleAsync(context);
- Assert.Equal(shouldSucceed, context.HasSucceeded);
- }
- }
-}
diff --git a/tests/Jellyfin.Api.Tests/Auth/RequiresElevationPolicy/RequiresElevationHandlerTests.cs b/tests/Jellyfin.Api.Tests/Auth/RequiresElevationPolicy/RequiresElevationHandlerTests.cs
deleted file mode 100644
index ffe88fcdeb..0000000000
--- a/tests/Jellyfin.Api.Tests/Auth/RequiresElevationPolicy/RequiresElevationHandlerTests.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using AutoFixture;
-using AutoFixture.AutoMoq;
-using Jellyfin.Api.Auth.RequiresElevationPolicy;
-using Jellyfin.Api.Constants;
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Controller.Library;
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Http;
-using Moq;
-using Xunit;
-
-namespace Jellyfin.Api.Tests.Auth.RequiresElevationPolicy
-{
- public class RequiresElevationHandlerTests
- {
- private readonly Mock _configurationManagerMock;
- private readonly List _requirements;
- private readonly RequiresElevationHandler _sut;
- private readonly Mock _userManagerMock;
- private readonly Mock _httpContextAccessor;
-
- public RequiresElevationHandlerTests()
- {
- var fixture = new Fixture().Customize(new AutoMoqCustomization());
- _configurationManagerMock = fixture.Freeze>();
- _requirements = new List { new RequiresElevationRequirement() };
- _userManagerMock = fixture.Freeze>();
- _httpContextAccessor = fixture.Freeze>();
-
- _sut = fixture.Create();
- }
-
- [Theory]
- [InlineData(UserRoles.Administrator, true)]
- [InlineData(UserRoles.User, false)]
- [InlineData(UserRoles.Guest, false)]
- public async Task ShouldHandleRolesCorrectly(string role, bool shouldSucceed)
- {
- TestHelpers.SetupConfigurationManager(_configurationManagerMock, true);
- var claims = TestHelpers.SetupUser(
- _userManagerMock,
- _httpContextAccessor,
- role);
-
- var context = new AuthorizationHandlerContext(_requirements, claims, null);
-
- await _sut.HandleAsync(context);
- Assert.Equal(shouldSucceed, context.HasSucceeded);
- }
- }
-}