fix(api): reject unsupported CollectionType on rerun-collection create/update (#152 review)
The rerun request mapping's catch-all routed Playlist/RerunFirstRun/RerunRerun/ SearchQuery/Fake* to MediaItemId, so POST/PUT with those persisted a wrong-kind id and returned 201 instead of 422. Guard both verbs with IsSupportedSelectionType. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,27 @@ namespace ErsatzTV.Controllers.Api.Requests;
|
||||
// doing extra lookup queries. The remaining VMs are left null (the handler expects that).
|
||||
internal static class RerunCollectionRequestMapping
|
||||
{
|
||||
/// <summary>
|
||||
/// The only <see cref="CollectionType" /> values valid as a rerun collection's selected
|
||||
/// source. Excludes Playlist / RerunFirstRun / RerunRerun / SearchQuery / Fake* — those
|
||||
/// are not media-item-backed collection types and must not be resolved via
|
||||
/// <see cref="ResolveSelection" />. Callers (the controller) must check this first.
|
||||
/// </summary>
|
||||
public static bool IsSupportedSelectionType(CollectionType collectionType) =>
|
||||
collectionType is CollectionType.Collection
|
||||
or CollectionType.MultiCollection
|
||||
or CollectionType.SmartCollection
|
||||
or CollectionType.TelevisionShow
|
||||
or CollectionType.TelevisionSeason
|
||||
or CollectionType.Artist
|
||||
or CollectionType.Movie
|
||||
or CollectionType.Episode
|
||||
or CollectionType.MusicVideo
|
||||
or CollectionType.OtherVideo
|
||||
or CollectionType.Song
|
||||
or CollectionType.Image
|
||||
or CollectionType.RemoteStream;
|
||||
|
||||
public static (MediaCollectionViewModel Collection,
|
||||
MultiCollectionViewModel MultiCollection,
|
||||
SmartCollectionViewModel SmartCollection,
|
||||
@@ -43,7 +64,9 @@ internal static class RerunCollectionRequestMapping
|
||||
|
||||
// Any media-item-backed collection type (TelevisionShow, TelevisionSeason,
|
||||
// Artist, Movie, Episode, MusicVideo, OtherVideo, Song, Image, ...) resolves to
|
||||
// the MediaItem VM keyed by media item id.
|
||||
// the MediaItem VM keyed by media item id. The caller (RerunCollectionController)
|
||||
// has already validated CollectionType via IsSupportedSelectionType, so this
|
||||
// catch-all only ever receives a real media-item type.
|
||||
_ => (
|
||||
null,
|
||||
null,
|
||||
|
||||
@@ -62,6 +62,13 @@ public class RerunCollectionController(IMediator mediator) : ControllerBase
|
||||
[Required] [FromBody] CreateRerunCollectionRequest request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (!RerunCollectionRequestMapping.IsSupportedSelectionType(request.CollectionType))
|
||||
{
|
||||
return BaseError.New(
|
||||
$"Unsupported collection type '{request.CollectionType}' for a rerun collection")
|
||||
.ToErrorResult();
|
||||
}
|
||||
|
||||
Either<BaseError, RerunCollectionViewModel> result =
|
||||
await mediator.Send(request.ToCommand(), cancellationToken);
|
||||
return result.ToCreatedResult(
|
||||
@@ -81,6 +88,13 @@ public class RerunCollectionController(IMediator mediator) : ControllerBase
|
||||
[Required] [FromBody] UpdateRerunCollectionRequest request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (!RerunCollectionRequestMapping.IsSupportedSelectionType(request.CollectionType))
|
||||
{
|
||||
return BaseError.New(
|
||||
$"Unsupported collection type '{request.CollectionType}' for a rerun collection")
|
||||
.ToErrorResult();
|
||||
}
|
||||
|
||||
Either<BaseError, Unit> result = await mediator.Send(request.ToCommand(id), cancellationToken);
|
||||
return await result.Match(
|
||||
Left: error => Task.FromResult(error.ToErrorResult()),
|
||||
|
||||
Reference in New Issue
Block a user