Add track coauthors with invitations, acceptance and coauthor-aware track responses

Owners invite existing users to coauthor a track; invitees accept or reject,
and either side can remove a coauthor. Only accepted coauthors appear in track
responses and in the coauthor's public track list. The owner also receives the
full invitation list with statuses on the user tracks response.
This commit is contained in:
2026-09-25 02:14:23 +02:00
parent a888a44b41
commit 03f5936944
29 changed files with 2267 additions and 18 deletions
@@ -3,6 +3,8 @@ using Musify.Api.Authentication;
using Musify.Api.Extensions;
using Musify.Api.Filters;
using Musify.Api.Models;
using Musify.Application.Coauthors;
using Musify.Application.Coauthors.Responses;
using Musify.Application.Shared;
using Musify.Application.Tracks;
using Musify.Application.Tracks.Responses;
@@ -24,6 +26,14 @@ namespace Musify.Api.Endpoints
.WithSummary("Get paginated users")
.Produces<PaginatedResponse<UserSummaryResponse>>();
group.MapGet("/me/coauthor-invitations", GetCoauthorInvitations)
.AddEndpointFilter<ValidationFilter<PageQuery>>()
.WithName("GetCoauthorInvitations")
.WithSummary("Get your pending coauthor invitations with the track title and owner")
.RequireAuthorization()
.Produces<PaginatedResponse<CoauthorInvitationResponse>>()
.Produces(StatusCodes.Status401Unauthorized);
group.MapGet("/{id:long}", GetUserById)
.WithName("GetUserById")
.WithSummary("Get a user by id")
@@ -108,6 +118,16 @@ namespace Musify.Api.Endpoints
return Results.Ok(result);
}
private static async Task<IResult> GetCoauthorInvitations(
IMediator mediator,
CurrentUser currentUser,
[AsParameters] PageQuery page,
CancellationToken cancellationToken)
{
var result = await mediator.Send(new GetCoauthorInvitationsQuery(currentUser.RequiredId, page.PageNumber, page.PageSize), cancellationToken);
return Results.Ok(result);
}
private static async Task<IResult> GetUserById(
IMediator mediator,
long id,