Changes
This commit is contained in:
@@ -60,11 +60,7 @@
|
||||
"OriginalPicturesFolder": "OriginalPictures",
|
||||
"SmallPicturesFolder": "SmallPictures",
|
||||
"MediumPicturesFolder": "MediumPictures",
|
||||
"LargePicturesFolder": "LargePictures",
|
||||
"PresetOriginalPicture": "PresetOriginalPicture.webp",
|
||||
"PresetSmallPicture": "PresetSmallPicture.webp",
|
||||
"PresetMediumPicture": "PresetMediumPicture.webp",
|
||||
"PresetLargePicture": "PresetLargePicture.webp"
|
||||
"LargePicturesFolder": "LargePictures"
|
||||
},
|
||||
"PicturesSizes": {
|
||||
"SmallPictureWidth": 128,
|
||||
|
||||
@@ -34,30 +34,12 @@ namespace Musify.Application.Configuration
|
||||
[Required]
|
||||
public string LargePicturesFolder { get; set; } = "LargePictures";
|
||||
|
||||
[Required]
|
||||
public string PresetOriginalPicture { get; set; } = "PresetOriginalPicture.webp";
|
||||
|
||||
[Required]
|
||||
public string PresetSmallPicture { get; set; } = "PresetSmallPicture.webp";
|
||||
|
||||
[Required]
|
||||
public string PresetMediumPicture { get; set; } = "PresetMediumPicture.webp";
|
||||
|
||||
[Required]
|
||||
public string PresetLargePicture { get; set; } = "PresetLargePicture.webp";
|
||||
|
||||
public string SmallPicturesPath => StorageKey.Combine(ParentFolders, SmallPicturesFolder);
|
||||
|
||||
public string MediumPicturesPath => StorageKey.Combine(ParentFolders, MediumPicturesFolder);
|
||||
|
||||
public string LargePicturesPath => StorageKey.Combine(ParentFolders, LargePicturesFolder);
|
||||
|
||||
public string PresetSmallPicturePath => StorageKey.Combine(ParentFolders, PresetSmallPicture);
|
||||
|
||||
public string PresetMediumPicturePath => StorageKey.Combine(ParentFolders, PresetMediumPicture);
|
||||
|
||||
public string PresetLargePicturePath => StorageKey.Combine(ParentFolders, PresetLargePicture);
|
||||
|
||||
public string OriginalPicturesPath => StorageKey.Combine(ParentFolders, OriginalPicturesFolder);
|
||||
|
||||
public string BuildOriginalPicturePath(string pictureName) => StorageKey.Combine(ParentFolders, OriginalPicturesFolder, pictureName);
|
||||
|
||||
@@ -11,6 +11,10 @@ namespace Musify.Application.Contracts
|
||||
|
||||
DbSet<Track> Tracks { get; }
|
||||
|
||||
DbSet<LocalTrack> LocalTracks { get; }
|
||||
|
||||
DbSet<ExternalTrack> ExternalTracks { get; }
|
||||
|
||||
DbSet<Artist> Artists { get; }
|
||||
|
||||
DbSet<TrackArtist> TrackArtists { get; }
|
||||
|
||||
@@ -42,8 +42,6 @@ namespace Musify.Application.PlayLists
|
||||
}
|
||||
|
||||
UploadIntent? pictureIntent = null;
|
||||
string originalPictureName;
|
||||
|
||||
if (request.PictureIntentId.HasValue)
|
||||
{
|
||||
var validation = await uploadIntentValidator.ValidateAndLoadAsync(
|
||||
@@ -53,11 +51,6 @@ namespace Musify.Application.PlayLists
|
||||
return validation.Errors;
|
||||
|
||||
pictureIntent = validation.Value;
|
||||
originalPictureName = pictureIntent.ObjectName;
|
||||
}
|
||||
else
|
||||
{
|
||||
originalPictureName = playListConfiguration.Routes.PresetOriginalPicture;
|
||||
}
|
||||
|
||||
var playList = new PlayList
|
||||
@@ -66,20 +59,15 @@ namespace Musify.Application.PlayLists
|
||||
Name = request.Name,
|
||||
NormalizedName = request.Name.Trim().ToUpperInvariant(),
|
||||
Description = request.Description,
|
||||
Pictures = new PlayListPictures
|
||||
{
|
||||
OriginalName = originalPictureName,
|
||||
SmallName = playListConfiguration.Routes.PresetSmallPicture,
|
||||
MediumName = playListConfiguration.Routes.PresetMediumPicture,
|
||||
LargeName = playListConfiguration.Routes.PresetLargePicture
|
||||
}
|
||||
Pictures = pictureIntent == null ? null
|
||||
: new PlayListPictures { OriginalName = pictureIntent.ObjectName }
|
||||
};
|
||||
|
||||
await database.PlayLists.AddAsync(playList, cancellationToken);
|
||||
|
||||
if (pictureIntent is not null)
|
||||
if (pictureIntent != null)
|
||||
{
|
||||
var finalPictureKey = playListConfiguration.Routes.BuildOriginalPicturePath(request.UserId, originalPictureName);
|
||||
var finalPictureKey = playListConfiguration.Routes.BuildOriginalPicturePath(request.UserId, pictureIntent.ObjectName);
|
||||
var publishResult = await PublishCreatePlayListEventAsync(
|
||||
playList.Id, pictureIntent, finalPictureKey, cancellationToken);
|
||||
if (publishResult.IsError)
|
||||
|
||||
@@ -20,23 +20,23 @@ namespace Musify.Application.PlayLists
|
||||
{
|
||||
public async ValueTask<ErrorOr<PlayListCoverLocation>> Handle(GetPlayListCoverQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var playList = await database.PlayLists.AsNoTracking()
|
||||
var pictures = await database.PlayLists.AsNoTracking()
|
||||
.Where(p => p.Id == request.PlayListId)
|
||||
.Select(p => new { p.Pictures.SmallName, p.Pictures.MediumName, p.Pictures.LargeName })
|
||||
.Select(p => p.Pictures)
|
||||
.SingleOrDefaultAsync(cancellationToken);
|
||||
|
||||
if (playList == null)
|
||||
if (pictures is null)
|
||||
return Error.NotFound();
|
||||
|
||||
var routes = playListConfiguration.Routes;
|
||||
var (name, key, presetName) = request.Size.ToLowerInvariant() switch
|
||||
var (name, key) = request.Size.ToLowerInvariant() switch
|
||||
{
|
||||
"small" => (playList.SmallName, BuildKey(routes.BuildSmallPicturePath, playList.SmallName), routes.PresetSmallPicture),
|
||||
"large" => (playList.LargeName, BuildKey(routes.BuildLargePicturePath, playList.LargeName), routes.PresetLargePicture),
|
||||
_ => (playList.MediumName, BuildKey(routes.BuildMediumPicturePath, playList.MediumName), routes.PresetMediumPicture)
|
||||
"small" => (pictures.SmallName, BuildKey(routes.BuildSmallPicturePath, pictures.SmallName)),
|
||||
"large" => (pictures.LargeName, BuildKey(routes.BuildLargePicturePath, pictures.LargeName)),
|
||||
_ => (pictures.MediumName, BuildKey(routes.BuildMediumPicturePath, pictures.MediumName))
|
||||
};
|
||||
|
||||
if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(key) || name == presetName)
|
||||
if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(key))
|
||||
return Error.NotFound();
|
||||
|
||||
var contentType = MimeUtility.GetMimeMapping(name);
|
||||
|
||||
@@ -4,6 +4,7 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Musify.Application.Contracts;
|
||||
using Musify.Application.Shared;
|
||||
using Musify.Application.Tracks.Responses;
|
||||
using Musify.Domain.Entities;
|
||||
using X.PagedList;
|
||||
using X.PagedList.EF;
|
||||
|
||||
@@ -28,9 +29,9 @@ namespace Musify.Application.PlayLists
|
||||
|
||||
var tracksQuery = database.PlayListHasTracks
|
||||
.AsNoTracking()
|
||||
.Include(plt => plt.Track)
|
||||
.ThenInclude(track => track.TrackArtists)
|
||||
.Include(plt => ((ExternalTrack)plt.Track).TrackArtists)
|
||||
.ThenInclude(trackArtist => trackArtist.Artist)
|
||||
.Include(plt => ((LocalTrack)plt.Track).Owner)
|
||||
.Where(plt => plt.PlayListId == request.PlayListId);
|
||||
|
||||
var totalCount = await tracksQuery.CountAsync(cancellationToken);
|
||||
|
||||
@@ -5,10 +5,10 @@ namespace Musify.Application.PlayLists.Responses
|
||||
public record PlayListApplicationResponse(
|
||||
Guid Id,
|
||||
string Name,
|
||||
string Description,
|
||||
string SmallImageKeyName,
|
||||
string MediumImageKeyName,
|
||||
string LargeImageKeyName,
|
||||
string? Description,
|
||||
string? SmallImageKeyName,
|
||||
string? MediumImageKeyName,
|
||||
string? LargeImageKeyName,
|
||||
DateTime CreatedAt,
|
||||
DateTime UpdatedAt)
|
||||
{
|
||||
@@ -18,9 +18,9 @@ namespace Musify.Application.PlayLists.Responses
|
||||
playList.Id,
|
||||
playList.Name,
|
||||
playList.Description,
|
||||
playList.Pictures.SmallName,
|
||||
playList.Pictures.MediumName,
|
||||
playList.Pictures.LargeName,
|
||||
playList.Pictures?.SmallName,
|
||||
playList.Pictures?.MediumName,
|
||||
playList.Pictures?.LargeName,
|
||||
playList.CreatedAt,
|
||||
playList.UpdatedAt);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ using Musify.Application.Events;
|
||||
using Musify.Application.PlayLists.Responses;
|
||||
using Musify.Application.Services;
|
||||
using Musify.Domain.Entities;
|
||||
using Musify.Domain.ValueObjects;
|
||||
using Musify.Application.Contracts;
|
||||
|
||||
namespace Musify.Application.PlayLists
|
||||
@@ -68,7 +69,7 @@ namespace Musify.Application.PlayLists
|
||||
return validation.Errors;
|
||||
|
||||
pictureIntent = validation.Value;
|
||||
playListEntity.Pictures.OriginalName = pictureIntent.ObjectName;
|
||||
playListEntity.Pictures = new PlayListPictures { OriginalName = pictureIntent.ObjectName };
|
||||
finalPictureKey = playListConfiguration.Routes.BuildOriginalPicturePath(request.UserId, pictureIntent.ObjectName);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ using Musify.Domain.ValueObjects;
|
||||
|
||||
namespace Musify.Application.Services;
|
||||
|
||||
public sealed record YouTubeTrackProvision(Track Track, YouTubeSongResult? Song);
|
||||
public sealed record YouTubeTrackProvision(ExternalTrack Track, YouTubeSongResult? Song);
|
||||
|
||||
public sealed class YouTubeTrackProvisioner(
|
||||
IDatabase database,
|
||||
@@ -16,8 +16,8 @@ public sealed class YouTubeTrackProvisioner(
|
||||
TrackConfiguration trackConfiguration,
|
||||
ILogger<YouTubeTrackProvisioner> logger)
|
||||
{
|
||||
public Task<Track?> FindAsync(string videoId, CancellationToken cancellationToken) =>
|
||||
database.Tracks
|
||||
public Task<ExternalTrack?> FindAsync(string videoId, CancellationToken cancellationToken) =>
|
||||
database.ExternalTracks
|
||||
.Include(track => track.TrackArtists)
|
||||
.ThenInclude(trackArtist => trackArtist.Artist)
|
||||
.SingleOrDefaultAsync(t => t.Source == TrackSource.YouTube && t.ExternalId == videoId, cancellationToken);
|
||||
@@ -44,7 +44,7 @@ public sealed class YouTubeTrackProvisioner(
|
||||
artists.Add(await GetOrCreateArtistAsync(artistRef, cancellationToken));
|
||||
|
||||
var title = Truncate(song.Title, 50);
|
||||
var track = new Track
|
||||
var track = new ExternalTrack
|
||||
{
|
||||
Title = title,
|
||||
NormalizedTitle = title.ToUpperInvariant(),
|
||||
@@ -65,7 +65,7 @@ public sealed class YouTubeTrackProvisioner(
|
||||
}
|
||||
};
|
||||
|
||||
await database.Tracks.AddAsync(track, cancellationToken);
|
||||
await database.ExternalTracks.AddAsync(track, cancellationToken);
|
||||
|
||||
for (var position = 0; position < artists.Count; position++)
|
||||
{
|
||||
@@ -85,7 +85,7 @@ public sealed class YouTubeTrackProvisioner(
|
||||
}
|
||||
catch (DbUpdateException)
|
||||
{
|
||||
database.Tracks.Remove(track);
|
||||
database.ExternalTracks.Remove(track);
|
||||
var refetched = await FindAsync(videoId, cancellationToken);
|
||||
if (refetched is null)
|
||||
{
|
||||
@@ -100,43 +100,17 @@ public sealed class YouTubeTrackProvisioner(
|
||||
{
|
||||
var name = Truncate(reference.Name, 200);
|
||||
var normalized = name.ToUpperInvariant();
|
||||
var byExternalId = !string.IsNullOrEmpty(reference.Id);
|
||||
var externalId = reference.Id ?? $"name:{normalized}";
|
||||
|
||||
var existing = byExternalId
|
||||
? await database.Artists.SingleOrDefaultAsync(a => a.ExternalId == reference.Id, cancellationToken)
|
||||
: await database.Artists.SingleOrDefaultAsync(a => a.ExternalId == null && a.UserId == null && a.NormalizedName == normalized, cancellationToken);
|
||||
var existing = await database.Artists.SingleOrDefaultAsync(a => a.ExternalId == externalId, cancellationToken);
|
||||
if (existing is not null)
|
||||
return existing;
|
||||
|
||||
if (byExternalId)
|
||||
{
|
||||
var adoptable = await database.Artists
|
||||
.SingleOrDefaultAsync(a => a.ExternalId == null && a.UserId == null && a.NormalizedName == normalized, cancellationToken);
|
||||
if (adoptable is not null)
|
||||
{
|
||||
var previousName = adoptable.Name;
|
||||
adoptable.ExternalId = reference.Id;
|
||||
adoptable.Name = name;
|
||||
|
||||
try
|
||||
{
|
||||
await database.SaveChangesAsync(cancellationToken);
|
||||
return adoptable;
|
||||
}
|
||||
catch (DbUpdateException)
|
||||
{
|
||||
adoptable.ExternalId = null;
|
||||
adoptable.Name = previousName;
|
||||
return await database.Artists.SingleAsync(a => a.ExternalId == reference.Id, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var artist = new Artist
|
||||
{
|
||||
Name = name,
|
||||
NormalizedName = normalized,
|
||||
ExternalId = byExternalId ? reference.Id : null
|
||||
ExternalId = externalId
|
||||
};
|
||||
|
||||
await database.Artists.AddAsync(artist, cancellationToken);
|
||||
@@ -149,9 +123,7 @@ public sealed class YouTubeTrackProvisioner(
|
||||
catch (DbUpdateException)
|
||||
{
|
||||
database.Artists.Remove(artist);
|
||||
return byExternalId
|
||||
? await database.Artists.SingleAsync(a => a.ExternalId == reference.Id, cancellationToken)
|
||||
: await database.Artists.SingleAsync(a => a.ExternalId == null && a.UserId == null && a.NormalizedName == normalized, cancellationToken);
|
||||
return await database.Artists.SingleAsync(a => a.ExternalId == externalId, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Musify.Application.Tracks
|
||||
{
|
||||
public async ValueTask<ErrorOr<TrackApplicationResponse>> Handle(CreateTrackCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var user = await database.Users.AsNoTracking()
|
||||
var user = await database.Users
|
||||
.SingleOrDefaultAsync(u => u.Id == request.UserId, cancellationToken);
|
||||
if (user is null)
|
||||
{
|
||||
@@ -59,13 +59,12 @@ namespace Musify.Application.Tracks
|
||||
var finalAudioKey = trackConfiguration.Routes.BuildOriginalAudioPath(request.UserId, audioIntent.ObjectName);
|
||||
var audioProcessedFolderKey = trackConfiguration.Routes.BuildProcessedAudioPath(Guid.NewGuid().ToString());
|
||||
|
||||
var artist = await GetOrCreateUserArtistAsync(user, cancellationToken);
|
||||
|
||||
var trackEntity = new Track
|
||||
var trackEntity = new LocalTrack
|
||||
{
|
||||
Title = request.Title,
|
||||
NormalizedTitle = request.Title.ToUpperInvariant(),
|
||||
OwnerUserId = user.Id,
|
||||
Owner = user,
|
||||
Pictures = new TrackPictures
|
||||
{
|
||||
OriginalName = pictureIntent.ObjectName,
|
||||
@@ -81,14 +80,7 @@ namespace Musify.Application.Tracks
|
||||
}
|
||||
};
|
||||
|
||||
await database.Tracks.AddAsync(trackEntity, cancellationToken);
|
||||
|
||||
await database.TrackArtists.AddAsync(new TrackArtist
|
||||
{
|
||||
TrackId = trackEntity.Id,
|
||||
ArtistId = artist.Id,
|
||||
Position = 0
|
||||
}, cancellationToken);
|
||||
await database.LocalTracks.AddAsync(trackEntity, cancellationToken);
|
||||
|
||||
await database.UserHasTracks.AddAsync(new UserHasTrack
|
||||
{
|
||||
@@ -141,32 +133,5 @@ namespace Musify.Application.Tracks
|
||||
|
||||
return TrackApplicationResponse.FromEntity(trackEntity, listensCount: 0);
|
||||
}
|
||||
|
||||
private async Task<Artist> GetOrCreateUserArtistAsync(User user, CancellationToken cancellationToken)
|
||||
{
|
||||
var existing = await database.Artists.SingleOrDefaultAsync(a => a.UserId == user.Id, cancellationToken);
|
||||
if (existing is not null)
|
||||
return existing;
|
||||
|
||||
var artist = new Artist
|
||||
{
|
||||
Name = user.Name,
|
||||
NormalizedName = user.NormalizedName,
|
||||
UserId = user.Id
|
||||
};
|
||||
|
||||
await database.Artists.AddAsync(artist, cancellationToken);
|
||||
|
||||
try
|
||||
{
|
||||
await database.SaveChangesAsync(cancellationToken);
|
||||
return artist;
|
||||
}
|
||||
catch (DbUpdateException)
|
||||
{
|
||||
database.Artists.Remove(artist);
|
||||
return await database.Artists.SingleAsync(a => a.UserId == user.Id, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using ErrorOr;
|
||||
using Mediator;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Musify.Domain.Entities;
|
||||
using Musify.Domain.ValueObjects;
|
||||
using Musify.Application.Events;
|
||||
using Musify.Application.Contracts;
|
||||
@@ -28,7 +29,7 @@ namespace Musify.Application.Tracks
|
||||
return Error.NotFound();
|
||||
}
|
||||
|
||||
if (track.OwnerUserId != request.UserId)
|
||||
if (track is not LocalTrack localTrack || localTrack.OwnerUserId != request.UserId)
|
||||
{
|
||||
logger.LogWarning("User {UserId} unauthorized to delete track {TrackId}", request.UserId, request.TrackId);
|
||||
return Error.Unauthorized();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Musify.Application.Contracts;
|
||||
using Musify.Application.Tracks.Responses;
|
||||
using Musify.Domain.Entities;
|
||||
|
||||
namespace Musify.Application.Tracks
|
||||
{
|
||||
@@ -24,8 +25,9 @@ namespace Musify.Application.Tracks
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var tracksById = await database.Tracks
|
||||
.Include(t => t.TrackArtists)
|
||||
.Include(t => ((ExternalTrack)t).TrackArtists)
|
||||
.ThenInclude(trackArtist => trackArtist.Artist)
|
||||
.Include(t => ((LocalTrack)t).Owner)
|
||||
.Where(t => recentTrackIds.Contains(t.Id))
|
||||
.Select(t => new { t.Id, Track = t, ListensCount = t.ListeningHistories.Count } )
|
||||
.ToDictionaryAsync(t => t.Id, cancellationToken);
|
||||
|
||||
@@ -3,6 +3,7 @@ using Mediator;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Musify.Application.Contracts;
|
||||
using Musify.Application.Tracks.Responses;
|
||||
using Musify.Domain.Entities;
|
||||
|
||||
namespace Musify.Application.Tracks
|
||||
{
|
||||
@@ -15,8 +16,9 @@ namespace Musify.Application.Tracks
|
||||
public async ValueTask<ErrorOr<TrackApplicationResponse>> Handle(GetTrackByIdQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await database.Tracks.AsNoTracking()
|
||||
.Include(t => t.TrackArtists)
|
||||
.Include(t => ((ExternalTrack)t).TrackArtists)
|
||||
.ThenInclude(trackArtist => trackArtist.Artist)
|
||||
.Include(t => ((LocalTrack)t).Owner)
|
||||
.Where(t => t.Id == request.TrackId)
|
||||
.Select(t => new { Track = t, ListensCount = t.ListeningHistories.Count })
|
||||
.SingleOrDefaultAsync(cancellationToken);
|
||||
|
||||
@@ -6,6 +6,7 @@ using Musify.Application.Tracks.Responses;
|
||||
using X.PagedList;
|
||||
using X.PagedList.EF;
|
||||
using Musify.Application.Contracts;
|
||||
using Musify.Domain.Entities;
|
||||
|
||||
namespace Musify.Application.Tracks
|
||||
{
|
||||
@@ -19,9 +20,9 @@ namespace Musify.Application.Tracks
|
||||
{
|
||||
var tracksQuery = database.UserHasTracks
|
||||
.AsNoTracking()
|
||||
.Include(ut => ut.Track)
|
||||
.ThenInclude(track => track.TrackArtists)
|
||||
.Include(ut => ((ExternalTrack)ut.Track).TrackArtists)
|
||||
.ThenInclude(trackArtist => trackArtist.Artist)
|
||||
.Include(ut => ((LocalTrack)ut.Track).Owner)
|
||||
.AsQueryable();
|
||||
|
||||
if (!string.IsNullOrEmpty(request.Name))
|
||||
|
||||
@@ -6,6 +6,7 @@ using Musify.Application.Tracks.Responses;
|
||||
using X.PagedList;
|
||||
using X.PagedList.EF;
|
||||
using Musify.Application.Contracts;
|
||||
using Musify.Domain.Entities;
|
||||
|
||||
namespace Musify.Application.Tracks
|
||||
{
|
||||
@@ -26,9 +27,9 @@ namespace Musify.Application.Tracks
|
||||
|
||||
var tracksQuery = database.UserHasTracks
|
||||
.AsNoTracking()
|
||||
.Include(ut => ut.Track)
|
||||
.ThenInclude(track => track.TrackArtists)
|
||||
.Include(ut => ((ExternalTrack)ut.Track).TrackArtists)
|
||||
.ThenInclude(trackArtist => trackArtist.Artist)
|
||||
.Include(ut => ((LocalTrack)ut.Track).Owner)
|
||||
.Where(p => p.UserId == request.UserId);
|
||||
|
||||
if (!string.IsNullOrEmpty(request.Name))
|
||||
|
||||
@@ -22,23 +22,23 @@ namespace Musify.Application.Tracks.Responses
|
||||
track.Id,
|
||||
track.Title,
|
||||
FormatArtist(track),
|
||||
track.Source,
|
||||
track.ExternalId,
|
||||
track is ExternalTrack external ? external.Source : TrackSource.Local,
|
||||
(track as ExternalTrack)?.ExternalId,
|
||||
track.Audio.TranscodeStatus,
|
||||
track.DurationSeconds,
|
||||
listensCount,
|
||||
track.OwnerUserId,
|
||||
(track as LocalTrack)?.OwnerUserId,
|
||||
track.CreatedAt,
|
||||
track.UpdatedAt);
|
||||
|
||||
private static string? FormatArtist(Track track)
|
||||
private static string? FormatArtist(Track track) => track switch
|
||||
{
|
||||
if (track.TrackArtists.Count == 0)
|
||||
return null;
|
||||
|
||||
return string.Join(", ", track.TrackArtists
|
||||
.OrderBy(trackArtist => trackArtist.Position)
|
||||
.Select(trackArtist => trackArtist.Artist.Name));
|
||||
}
|
||||
LocalTrack local => local.Owner.Name,
|
||||
ExternalTrack { TrackArtists.Count: > 0 } external =>
|
||||
string.Join(", ", external.TrackArtists
|
||||
.OrderBy(trackArtist => trackArtist.Position)
|
||||
.Select(trackArtist => trackArtist.Artist.Name)),
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,14 +47,6 @@ namespace Musify.Application.Users
|
||||
user.SecondName = request.SecondName;
|
||||
user.ProfilePictureUrl = request.ProfilePictureUrl;
|
||||
|
||||
var artist = await database.Artists
|
||||
.SingleOrDefaultAsync(a => a.UserId == request.Id, cancellationToken);
|
||||
if (artist is not null)
|
||||
{
|
||||
artist.Name = request.Name;
|
||||
artist.NormalizedName = request.Name.ToUpperInvariant();
|
||||
}
|
||||
|
||||
var written = await database.SaveChangesAsync(cancellationToken);
|
||||
if (written > 0)
|
||||
logger.LogInformation("Synced profile for user {UserId}", request.Id);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Musify.Domain.Abstractions;
|
||||
|
||||
namespace Musify.Domain.Entities
|
||||
@@ -18,10 +17,9 @@ namespace Musify.Domain.Entities
|
||||
[MaxLength(200)]
|
||||
public required string NormalizedName { get; set; }
|
||||
|
||||
public long? UserId { get; set; }
|
||||
|
||||
[Required]
|
||||
[MaxLength(64)]
|
||||
public string? ExternalId { get; set; }
|
||||
public required string ExternalId { get; set; }
|
||||
|
||||
[Required]
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
@@ -29,9 +27,6 @@ namespace Musify.Domain.Entities
|
||||
[Required]
|
||||
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
|
||||
|
||||
[ForeignKey(nameof(UserId)) ]
|
||||
public User? User { get; set; }
|
||||
|
||||
public ICollection<TrackArtist> TrackArtists { get; set; } = new List<TrackArtist>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Musify.Domain.ValueObjects;
|
||||
|
||||
namespace Musify.Domain.Entities
|
||||
{
|
||||
public class ExternalTrack : Track
|
||||
{
|
||||
[Required]
|
||||
public required TrackSource Source { get; set; }
|
||||
|
||||
[Required]
|
||||
[MaxLength(64)]
|
||||
public required string ExternalId { get; set; }
|
||||
|
||||
public ICollection<TrackArtist> TrackArtists { get; set; } = new List<TrackArtist>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Musify.Domain.Entities
|
||||
{
|
||||
public class LocalTrack : Track
|
||||
{
|
||||
[Required]
|
||||
public required long OwnerUserId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(OwnerUserId)) ]
|
||||
public required User Owner { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -26,9 +26,9 @@ namespace Musify.Domain.Entities
|
||||
|
||||
[Required]
|
||||
[MaxLength(256)]
|
||||
public string Description { get; set; } = "No description was provided.";
|
||||
public string? Description { get; set; }
|
||||
|
||||
public required PlayListPictures Pictures { get; set; }
|
||||
public PlayListPictures? Pictures { get; set; }
|
||||
|
||||
[Required]
|
||||
public LifeCycleStatus LifeCycleStatus { get; set; } = LifeCycleStatus.Active;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Musify.Domain.Abstractions;
|
||||
using Musify.Domain.ValueObjects;
|
||||
|
||||
namespace Musify.Domain.Entities
|
||||
{
|
||||
#pragma warning disable CS8618
|
||||
public class Track : IAuditable
|
||||
public abstract class Track : IAuditable
|
||||
{
|
||||
[Key]
|
||||
public Guid Id { get; set; } = Guid.NewGuid();
|
||||
@@ -22,14 +21,6 @@ namespace Musify.Domain.Entities
|
||||
[Required]
|
||||
public int DurationSeconds { get; set; }
|
||||
|
||||
public long? OwnerUserId { get; set; }
|
||||
|
||||
[Required]
|
||||
public TrackSource Source { get; set; } = TrackSource.Local;
|
||||
|
||||
[MaxLength(16)]
|
||||
public string? ExternalId { get; set; }
|
||||
|
||||
[Required]
|
||||
public LifeCycleStatus LifeCycleStatus { get; set; } = LifeCycleStatus.Active;
|
||||
|
||||
@@ -43,18 +34,10 @@ namespace Musify.Domain.Entities
|
||||
|
||||
public TrackAudio Audio { get; set; } = new();
|
||||
|
||||
[ForeignKey(nameof(OwnerUserId)) ]
|
||||
public User? Owner { get; set; }
|
||||
|
||||
public ICollection<UserHasTrack> UserTracks { get; set; } = new List<UserHasTrack>();
|
||||
|
||||
public ICollection<PlayListHasTrack> PlayListTracks { get; set; } = new List<PlayListHasTrack>();
|
||||
|
||||
public ICollection<ListeningHistory> ListeningHistories { get; set; } = new List<ListeningHistory>();
|
||||
|
||||
public ICollection<TrackArtist> TrackArtists { get; set; } = new List<TrackArtist>();
|
||||
|
||||
[NotMapped]
|
||||
public bool IsExternal => Source != TrackSource.Local;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Musify.Domain.Entities
|
||||
public int Position { get; set; } = 0;
|
||||
|
||||
[ForeignKey(nameof(TrackId)) ]
|
||||
public Track Track { get; set; }
|
||||
public ExternalTrack Track { get; set; }
|
||||
|
||||
[ForeignKey(nameof(ArtistId)) ]
|
||||
public Artist Artist { get; set; }
|
||||
|
||||
@@ -2,12 +2,12 @@ namespace Musify.Domain.ValueObjects
|
||||
{
|
||||
public class PlayListPictures
|
||||
{
|
||||
public required string OriginalName { get; set; }
|
||||
public string? OriginalName { get; set; }
|
||||
|
||||
public required string SmallName { get; set; }
|
||||
public string? SmallName { get; set; }
|
||||
|
||||
public required string MediumName { get; set; }
|
||||
public string? MediumName { get; set; }
|
||||
|
||||
public required string LargeName { get; set; }
|
||||
public string? LargeName { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
+15
-4
@@ -2,6 +2,7 @@ using MassTransit;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Musify.Application.Contracts;
|
||||
using Musify.Application.Events;
|
||||
using Musify.Domain.ValueObjects;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
@@ -37,6 +38,13 @@ namespace Musify.Infrastructure.MassTransit.Activities.Pictures
|
||||
throw new InvalidOperationException($"PlayList with id {executeContext.Arguments.PlayListId} not found");
|
||||
}
|
||||
|
||||
if (playList.Pictures is null)
|
||||
{
|
||||
logger.LogWarning("Playlist {PlayListId} has no pending picture upload",
|
||||
executeContext.Arguments.PlayListId);
|
||||
throw new InvalidOperationException($"PlayList with id {executeContext.Arguments.PlayListId} has no pending picture upload");
|
||||
}
|
||||
|
||||
var log = new UpdatePlayListPictureLog(
|
||||
playList.Id,
|
||||
playList.Pictures.OriginalName,
|
||||
@@ -82,10 +90,13 @@ namespace Musify.Infrastructure.MassTransit.Activities.Pictures
|
||||
return compensateContext.Compensated();
|
||||
}
|
||||
|
||||
playList.Pictures.OriginalName = compensateContext.Log.PreviousOriginalPictureKey;
|
||||
playList.Pictures.SmallName = compensateContext.Log.PreviousSmallPictureKey;
|
||||
playList.Pictures.MediumName = compensateContext.Log.PreviousMediumPictureKey;
|
||||
playList.Pictures.LargeName = compensateContext.Log.PreviousLargePictureKey;
|
||||
playList.Pictures = new PlayListPictures
|
||||
{
|
||||
OriginalName = compensateContext.Log.PreviousOriginalPictureKey,
|
||||
SmallName = compensateContext.Log.PreviousSmallPictureKey,
|
||||
MediumName = compensateContext.Log.PreviousMediumPictureKey,
|
||||
LargeName = compensateContext.Log.PreviousLargePictureKey
|
||||
};
|
||||
|
||||
database.PlayLists.Update(playList);
|
||||
await database.SaveChangesAsync(compensateContext.CancellationToken);
|
||||
|
||||
@@ -2,8 +2,8 @@ namespace Musify.Infrastructure.MassTransit.Logs
|
||||
{
|
||||
public record UpdatePlayListPictureLog(
|
||||
Guid PlayListId,
|
||||
string PreviousOriginalPictureKey,
|
||||
string PreviousSmallPictureKey,
|
||||
string PreviousMediumPictureKey,
|
||||
string PreviousLargePictureKey);
|
||||
string? PreviousOriginalPictureKey,
|
||||
string? PreviousSmallPictureKey,
|
||||
string? PreviousMediumPictureKey,
|
||||
string? PreviousLargePictureKey);
|
||||
}
|
||||
|
||||
+9
-9
@@ -37,49 +37,49 @@ namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders
|
||||
EndpointHelper.BuildExecuteActivityUri(MarkPlayListAsRemovingActivity.ExecuteEndpointName),
|
||||
new MarkPlayListAsRemovingArguments(playListId));
|
||||
|
||||
if (playList is not null)
|
||||
if (playList?.Pictures is not null)
|
||||
{
|
||||
var bucket = storageConfiguration.Bucket;
|
||||
var routes = playListConfiguration.Routes;
|
||||
|
||||
if (playList.Pictures.OriginalName != routes.PresetOriginalPicture)
|
||||
if (playList.Pictures.OriginalName is { } originalName)
|
||||
{
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemovePlayListOriginalPicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
routes.BuildOriginalPicturePath(userId, playList.Pictures.OriginalName)));
|
||||
routes.BuildOriginalPicturePath(userId, originalName)));
|
||||
}
|
||||
|
||||
if (playList.Pictures.SmallName != routes.PresetSmallPicture)
|
||||
if (playList.Pictures.SmallName is { } smallName)
|
||||
{
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemovePlayListSmallPicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
routes.BuildSmallPicturePath(playList.Pictures.SmallName)));
|
||||
routes.BuildSmallPicturePath(smallName)));
|
||||
}
|
||||
|
||||
if (playList.Pictures.MediumName != routes.PresetMediumPicture)
|
||||
if (playList.Pictures.MediumName is { } mediumName)
|
||||
{
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemovePlayListMediumPicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
routes.BuildMediumPicturePath(playList.Pictures.MediumName)));
|
||||
routes.BuildMediumPicturePath(mediumName)));
|
||||
}
|
||||
|
||||
if (playList.Pictures.LargeName != routes.PresetLargePicture)
|
||||
if (playList.Pictures.LargeName is { } largeName)
|
||||
{
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemovePlayListLargePicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
routes.BuildLargePicturePath(playList.Pictures.LargeName)));
|
||||
routes.BuildLargePicturePath(largeName)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,21 +30,6 @@ namespace Musify.Infrastructure.Persistence
|
||||
trackProcessing.Property(state => state.CorrelationId).ValueGeneratedNever();
|
||||
trackProcessing.Property(state => state.CurrentState).HasMaxLength(64);
|
||||
|
||||
modelBuilder.Entity<Track>()
|
||||
.HasIndex(track => new { track.Source, track.ExternalId })
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<Track>()
|
||||
.HasOne(track => track.Owner)
|
||||
.WithMany()
|
||||
.HasForeignKey(track => track.OwnerUserId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<Track>()
|
||||
.ToTable(t => t.HasCheckConstraint(
|
||||
"CK_Tracks_OwnerUserId_Source",
|
||||
"(\"OwnerUserId\" IS NOT NULL) = (\"Source\" = 0)"));
|
||||
|
||||
modelBuilder.Entity<Track>()
|
||||
.OwnsOne(track => track.Pictures, pictures =>
|
||||
{
|
||||
@@ -68,6 +53,22 @@ namespace Musify.Infrastructure.Persistence
|
||||
});
|
||||
modelBuilder.Entity<Track>().Navigation(track => track.Audio).IsRequired();
|
||||
|
||||
modelBuilder.Entity<LocalTrack>()
|
||||
.ToTable("LocalTracks");
|
||||
|
||||
modelBuilder.Entity<LocalTrack>()
|
||||
.HasOne(track => track.Owner)
|
||||
.WithMany()
|
||||
.HasForeignKey(track => track.OwnerUserId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<ExternalTrack>()
|
||||
.ToTable("ExternalTracks");
|
||||
|
||||
modelBuilder.Entity<ExternalTrack>()
|
||||
.HasIndex(track => new { track.Source, track.ExternalId })
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<TrackArtist>()
|
||||
.HasKey(trackArtist => new { trackArtist.TrackId, trackArtist.ArtistId });
|
||||
|
||||
@@ -83,19 +84,10 @@ namespace Musify.Infrastructure.Persistence
|
||||
.HasForeignKey(trackArtist => trackArtist.ArtistId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<Artist>()
|
||||
.HasIndex(artist => artist.UserId)
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<Artist>()
|
||||
.HasIndex(artist => artist.ExternalId)
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<Artist>()
|
||||
.HasIndex(artist => artist.NormalizedName)
|
||||
.IsUnique()
|
||||
.HasFilter("\"ExternalId\" IS NULL AND \"UserId\" IS NULL");
|
||||
|
||||
modelBuilder.Entity<PlayList>()
|
||||
.OwnsOne(playList => playList.Pictures, pictures =>
|
||||
{
|
||||
@@ -104,7 +96,7 @@ namespace Musify.Infrastructure.Persistence
|
||||
pictures.Property(p => p.MediumName).HasColumnName("MediumPictureName").HasMaxLength(64);
|
||||
pictures.Property(p => p.LargeName).HasColumnName("LargePictureName").HasMaxLength(64);
|
||||
});
|
||||
modelBuilder.Entity<PlayList>().Navigation(playList => playList.Pictures).IsRequired();
|
||||
modelBuilder.Entity<PlayList>().Navigation(playList => playList.Pictures).IsRequired(false);
|
||||
|
||||
var playListProcessing = modelBuilder.Entity<PlayListProcessingState>();
|
||||
playListProcessing.HasKey(state => state.CorrelationId);
|
||||
@@ -116,6 +108,10 @@ namespace Musify.Infrastructure.Persistence
|
||||
|
||||
public DbSet<Track> Tracks => Set<Track>();
|
||||
|
||||
public DbSet<LocalTrack> LocalTracks => Set<LocalTrack>();
|
||||
|
||||
public DbSet<ExternalTrack> ExternalTracks => Set<ExternalTrack>();
|
||||
|
||||
public DbSet<Artist> Artists => Set<Artist>();
|
||||
|
||||
public DbSet<TrackArtist> TrackArtists => Set<TrackArtist>();
|
||||
|
||||
+903
@@ -0,0 +1,903 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Musify.Infrastructure.Persistence;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Musify.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
[DbContext(typeof(Database))]
|
||||
[Migration("20260717172507_SplitTrackIntoLocalAndExternal")]
|
||||
partial class SplitTrackIntoLocalAndExternal
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "10.0.8")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.InboxState", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<DateTime?>("Consumed")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("ConsumerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime?>("Delivered")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTime?>("ExpirationTime")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<long?>("LastSequenceNumber")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<Guid>("LockId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("MessageId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("ReceiveCount")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTime>("Received")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<byte[]>("RowVersion")
|
||||
.IsConcurrencyToken()
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Delivered");
|
||||
|
||||
b.ToTable("InboxState");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxMessage", b =>
|
||||
{
|
||||
b.Property<long>("SequenceNumber")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("SequenceNumber"));
|
||||
|
||||
b.Property<string>("Body")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ContentType")
|
||||
.IsRequired()
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
||||
b.Property<Guid?>("ConversationId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("CorrelationId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("DestinationAddress")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
||||
b.Property<DateTime?>("EnqueueTime")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTime?>("ExpirationTime")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("FaultAddress")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
||||
b.Property<string>("Headers")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("InboxConsumerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("InboxMessageId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("InitiatorId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("MessageId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("MessageType")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("OutboxId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Properties")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("RequestId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("ResponseAddress")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
||||
b.Property<DateTime>("SentTime")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("SourceAddress")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
||||
b.HasKey("SequenceNumber");
|
||||
|
||||
b.HasIndex("EnqueueTime");
|
||||
|
||||
b.HasIndex("ExpirationTime");
|
||||
|
||||
b.HasIndex("OutboxId", "SequenceNumber")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("InboxMessageId", "InboxConsumerId", "SequenceNumber")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("OutboxMessage");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxState", b =>
|
||||
{
|
||||
b.Property<Guid>("OutboxId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("Created")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTime?>("Delivered")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<long?>("LastSequenceNumber")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<Guid>("LockId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte[]>("RowVersion")
|
||||
.IsConcurrencyToken()
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.HasKey("OutboxId");
|
||||
|
||||
b.HasIndex("Created");
|
||||
|
||||
b.ToTable("OutboxState");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.Artist", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("ExternalId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ExternalId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Artists");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.ListeningHistory", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("ListenedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("TrackId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<long>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("TrackId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("ListeningHistory");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.PlayList", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
||||
b.Property<int>("LifeCycleStatus")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<long>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("PlayLists");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.PlayListHasTrack", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("AddedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("PlayListId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Position")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<Guid>("TrackId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PlayListId");
|
||||
|
||||
b.HasIndex("TrackId");
|
||||
|
||||
b.ToTable("PlayListHasTrack");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.Track", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<int>("DurationSeconds")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("LifeCycleStatus")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("NormalizedTitle")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Tracks");
|
||||
|
||||
b.UseTptMappingStrategy();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.TrackArtist", b =>
|
||||
{
|
||||
b.Property<Guid>("TrackId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("ArtistId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Position")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("TrackId", "ArtistId");
|
||||
|
||||
b.HasIndex("ArtistId");
|
||||
|
||||
b.ToTable("TrackArtist");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.Upload", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Bucket")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ContentType")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("CreatedTime")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("State")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Upload");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.UploadIntent", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Bucket")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
|
||||
b.Property<string>("ContentType")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<long?>("ExpectedSizeBytes")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<DateTime>("ExpiresAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)");
|
||||
|
||||
b.Property<string>("ObjectName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
|
||||
b.Property<int>("Purpose")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<long>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("UploadIntents");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.User", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("FirstName")
|
||||
.HasMaxLength(48)
|
||||
.HasColumnType("character varying(48)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(48)
|
||||
.HasColumnType("character varying(48)");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(48)
|
||||
.HasColumnType("character varying(48)");
|
||||
|
||||
b.Property<string>("ProfilePictureUrl")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)");
|
||||
|
||||
b.Property<string>("SecondName")
|
||||
.HasMaxLength(48)
|
||||
.HasColumnType("character varying(48)");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.UserHasTrack", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("TrackId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<long>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("TrackId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("UserHasTrack");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Infrastructure.MassTransit.Sagas.PlayListProcessingState", b =>
|
||||
{
|
||||
b.Property<Guid>("CorrelationId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Bucket")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("CurrentState")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<string>("PictureKey")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("CorrelationId");
|
||||
|
||||
b.ToTable("PlayListProcessingState");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Infrastructure.MassTransit.Sagas.TrackProcessingState", b =>
|
||||
{
|
||||
b.Property<Guid>("CorrelationId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("AudioKey")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<bool>("AudioProcessed")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("Bucket")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("CurrentState")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<string>("PictureKey")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<bool>("PictureProcessed")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("CorrelationId");
|
||||
|
||||
b.ToTable("TrackProcessingState");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.ExternalTrack", b =>
|
||||
{
|
||||
b.HasBaseType("Musify.Domain.Entities.Track");
|
||||
|
||||
b.Property<string>("ExternalId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<int>("Source")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasIndex("Source", "ExternalId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("ExternalTracks", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.LocalTrack", b =>
|
||||
{
|
||||
b.HasBaseType("Musify.Domain.Entities.Track");
|
||||
|
||||
b.Property<long>("OwnerUserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasIndex("OwnerUserId");
|
||||
|
||||
b.ToTable("LocalTracks", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxMessage", b =>
|
||||
{
|
||||
b.HasOne("MassTransit.EntityFrameworkCoreIntegration.OutboxState", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("OutboxId");
|
||||
|
||||
b.HasOne("MassTransit.EntityFrameworkCoreIntegration.InboxState", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("InboxMessageId", "InboxConsumerId")
|
||||
.HasPrincipalKey("MessageId", "ConsumerId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.ListeningHistory", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.Track", "Track")
|
||||
.WithMany("ListeningHistories")
|
||||
.HasForeignKey("TrackId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Musify.Domain.Entities.User", "User")
|
||||
.WithMany("ListeningHistories")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Track");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.PlayList", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.User", "User")
|
||||
.WithMany("PlayLists")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.OwnsOne("Musify.Domain.ValueObjects.PlayListPictures", "Pictures", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("PlayListId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<string>("LargeName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("LargePictureName");
|
||||
|
||||
b1.Property<string>("MediumName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("MediumPictureName");
|
||||
|
||||
b1.Property<string>("OriginalName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("OriginalPictureName");
|
||||
|
||||
b1.Property<string>("SmallName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("SmallPictureName");
|
||||
|
||||
b1.HasKey("PlayListId");
|
||||
|
||||
b1.ToTable("PlayLists");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("PlayListId");
|
||||
});
|
||||
|
||||
b.Navigation("Pictures")
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.PlayListHasTrack", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.PlayList", "PlayList")
|
||||
.WithMany("PlayListTracks")
|
||||
.HasForeignKey("PlayListId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Musify.Domain.Entities.Track", "Track")
|
||||
.WithMany("PlayListTracks")
|
||||
.HasForeignKey("TrackId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("PlayList");
|
||||
|
||||
b.Navigation("Track");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.Track", b =>
|
||||
{
|
||||
b.OwnsOne("Musify.Domain.ValueObjects.TrackAudio", "Audio", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("TrackId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<bool>("DownloadRequested")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("DownloadRequested");
|
||||
|
||||
b1.Property<string>("FolderName")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("AudioFolderName");
|
||||
|
||||
b1.Property<DateTime?>("LastRetryAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("LastRetryAt");
|
||||
|
||||
b1.Property<string>("OriginalName")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("OriginalAudioName");
|
||||
|
||||
b1.Property<int>("RetryCount")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("RetryCount");
|
||||
|
||||
b1.Property<int>("TranscodeStatus")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("AudioTranscodeProcessingStatus");
|
||||
|
||||
b1.HasKey("TrackId");
|
||||
|
||||
b1.ToTable("Tracks");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("TrackId");
|
||||
});
|
||||
|
||||
b.OwnsOne("Musify.Domain.ValueObjects.TrackPictures", "Pictures", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("TrackId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<string>("LargeName")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("LargePictureName");
|
||||
|
||||
b1.Property<string>("MediumName")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("MediumPictureName");
|
||||
|
||||
b1.Property<string>("OriginalName")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("OriginalPictureName");
|
||||
|
||||
b1.Property<int>("ProcessingStatus")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("PicturesProcessingStatus");
|
||||
|
||||
b1.Property<string>("SmallName")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("SmallPictureName");
|
||||
|
||||
b1.HasKey("TrackId");
|
||||
|
||||
b1.ToTable("Tracks");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("TrackId");
|
||||
});
|
||||
|
||||
b.Navigation("Audio")
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Pictures")
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.TrackArtist", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.Artist", "Artist")
|
||||
.WithMany("TrackArtists")
|
||||
.HasForeignKey("ArtistId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Musify.Domain.Entities.ExternalTrack", "Track")
|
||||
.WithMany("TrackArtists")
|
||||
.HasForeignKey("TrackId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Artist");
|
||||
|
||||
b.Navigation("Track");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.UploadIntent", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.UserHasTrack", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.Track", "Track")
|
||||
.WithMany("UserTracks")
|
||||
.HasForeignKey("TrackId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Musify.Domain.Entities.User", "User")
|
||||
.WithMany("UserTracks")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Track");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.ExternalTrack", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.Track", null)
|
||||
.WithOne()
|
||||
.HasForeignKey("Musify.Domain.Entities.ExternalTrack", "Id")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.LocalTrack", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.Track", null)
|
||||
.WithOne()
|
||||
.HasForeignKey("Musify.Domain.Entities.LocalTrack", "Id")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Musify.Domain.Entities.User", "Owner")
|
||||
.WithMany()
|
||||
.HasForeignKey("OwnerUserId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Owner");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.Artist", b =>
|
||||
{
|
||||
b.Navigation("TrackArtists");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.PlayList", b =>
|
||||
{
|
||||
b.Navigation("PlayListTracks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.Track", b =>
|
||||
{
|
||||
b.Navigation("ListeningHistories");
|
||||
|
||||
b.Navigation("PlayListTracks");
|
||||
|
||||
b.Navigation("UserTracks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.User", b =>
|
||||
{
|
||||
b.Navigation("ListeningHistories");
|
||||
|
||||
b.Navigation("PlayLists");
|
||||
|
||||
b.Navigation("UserTracks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.ExternalTrack", b =>
|
||||
{
|
||||
b.Navigation("TrackArtists");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
+274
@@ -0,0 +1,274 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Musify.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class SplitTrackIntoLocalAndExternal : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_TrackArtist_Tracks_TrackId",
|
||||
table: "TrackArtist");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Tracks_User_OwnerUserId",
|
||||
table: "Tracks");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Tracks_OwnerUserId",
|
||||
table: "Tracks");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Tracks_Source_ExternalId",
|
||||
table: "Tracks");
|
||||
|
||||
migrationBuilder.DropCheckConstraint(
|
||||
name: "CK_Tracks_OwnerUserId_Source",
|
||||
table: "Tracks");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ExternalTracks",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Source = table.Column<int>(type: "integer", nullable: false),
|
||||
ExternalId = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_ExternalTracks", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_ExternalTracks_Tracks_Id",
|
||||
column: x => x.Id,
|
||||
principalTable: "Tracks",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "LocalTracks",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
OwnerUserId = table.Column<long>(type: "bigint", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_LocalTracks", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_LocalTracks_Tracks_Id",
|
||||
column: x => x.Id,
|
||||
principalTable: "Tracks",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_LocalTracks_User_OwnerUserId",
|
||||
column: x => x.OwnerUserId,
|
||||
principalTable: "User",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ExternalTracks_Source_ExternalId",
|
||||
table: "ExternalTracks",
|
||||
columns: new[] { "Source", "ExternalId" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_LocalTracks_OwnerUserId",
|
||||
table: "LocalTracks",
|
||||
column: "OwnerUserId");
|
||||
|
||||
migrationBuilder.Sql(
|
||||
"""
|
||||
INSERT INTO "LocalTracks" ("Id", "OwnerUserId")
|
||||
SELECT "Id", "OwnerUserId" FROM "Tracks" WHERE "Source" = 0;
|
||||
""");
|
||||
|
||||
migrationBuilder.Sql(
|
||||
"""
|
||||
INSERT INTO "ExternalTracks" ("Id", "Source", "ExternalId")
|
||||
SELECT "Id", "Source", "ExternalId" FROM "Tracks" WHERE "Source" <> 0;
|
||||
""");
|
||||
|
||||
migrationBuilder.Sql(
|
||||
"""
|
||||
DELETE FROM "TrackArtist" tra
|
||||
USING "Tracks" t
|
||||
WHERE tra."TrackId" = t."Id" AND t."Source" = 0;
|
||||
""");
|
||||
|
||||
migrationBuilder.Sql(
|
||||
"""
|
||||
DELETE FROM "Artists" WHERE "UserId" IS NOT NULL;
|
||||
""");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_TrackArtist_ExternalTracks_TrackId",
|
||||
table: "TrackArtist",
|
||||
column: "TrackId",
|
||||
principalTable: "ExternalTracks",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ExternalId",
|
||||
table: "Tracks");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "OwnerUserId",
|
||||
table: "Tracks");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Source",
|
||||
table: "Tracks");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Artists_NormalizedName",
|
||||
table: "Artists");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Artists_UserId",
|
||||
table: "Artists");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Artists_User_UserId",
|
||||
table: "Artists");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "UserId",
|
||||
table: "Artists");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "ExternalId",
|
||||
table: "Artists",
|
||||
type: "character varying(64)",
|
||||
maxLength: 64,
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(64)",
|
||||
oldMaxLength: 64,
|
||||
oldNullable: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_TrackArtist_ExternalTracks_TrackId",
|
||||
table: "TrackArtist");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "ExternalId",
|
||||
table: "Tracks",
|
||||
type: "character varying(16)",
|
||||
maxLength: 16,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<long>(
|
||||
name: "OwnerUserId",
|
||||
table: "Tracks",
|
||||
type: "bigint",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "Source",
|
||||
table: "Tracks",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.Sql(
|
||||
"""
|
||||
UPDATE "Tracks" t SET "OwnerUserId" = lt."OwnerUserId", "Source" = 0
|
||||
FROM "LocalTracks" lt WHERE lt."Id" = t."Id";
|
||||
""");
|
||||
|
||||
migrationBuilder.Sql(
|
||||
"""
|
||||
UPDATE "Tracks" t SET "ExternalId" = et."ExternalId", "Source" = et."Source"
|
||||
FROM "ExternalTracks" et WHERE et."Id" = t."Id";
|
||||
""");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "ExternalTracks");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "LocalTracks");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "ExternalId",
|
||||
table: "Artists",
|
||||
type: "character varying(64)",
|
||||
maxLength: 64,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(64)",
|
||||
oldMaxLength: 64);
|
||||
|
||||
migrationBuilder.AddColumn<long>(
|
||||
name: "UserId",
|
||||
table: "Artists",
|
||||
type: "bigint",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Tracks_OwnerUserId",
|
||||
table: "Tracks",
|
||||
column: "OwnerUserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Tracks_Source_ExternalId",
|
||||
table: "Tracks",
|
||||
columns: new[] { "Source", "ExternalId" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.AddCheckConstraint(
|
||||
name: "CK_Tracks_OwnerUserId_Source",
|
||||
table: "Tracks",
|
||||
sql: "(\"OwnerUserId\" IS NOT NULL) = (\"Source\" = 0)");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Artists_NormalizedName",
|
||||
table: "Artists",
|
||||
column: "NormalizedName",
|
||||
unique: true,
|
||||
filter: "\"ExternalId\" IS NULL AND \"UserId\" IS NULL");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Artists_UserId",
|
||||
table: "Artists",
|
||||
column: "UserId",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Artists_User_UserId",
|
||||
table: "Artists",
|
||||
column: "UserId",
|
||||
principalTable: "User",
|
||||
principalColumn: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_TrackArtist_Tracks_TrackId",
|
||||
table: "TrackArtist",
|
||||
column: "TrackId",
|
||||
principalTable: "Tracks",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Tracks_User_OwnerUserId",
|
||||
table: "Tracks",
|
||||
column: "OwnerUserId",
|
||||
principalTable: "User",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
}
|
||||
}
|
||||
}
|
||||
+898
@@ -0,0 +1,898 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Musify.Infrastructure.Persistence;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Musify.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
[DbContext(typeof(Database))]
|
||||
[Migration("20260717223358_MakePlayListPicturesNullable")]
|
||||
partial class MakePlayListPicturesNullable
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "10.0.8")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.InboxState", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<DateTime?>("Consumed")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("ConsumerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime?>("Delivered")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTime?>("ExpirationTime")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<long?>("LastSequenceNumber")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<Guid>("LockId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("MessageId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("ReceiveCount")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTime>("Received")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<byte[]>("RowVersion")
|
||||
.IsConcurrencyToken()
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Delivered");
|
||||
|
||||
b.ToTable("InboxState");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxMessage", b =>
|
||||
{
|
||||
b.Property<long>("SequenceNumber")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("SequenceNumber"));
|
||||
|
||||
b.Property<string>("Body")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ContentType")
|
||||
.IsRequired()
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
||||
b.Property<Guid?>("ConversationId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("CorrelationId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("DestinationAddress")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
||||
b.Property<DateTime?>("EnqueueTime")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTime?>("ExpirationTime")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("FaultAddress")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
||||
b.Property<string>("Headers")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("InboxConsumerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("InboxMessageId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("InitiatorId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("MessageId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("MessageType")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("OutboxId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Properties")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("RequestId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("ResponseAddress")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
||||
b.Property<DateTime>("SentTime")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("SourceAddress")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
||||
b.HasKey("SequenceNumber");
|
||||
|
||||
b.HasIndex("EnqueueTime");
|
||||
|
||||
b.HasIndex("ExpirationTime");
|
||||
|
||||
b.HasIndex("OutboxId", "SequenceNumber")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("InboxMessageId", "InboxConsumerId", "SequenceNumber")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("OutboxMessage");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxState", b =>
|
||||
{
|
||||
b.Property<Guid>("OutboxId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("Created")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTime?>("Delivered")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<long?>("LastSequenceNumber")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<Guid>("LockId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte[]>("RowVersion")
|
||||
.IsConcurrencyToken()
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.HasKey("OutboxId");
|
||||
|
||||
b.HasIndex("Created");
|
||||
|
||||
b.ToTable("OutboxState");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.Artist", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("ExternalId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ExternalId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Artists");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.ListeningHistory", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("ListenedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("TrackId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<long>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("TrackId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("ListeningHistory");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.PlayList", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
||||
b.Property<int>("LifeCycleStatus")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<long>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("PlayLists");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.PlayListHasTrack", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("AddedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("PlayListId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Position")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<Guid>("TrackId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PlayListId");
|
||||
|
||||
b.HasIndex("TrackId");
|
||||
|
||||
b.ToTable("PlayListHasTrack");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.Track", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<int>("DurationSeconds")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("LifeCycleStatus")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("NormalizedTitle")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Tracks");
|
||||
|
||||
b.UseTptMappingStrategy();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.TrackArtist", b =>
|
||||
{
|
||||
b.Property<Guid>("TrackId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("ArtistId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Position")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("TrackId", "ArtistId");
|
||||
|
||||
b.HasIndex("ArtistId");
|
||||
|
||||
b.ToTable("TrackArtist");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.Upload", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Bucket")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ContentType")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("CreatedTime")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("State")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Upload");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.UploadIntent", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Bucket")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
|
||||
b.Property<string>("ContentType")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<long?>("ExpectedSizeBytes")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<DateTime>("ExpiresAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)");
|
||||
|
||||
b.Property<string>("ObjectName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
|
||||
b.Property<int>("Purpose")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<long>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("UploadIntents");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.User", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("FirstName")
|
||||
.HasMaxLength(48)
|
||||
.HasColumnType("character varying(48)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(48)
|
||||
.HasColumnType("character varying(48)");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(48)
|
||||
.HasColumnType("character varying(48)");
|
||||
|
||||
b.Property<string>("ProfilePictureUrl")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)");
|
||||
|
||||
b.Property<string>("SecondName")
|
||||
.HasMaxLength(48)
|
||||
.HasColumnType("character varying(48)");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.UserHasTrack", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("TrackId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<long>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("TrackId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("UserHasTrack");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Infrastructure.MassTransit.Sagas.PlayListProcessingState", b =>
|
||||
{
|
||||
b.Property<Guid>("CorrelationId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Bucket")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("CurrentState")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<string>("PictureKey")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("CorrelationId");
|
||||
|
||||
b.ToTable("PlayListProcessingState");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Infrastructure.MassTransit.Sagas.TrackProcessingState", b =>
|
||||
{
|
||||
b.Property<Guid>("CorrelationId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("AudioKey")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<bool>("AudioProcessed")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("Bucket")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("CurrentState")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<string>("PictureKey")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<bool>("PictureProcessed")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("CorrelationId");
|
||||
|
||||
b.ToTable("TrackProcessingState");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.ExternalTrack", b =>
|
||||
{
|
||||
b.HasBaseType("Musify.Domain.Entities.Track");
|
||||
|
||||
b.Property<string>("ExternalId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<int>("Source")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasIndex("Source", "ExternalId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("ExternalTracks", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.LocalTrack", b =>
|
||||
{
|
||||
b.HasBaseType("Musify.Domain.Entities.Track");
|
||||
|
||||
b.Property<long>("OwnerUserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasIndex("OwnerUserId");
|
||||
|
||||
b.ToTable("LocalTracks", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxMessage", b =>
|
||||
{
|
||||
b.HasOne("MassTransit.EntityFrameworkCoreIntegration.OutboxState", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("OutboxId");
|
||||
|
||||
b.HasOne("MassTransit.EntityFrameworkCoreIntegration.InboxState", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("InboxMessageId", "InboxConsumerId")
|
||||
.HasPrincipalKey("MessageId", "ConsumerId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.ListeningHistory", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.Track", "Track")
|
||||
.WithMany("ListeningHistories")
|
||||
.HasForeignKey("TrackId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Musify.Domain.Entities.User", "User")
|
||||
.WithMany("ListeningHistories")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Track");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.PlayList", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.User", "User")
|
||||
.WithMany("PlayLists")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.OwnsOne("Musify.Domain.ValueObjects.PlayListPictures", "Pictures", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("PlayListId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<string>("LargeName")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("LargePictureName");
|
||||
|
||||
b1.Property<string>("MediumName")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("MediumPictureName");
|
||||
|
||||
b1.Property<string>("OriginalName")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("OriginalPictureName");
|
||||
|
||||
b1.Property<string>("SmallName")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("SmallPictureName");
|
||||
|
||||
b1.HasKey("PlayListId");
|
||||
|
||||
b1.ToTable("PlayLists");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("PlayListId");
|
||||
});
|
||||
|
||||
b.Navigation("Pictures");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.PlayListHasTrack", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.PlayList", "PlayList")
|
||||
.WithMany("PlayListTracks")
|
||||
.HasForeignKey("PlayListId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Musify.Domain.Entities.Track", "Track")
|
||||
.WithMany("PlayListTracks")
|
||||
.HasForeignKey("TrackId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("PlayList");
|
||||
|
||||
b.Navigation("Track");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.Track", b =>
|
||||
{
|
||||
b.OwnsOne("Musify.Domain.ValueObjects.TrackAudio", "Audio", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("TrackId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<bool>("DownloadRequested")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("DownloadRequested");
|
||||
|
||||
b1.Property<string>("FolderName")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("AudioFolderName");
|
||||
|
||||
b1.Property<DateTime?>("LastRetryAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("LastRetryAt");
|
||||
|
||||
b1.Property<string>("OriginalName")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("OriginalAudioName");
|
||||
|
||||
b1.Property<int>("RetryCount")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("RetryCount");
|
||||
|
||||
b1.Property<int>("TranscodeStatus")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("AudioTranscodeProcessingStatus");
|
||||
|
||||
b1.HasKey("TrackId");
|
||||
|
||||
b1.ToTable("Tracks");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("TrackId");
|
||||
});
|
||||
|
||||
b.OwnsOne("Musify.Domain.ValueObjects.TrackPictures", "Pictures", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("TrackId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<string>("LargeName")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("LargePictureName");
|
||||
|
||||
b1.Property<string>("MediumName")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("MediumPictureName");
|
||||
|
||||
b1.Property<string>("OriginalName")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("OriginalPictureName");
|
||||
|
||||
b1.Property<int>("ProcessingStatus")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("PicturesProcessingStatus");
|
||||
|
||||
b1.Property<string>("SmallName")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("SmallPictureName");
|
||||
|
||||
b1.HasKey("TrackId");
|
||||
|
||||
b1.ToTable("Tracks");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("TrackId");
|
||||
});
|
||||
|
||||
b.Navigation("Audio")
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Pictures")
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.TrackArtist", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.Artist", "Artist")
|
||||
.WithMany("TrackArtists")
|
||||
.HasForeignKey("ArtistId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Musify.Domain.Entities.ExternalTrack", "Track")
|
||||
.WithMany("TrackArtists")
|
||||
.HasForeignKey("TrackId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Artist");
|
||||
|
||||
b.Navigation("Track");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.UploadIntent", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.UserHasTrack", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.Track", "Track")
|
||||
.WithMany("UserTracks")
|
||||
.HasForeignKey("TrackId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Musify.Domain.Entities.User", "User")
|
||||
.WithMany("UserTracks")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Track");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.ExternalTrack", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.Track", null)
|
||||
.WithOne()
|
||||
.HasForeignKey("Musify.Domain.Entities.ExternalTrack", "Id")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.LocalTrack", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.Track", null)
|
||||
.WithOne()
|
||||
.HasForeignKey("Musify.Domain.Entities.LocalTrack", "Id")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Musify.Domain.Entities.User", "Owner")
|
||||
.WithMany()
|
||||
.HasForeignKey("OwnerUserId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Owner");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.Artist", b =>
|
||||
{
|
||||
b.Navigation("TrackArtists");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.PlayList", b =>
|
||||
{
|
||||
b.Navigation("PlayListTracks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.Track", b =>
|
||||
{
|
||||
b.Navigation("ListeningHistories");
|
||||
|
||||
b.Navigation("PlayListTracks");
|
||||
|
||||
b.Navigation("UserTracks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.User", b =>
|
||||
{
|
||||
b.Navigation("ListeningHistories");
|
||||
|
||||
b.Navigation("PlayLists");
|
||||
|
||||
b.Navigation("UserTracks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.ExternalTrack", b =>
|
||||
{
|
||||
b.Navigation("TrackArtists");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Musify.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class MakePlayListPicturesNullable : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "SmallPictureName",
|
||||
table: "PlayLists",
|
||||
type: "character varying(64)",
|
||||
maxLength: 64,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(64)",
|
||||
oldMaxLength: 64);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "OriginalPictureName",
|
||||
table: "PlayLists",
|
||||
type: "character varying(64)",
|
||||
maxLength: 64,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(64)",
|
||||
oldMaxLength: 64);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "MediumPictureName",
|
||||
table: "PlayLists",
|
||||
type: "character varying(64)",
|
||||
maxLength: 64,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(64)",
|
||||
oldMaxLength: 64);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "LargePictureName",
|
||||
table: "PlayLists",
|
||||
type: "character varying(64)",
|
||||
maxLength: 64,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(64)",
|
||||
oldMaxLength: 64);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "SmallPictureName",
|
||||
table: "PlayLists",
|
||||
type: "character varying(64)",
|
||||
maxLength: 64,
|
||||
nullable: false,
|
||||
defaultValue: "",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(64)",
|
||||
oldMaxLength: 64,
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "OriginalPictureName",
|
||||
table: "PlayLists",
|
||||
type: "character varying(64)",
|
||||
maxLength: 64,
|
||||
nullable: false,
|
||||
defaultValue: "",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(64)",
|
||||
oldMaxLength: 64,
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "MediumPictureName",
|
||||
table: "PlayLists",
|
||||
type: "character varying(64)",
|
||||
maxLength: 64,
|
||||
nullable: false,
|
||||
defaultValue: "",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(64)",
|
||||
oldMaxLength: 64,
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "LargePictureName",
|
||||
table: "PlayLists",
|
||||
type: "character varying(64)",
|
||||
maxLength: 64,
|
||||
nullable: false,
|
||||
defaultValue: "",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(64)",
|
||||
oldMaxLength: 64,
|
||||
oldNullable: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -200,6 +200,7 @@ namespace Musify.Infrastructure.Persistence.Migrations
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("ExternalId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
@@ -216,21 +217,11 @@ namespace Musify.Infrastructure.Persistence.Migrations
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<long?>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ExternalId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasFilter("\"ExternalId\" IS NULL AND \"UserId\" IS NULL");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Artists");
|
||||
});
|
||||
|
||||
@@ -337,10 +328,6 @@ namespace Musify.Infrastructure.Persistence.Migrations
|
||||
b.Property<int>("DurationSeconds")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("ExternalId")
|
||||
.HasMaxLength(16)
|
||||
.HasColumnType("character varying(16)");
|
||||
|
||||
b.Property<int>("LifeCycleStatus")
|
||||
.HasColumnType("integer");
|
||||
|
||||
@@ -349,12 +336,6 @@ namespace Musify.Infrastructure.Persistence.Migrations
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<long?>("OwnerUserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<int>("Source")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
@@ -365,15 +346,9 @@ namespace Musify.Infrastructure.Persistence.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("OwnerUserId");
|
||||
b.ToTable("Tracks");
|
||||
|
||||
b.HasIndex("Source", "ExternalId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Tracks", t =>
|
||||
{
|
||||
t.HasCheckConstraint("CK_Tracks_OwnerUserId_Source", "(\"OwnerUserId\" IS NOT NULL) = (\"Source\" = 0)");
|
||||
});
|
||||
b.UseTptMappingStrategy();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.TrackArtist", b =>
|
||||
@@ -596,6 +571,36 @@ namespace Musify.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("TrackProcessingState");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.ExternalTrack", b =>
|
||||
{
|
||||
b.HasBaseType("Musify.Domain.Entities.Track");
|
||||
|
||||
b.Property<string>("ExternalId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<int>("Source")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasIndex("Source", "ExternalId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("ExternalTracks", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.LocalTrack", b =>
|
||||
{
|
||||
b.HasBaseType("Musify.Domain.Entities.Track");
|
||||
|
||||
b.Property<long>("OwnerUserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasIndex("OwnerUserId");
|
||||
|
||||
b.ToTable("LocalTracks", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxMessage", b =>
|
||||
{
|
||||
b.HasOne("MassTransit.EntityFrameworkCoreIntegration.OutboxState", null)
|
||||
@@ -608,15 +613,6 @@ namespace Musify.Infrastructure.Persistence.Migrations
|
||||
.HasPrincipalKey("MessageId", "ConsumerId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.Artist", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.ListeningHistory", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.Track", "Track")
|
||||
@@ -650,25 +646,21 @@ namespace Musify.Infrastructure.Persistence.Migrations
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<string>("LargeName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("LargePictureName");
|
||||
|
||||
b1.Property<string>("MediumName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("MediumPictureName");
|
||||
|
||||
b1.Property<string>("OriginalName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("OriginalPictureName");
|
||||
|
||||
b1.Property<string>("SmallName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("SmallPictureName");
|
||||
@@ -681,8 +673,7 @@ namespace Musify.Infrastructure.Persistence.Migrations
|
||||
.HasForeignKey("PlayListId");
|
||||
});
|
||||
|
||||
b.Navigation("Pictures")
|
||||
.IsRequired();
|
||||
b.Navigation("Pictures");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
@@ -708,11 +699,6 @@ namespace Musify.Infrastructure.Persistence.Migrations
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.Track", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.User", "Owner")
|
||||
.WithMany()
|
||||
.HasForeignKey("OwnerUserId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
b.OwnsOne("Musify.Domain.ValueObjects.TrackAudio", "Audio", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("TrackId")
|
||||
@@ -792,8 +778,6 @@ namespace Musify.Infrastructure.Persistence.Migrations
|
||||
b.Navigation("Audio")
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Owner");
|
||||
|
||||
b.Navigation("Pictures")
|
||||
.IsRequired();
|
||||
});
|
||||
@@ -806,7 +790,7 @@ namespace Musify.Infrastructure.Persistence.Migrations
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Musify.Domain.Entities.Track", "Track")
|
||||
b.HasOne("Musify.Domain.Entities.ExternalTrack", "Track")
|
||||
.WithMany("TrackArtists")
|
||||
.HasForeignKey("TrackId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
@@ -847,6 +831,32 @@ namespace Musify.Infrastructure.Persistence.Migrations
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.ExternalTrack", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.Track", null)
|
||||
.WithOne()
|
||||
.HasForeignKey("Musify.Domain.Entities.ExternalTrack", "Id")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.LocalTrack", b =>
|
||||
{
|
||||
b.HasOne("Musify.Domain.Entities.Track", null)
|
||||
.WithOne()
|
||||
.HasForeignKey("Musify.Domain.Entities.LocalTrack", "Id")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Musify.Domain.Entities.User", "Owner")
|
||||
.WithMany()
|
||||
.HasForeignKey("OwnerUserId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Owner");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.Artist", b =>
|
||||
{
|
||||
b.Navigation("TrackArtists");
|
||||
@@ -863,8 +873,6 @@ namespace Musify.Infrastructure.Persistence.Migrations
|
||||
|
||||
b.Navigation("PlayListTracks");
|
||||
|
||||
b.Navigation("TrackArtists");
|
||||
|
||||
b.Navigation("UserTracks");
|
||||
});
|
||||
|
||||
@@ -876,6 +884,11 @@ namespace Musify.Infrastructure.Persistence.Migrations
|
||||
|
||||
b.Navigation("UserTracks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Musify.Domain.Entities.ExternalTrack", b =>
|
||||
{
|
||||
b.Navigation("TrackArtists");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,11 +41,7 @@
|
||||
"OriginalPicturesFolder": "OriginalPictures",
|
||||
"SmallPicturesFolder": "SmallPictures",
|
||||
"MediumPicturesFolder": "MediumPictures",
|
||||
"LargePicturesFolder": "LargePictures",
|
||||
"PresetOriginalPicture": "PresetOriginalPicture.webp",
|
||||
"PresetSmallPicture": "PresetSmallPicture.webp",
|
||||
"PresetMediumPicture": "PresetMediumPicture.webp",
|
||||
"PresetLargePicture": "PresetLargePicture.webp"
|
||||
"LargePicturesFolder": "LargePictures"
|
||||
},
|
||||
"PicturesSizes": {
|
||||
"SmallPictureWidth": 128,
|
||||
|
||||
Reference in New Issue
Block a user