aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Api/Controllers
diff options
context:
space:
mode:
Diffstat (limited to 'Jellyfin.Api/Controllers')
-rw-r--r--Jellyfin.Api/Controllers/ItemUpdateController.cs49
-rw-r--r--Jellyfin.Api/Controllers/ItemsController.cs7
-rw-r--r--Jellyfin.Api/Controllers/UserLibraryController.cs159
3 files changed, 191 insertions, 24 deletions
diff --git a/Jellyfin.Api/Controllers/ItemUpdateController.cs b/Jellyfin.Api/Controllers/ItemUpdateController.cs
index 230fbfb2c..9c7148241 100644
--- a/Jellyfin.Api/Controllers/ItemUpdateController.cs
+++ b/Jellyfin.Api/Controllers/ItemUpdateController.cs
@@ -98,7 +98,7 @@ public class ItemUpdateController : BaseJellyfinApiController
}).ToList());
}
- UpdateItem(request, item);
+ await UpdateItem(request, item).ConfigureAwait(false);
item.OnMetadataChanged();
@@ -147,7 +147,7 @@ public class ItemUpdateController : BaseJellyfinApiController
var info = new MetadataEditorInfo
{
- ParentalRatingOptions = _localizationManager.GetParentalRatings().ToArray(),
+ ParentalRatingOptions = _localizationManager.GetParentalRatings().ToList(),
ExternalIdInfos = _providerManager.GetExternalIdInfos(item).ToArray(),
Countries = _localizationManager.GetCountries().ToArray(),
Cultures = _localizationManager.GetCultures().ToArray()
@@ -224,7 +224,7 @@ public class ItemUpdateController : BaseJellyfinApiController
return NoContent();
}
- private void UpdateItem(BaseItemDto request, BaseItem item)
+ private async Task UpdateItem(BaseItemDto request, BaseItem item)
{
item.Name = request.Name;
item.ForcedSortName = request.ForcedSortName;
@@ -266,9 +266,50 @@ public class ItemUpdateController : BaseJellyfinApiController
item.EndDate = request.EndDate.HasValue ? NormalizeDateTime(request.EndDate.Value) : null;
item.PremiereDate = request.PremiereDate.HasValue ? NormalizeDateTime(request.PremiereDate.Value) : null;
item.ProductionYear = request.ProductionYear;
- item.OfficialRating = string.IsNullOrWhiteSpace(request.OfficialRating) ? null : request.OfficialRating;
+
+ request.OfficialRating = string.IsNullOrWhiteSpace(request.OfficialRating) ? null : request.OfficialRating;
+ item.OfficialRating = request.OfficialRating;
item.CustomRating = request.CustomRating;
+ if (item is Series rseries)
+ {
+ foreach (Season season in rseries.Children)
+ {
+ season.OfficialRating = request.OfficialRating;
+ season.CustomRating = request.CustomRating;
+ season.OnMetadataChanged();
+ await season.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
+
+ foreach (Episode ep in season.Children)
+ {
+ ep.OfficialRating = request.OfficialRating;
+ ep.CustomRating = request.CustomRating;
+ ep.OnMetadataChanged();
+ await ep.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
+ }
+ }
+ }
+ else if (item is Season season)
+ {
+ foreach (Episode ep in season.Children)
+ {
+ ep.OfficialRating = request.OfficialRating;
+ ep.CustomRating = request.CustomRating;
+ ep.OnMetadataChanged();
+ await ep.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
+ }
+ }
+ else if (item is MusicAlbum album)
+ {
+ foreach (BaseItem track in album.Children)
+ {
+ track.OfficialRating = request.OfficialRating;
+ track.CustomRating = request.CustomRating;
+ track.OnMetadataChanged();
+ await track.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
+ }
+ }
+
if (request.ProductionLocations is not null)
{
item.ProductionLocations = request.ProductionLocations;
diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs
index 728e62810..377526729 100644
--- a/Jellyfin.Api/Controllers/ItemsController.cs
+++ b/Jellyfin.Api/Controllers/ItemsController.cs
@@ -411,6 +411,13 @@ public class ItemsController : BaseJellyfinApiController
query.SeriesStatuses = seriesStatus;
}
+ // Exclude Blocked Unrated Items
+ var blockedUnratedItems = user?.GetPreferenceValues<UnratedItem>(PreferenceKind.BlockUnratedItems);
+ if (blockedUnratedItems is not null)
+ {
+ query.BlockUnratedItems = blockedUnratedItems;
+ }
+
// ExcludeLocationTypes
if (excludeLocationTypes.Any(t => t == LocationType.Virtual))
{
diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs
index 1233995b4..2c4fe9186 100644
--- a/Jellyfin.Api/Controllers/UserLibraryController.cs
+++ b/Jellyfin.Api/Controllers/UserLibraryController.cs
@@ -6,6 +6,7 @@ using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.ModelBinders;
+using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
@@ -72,7 +73,7 @@ public class UserLibraryController : BaseJellyfinApiController
/// <param name="userId">User id.</param>
/// <param name="itemId">Item id.</param>
/// <response code="200">Item returned.</response>
- /// <returns>An <see cref="OkResult"/> containing the d item.</returns>
+ /// <returns>An <see cref="OkResult"/> containing the item.</returns>
[HttpGet("Users/{userId}/Items/{itemId}")]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<BaseItemDto>> GetItem([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId)
@@ -86,11 +87,19 @@ public class UserLibraryController : BaseJellyfinApiController
var item = itemId.Equals(default)
? _libraryManager.GetUserRootFolder()
: _libraryManager.GetItemById(itemId);
+
if (item is null)
{
return NotFound();
}
+ if (item is not UserRootFolder
+ // Check the item is visible for the user
+ && !item.IsVisible(user))
+ {
+ return Unauthorized($"{user.Username} is not permitted to access item {item.Name}.");
+ }
+
await RefreshItemOnDemandIfNeeded(item).ConfigureAwait(false);
var dtoOptions = new DtoOptions().AddClientFields(User);
@@ -139,11 +148,19 @@ public class UserLibraryController : BaseJellyfinApiController
var item = itemId.Equals(default)
? _libraryManager.GetUserRootFolder()
: _libraryManager.GetItemById(itemId);
+
if (item is null)
{
return NotFound();
}
+ if (item is not UserRootFolder
+ // Check the item is visible for the user
+ && !item.IsVisible(user))
+ {
+ return Unauthorized($"{user.Username} is not permitted to access item {item.Name}.");
+ }
+
var items = await _libraryManager.GetIntros(item, user).ConfigureAwait(false);
var dtoOptions = new DtoOptions().AddClientFields(User);
var dtos = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)).ToArray();
@@ -162,7 +179,29 @@ public class UserLibraryController : BaseJellyfinApiController
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<UserItemDataDto> MarkFavoriteItem([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId)
{
- return MarkFavorite(userId, itemId, true);
+ var user = _userManager.GetUserById(userId);
+ if (user is null)
+ {
+ return NotFound();
+ }
+
+ var item = itemId.Equals(default)
+ ? _libraryManager.GetUserRootFolder()
+ : _libraryManager.GetItemById(itemId);
+
+ if (item is null)
+ {
+ return NotFound();
+ }
+
+ if (item is not UserRootFolder
+ // Check the item is visible for the user
+ && !item.IsVisible(user))
+ {
+ return Unauthorized($"{user.Username} is not permitted to access item {item.Name}.");
+ }
+
+ return MarkFavorite(user, item, true);
}
/// <summary>
@@ -176,7 +215,29 @@ public class UserLibraryController : BaseJellyfinApiController
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<UserItemDataDto> UnmarkFavoriteItem([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId)
{
- return MarkFavorite(userId, itemId, false);
+ var user = _userManager.GetUserById(userId);
+ if (user is null)
+ {
+ return NotFound();
+ }
+
+ var item = itemId.Equals(default)
+ ? _libraryManager.GetUserRootFolder()
+ : _libraryManager.GetItemById(itemId);
+
+ if (item is null)
+ {
+ return NotFound();
+ }
+
+ if (item is not UserRootFolder
+ // Check the item is visible for the user
+ && !item.IsVisible(user))
+ {
+ return Unauthorized($"{user.Username} is not permitted to access item {item.Name}.");
+ }
+
+ return MarkFavorite(user, item, false);
}
/// <summary>
@@ -190,7 +251,29 @@ public class UserLibraryController : BaseJellyfinApiController
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<UserItemDataDto> DeleteUserItemRating([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId)
{
- return UpdateUserItemRatingInternal(userId, itemId, null);
+ var user = _userManager.GetUserById(userId);
+ if (user is null)
+ {
+ return NotFound();
+ }
+
+ var item = itemId.Equals(default)
+ ? _libraryManager.GetUserRootFolder()
+ : _libraryManager.GetItemById(itemId);
+
+ if (item is null)
+ {
+ return NotFound();
+ }
+
+ if (item is not UserRootFolder
+ // Check the item is visible for the user
+ && !item.IsVisible(user))
+ {
+ return Unauthorized($"{user.Username} is not permitted to access item {item.Name}.");
+ }
+
+ return UpdateUserItemRatingInternal(user, item, null);
}
/// <summary>
@@ -205,7 +288,29 @@ public class UserLibraryController : BaseJellyfinApiController
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<UserItemDataDto> UpdateUserItemRating([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId, [FromQuery] bool? likes)
{
- return UpdateUserItemRatingInternal(userId, itemId, likes);
+ var user = _userManager.GetUserById(userId);
+ if (user is null)
+ {
+ return NotFound();
+ }
+
+ var item = itemId.Equals(default)
+ ? _libraryManager.GetUserRootFolder()
+ : _libraryManager.GetItemById(itemId);
+
+ if (item is null)
+ {
+ return NotFound();
+ }
+
+ if (item is not UserRootFolder
+ // Check the item is visible for the user
+ && !item.IsVisible(user))
+ {
+ return Unauthorized($"{user.Username} is not permitted to access item {item.Name}.");
+ }
+
+ return UpdateUserItemRatingInternal(user, item, likes);
}
/// <summary>
@@ -228,13 +333,20 @@ public class UserLibraryController : BaseJellyfinApiController
var item = itemId.Equals(default)
? _libraryManager.GetUserRootFolder()
: _libraryManager.GetItemById(itemId);
+
if (item is null)
{
return NotFound();
}
- var dtoOptions = new DtoOptions().AddClientFields(User);
+ if (item is not UserRootFolder
+ // Check the item is visible for the user
+ && !item.IsVisible(user))
+ {
+ return Unauthorized($"{user.Username} is not permitted to access item {item.Name}.");
+ }
+ var dtoOptions = new DtoOptions().AddClientFields(User);
if (item is IHasTrailers hasTrailers)
{
var trailers = hasTrailers.LocalTrailers;
@@ -266,11 +378,19 @@ public class UserLibraryController : BaseJellyfinApiController
var item = itemId.Equals(default)
? _libraryManager.GetUserRootFolder()
: _libraryManager.GetItemById(itemId);
+
if (item is null)
{
return NotFound();
}
+ if (item is not UserRootFolder
+ // Check the item is visible for the user
+ && !item.IsVisible(user))
+ {
+ return Unauthorized($"{user.Username} is not permitted to access item {item.Name}.");
+ }
+
var dtoOptions = new DtoOptions().AddClientFields(User);
return Ok(item
@@ -385,15 +505,11 @@ public class UserLibraryController : BaseJellyfinApiController
/// <summary>
/// Marks the favorite.
/// </summary>
- /// <param name="userId">The user id.</param>
- /// <param name="itemId">The item id.</param>
+ /// <param name="user">The user.</param>
+ /// <param name="item">The item.</param>
/// <param name="isFavorite">if set to <c>true</c> [is favorite].</param>
- private UserItemDataDto MarkFavorite(Guid userId, Guid itemId, bool isFavorite)
+ private UserItemDataDto MarkFavorite(User user, BaseItem item, bool isFavorite)
{
- var user = _userManager.GetUserById(userId);
-
- var item = itemId.Equals(default) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(itemId);
-
// Get the user data for this item
var data = _userDataRepository.GetUserData(user, item);
@@ -408,15 +524,11 @@ public class UserLibraryController : BaseJellyfinApiController
/// <summary>
/// Updates the user item rating.
/// </summary>
- /// <param name="userId">The user id.</param>
- /// <param name="itemId">The item id.</param>
+ /// <param name="user">The user.</param>
+ /// <param name="item">The item.</param>
/// <param name="likes">if set to <c>true</c> [likes].</param>
- private UserItemDataDto UpdateUserItemRatingInternal(Guid userId, Guid itemId, bool? likes)
+ private UserItemDataDto UpdateUserItemRatingInternal(User user, BaseItem item, bool? likes)
{
- var user = _userManager.GetUserById(userId);
-
- var item = itemId.Equals(default) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(itemId);
-
// Get the user data for this item
var data = _userDataRepository.GetUserData(user, item);
@@ -455,6 +567,13 @@ public class UserLibraryController : BaseJellyfinApiController
return NotFound();
}
+ if (item is not UserRootFolder
+ // Check the item is visible for the user
+ && !item.IsVisible(user))
+ {
+ return Unauthorized($"{user.Username} is not permitted to access item {item.Name}.");
+ }
+
var result = await _lyricManager.GetLyrics(item).ConfigureAwait(false);
if (result is not null)
{