diff options
| author | cvium <clausvium@gmail.com> | 2020-12-03 10:43:44 +0100 |
|---|---|---|
| committer | cvium <clausvium@gmail.com> | 2020-12-03 10:43:44 +0100 |
| commit | 7e0ea296c383b9b9cd778bb12834c2a73df3d1ea (patch) | |
| tree | b0acc0b4b3743f134f1073fcb17e2a3eadac181f /Jellyfin.Api | |
| parent | b57ace7888db78a655a00a277e7eb5c4a4eba294 (diff) | |
Move request validation to auth policies
Diffstat (limited to 'Jellyfin.Api')
4 files changed, 103 insertions, 1 deletions
diff --git a/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs b/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs new file mode 100644 index 0000000000..2c3294523f --- /dev/null +++ b/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs @@ -0,0 +1,58 @@ +using System.Threading.Tasks; +using Jellyfin.Api.Helpers; +using Jellyfin.Data.Enums; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Library; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; + +namespace Jellyfin.Api.Auth.SyncPlayAccessPolicy +{ + /// <summary> + /// Default authorization handler. + /// </summary> + public class SyncPlayAccessHandler : BaseAuthorizationHandler<SyncPlayAccessRequirement> + { + private readonly IUserManager _userManager; + + /// <summary> + /// Initializes a new instance of the <see cref="SyncPlayAccessHandler"/> class. + /// </summary> + /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param> + /// <param name="networkManager">Instance of the <see cref="INetworkManager"/> interface.</param> + /// <param name="httpContextAccessor">Instance of the <see cref="IHttpContextAccessor"/> interface.</param> + public SyncPlayAccessHandler( + IUserManager userManager, + INetworkManager networkManager, + IHttpContextAccessor httpContextAccessor) + : base(userManager, networkManager, httpContextAccessor) + { + _userManager = userManager; + } + + /// <inheritdoc /> + protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, SyncPlayAccessRequirement requirement) + { + if (!ValidateClaims(context.User)) + { + context.Fail(); + return Task.CompletedTask; + } + + var userId = ClaimHelpers.GetUserId(context.User); + var user = _userManager.GetUserById(userId!.Value); + + if ((requirement.RequiredAccess.HasValue && user.SyncPlayAccess == requirement.RequiredAccess) + || (user.SyncPlayAccess == SyncPlayAccess.JoinGroups || user.SyncPlayAccess == SyncPlayAccess.CreateAndJoinGroups)) + { + context.Succeed(requirement); + } + else + { + context.Fail(); + } + + return Task.CompletedTask; + } + } +} diff --git a/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessRequirement.cs b/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessRequirement.cs new file mode 100644 index 0000000000..7fcaf69f6e --- /dev/null +++ b/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessRequirement.cs @@ -0,0 +1,33 @@ +using Jellyfin.Data.Enums; +using Microsoft.AspNetCore.Authorization; + +namespace Jellyfin.Api.Auth.SyncPlayAccessPolicy +{ + /// <summary> + /// The default authorization requirement. + /// </summary> + public class SyncPlayAccessRequirement : IAuthorizationRequirement + { + /// <summary> + /// Initializes a new instance of the <see cref="SyncPlayAccessRequirement"/> class. + /// </summary> + /// <param name="requiredAccess">A value of <see cref="SyncPlayAccess"/>.</param> + public SyncPlayAccessRequirement(SyncPlayAccess requiredAccess) + { + RequiredAccess = requiredAccess; + } + + /// <summary> + /// Initializes a new instance of the <see cref="SyncPlayAccessRequirement"/> class. + /// </summary> + public SyncPlayAccessRequirement() + { + RequiredAccess = null; + } + + /// <summary> + /// Gets the required SyncPlay access. + /// </summary> + public SyncPlayAccess? RequiredAccess { get; } + } +} diff --git a/Jellyfin.Api/Constants/Policies.cs b/Jellyfin.Api/Constants/Policies.cs index 7d77674700..b35ceea1a3 100644 --- a/Jellyfin.Api/Constants/Policies.cs +++ b/Jellyfin.Api/Constants/Policies.cs @@ -49,5 +49,15 @@ namespace Jellyfin.Api.Constants /// Policy name for escaping schedule controls or requiring first time setup. /// </summary> public const string FirstTimeSetupOrIgnoreParentalControl = "FirstTimeSetupOrIgnoreParentalControl"; + + /// <summary> + /// Policy name for requiring access to SyncPlay. + /// </summary> + public const string SyncPlayAccess = "SyncPlayAccess"; + + /// <summary> + /// Policy name for requiring group creation access to SyncPlay. + /// </summary> + public const string SyncPlayCreateGroupAccess = "SyncPlayCreateGroupAccess"; } } diff --git a/Jellyfin.Api/Controllers/SyncPlayController.cs b/Jellyfin.Api/Controllers/SyncPlayController.cs index ed5ea3c8a7..763940c733 100644 --- a/Jellyfin.Api/Controllers/SyncPlayController.cs +++ b/Jellyfin.Api/Controllers/SyncPlayController.cs @@ -20,7 +20,7 @@ namespace Jellyfin.Api.Controllers /// <summary> /// The sync play controller. /// </summary> - [Authorize(Policy = Policies.DefaultAuthorization)] + [Authorize(Policy = Policies.SyncPlayAccess)] public class SyncPlayController : BaseJellyfinApiController { private readonly ISessionManager _sessionManager; @@ -51,6 +51,7 @@ namespace Jellyfin.Api.Controllers /// <returns>A <see cref="NoContentResult"/> indicating success.</returns> [HttpPost("New")] [ProducesResponseType(StatusCodes.Status204NoContent)] + [Authorize(Policy = Policies.SyncPlayCreateGroupAccess)] public ActionResult SyncPlayCreateGroup( [FromBody, Required] NewGroupRequestBody requestData) { |
