diff options
Diffstat (limited to 'Jellyfin.Api/Controllers')
| -rw-r--r-- | Jellyfin.Api/Controllers/ItemsController.cs | 52 | ||||
| -rw-r--r-- | Jellyfin.Api/Controllers/LibraryController.cs | 2 | ||||
| -rw-r--r-- | Jellyfin.Api/Controllers/MoviesController.cs | 20 | ||||
| -rw-r--r-- | Jellyfin.Api/Controllers/PlaystateController.cs | 4 | ||||
| -rw-r--r-- | Jellyfin.Api/Controllers/SessionController.cs | 4 | ||||
| -rw-r--r-- | Jellyfin.Api/Controllers/TrailersController.cs | 8 | ||||
| -rw-r--r-- | Jellyfin.Api/Controllers/UniversalAudioController.cs | 2 | ||||
| -rw-r--r-- | Jellyfin.Api/Controllers/UserLibraryController.cs | 45 |
8 files changed, 77 insertions, 60 deletions
diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs index 80ae5abcb..3ee5b8d73 100644 --- a/Jellyfin.Api/Controllers/ItemsController.cs +++ b/Jellyfin.Api/Controllers/ItemsController.cs @@ -87,9 +87,9 @@ namespace Jellyfin.Api.Controllers /// <param name="minDateLastSavedForUser">Optional. The minimum last saved date for the current user. Format = ISO.</param> /// <param name="maxPremiereDate">Optional. The maximum premiere date. Format = ISO.</param> /// <param name="hasOverview">Optional filter by items that have an overview or not.</param> - /// <param name="hasImdbId">Optional filter by items that have an imdb id or not.</param> - /// <param name="hasTmdbId">Optional filter by items that have a tmdb id or not.</param> - /// <param name="hasTvdbId">Optional filter by items that have a tvdb id or not.</param> + /// <param name="hasImdbId">Optional filter by items that have an IMDb id or not.</param> + /// <param name="hasTmdbId">Optional filter by items that have a TMDb id or not.</param> + /// <param name="hasTvdbId">Optional filter by items that have a TVDb id or not.</param> /// <param name="isMovie">Optional filter for live tv movies.</param> /// <param name="isSeries">Optional filter for live tv series.</param> /// <param name="isNews">Optional filter for live tv news.</param> @@ -100,7 +100,7 @@ namespace Jellyfin.Api.Controllers /// <param name="limit">Optional. The maximum number of records to return.</param> /// <param name="recursive">When searching within folders, this determines whether or not the search will be recursive. true/false.</param> /// <param name="searchTerm">Optional. Filter based on a search term.</param> - /// <param name="sortOrder">Sort Order - Ascending,Descending.</param> + /// <param name="sortOrder">Sort Order - Ascending, Descending.</param> /// <param name="parentId">Specify this to localize the search to a specific item or folder. Omit to use the root.</param> /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines.</param> /// <param name="excludeItemTypes">Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited.</param> @@ -282,39 +282,13 @@ namespace Jellyfin.Api.Controllers includeItemTypes = new[] { BaseItemKind.Playlist }; } - var enabledChannels = isApiKey - ? Array.Empty<Guid>() - : user!.GetPreferenceValues<Guid>(PreferenceKind.EnabledChannels); - - // api keys are always enabled for all folders - bool isInEnabledFolder = isApiKey - || Array.IndexOf(user!.GetPreferenceValues<Guid>(PreferenceKind.EnabledFolders), item.Id) != -1 - // Assume all folders inside an EnabledChannel are enabled - || Array.IndexOf(enabledChannels, item.Id) != -1 - // Assume all items inside an EnabledChannel are enabled - || Array.IndexOf(enabledChannels, item.ChannelId) != -1; - - if (!isInEnabledFolder) - { - var collectionFolders = _libraryManager.GetCollectionFolders(item); - foreach (var collectionFolder in collectionFolders) - { - // api keys never enter this block, so user is never null - if (user!.GetPreferenceValues<Guid>(PreferenceKind.EnabledFolders).Contains(collectionFolder.Id)) - { - isInEnabledFolder = true; - } - } - } - - // api keys are always enabled for all folders, so user is never null if (item is not UserRootFolder - && !isInEnabledFolder - && !user!.HasPermission(PermissionKind.EnableAllFolders) - && !user.HasPermission(PermissionKind.EnableAllChannels) - && !string.Equals(collectionType, CollectionType.Folders, StringComparison.OrdinalIgnoreCase)) + // api keys can always access all folders + && !isApiKey + // check the item is visible for the user + && !item.IsVisible(user)) { - _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}."); } @@ -562,9 +536,9 @@ namespace Jellyfin.Api.Controllers /// <param name="minDateLastSavedForUser">Optional. The minimum last saved date for the current user. Format = ISO.</param> /// <param name="maxPremiereDate">Optional. The maximum premiere date. Format = ISO.</param> /// <param name="hasOverview">Optional filter by items that have an overview or not.</param> - /// <param name="hasImdbId">Optional filter by items that have an imdb id or not.</param> - /// <param name="hasTmdbId">Optional filter by items that have a tmdb id or not.</param> - /// <param name="hasTvdbId">Optional filter by items that have a tvdb id or not.</param> + /// <param name="hasImdbId">Optional filter by items that have an IMDb id or not.</param> + /// <param name="hasTmdbId">Optional filter by items that have a TMDb id or not.</param> + /// <param name="hasTvdbId">Optional filter by items that have a TVDb id or not.</param> /// <param name="isMovie">Optional filter for live tv movies.</param> /// <param name="isSeries">Optional filter for live tv series.</param> /// <param name="isNews">Optional filter for live tv news.</param> @@ -575,7 +549,7 @@ namespace Jellyfin.Api.Controllers /// <param name="limit">Optional. The maximum number of records to return.</param> /// <param name="recursive">When searching within folders, this determines whether or not the search will be recursive. true/false.</param> /// <param name="searchTerm">Optional. Filter based on a search term.</param> - /// <param name="sortOrder">Sort Order - Ascending,Descending.</param> + /// <param name="sortOrder">Sort Order - Ascending, Descending.</param> /// <param name="parentId">Specify this to localize the search to a specific item or folder. Omit to use the root.</param> /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines.</param> /// <param name="excludeItemTypes">Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited.</param> diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs index e9492a6a4..7a57bf1a2 100644 --- a/Jellyfin.Api/Controllers/LibraryController.cs +++ b/Jellyfin.Api/Controllers/LibraryController.cs @@ -485,7 +485,7 @@ namespace Jellyfin.Api.Controllers /// <response code="200">Media folders returned.</response> /// <returns>List of user media folders.</returns> [HttpGet("Library/MediaFolders")] - [Authorize(Policy = Policies.DefaultAuthorization)] + [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult<QueryResult<BaseItemDto>> GetMediaFolders([FromQuery] bool? isHidden) { diff --git a/Jellyfin.Api/Controllers/MoviesController.cs b/Jellyfin.Api/Controllers/MoviesController.cs index 8195fc760..03f864b4a 100644 --- a/Jellyfin.Api/Controllers/MoviesController.cs +++ b/Jellyfin.Api/Controllers/MoviesController.cs @@ -193,7 +193,7 @@ namespace Jellyfin.Api.Controllers new InternalItemsQuery(user) { Person = name, - // Account for duplicates by imdb id, since the database doesn't support this yet + // Account for duplicates by IMDb id, since the database doesn't support this yet Limit = itemLimit + 2, PersonTypes = new[] { PersonType.Director }, IncludeItemTypes = itemTypes.ToArray(), @@ -232,15 +232,15 @@ namespace Jellyfin.Api.Controllers foreach (var name in names) { var items = _libraryManager.GetItemList(new InternalItemsQuery(user) - { - Person = name, - // Account for duplicates by imdb id, since the database doesn't support this yet - Limit = itemLimit + 2, - IncludeItemTypes = itemTypes.ToArray(), - IsMovie = true, - EnableGroupByMetadataKey = true, - DtoOptions = dtoOptions - }).GroupBy(i => i.GetProviderId(MediaBrowser.Model.Entities.MetadataProvider.Imdb) ?? Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture)) + { + Person = name, + // Account for duplicates by IMDb id, since the database doesn't support this yet + Limit = itemLimit + 2, + IncludeItemTypes = itemTypes.ToArray(), + IsMovie = true, + EnableGroupByMetadataKey = true, + DtoOptions = dtoOptions + }).GroupBy(i => i.GetProviderId(MediaBrowser.Model.Entities.MetadataProvider.Imdb) ?? Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture)) .Select(x => x.First()) .Take(itemLimit) .ToList(); diff --git a/Jellyfin.Api/Controllers/PlaystateController.cs b/Jellyfin.Api/Controllers/PlaystateController.cs index 0dd4bf803..3a2ba033e 100644 --- a/Jellyfin.Api/Controllers/PlaystateController.cs +++ b/Jellyfin.Api/Controllers/PlaystateController.cs @@ -274,7 +274,7 @@ namespace Jellyfin.Api.Controllers }; playbackProgressInfo.PlayMethod = ValidatePlayMethod(playbackProgressInfo.PlayMethod, playbackProgressInfo.PlaySessionId); - playbackProgressInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);; + playbackProgressInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); await _sessionManager.OnPlaybackProgress(playbackProgressInfo).ConfigureAwait(false); return NoContent(); } @@ -319,7 +319,7 @@ namespace Jellyfin.Api.Controllers await _transcodingJobHelper.KillTranscodingJobs(User.GetDeviceId()!, playbackStopInfo.PlaySessionId, s => true).ConfigureAwait(false); } - playbackStopInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);; + playbackStopInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); await _sessionManager.OnPlaybackStopped(playbackStopInfo).ConfigureAwait(false); return NoContent(); } diff --git a/Jellyfin.Api/Controllers/SessionController.cs b/Jellyfin.Api/Controllers/SessionController.cs index 28415555e..31b95162d 100644 --- a/Jellyfin.Api/Controllers/SessionController.cs +++ b/Jellyfin.Api/Controllers/SessionController.cs @@ -182,7 +182,7 @@ namespace Jellyfin.Api.Controllers }; await _sessionManager.SendPlayCommand( - await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false), + await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false), sessionId, playRequest, CancellationToken.None) @@ -210,7 +210,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? controllingUserId) { await _sessionManager.SendPlaystateCommand( - await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false), + await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false), sessionId, new PlaystateRequest() { diff --git a/Jellyfin.Api/Controllers/TrailersController.cs b/Jellyfin.Api/Controllers/TrailersController.cs index b296d1c96..53a839e43 100644 --- a/Jellyfin.Api/Controllers/TrailersController.cs +++ b/Jellyfin.Api/Controllers/TrailersController.cs @@ -55,9 +55,9 @@ namespace Jellyfin.Api.Controllers /// <param name="minDateLastSavedForUser">Optional. The minimum last saved date for the current user. Format = ISO.</param> /// <param name="maxPremiereDate">Optional. The maximum premiere date. Format = ISO.</param> /// <param name="hasOverview">Optional filter by items that have an overview or not.</param> - /// <param name="hasImdbId">Optional filter by items that have an imdb id or not.</param> - /// <param name="hasTmdbId">Optional filter by items that have a tmdb id or not.</param> - /// <param name="hasTvdbId">Optional filter by items that have a tvdb id or not.</param> + /// <param name="hasImdbId">Optional filter by items that have an IMDb id or not.</param> + /// <param name="hasTmdbId">Optional filter by items that have a TMDb id or not.</param> + /// <param name="hasTvdbId">Optional filter by items that have a TVDb id or not.</param> /// <param name="isMovie">Optional filter for live tv movies.</param> /// <param name="isSeries">Optional filter for live tv series.</param> /// <param name="isNews">Optional filter for live tv news.</param> @@ -68,7 +68,7 @@ namespace Jellyfin.Api.Controllers /// <param name="limit">Optional. The maximum number of records to return.</param> /// <param name="recursive">When searching within folders, this determines whether or not the search will be recursive. true/false.</param> /// <param name="searchTerm">Optional. Filter based on a search term.</param> - /// <param name="sortOrder">Sort Order - Ascending,Descending.</param> + /// <param name="sortOrder">Sort Order - Ascending, Descending.</param> /// <param name="parentId">Specify this to localize the search to a specific item or folder. Omit to use the root.</param> /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines.</param> /// <param name="excludeItemTypes">Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited.</param> diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index 01e13b4fe..d77126a35 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -108,7 +108,7 @@ namespace Jellyfin.Api.Controllers { var deviceProfile = GetDeviceProfile(container, transcodingContainer, audioCodec, transcodingProtocol, breakOnNonKeyFrames, transcodingAudioChannels, maxAudioSampleRate, maxAudioBitDepth, maxAudioChannels); - if (!userId.HasValue || userId.Value.Equals(Guid.Empty)) + if (!userId.HasValue || userId.Value.Equals(default)) { userId = User.GetUserId(); } diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs index ee8a17b62..8a2d5a27d 100644 --- a/Jellyfin.Api/Controllers/UserLibraryController.cs +++ b/Jellyfin.Api/Controllers/UserLibraryController.cs @@ -7,11 +7,13 @@ using System.Threading.Tasks; using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; using Jellyfin.Api.ModelBinders; +using Jellyfin.Api.Models.UserDtos; using Jellyfin.Data.Enums; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Lyrics; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -36,6 +38,7 @@ namespace Jellyfin.Api.Controllers private readonly IDtoService _dtoService; private readonly IUserViewManager _userViewManager; private readonly IFileSystem _fileSystem; + private readonly ILyricManager _lyricManager; /// <summary> /// Initializes a new instance of the <see cref="UserLibraryController"/> class. @@ -46,13 +49,15 @@ namespace Jellyfin.Api.Controllers /// <param name="dtoService">Instance of the <see cref="IDtoService"/> interface.</param> /// <param name="userViewManager">Instance of the <see cref="IUserViewManager"/> interface.</param> /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param> + /// <param name="lyricManager">Instance of the <see cref="ILyricManager"/> interface.</param> public UserLibraryController( IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IDtoService dtoService, IUserViewManager userViewManager, - IFileSystem fileSystem) + IFileSystem fileSystem, + ILyricManager lyricManager) { _userManager = userManager; _userDataRepository = userDataRepository; @@ -60,6 +65,7 @@ namespace Jellyfin.Api.Controllers _dtoService = dtoService; _userViewManager = userViewManager; _fileSystem = fileSystem; + _lyricManager = lyricManager; } /// <summary> @@ -381,5 +387,42 @@ namespace Jellyfin.Api.Controllers return _userDataRepository.GetUserDataDto(item, user); } + + /// <summary> + /// Gets an item's lyrics. + /// </summary> + /// <param name="userId">User id.</param> + /// <param name="itemId">Item id.</param> + /// <response code="200">Lyrics returned.</response> + /// <response code="404">Something went wrong. No Lyrics will be returned.</response> + /// <returns>An <see cref="OkResult"/> containing the item's lyrics.</returns> + [HttpGet("Users/{userId}/Items/{itemId}/Lyrics")] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task<ActionResult<LyricResponse>> GetLyrics([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId) + { + var user = _userManager.GetUserById(userId); + + if (user == null) + { + return NotFound(); + } + + var item = itemId.Equals(default) + ? _libraryManager.GetUserRootFolder() + : _libraryManager.GetItemById(itemId); + + if (item == null) + { + return NotFound(); + } + + var result = await _lyricManager.GetLyrics(item).ConfigureAwait(false); + if (result is not null) + { + return Ok(result); + } + + return NotFound(); + } } } |
