Unify API route parameters, return IResult everywhere, merge picture upload DTOs and centralize validation limits
Guid and long route constraints, id/trackId parameter names, Update*Request without the New prefix, sentence-case operation summaries, shared security scheme id and a single Limits class.
This commit is contained in:
@@ -4,12 +4,12 @@ using Musify.Api.DataTransferObjects;
|
||||
using Musify.Api.DataTransferObjects.Albums;
|
||||
using Musify.Api.Extensions;
|
||||
using Musify.Api.Filters;
|
||||
using Musify.Api.Models;
|
||||
using Musify.Application.Albums;
|
||||
using Musify.Application.Albums.Responses;
|
||||
using Musify.Application.Contracts;
|
||||
using Musify.Application.Pictures;
|
||||
using Musify.Application.Pictures.Responses;
|
||||
using Musify.Api.Models;
|
||||
using Musify.Application.Shared;
|
||||
using Musify.Application.Tracks.Responses;
|
||||
|
||||
@@ -27,46 +27,46 @@ public static class AlbumEndpoints
|
||||
group.MapGet("/", GetAlbums)
|
||||
.AddEndpointFilter<ValidationFilter<PageQuery>>()
|
||||
.WithName("GetAlbums")
|
||||
.WithSummary("Get Paginated Albums, Optionally Filtered By Title.")
|
||||
.WithSummary("Get paginated albums, optionally filtered by title")
|
||||
.Produces<PaginatedResponse<AlbumApplicationResponse>>();
|
||||
|
||||
group.MapGet("/{id}", GetAlbumById)
|
||||
group.MapGet("/{id:guid}", GetAlbumById)
|
||||
.WithName("GetAlbumById")
|
||||
.WithSummary("Get An Album By Id.")
|
||||
.WithSummary("Get an album by id")
|
||||
.Produces<AlbumApplicationResponse>()
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
group.MapGet("/users/{userId}", GetAlbumsByUserId)
|
||||
group.MapGet("/users/{userId:long}", GetAlbumsByUserId)
|
||||
.AddEndpointFilter<ValidationFilter<PageQuery>>()
|
||||
.WithName("GetAlbumsByUserId")
|
||||
.WithSummary("Get Paginated Albums For A User.")
|
||||
.WithSummary("Get paginated albums for a user")
|
||||
.Produces<PaginatedResponse<AlbumApplicationResponse>>()
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
group.MapGet("/recent", GetRecentlyListenedAlbums)
|
||||
.WithName("GetRecentlyListenedAlbums")
|
||||
.WithSummary("Get The Albums The Current User Listened To Most Recently.")
|
||||
.WithSummary("Get the albums the current user listened to most recently")
|
||||
.RequireAuthorization()
|
||||
.Produces<IReadOnlyList<AlbumApplicationResponse>>()
|
||||
.Produces(StatusCodes.Status401Unauthorized);
|
||||
|
||||
group.MapGet("/{albumId}/tracks", GetAlbumTracks)
|
||||
group.MapGet("/{id:guid}/tracks", GetAlbumTracks)
|
||||
.AddEndpointFilter<ValidationFilter<PageQuery>>()
|
||||
.WithName("GetAlbumTracks")
|
||||
.WithSummary("Get The Tracks Of An Album Ordered By Track Number.")
|
||||
.WithSummary("Get the tracks of an album ordered by track number")
|
||||
.Produces<PaginatedResponse<TrackApplicationResponse>>()
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
group.MapGet("/{id}/cover", GetAlbumCover)
|
||||
group.MapGet("/{id:guid}/cover", GetAlbumCover)
|
||||
.WithName("GetAlbumCover")
|
||||
.WithSummary("Get An Album Cover Image.")
|
||||
.WithSummary("Get an album cover image")
|
||||
.Produces(StatusCodes.Status200OK)
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
group.MapPost("/upload-picture", RequestAlbumPictureUpload)
|
||||
.WithName("RequestAlbumPictureUpload")
|
||||
.WithSummary("Request A Pre-Signed URL To Upload An Album Picture.")
|
||||
.AddEndpointFilter<ValidationFilter<RequestAlbumPictureUploadRequest>>()
|
||||
.WithSummary("Request a pre-signed URL to upload an album picture")
|
||||
.AddEndpointFilter<ValidationFilter<PictureUploadRequest>>()
|
||||
.RequireAuthorization()
|
||||
.Produces<PictureUploadResponse>()
|
||||
.ProducesValidationProblem()
|
||||
@@ -75,7 +75,7 @@ public static class AlbumEndpoints
|
||||
|
||||
group.MapPost("/", CreateAlbum)
|
||||
.WithName("CreateAlbum")
|
||||
.WithSummary("Create A New Album.")
|
||||
.WithSummary("Create a new album")
|
||||
.AddEndpointFilter<ValidationFilter<CreateAlbumRequest>>()
|
||||
.RequireAuthorization()
|
||||
.Produces<AlbumApplicationResponse>(StatusCodes.Status201Created)
|
||||
@@ -83,9 +83,9 @@ public static class AlbumEndpoints
|
||||
.Produces(StatusCodes.Status401Unauthorized)
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
group.MapPut("/{albumId}", UpdateAlbum)
|
||||
group.MapPut("/{id:guid}", UpdateAlbum)
|
||||
.WithName("UpdateAlbum")
|
||||
.WithSummary("Update An Album.")
|
||||
.WithSummary("Update an album")
|
||||
.AddEndpointFilter<ValidationFilter<UpdateAlbumRequest>>()
|
||||
.RequireAuthorization()
|
||||
.Produces<AlbumApplicationResponse>()
|
||||
@@ -94,18 +94,18 @@ public static class AlbumEndpoints
|
||||
.Produces(StatusCodes.Status403Forbidden)
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
group.MapDelete("/{albumId}", DeleteAlbum)
|
||||
group.MapDelete("/{id:guid}", DeleteAlbum)
|
||||
.WithName("DeleteAlbum")
|
||||
.WithSummary("Delete An Album.")
|
||||
.WithSummary("Delete an album")
|
||||
.RequireAuthorization()
|
||||
.Produces(StatusCodes.Status204NoContent)
|
||||
.Produces(StatusCodes.Status401Unauthorized)
|
||||
.Produces(StatusCodes.Status403Forbidden)
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
group.MapPost("/{id}/tracks", AddAlbumTracks)
|
||||
group.MapPost("/{id:guid}/tracks", AddAlbumTracks)
|
||||
.WithName("AddAlbumTracks")
|
||||
.WithSummary("Add Your Uploaded Tracks To An Album, Skipping The Ones It Already Has.")
|
||||
.WithSummary("Add your uploaded tracks to an album, skipping the ones it already has")
|
||||
.AddEndpointFilter<ValidationFilter<AddTracksRequest>>()
|
||||
.RequireAuthorization()
|
||||
.Produces(StatusCodes.Status204NoContent)
|
||||
@@ -115,9 +115,9 @@ public static class AlbumEndpoints
|
||||
.Produces(StatusCodes.Status404NotFound)
|
||||
.Produces(StatusCodes.Status409Conflict);
|
||||
|
||||
group.MapDelete("/{albumId}/tracks/{trackId}", RemoveTrackFromAlbum)
|
||||
group.MapDelete("/{id:guid}/tracks/{trackId:guid}", RemoveTrackFromAlbum)
|
||||
.WithName("RemoveTrackFromAlbum")
|
||||
.WithSummary("Remove A Track From An Album.")
|
||||
.WithSummary("Remove a track from an album")
|
||||
.RequireAuthorization()
|
||||
.Produces(StatusCodes.Status204NoContent)
|
||||
.Produces(StatusCodes.Status401Unauthorized)
|
||||
@@ -176,11 +176,11 @@ public static class AlbumEndpoints
|
||||
|
||||
private static async Task<IResult> GetAlbumTracks(
|
||||
IMediator mediator,
|
||||
Guid albumId,
|
||||
Guid id,
|
||||
CancellationToken cancellationToken,
|
||||
[AsParameters] PageQuery page)
|
||||
{
|
||||
var result = await mediator.Send(new GetAlbumTracksQuery(albumId, page.PageNumber, page.PageSize), cancellationToken);
|
||||
var result = await mediator.Send(new GetAlbumTracksQuery(id, page.PageNumber, page.PageSize), cancellationToken);
|
||||
return result.ToHttpResult();
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ public static class AlbumEndpoints
|
||||
private static async Task<IResult> RequestAlbumPictureUpload(
|
||||
IMediator mediator,
|
||||
CurrentUser currentUser,
|
||||
RequestAlbumPictureUploadRequest request,
|
||||
PictureUploadRequest request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await mediator.Send(
|
||||
@@ -224,12 +224,12 @@ public static class AlbumEndpoints
|
||||
private static async Task<IResult> UpdateAlbum(
|
||||
IMediator mediator,
|
||||
CurrentUser currentUser,
|
||||
Guid albumId,
|
||||
Guid id,
|
||||
UpdateAlbumRequest request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await mediator.Send(
|
||||
new UpdateAlbumCommand(currentUser.RequiredId, albumId, request.NewTitle, request.NewDescription, request.NewReleaseYear, request.NewPictureIntentId),
|
||||
new UpdateAlbumCommand(currentUser.RequiredId, id, request.Title, request.Description, request.ReleaseYear, request.PictureIntentId),
|
||||
cancellationToken);
|
||||
|
||||
return result.ToHttpResult();
|
||||
@@ -238,10 +238,10 @@ public static class AlbumEndpoints
|
||||
private static async Task<IResult> DeleteAlbum(
|
||||
IMediator mediator,
|
||||
CurrentUser currentUser,
|
||||
Guid albumId,
|
||||
Guid id,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await mediator.Send(new DeleteAlbumCommand(currentUser.RequiredId, albumId), cancellationToken);
|
||||
var result = await mediator.Send(new DeleteAlbumCommand(currentUser.RequiredId, id), cancellationToken);
|
||||
return result.ToHttpResult();
|
||||
}
|
||||
|
||||
@@ -262,12 +262,12 @@ public static class AlbumEndpoints
|
||||
private static async Task<IResult> RemoveTrackFromAlbum(
|
||||
IMediator mediator,
|
||||
CurrentUser currentUser,
|
||||
Guid albumId,
|
||||
Guid id,
|
||||
Guid trackId,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await mediator.Send(
|
||||
new RemoveTrackFromAlbumCommand(currentUser.RequiredId, albumId, trackId),
|
||||
new RemoveTrackFromAlbumCommand(currentUser.RequiredId, id, trackId),
|
||||
cancellationToken);
|
||||
|
||||
return result.ToHttpResult();
|
||||
|
||||
@@ -13,16 +13,17 @@ public static class ConfigEndpoints
|
||||
|
||||
group.MapGet("/playback", GetPlaybackPublicConfig)
|
||||
.WithName("GetPlaybackPublicConfig")
|
||||
.WithSummary("Get The Public Playback Configuration (Whether Anonymous Listening Is Allowed). Works Anonymously.")
|
||||
.WithSummary("Get the public playback configuration (whether anonymous listening is allowed). Works anonymously")
|
||||
.Produces<PlaybackPublicConfigResponse>();
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
private static async Task<PlaybackPublicConfigResponse> GetPlaybackPublicConfig(
|
||||
private static async Task<IResult> GetPlaybackPublicConfig(
|
||||
IMediator mediator,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return await mediator.Send(new GetPlaybackPublicConfigQuery(), cancellationToken);
|
||||
var result = await mediator.Send(new GetPlaybackPublicConfigQuery(), cancellationToken);
|
||||
return Results.Ok(result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,28 +13,30 @@ public static class GenreEndpoints
|
||||
|
||||
group.MapGet("/", GetGenres)
|
||||
.WithName("GetGenres")
|
||||
.WithSummary("Get The Genres That Have At Least One Track, Most Populated First. Works Anonymously.")
|
||||
.WithSummary("Get the genres that have at least one track, most populated first. Works anonymously")
|
||||
.Produces<IReadOnlyList<GenreResponse>>();
|
||||
|
||||
group.MapGet("/available", GetAvailableGenres)
|
||||
.WithName("GetAvailableGenres")
|
||||
.WithSummary("Get Every Genre A Track Can Be Tagged With, Including The Genres It Cannot Be Combined With. Works Anonymously.")
|
||||
.WithSummary("Get every genre a track can be tagged with, including the genres it cannot be combined with. Works anonymously")
|
||||
.Produces<IReadOnlyList<AvailableGenreResponse>>();
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
private static async Task<IReadOnlyList<AvailableGenreResponse>> GetAvailableGenres(
|
||||
private static async Task<IResult> GetAvailableGenres(
|
||||
IMediator mediator,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return await mediator.Send(new GetAvailableGenresQuery(), cancellationToken);
|
||||
var result = await mediator.Send(new GetAvailableGenresQuery(), cancellationToken);
|
||||
return Results.Ok(result);
|
||||
}
|
||||
|
||||
private static async Task<IReadOnlyList<GenreResponse>> GetGenres(
|
||||
private static async Task<IResult> GetGenres(
|
||||
IMediator mediator,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return await mediator.Send(new GetGenresQuery(), cancellationToken);
|
||||
var result = await mediator.Send(new GetGenresQuery(), cancellationToken);
|
||||
return Results.Ok(result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@ using Mediator;
|
||||
using Musify.Api.Authentication;
|
||||
using Musify.Api.DataTransferObjects.Likes;
|
||||
using Musify.Api.Extensions;
|
||||
using Musify.Application.Likes;
|
||||
using Musify.Api.Filters;
|
||||
using Musify.Api.Models;
|
||||
using Musify.Application.Likes;
|
||||
using Musify.Application.Shared;
|
||||
using Musify.Application.Tracks.Responses;
|
||||
using Musify.Api.Filters;
|
||||
|
||||
namespace Musify.Api.Endpoints;
|
||||
|
||||
@@ -21,13 +21,13 @@ public static class LikeEndpoints
|
||||
group.MapGet("/", GetLikedTracks)
|
||||
.AddEndpointFilter<ValidationFilter<PageQuery>>()
|
||||
.WithName("GetLikedTracks")
|
||||
.WithSummary("Get The Current User'S Liked Tracks.")
|
||||
.WithSummary("Get the current user's liked tracks")
|
||||
.Produces<PaginatedResponse<TrackApplicationResponse>>()
|
||||
.Produces(StatusCodes.Status401Unauthorized);
|
||||
|
||||
group.MapPost("/toggle", ToggleTrackLike)
|
||||
.WithName("ToggleTrackLike")
|
||||
.WithSummary("Like Or Unlike A Track By Id.")
|
||||
.WithSummary("Like or unlike a track by id")
|
||||
.Produces<bool>()
|
||||
.Produces(StatusCodes.Status401Unauthorized)
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
@@ -16,13 +16,13 @@ public static class MixEndpoints
|
||||
|
||||
group.MapGet("/", GetMixes)
|
||||
.WithName("GetMixes")
|
||||
.WithSummary("Get The Server-Generated Mixes Of The Current User.")
|
||||
.WithSummary("Get the server-generated mixes of the current user")
|
||||
.Produces<IReadOnlyList<MixApplicationResponse>>()
|
||||
.Produces(StatusCodes.Status401Unauthorized);
|
||||
|
||||
group.MapGet("/{id}", GetMixById)
|
||||
group.MapGet("/{id:guid}", GetMixById)
|
||||
.WithName("GetMixById")
|
||||
.WithSummary("Get A Mix With All Of Its Songs.")
|
||||
.WithSummary("Get a mix with all of its songs")
|
||||
.Produces<MixApplicationResponse>()
|
||||
.Produces(StatusCodes.Status401Unauthorized)
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
@@ -4,12 +4,12 @@ using Musify.Api.DataTransferObjects;
|
||||
using Musify.Api.DataTransferObjects.PlayLists;
|
||||
using Musify.Api.Extensions;
|
||||
using Musify.Api.Filters;
|
||||
using Musify.Api.Models;
|
||||
using Musify.Application.Contracts;
|
||||
using Musify.Application.Pictures;
|
||||
using Musify.Application.Pictures.Responses;
|
||||
using Musify.Application.PlayLists;
|
||||
using Musify.Application.PlayLists.Responses;
|
||||
using Musify.Api.Models;
|
||||
using Musify.Application.Shared;
|
||||
using Musify.Application.Tracks.Responses;
|
||||
|
||||
@@ -22,34 +22,34 @@ public static class PlayListEndpoints
|
||||
var group = app.MapGroup("/playlists")
|
||||
.WithTags("PlayLists");
|
||||
|
||||
group.MapGet("/{id}", GetPlayListById)
|
||||
group.MapGet("/{id:guid}", GetPlayListById)
|
||||
.WithName("GetPlayListById")
|
||||
.WithSummary("Get A PlayList By Id.")
|
||||
.WithSummary("Get a playlist by id")
|
||||
.Produces<PlayListApplicationResponse>()
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
group.MapGet("/users/{userId}", GetPlayListsByUserId)
|
||||
group.MapGet("/users/{userId:long}", GetPlayListsByUserId)
|
||||
.AddEndpointFilter<ValidationFilter<PageQuery>>()
|
||||
.WithName("GetPlayListsByUserId")
|
||||
.WithSummary("Get Paginated PlayLists For A User. Private PlayLists Are Only Returned To Their Owner.")
|
||||
.WithSummary("Get paginated playlists for a user. Private playlists are only returned to their owner")
|
||||
.Produces<PaginatedResponse<PlayListApplicationResponse>>();
|
||||
|
||||
group.MapGet("/{playlistId}/tracks", GetPlayListTracks)
|
||||
group.MapGet("/{id:guid}/tracks", GetPlayListTracks)
|
||||
.AddEndpointFilter<ValidationFilter<PageQuery>>()
|
||||
.WithName("GetPlayListTracks")
|
||||
.WithSummary("Get Paginated Tracks Of A PlayList.")
|
||||
.WithSummary("Get paginated tracks of a playlist")
|
||||
.Produces<PaginatedResponse<TrackApplicationResponse>>()
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
group.MapGet("/{id}/cover", GetPlayListCover)
|
||||
group.MapGet("/{id:guid}/cover", GetPlayListCover)
|
||||
.WithName("GetPlayListCover")
|
||||
.WithSummary("Get A PlayList Cover Image.")
|
||||
.WithSummary("Get a playlist cover image")
|
||||
.Produces(StatusCodes.Status200OK)
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
group.MapPost("/", CreatePlayList)
|
||||
.WithName("CreatePlayList")
|
||||
.WithSummary("Create A New PlayList.")
|
||||
.WithSummary("Create a new playlist")
|
||||
.AddEndpointFilter<ValidationFilter<CreatePlayListRequest>>()
|
||||
.RequireAuthorization()
|
||||
.Produces<PlayListApplicationResponse>(StatusCodes.Status201Created)
|
||||
@@ -57,9 +57,9 @@ public static class PlayListEndpoints
|
||||
.Produces(StatusCodes.Status401Unauthorized)
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
group.MapPut("/{playlistId}", UpdatePlayList)
|
||||
group.MapPut("/{id:guid}", UpdatePlayList)
|
||||
.WithName("UpdatePlayList")
|
||||
.WithSummary("Update An Existing PlayList.")
|
||||
.WithSummary("Update an existing playlist")
|
||||
.AddEndpointFilter<ValidationFilter<UpdatePlayListRequest>>()
|
||||
.RequireAuthorization()
|
||||
.Produces<PlayListApplicationResponse>()
|
||||
@@ -68,9 +68,9 @@ public static class PlayListEndpoints
|
||||
.Produces(StatusCodes.Status403Forbidden)
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
group.MapDelete("/{playlistId}", DeletePlayList)
|
||||
group.MapDelete("/{id:guid}", DeletePlayList)
|
||||
.WithName("DeletePlayList")
|
||||
.WithSummary("Delete A PlayList.")
|
||||
.WithSummary("Delete a playlist")
|
||||
.RequireAuthorization()
|
||||
.Produces(StatusCodes.Status204NoContent)
|
||||
.Produces(StatusCodes.Status401Unauthorized)
|
||||
@@ -79,17 +79,17 @@ public static class PlayListEndpoints
|
||||
|
||||
group.MapPost("/upload-picture", RequestPlayListPictureUpload)
|
||||
.WithName("RequestPlayListPictureUpload")
|
||||
.WithSummary("Request A Pre-Signed URL To Upload A PlayList Picture.")
|
||||
.AddEndpointFilter<ValidationFilter<RequestPlayListPictureUploadRequest>>()
|
||||
.WithSummary("Request a pre-signed URL to upload a playlist picture")
|
||||
.AddEndpointFilter<ValidationFilter<PictureUploadRequest>>()
|
||||
.RequireAuthorization()
|
||||
.Produces<PictureUploadResponse>()
|
||||
.ProducesValidationProblem()
|
||||
.Produces(StatusCodes.Status401Unauthorized)
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
group.MapPost("/{id}/tracks", AddPlayListTracks)
|
||||
group.MapPost("/{id:guid}/tracks", AddPlayListTracks)
|
||||
.WithName("AddPlayListTracks")
|
||||
.WithSummary("Add Tracks To A PlayList, Skipping The Ones It Already Has.")
|
||||
.WithSummary("Add tracks to a playlist, skipping the ones it already has")
|
||||
.AddEndpointFilter<ValidationFilter<AddTracksRequest>>()
|
||||
.RequireAuthorization()
|
||||
.Produces(StatusCodes.Status204NoContent)
|
||||
@@ -99,9 +99,9 @@ public static class PlayListEndpoints
|
||||
.Produces(StatusCodes.Status404NotFound)
|
||||
.Produces(StatusCodes.Status409Conflict);
|
||||
|
||||
group.MapDelete("/{playlistId}/tracks/{trackId}", RemoveTrackFromPlayList)
|
||||
group.MapDelete("/{id:guid}/tracks/{trackId:guid}", RemoveTrackFromPlayList)
|
||||
.WithName("RemoveTrackFromPlayList")
|
||||
.WithSummary("Remove A Track From A PlayList.")
|
||||
.WithSummary("Remove a track from a playlist")
|
||||
.RequireAuthorization()
|
||||
.Produces(StatusCodes.Status204NoContent)
|
||||
.Produces(StatusCodes.Status401Unauthorized)
|
||||
@@ -136,11 +136,11 @@ public static class PlayListEndpoints
|
||||
private static async Task<IResult> GetPlayListTracks(
|
||||
IMediator mediator,
|
||||
CurrentUser currentUser,
|
||||
Guid playlistId,
|
||||
Guid id,
|
||||
CancellationToken cancellationToken,
|
||||
[AsParameters] PageQuery page)
|
||||
{
|
||||
var result = await mediator.Send(new GetPlayListTracksQuery(playlistId, page.PageNumber, page.PageSize, currentUser.Id), cancellationToken);
|
||||
var result = await mediator.Send(new GetPlayListTracksQuery(id, page.PageNumber, page.PageSize, currentUser.Id), cancellationToken);
|
||||
return result.ToHttpResult();
|
||||
}
|
||||
|
||||
@@ -171,12 +171,12 @@ public static class PlayListEndpoints
|
||||
private static async Task<IResult> UpdatePlayList(
|
||||
IMediator mediator,
|
||||
CurrentUser currentUser,
|
||||
Guid playlistId,
|
||||
Guid id,
|
||||
UpdatePlayListRequest request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await mediator.Send(
|
||||
new UpdatePlayListCommand(currentUser.RequiredId, playlistId, request.NewName, request.NewDescription, request.NewPictureIntentId, request.NewVisibility),
|
||||
new UpdatePlayListCommand(currentUser.RequiredId, id, request.Name, request.Description, request.PictureIntentId, request.Visibility),
|
||||
cancellationToken);
|
||||
|
||||
return result.ToHttpResult();
|
||||
@@ -185,17 +185,17 @@ public static class PlayListEndpoints
|
||||
private static async Task<IResult> DeletePlayList(
|
||||
IMediator mediator,
|
||||
CurrentUser currentUser,
|
||||
Guid playlistId,
|
||||
Guid id,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await mediator.Send(new DeletePlayListCommand(currentUser.RequiredId, playlistId), cancellationToken);
|
||||
var result = await mediator.Send(new DeletePlayListCommand(currentUser.RequiredId, id), cancellationToken);
|
||||
return result.ToHttpResult();
|
||||
}
|
||||
|
||||
private static async Task<IResult> RequestPlayListPictureUpload(
|
||||
IMediator mediator,
|
||||
CurrentUser currentUser,
|
||||
RequestPlayListPictureUploadRequest request,
|
||||
PictureUploadRequest request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await mediator.Send(
|
||||
@@ -222,12 +222,12 @@ public static class PlayListEndpoints
|
||||
private static async Task<IResult> RemoveTrackFromPlayList(
|
||||
IMediator mediator,
|
||||
CurrentUser currentUser,
|
||||
Guid playlistId,
|
||||
Guid id,
|
||||
Guid trackId,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await mediator.Send(
|
||||
new RemoveTrackFromPlayListCommand(currentUser.RequiredId, playlistId, trackId),
|
||||
new RemoveTrackFromPlayListCommand(currentUser.RequiredId, id, trackId),
|
||||
cancellationToken);
|
||||
|
||||
return result.ToHttpResult();
|
||||
|
||||
@@ -3,9 +3,9 @@ using Musify.Api.Authentication;
|
||||
using Musify.Api.DataTransferObjects.Tracks;
|
||||
using Musify.Api.Extensions;
|
||||
using Musify.Api.Filters;
|
||||
using Musify.Api.Models;
|
||||
using Musify.Application.Contracts;
|
||||
using Musify.Application.Pictures;
|
||||
using Musify.Api.Models;
|
||||
using Musify.Application.Shared;
|
||||
using Musify.Application.Tracks;
|
||||
using Musify.Application.Tracks.Responses;
|
||||
@@ -22,47 +22,47 @@ public static class TrackEndpoints
|
||||
group.MapGet("/", GetTracks)
|
||||
.AddEndpointFilter<ValidationFilter<PageQuery>>()
|
||||
.WithName("GetTracks")
|
||||
.WithSummary("Get Paginated Tracks, Optionally Filtered By Name And Genre.")
|
||||
.WithSummary("Get paginated tracks, optionally filtered by name and genre")
|
||||
.Produces<PaginatedResponse<TrackApplicationResponse>>()
|
||||
.ProducesValidationProblem();
|
||||
|
||||
group.MapGet("/{id}", GetTrackById)
|
||||
group.MapGet("/{id:guid}", GetTrackById)
|
||||
.WithName("GetTrackById")
|
||||
.WithSummary("Get A Track By Id.")
|
||||
.WithSummary("Get a track by id")
|
||||
.Produces<TrackApplicationResponse>()
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
group.MapGet("/{id}/cover", GetTrackCover)
|
||||
group.MapGet("/{id:guid}/cover", GetTrackCover)
|
||||
.WithName("GetTrackCover")
|
||||
.WithSummary("Get A Track Cover Image.")
|
||||
.WithSummary("Get a track cover image")
|
||||
.Produces(StatusCodes.Status200OK)
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
group.MapGet("/{id}/stream", GetTrackStream)
|
||||
group.MapGet("/{id:guid}/stream", GetTrackStream)
|
||||
.WithName("GetTrackStream")
|
||||
.WithSummary("Get A Streaming Manifest URL And Ticket For A Track. Works Anonymously When The Playback Configuration Allows It.")
|
||||
.WithSummary("Get a streaming manifest URL and ticket for a track. Works anonymously when the playback configuration allows it")
|
||||
.Produces<TrackStreamResponse>()
|
||||
.Produces(StatusCodes.Status401Unauthorized)
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
group.MapPut("/listens/{listenId}/progress", RecordListeningProgress)
|
||||
group.MapPut("/listens/{listenId:guid}/progress", RecordListeningProgress)
|
||||
.AddEndpointFilter<ValidationFilter<RecordListeningProgressRequest>>()
|
||||
.WithName("RecordListeningProgress")
|
||||
.WithSummary("Report The Total Seconds Actually Played For A Listen Started By The Stream Endpoint.")
|
||||
.WithSummary("Report the total seconds actually played for a listen started by the stream endpoint")
|
||||
.RequireAuthorization()
|
||||
.Produces(StatusCodes.Status204NoContent)
|
||||
.Produces(StatusCodes.Status401Unauthorized)
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
group.MapGet("/users/{userId}", GetTracksByUserId)
|
||||
group.MapGet("/users/{userId:long}", GetTracksByUserId)
|
||||
.AddEndpointFilter<ValidationFilter<PageQuery>>()
|
||||
.WithName("GetTracksByUserId")
|
||||
.WithSummary("Get Paginated Tracks For A User.")
|
||||
.WithSummary("Get paginated tracks for a user")
|
||||
.Produces<PaginatedResponse<TrackApplicationResponse>>();
|
||||
|
||||
group.MapPost("/", CreateTrack)
|
||||
.WithName("CreateTrack")
|
||||
.WithSummary("Create A New Track.")
|
||||
.WithSummary("Create a new track")
|
||||
.AddEndpointFilter<ValidationFilter<CreateTrackRequest>>()
|
||||
.RequireAuthorization()
|
||||
.Produces<TrackApplicationResponse>(StatusCodes.Status201Created)
|
||||
@@ -71,9 +71,9 @@ public static class TrackEndpoints
|
||||
.Produces(StatusCodes.Status404NotFound)
|
||||
.Produces(StatusCodes.Status409Conflict);
|
||||
|
||||
group.MapDelete("/{trackId}", DeleteTrack)
|
||||
group.MapDelete("/{id:guid}", DeleteTrack)
|
||||
.WithName("DeleteTrack")
|
||||
.WithSummary("Delete A Track.")
|
||||
.WithSummary("Delete a track")
|
||||
.RequireAuthorization()
|
||||
.Produces(StatusCodes.Status204NoContent)
|
||||
.Produces(StatusCodes.Status401Unauthorized)
|
||||
@@ -83,7 +83,7 @@ public static class TrackEndpoints
|
||||
|
||||
group.MapPost("/upload-urls", RequestTrackUploadUrls)
|
||||
.WithName("RequestTrackUploadUrls")
|
||||
.WithSummary("Request Pre-Signed URLs To Upload Track Picture And Audio.")
|
||||
.WithSummary("Request pre-signed URLs to upload track picture and audio")
|
||||
.AddEndpointFilter<ValidationFilter<RequestTrackUploadUrlsRequest>>()
|
||||
.RequireAuthorization()
|
||||
.Produces<TrackUploadUrlsResponse>()
|
||||
@@ -176,10 +176,10 @@ public static class TrackEndpoints
|
||||
private static async Task<IResult> DeleteTrack(
|
||||
IMediator mediator,
|
||||
CurrentUser currentUser,
|
||||
Guid trackId,
|
||||
Guid id,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await mediator.Send(new DeleteTrackCommand(currentUser.RequiredId, trackId), cancellationToken);
|
||||
var result = await mediator.Send(new DeleteTrackCommand(currentUser.RequiredId, id), cancellationToken);
|
||||
return result.ToHttpResult();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
using Mediator;
|
||||
using Musify.Api.Authentication;
|
||||
using Musify.Api.Extensions;
|
||||
using Musify.Api.Filters;
|
||||
using Musify.Api.Models;
|
||||
using Musify.Application.Shared;
|
||||
using Musify.Application.Tracks;
|
||||
using Musify.Application.Tracks.Responses;
|
||||
using Musify.Application.Users;
|
||||
using Musify.Application.Users.Responses;
|
||||
using Musify.Api.Filters;
|
||||
|
||||
namespace Musify.Api.Endpoints;
|
||||
|
||||
@@ -21,75 +21,75 @@ public static class UserEndpoints
|
||||
group.MapGet("/", GetUsers)
|
||||
.AddEndpointFilter<ValidationFilter<PageQuery>>()
|
||||
.WithName("GetUsers")
|
||||
.WithSummary("Get Paginated Users.")
|
||||
.WithSummary("Get paginated users")
|
||||
.Produces<PaginatedResponse<UserSummaryResponse>>();
|
||||
|
||||
group.MapGet("/{id}", GetUserById)
|
||||
group.MapGet("/{id:long}", GetUserById)
|
||||
.WithName("GetUserById")
|
||||
.WithSummary("Get A User By Id.")
|
||||
.WithSummary("Get a user by id")
|
||||
.Produces<UserApplicationResponse>()
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
group.MapGet("/{id}/listening-history", GetListeningHistory)
|
||||
group.MapGet("/{id:long}/listening-history", GetListeningHistory)
|
||||
.WithName("GetListeningHistory")
|
||||
.WithSummary("Get A User'S Listening History.")
|
||||
.WithSummary("Get a user's listening history")
|
||||
.Produces<IEnumerable<TrackApplicationResponse>>()
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
group.MapGet("/{id}/listening-stats", GetListeningStats)
|
||||
group.MapGet("/{id:long}/listening-stats", GetListeningStats)
|
||||
.WithName("GetListeningStats")
|
||||
.WithSummary("Get A User'S Listening Stats For The Current Week And Streak.")
|
||||
.WithSummary("Get a user's listening stats for the current week and streak")
|
||||
.RequireAuthorization()
|
||||
.Produces<ListeningStatsResponse>()
|
||||
.Produces(StatusCodes.Status401Unauthorized)
|
||||
.Produces(StatusCodes.Status403Forbidden);
|
||||
|
||||
group.MapGet("/{id}/last-listened-track", GetLastTrackListenedByUserId)
|
||||
group.MapGet("/{id:long}/last-listened-track", GetLastTrackListenedByUserId)
|
||||
.WithName("GetLastTrackListenedByUserId")
|
||||
.WithSummary("Get The Last Track A User Listened To.")
|
||||
.WithSummary("Get the last track a user listened to")
|
||||
.Produces<TrackApplicationResponse>()
|
||||
.Produces(StatusCodes.Status204NoContent);
|
||||
|
||||
group.MapGet("/{id}/profile", GetUserProfile)
|
||||
group.MapGet("/{id:long}/profile", GetUserProfile)
|
||||
.WithName("GetUserProfile")
|
||||
.WithSummary("Get A User'S Public Profile, Including Follower Counts.")
|
||||
.WithSummary("Get a user's public profile, including follower counts")
|
||||
.Produces<UserProfileResponse>()
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
group.MapGet("/{id}/followers", GetFollowers)
|
||||
group.MapGet("/{id:long}/followers", GetFollowers)
|
||||
.AddEndpointFilter<ValidationFilter<PageQuery>>()
|
||||
.WithName("GetUserFollowers")
|
||||
.WithSummary("Get The Users Following A User. Visible To The User And To Mutual Followers.")
|
||||
.WithSummary("Get the users following a user. Visible to the user and to mutual followers")
|
||||
.Produces<PaginatedResponse<UserSummaryResponse>>()
|
||||
.Produces(StatusCodes.Status403Forbidden)
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
group.MapGet("/{id}/following", GetFollowing)
|
||||
group.MapGet("/{id:long}/following", GetFollowing)
|
||||
.AddEndpointFilter<ValidationFilter<PageQuery>>()
|
||||
.WithName("GetUserFollowing")
|
||||
.WithSummary("Get The Users A User Follows.")
|
||||
.WithSummary("Get the users a user follows")
|
||||
.Produces<PaginatedResponse<UserSummaryResponse>>()
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
group.MapGet("/{id}/is-following", IsFollowing)
|
||||
group.MapGet("/{id:long}/is-following", IsFollowing)
|
||||
.WithName("IsFollowingUser")
|
||||
.WithSummary("Check Whether The Current User Follows Another User.")
|
||||
.WithSummary("Check whether the current user follows another user")
|
||||
.RequireAuthorization()
|
||||
.Produces<bool>()
|
||||
.Produces(StatusCodes.Status401Unauthorized);
|
||||
|
||||
group.MapPost("/{id}/follow", FollowUser)
|
||||
group.MapPost("/{id:long}/follow", FollowUser)
|
||||
.WithName("FollowUser")
|
||||
.WithSummary("Follow A User.")
|
||||
.WithSummary("Follow a user")
|
||||
.RequireAuthorization()
|
||||
.Produces(StatusCodes.Status204NoContent)
|
||||
.Produces(StatusCodes.Status401Unauthorized)
|
||||
.Produces(StatusCodes.Status404NotFound)
|
||||
.ProducesValidationProblem();
|
||||
|
||||
group.MapDelete("/{id}/follow", UnfollowUser)
|
||||
group.MapDelete("/{id:long}/follow", UnfollowUser)
|
||||
.WithName("UnfollowUser")
|
||||
.WithSummary("Unfollow A User.")
|
||||
.WithSummary("Unfollow a user")
|
||||
.RequireAuthorization()
|
||||
.Produces(StatusCodes.Status204NoContent)
|
||||
.Produces(StatusCodes.Status401Unauthorized);
|
||||
@@ -117,12 +117,13 @@ public static class UserEndpoints
|
||||
return result.ToHttpResult();
|
||||
}
|
||||
|
||||
private static async Task<IEnumerable<TrackApplicationResponse>> GetListeningHistory(
|
||||
private static async Task<IResult> GetListeningHistory(
|
||||
IMediator mediator,
|
||||
long id,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return await mediator.Send(new GetListeningHistoryQuery(id), cancellationToken);
|
||||
var result = await mediator.Send(new GetListeningHistoryQuery(id), cancellationToken);
|
||||
return Results.Ok(result);
|
||||
}
|
||||
|
||||
private static async Task<IResult> GetListeningStats(
|
||||
@@ -132,9 +133,10 @@ public static class UserEndpoints
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (currentUser.RequiredId != id)
|
||||
return Results.StatusCode(StatusCodes.Status403Forbidden);
|
||||
return Results.Problem(statusCode: StatusCodes.Status403Forbidden);
|
||||
|
||||
return Results.Ok(await mediator.Send(new GetListeningStatsQuery(id), cancellationToken));
|
||||
var result = await mediator.Send(new GetListeningStatsQuery(id), cancellationToken);
|
||||
return Results.Ok(result);
|
||||
}
|
||||
|
||||
private static async Task<IResult> GetLastTrackListenedByUserId(
|
||||
@@ -178,13 +180,14 @@ public static class UserEndpoints
|
||||
return result.ToHttpResult();
|
||||
}
|
||||
|
||||
private static async Task<bool> IsFollowing(
|
||||
private static async Task<IResult> IsFollowing(
|
||||
IMediator mediator,
|
||||
CurrentUser currentUser,
|
||||
long id,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return await mediator.Send(new IsFollowingUserQuery(currentUser.RequiredId, id), cancellationToken);
|
||||
var result = await mediator.Send(new IsFollowingUserQuery(currentUser.RequiredId, id), cancellationToken);
|
||||
return Results.Ok(result);
|
||||
}
|
||||
|
||||
private static async Task<IResult> FollowUser(
|
||||
|
||||
Reference in New Issue
Block a user