aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Api/Controllers
diff options
context:
space:
mode:
Diffstat (limited to 'Jellyfin.Api/Controllers')
-rw-r--r--Jellyfin.Api/Controllers/ItemsController.cs52
-rw-r--r--Jellyfin.Api/Controllers/LibraryController.cs2
-rw-r--r--Jellyfin.Api/Controllers/MoviesController.cs20
-rw-r--r--Jellyfin.Api/Controllers/PlaystateController.cs4
-rw-r--r--Jellyfin.Api/Controllers/SessionController.cs4
-rw-r--r--Jellyfin.Api/Controllers/TrailersController.cs8
-rw-r--r--Jellyfin.Api/Controllers/UniversalAudioController.cs2
-rw-r--r--Jellyfin.Api/Controllers/UserLibraryController.cs45
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();
+ }
}
}