Răsfoiți Sursa

don't require a user id for items api call using api key

Jason Dove 3 ani în urmă
părinte
comite
e4088ba0bd

+ 33 - 11
Jellyfin.Api/Controllers/ItemsController.cs

@@ -1,6 +1,7 @@
 using System;
 using System;
 using System.ComponentModel.DataAnnotations;
 using System.ComponentModel.DataAnnotations;
 using System.Linq;
 using System.Linq;
+using System.Threading.Tasks;
 using Jellyfin.Api.Constants;
 using Jellyfin.Api.Constants;
 using Jellyfin.Api.Extensions;
 using Jellyfin.Api.Extensions;
 using Jellyfin.Api.Helpers;
 using Jellyfin.Api.Helpers;
@@ -9,6 +10,7 @@ using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Dto;
 using MediaBrowser.Controller.Dto;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
 using MediaBrowser.Controller.Session;
 using MediaBrowser.Controller.Session;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
@@ -32,6 +34,7 @@ namespace Jellyfin.Api.Controllers
         private readonly ILibraryManager _libraryManager;
         private readonly ILibraryManager _libraryManager;
         private readonly ILocalizationManager _localization;
         private readonly ILocalizationManager _localization;
         private readonly IDtoService _dtoService;
         private readonly IDtoService _dtoService;
+        private readonly IAuthorizationContext _authContext;
         private readonly ILogger<ItemsController> _logger;
         private readonly ILogger<ItemsController> _logger;
         private readonly ISessionManager _sessionManager;
         private readonly ISessionManager _sessionManager;
 
 
@@ -42,6 +45,7 @@ namespace Jellyfin.Api.Controllers
         /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
         /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
         /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
         /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
         /// <param name="dtoService">Instance of the <see cref="IDtoService"/> interface.</param>
         /// <param name="dtoService">Instance of the <see cref="IDtoService"/> interface.</param>
+        /// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
         /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
         /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
         /// <param name="sessionManager">Instance of the <see cref="ISessionManager"/> interface.</param>
         /// <param name="sessionManager">Instance of the <see cref="ISessionManager"/> interface.</param>
         public ItemsController(
         public ItemsController(
@@ -49,6 +53,7 @@ namespace Jellyfin.Api.Controllers
             ILibraryManager libraryManager,
             ILibraryManager libraryManager,
             ILocalizationManager localization,
             ILocalizationManager localization,
             IDtoService dtoService,
             IDtoService dtoService,
+            IAuthorizationContext authContext,
             ILogger<ItemsController> logger,
             ILogger<ItemsController> logger,
             ISessionManager sessionManager)
             ISessionManager sessionManager)
         {
         {
@@ -56,6 +61,7 @@ namespace Jellyfin.Api.Controllers
             _libraryManager = libraryManager;
             _libraryManager = libraryManager;
             _localization = localization;
             _localization = localization;
             _dtoService = dtoService;
             _dtoService = dtoService;
+            _authContext = authContext;
             _logger = logger;
             _logger = logger;
             _sessionManager = sessionManager;
             _sessionManager = sessionManager;
         }
         }
@@ -151,8 +157,8 @@ namespace Jellyfin.Api.Controllers
         /// <returns>A <see cref="QueryResult{BaseItemDto}"/> with the items.</returns>
         /// <returns>A <see cref="QueryResult{BaseItemDto}"/> with the items.</returns>
         [HttpGet("Items")]
         [HttpGet("Items")]
         [ProducesResponseType(StatusCodes.Status200OK)]
         [ProducesResponseType(StatusCodes.Status200OK)]
