Merge pull request #16398 from Bond-009/invalidfilters

Return BadRequest when an invalid set of filters is given
This commit is contained in:
Bond-009
2026-03-13 20:23:23 +01:00
committed by GitHub
6 changed files with 104 additions and 167 deletions

View File

@@ -2289,7 +2289,7 @@ namespace Emby.Server.Implementations.Library
if (item is null)
{
return new List<Folder>();
return [];
}
return GetCollectionFoldersInternal(item, allUserRootChildren);

View File

@@ -187,39 +187,7 @@ public class ArtistsController : BaseJellyfinApiController
}).Where(i => i is not null).Select(i => i!.Id).ToArray();
}
foreach (var filter in filters)
{
switch (filter)
{
case ItemFilter.Dislikes:
query.IsLiked = false;
break;
case ItemFilter.IsFavorite:
query.IsFavorite = true;
break;
case ItemFilter.IsFavoriteOrLikes:
query.IsFavoriteOrLiked = true;
break;
case ItemFilter.IsFolder:
query.IsFolder = true;
break;
case ItemFilter.IsNotFolder:
query.IsFolder = false;
break;
case ItemFilter.IsPlayed:
query.IsPlayed = true;
break;
case ItemFilter.IsResumable:
query.IsResumable = true;
break;
case ItemFilter.IsUnplayed:
query.IsPlayed = false;
break;
case ItemFilter.Likes:
query.IsLiked = true;
break;
}
}
query.ApplyFilters(filters);
var result = _libraryManager.GetArtists(query);
@@ -390,39 +358,7 @@ public class ArtistsController : BaseJellyfinApiController
}).Where(i => i is not null).Select(i => i!.Id).ToArray();
}
foreach (var filter in filters)
{
switch (filter)
{
case ItemFilter.Dislikes:
query.IsLiked = false;
break;
case ItemFilter.IsFavorite:
query.IsFavorite = true;
break;
case ItemFilter.IsFavoriteOrLikes:
query.IsFavoriteOrLiked = true;
break;
case ItemFilter.IsFolder:
query.IsFolder = true;
break;
case ItemFilter.IsNotFolder:
query.IsFolder = false;
break;
case ItemFilter.IsPlayed:
query.IsPlayed = true;
break;
case ItemFilter.IsResumable:
query.IsResumable = true;
break;
case ItemFilter.IsUnplayed:
query.IsPlayed = false;
break;
case ItemFilter.Likes:
query.IsLiked = true;
break;
}
}
query.ApplyFilters(filters);
var result = _libraryManager.GetAlbumArtists(query);

View File

@@ -136,45 +136,13 @@ public class ChannelsController : BaseJellyfinApiController
{
Limit = limit,
StartIndex = startIndex,
ChannelIds = new[] { channelId },
ChannelIds = [channelId],
ParentId = folderId ?? Guid.Empty,
OrderBy = RequestHelpers.GetOrderBy(sortBy, sortOrder),
DtoOptions = new DtoOptions { Fields = fields }
};
foreach (var filter in filters)
{
switch (filter)
{
case ItemFilter.IsFolder:
query.IsFolder = true;
break;
case ItemFilter.IsNotFolder:
query.IsFolder = false;
break;
case ItemFilter.IsUnplayed:
query.IsPlayed = false;
break;
case ItemFilter.IsPlayed:
query.IsPlayed = true;
break;
case ItemFilter.IsFavorite:
query.IsFavorite = true;
break;
case ItemFilter.IsResumable:
query.IsResumable = true;
break;
case ItemFilter.Likes:
query.IsLiked = true;
break;
case ItemFilter.Dislikes:
query.IsLiked = false;
break;
case ItemFilter.IsFavoriteOrLikes:
query.IsFavoriteOrLiked = true;
break;
}
}
query.ApplyFilters(filters);
return await _channelManager.GetChannelItems(query, CancellationToken.None).ConfigureAwait(false);
}
@@ -215,39 +183,7 @@ public class ChannelsController : BaseJellyfinApiController
DtoOptions = new DtoOptions { Fields = fields }
};
foreach (var filter in filters)
{
switch (filter)
{
case ItemFilter.IsFolder:
query.IsFolder = true;
break;
case ItemFilter.IsNotFolder:
query.IsFolder = false;
break;
case ItemFilter.IsUnplayed:
query.IsPlayed = false;
break;
case ItemFilter.IsPlayed:
query.IsPlayed = true;
break;
case ItemFilter.IsFavorite:
query.IsFavorite = true;
break;
case ItemFilter.IsResumable:
query.IsResumable = true;
break;
case ItemFilter.Likes:
query.IsLiked = true;
break;
case ItemFilter.Dislikes:
query.IsLiked = false;
break;
case ItemFilter.IsFavoriteOrLikes:
query.IsFavoriteOrLiked = true;
break;
}
}
query.ApplyFilters(filters);
return await _channelManager.GetLatestChannelItems(query, CancellationToken.None).ConfigureAwait(false);
}

