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:
@@ -59,6 +59,8 @@ namespace Musify.Infrastructure.Persistence
|
||||
|
||||
public DbSet<UserFollow> UserFollows => Set<UserFollow>();
|
||||
|
||||
public DbSet<TrackCoauthor> TrackCoauthors => Set<TrackCoauthor>();
|
||||
|
||||
public async Task<IDatabaseTransaction> BeginTransactionAsync(System.Data.IsolationLevel isolationLevel, CancellationToken cancellationToken)
|
||||
{
|
||||
var transaction = await Database.BeginTransactionAsync(isolationLevel, cancellationToken);
|
||||
|
||||
+1142
File diff suppressed because it is too large
Load Diff
+61
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Musify.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddTrackCoauthors : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "TrackCoauthors",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
TrackId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
UserId = table.Column<long>(type: "bigint", nullable: false),
|
||||
Status = table.Column<int>(type: "integer", nullable: false),
|
||||
InvitedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||
RespondedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_TrackCoauthors", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_TrackCoauthors_Tracks_TrackId",
|
||||
column: x => x.TrackId,
|
||||
principalTable: "Tracks",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_TrackCoauthors_User_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "User",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_TrackCoauthors_TrackId_UserId",
|
||||
table: "TrackCoauthors",
|
||||
columns: new[] { "TrackId", "UserId" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_TrackCoauthors_UserId_Status",
|
||||
table: "TrackCoauthors",
|
||||
columns: new[] { "UserId", "Status" });
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "TrackCoauthors");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -467,6 +467,37 @@ namespace Musify.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("Tracks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.TrackCoauthor", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("InvitedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTime?>("RespondedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<Guid>("TrackId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<long>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("TrackId", "UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("UserId", "Status");
|
||||
|
||||
b.ToTable("TrackCoauthors");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.TrackLike", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@@ -989,6 +1020,25 @@ namespace Musify.Infrastructure.Persistence.Migrations
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.TrackCoauthor", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.Track", "Track")
|
||||
.WithMany("Coauthors")
|
||||
.HasForeignKey("TrackId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Musify.Domain.Entities.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Track");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.TrackLike", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.Track", "Track")
|
||||
@@ -1068,6 +1118,8 @@ namespace Musify.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
b.Navigation("AlbumTracks");
|
||||
|
||||
b.Navigation("Coauthors");
|
||||
|
||||
b.Navigation("ListeningHistories");
|
||||
|
||||
b.Navigation("PlayListTracks");
|
||||
|
||||
@@ -122,6 +122,25 @@ namespace Musify.Infrastructure.Persistence
|
||||
.HasIndex(trackTag => new { trackTag.TrackId, trackTag.Tag })
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<TrackCoauthor>()
|
||||
.HasOne(coauthor => coauthor.Track)
|
||||
.WithMany(track => track.Coauthors)
|
||||
.HasForeignKey(coauthor => coauthor.TrackId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<TrackCoauthor>()
|
||||
.HasOne(coauthor => coauthor.User)
|
||||
.WithMany()
|
||||
.HasForeignKey(coauthor => coauthor.UserId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<TrackCoauthor>()
|
||||
.HasIndex(coauthor => new { coauthor.TrackId, coauthor.UserId })
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<TrackCoauthor>()
|
||||
.HasIndex(coauthor => new { coauthor.UserId, coauthor.Status });
|
||||
|
||||
modelBuilder.Entity<UserFollow>()
|
||||
.HasOne(follow => follow.Follower)
|
||||
.WithMany()
|
||||
|
||||
Reference in New Issue
Block a user