-        public ActionResult<QueryResult<BaseItemDto>> GetItems(
-            [FromQuery] Guid userId,
+        public async Task<ActionResult<QueryResult<BaseItemDto>>> GetItems(
+            [FromQuery] Guid? userId,
             [FromQuery] string? maxOfficialRating,
             [FromQuery] string? maxOfficialRating,
             [FromQuery] bool? hasThemeSong,
             [FromQuery] bool? hasThemeSong,
             [FromQuery] bool? hasThemeVideo,
             [FromQuery] bool? hasThemeVideo,
@@ -238,7 +244,17 @@ namespace Jellyfin.Api.Controllers
             [FromQuery] bool enableTotalRecordCount = true,
             [FromQuery] bool enableTotalRecordCount = true,
             [FromQuery] bool? enableImages = true)
             [FromQuery] bool? enableImages = true)
         {
         {
-            var user = userId.Equals(default) ? null : _userManager.GetUserById(userId);
+            var auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false);
+
+            var user = !auth.IsApiKey && userId.HasValue && !userId.Equals(Guid.Empty)
+                ? _userManager.GetUserById(userId.Value)
+                : null;
+
+            if (!auth.IsApiKey && user is null)
+            {
+                return BadRequest("userId is required");
+            }
+
             var dtoOptions = new DtoOptions { Fields = fields }
             var dtoOptions = new DtoOptions { Fields = fields }
                 .AddClientFields(Request)
                 .AddClientFields(Request)
                 .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
                 .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
@@ -270,20 +286,26 @@ namespace Jellyfin.Api.Controllers
                 includeItemTypes = new[] { BaseItemKind.Playlist };
                 includeItemTypes = new[] { BaseItemKind.Playlist };
             }
             }
 
 
-            var enabledChannels = user!.GetPreferenceValues<Guid>(PreferenceKind.EnabledChannels);
+            var enabledChannels = auth.IsApiKey
+                ? Array.Empty<Guid>()
+                : user.GetPreferenceValues<Guid>(PreferenceKind.EnabledChannels);
 
 
-            bool isInEnabledFolder = Array.IndexOf(user.GetPreferenceValues<Guid>(PreferenceKind.EnabledFolders), item.Id) != -1
+            bool isInEnabledFolder = auth.IsApiKey
+                                     || Array.IndexOf(user.GetPreferenceValues<Guid>(PreferenceKind.EnabledFolders), item.Id) != -1
                                      // Assume all folders inside an EnabledChannel are enabled
                                      // Assume all folders inside an EnabledChannel are enabled
                                      || Array.IndexOf(enabledChannels, item.Id) != -1
                                      || Array.IndexOf(enabledChannels, item.Id) != -1
                                      // Assume all items inside an EnabledChannel are enabled
                                      // Assume all items inside an EnabledChannel are enabled
                                      || Array.IndexOf(enabledChannels, item.ChannelId) != -1;
                                      || Array.IndexOf(enabledChannels, item.ChannelId) != -1;
 
 
-            var collectionFolders = _libraryManager.GetCollectionFolders(item);
-            foreach (var collectionFolder in collectionFolders)
+            if (!isInEnabledFolder)
             {
             {
-                if (user.GetPreferenceValues<Guid>(PreferenceKind.EnabledFolders).Contains(collectionFolder.Id))
+                var collectionFolders = _libraryManager.GetCollectionFolders(item);
+                foreach (var collectionFolder in collectionFolders)
                 {
                 {
-                    isInEnabledFolder = true;
+                    if (user.GetPreferenceValues<Guid>(PreferenceKind.EnabledFolders).Contains(collectionFolder.Id))
+                    {
+                        isInEnabledFolder = true;
+                    }
                 }
                 }
             }
             }
 
 