View File

@@ -386,39 +386,7 @@ public class ItemsController : BaseJellyfinApiController
query.CollapseBoxSetItems = false;
}
foreach (var filter in filters)
{
switch (filter)
{
case ItemFilter.Dislikes:
query.IsLiked = false;
break;
case ItemFilter.IsFavorite:
query.IsFavorite = true;
break;
case ItemFilter.IsFavoriteOrLikes:
query.IsFavoriteOrLiked = true;
break;
case ItemFilter.IsFolder:
query.IsFolder = true;
break;
case ItemFilter.IsNotFolder:
query.IsFolder = false;
break;
case ItemFilter.IsPlayed:
query.IsPlayed = true;
break;
case ItemFilter.IsResumable:
query.IsResumable = true;
break;
case ItemFilter.IsUnplayed:
query.IsPlayed = false;
break;
case ItemFilter.Likes:
query.IsLiked = true;
break;
}
}
query.ApplyFilters(filters);
// Filter by Series Status
if (seriesStatus.Length != 0)

View File

@@ -10,6 +10,7 @@ using Jellyfin.Database.Implementations.Entities;
using Jellyfin.Database.Implementations.Enums;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
namespace MediaBrowser.Controller.Entities
{
@@ -388,5 +389,75 @@ namespace MediaBrowser.Controller.Entities
User = user;
}
public void ApplyFilters(ItemFilter[] filters)
{
static void ThrowConflictingFilters()
=> throw new ArgumentException("Conflicting filters", nameof(filters));
foreach (var filter in filters)
{
switch (filter)
{
case ItemFilter.IsFolder:
if (filters.Contains(ItemFilter.IsNotFolder))
{
ThrowConflictingFilters();
}
IsFolder = true;
break;
case ItemFilter.IsNotFolder:
if (filters.Contains(ItemFilter.IsFolder))
{
ThrowConflictingFilters();
}
IsFolder = false;
break;
case ItemFilter.IsUnplayed:
if (filters.Contains(ItemFilter.IsPlayed))
{
ThrowConflictingFilters();
}
IsPlayed = false;
break;
case ItemFilter.IsPlayed:
if (filters.Contains(ItemFilter.IsUnplayed))
{
ThrowConflictingFilters();
}
IsPlayed = true;
break;
case ItemFilter.IsFavorite:
IsFavorite = true;
break;
case ItemFilter.IsResumable:
IsResumable = true;
break;
case ItemFilter.Likes:
if (filters.Contains(ItemFilter.Dislikes))
{
ThrowConflictingFilters();
}
IsLiked = true;
break;
case ItemFilter.Dislikes:
if (filters.Contains(ItemFilter.Likes))
{
ThrowConflictingFilters();
}
IsLiked = false;
break;
case ItemFilter.IsFavoriteOrLikes:
IsFavoriteOrLiked = true;
break;
}
}
}
}
}

View File

@@ -0,0 +1,26 @@
using System;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Querying;
using Xunit;
namespace Jellyfin.Controller.Tests.Entities;
public class InternalItemsQueryTests
{
public static TheoryData<ItemFilter[]> ApplyFilters_Invalid()
{
var data = new TheoryData<ItemFilter[]>();
data.Add([ItemFilter.IsFolder, ItemFilter.IsNotFolder]);
data.Add([ItemFilter.IsPlayed, ItemFilter.IsUnplayed]);
data.Add([ItemFilter.Likes, ItemFilter.Dislikes]);
return data;
}
[Theory]
[MemberData(nameof(ApplyFilters_Invalid))]
public void ApplyFilters_Invalid_ThrowsArgumentException(ItemFilter[] filters)
{
var query = new InternalItemsQuery();
Assert.Throws<ArgumentException>(() => query.ApplyFilters(filters));
}
}