@@ -293,7 +315,7 @@ namespace Jellyfin.Api.Controllers
                 && !user.HasPermission(PermissionKind.EnableAllChannels)
                 && !user.HasPermission(PermissionKind.EnableAllChannels)
                 && !string.Equals(collectionType, CollectionType.Folders, StringComparison.OrdinalIgnoreCase))
                 && !string.Equals(collectionType, CollectionType.Folders, StringComparison.OrdinalIgnoreCase))
             {
             {
-                _logger.LogWarning("{UserName} is not permitted to access Library {ItemName}.", user.Username, item.Name);
+                _logger.LogWarning("{UserName} is not permitted to access Library {ItemName}", user.Username, item.Name);
                 return Unauthorized($"{user.Username} is not permitted to access Library {item.Name}.");
                 return Unauthorized($"{user.Username} is not permitted to access Library {item.Name}.");
             }
             }
 
 
@@ -606,7 +628,7 @@ namespace Jellyfin.Api.Controllers
         /// <returns>A <see cref="QueryResult{BaseItemDto}"/> with the items.</returns>
         /// <returns>A <see cref="QueryResult{BaseItemDto}"/> with the items.</returns>
         [HttpGet("Users/{userId}/Items")]
         [HttpGet("Users/{userId}/Items")]
         [ProducesResponseType(StatusCodes.Status200OK)]
         [ProducesResponseType(StatusCodes.Status200OK)]
-        public ActionResult<QueryResult<BaseItemDto>> GetItemsByUserId(
+        public Task<ActionResult<QueryResult<BaseItemDto>>> GetItemsByUserId(
             [FromRoute] Guid userId,
             [FromRoute] Guid userId,
             [FromQuery] string? maxOfficialRating,
             [FromQuery] string? maxOfficialRating,
             [FromQuery] bool? hasThemeSong,
             [FromQuery] bool? hasThemeSong,

+ 4 - 3
Jellyfin.Api/Controllers/TrailersController.cs

@@ -1,4 +1,5 @@
 using System;
 using System;
+using System.Threading.Tasks;
 using Jellyfin.Api.Constants;
 using Jellyfin.Api.Constants;
 using Jellyfin.Api.ModelBinders;
 using Jellyfin.Api.ModelBinders;
 using Jellyfin.Data.Enums;
 using Jellyfin.Data.Enums;
@@ -31,7 +32,7 @@ namespace Jellyfin.Api.Controllers
         /// <summary>
         /// <summary>
         /// Finds movies and trailers similar to a given trailer.
         /// Finds movies and trailers similar to a given trailer.
         /// </summary>
         /// </summary>
-        /// <param name="userId">The user id.</param>
+        /// <param name="userId">Optional user id.</param>
         /// <param name="maxOfficialRating">Optional filter by maximum official rating (PG, PG-13, TV-MA, etc).</param>
         /// <param name="maxOfficialRating">Optional filter by maximum official rating (PG, PG-13, TV-MA, etc).</param>
         /// <param name="hasThemeSong">Optional filter by items with theme songs.</param>
         /// <param name="hasThemeSong">Optional filter by items with theme songs.</param>
         /// <param name="hasThemeVideo">Optional filter by items with theme videos.</param>
         /// <param name="hasThemeVideo">Optional filter by items with theme videos.</param>
@@ -118,8 +119,8 @@ namespace Jellyfin.Api.Controllers
         /// <returns>A <see cref="QueryResult{BaseItemDto}"/> with the trailers.</returns>
         /// <returns>A <see cref="QueryResult{BaseItemDto}"/> with the trailers.</returns>
         [HttpGet]
         [HttpGet]
         [ProducesResponseType(StatusCodes.Status200OK)]
         [ProducesResponseType(StatusCodes.Status200OK)]
-        public ActionResult<QueryResult<BaseItemDto>> GetTrailers(
-            [FromQuery] Guid userId,
+        public Task<ActionResult<QueryResult<BaseItemDto>>> GetTrailers(
+            [FromQuery] Guid? userId,
             [FromQuery] string? maxOfficialRating,
             [FromQuery] string? maxOfficialRating,
             [FromQuery] bool? hasThemeSong,
             [FromQuery] bool? hasThemeSong,
             [FromQuery] bool? hasThemeVideo,
             [FromQuery] bool? hasThemeVideo,