chore: import MusifyBackend into monorepo (preserving history)

git-subtree-dir: MusifyBackend
git-subtree-mainline: 6829e769ed
git-subtree-split: ed7b00c2cc
This commit is contained in:
2026-07-05 03:20:43 +02:00
206 changed files with 11000 additions and 0 deletions
@@ -0,0 +1,40 @@
using Ardalis.Result;
using Mediator;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Musify.Application.Contracts;
using Musify.Application.Users.Commands;
using Musify.Application.Users.Responses;
namespace Musify.Application.Users.Handlers
{
public class CreateUserCommandHandler(IDatabase database, ILogger<CreateUserCommandHandler> logger)
: ICommandHandler<CreateUserCommand, Result<UserApplicationResponse> >
{
public async ValueTask<Result<UserApplicationResponse>> Handle(CreateUserCommand request, CancellationToken cancellationToken)
{
var userExists = await database.Users.AnyAsync(u => u.Id == request.Id, cancellationToken);
if (userExists)
{
logger.LogInformation("User {UserId} already exists", request.Id);
return Result<UserApplicationResponse>.Conflict($"User {request.Id} already exists");
}
var newUser = CreateUserCommand.ToEntity(request);
try
{
await database.Users.AddAsync(newUser, cancellationToken);
await database.SaveChangesAsync(cancellationToken);
}
catch (Exception exception)
{
logger.LogError(exception, "Failed to create user {UserId}", request.Id);
return Result.Error($"Failed to create user {request.Id}");
}
logger.LogInformation("Created user {UserId}", newUser.Id);
return Result.Created(UserApplicationResponse.FromEntity(newUser));
}
}
}
@@ -0,0 +1,26 @@
using Ardalis.Result;
using Mediator;
using Microsoft.EntityFrameworkCore;
using Musify.Application.Contracts;
using Musify.Application.Users.Queries;
using Musify.Application.Users.Responses;
namespace Musify.Application.Users.Handlers
{
public class GetUserByIdQueryHandler(IDatabase database)
: IQueryHandler<GetUserByIdQuery, Result<UserApplicationResponse> >
{
public async ValueTask<Result<UserApplicationResponse>> Handle(GetUserByIdQuery request, CancellationToken cancellationToken)
{
var user = await database.Users
.AsNoTracking()
.Where(u => u.Id == request.Id)
.Select(u => UserApplicationResponse.FromEntity(u))
.SingleOrDefaultAsync(cancellationToken);
return user is null
? Result<UserApplicationResponse>.NotFound()
: Result.Success(user);
}
}
}
@@ -0,0 +1,35 @@
using Ardalis.Result;
using Mediator;
using Microsoft.EntityFrameworkCore;
using Musify.Application.Pagination;
using Musify.Application.Users.Queries;
using Musify.Application.Users.Responses;
using X.PagedList.EF;
using Musify.Application.Contracts;
namespace Musify.Application.Users.Handlers
{
public class GetUsersQueryHandler(IDatabase database)
: IQueryHandler<GetUsersQuery, Result<PaginatedResponse<UserApplicationResponse> > >
{
public async ValueTask<Result<PaginatedResponse<UserApplicationResponse> >> Handle(GetUsersQuery request, CancellationToken cancellationToken)
{
var user = database.Users
.AsNoTracking()
.AsQueryable();
if (request.UsernameSearch is not null)
{
var normalizedUsername = request.UsernameSearch.Trim().ToUpperInvariant();
user = user.Where(u => u.NormalizedName.Contains(normalizedUsername));
}
var totalCount = await user.CountAsync(cancellationToken);
var pagedUser = await user
.Select(u => UserApplicationResponse.FromEntity(u))
.ToPagedListAsync(request.PageNumber, request.PageSize, totalCount, cancellationToken);
return Result.Success(PaginatedResponse<UserApplicationResponse>.FromPagedList(pagedUser));
}
}
}
@@ -0,0 +1,50 @@
using Ardalis.Result;
using Mediator;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Musify.Application.Contracts;
using Musify.Application.Users.Commands;
using Musify.Domain.Entities;
namespace Musify.Application.Users.Handlers
{
public class SyncUserCommandHandler(IDatabase database, ILogger<SyncUserCommandHandler> logger)
: ICommandHandler<SyncUserCommand, Result>
{
public async ValueTask<Result> Handle(SyncUserCommand request, CancellationToken cancellationToken)
{
var user = await database.Users
.SingleOrDefaultAsync(u => u.Id == request.Id, cancellationToken);
if (user is null)
{
await database.Users.AddAsync(new User
{
Id = request.Id,
Name = request.Name,
NormalizedName = request.Name.ToUpperInvariant(),
FirstName = request.FirstName,
SecondName = request.SecondName,
ProfilePictureUrl = request.ProfilePictureUrl
}, cancellationToken);
await database.SaveChangesAsync(cancellationToken);
logger.LogInformation("Provisioned user {UserId}", request.Id);
return Result.Success();
}
user.Name = request.Name;
user.NormalizedName = request.Name.ToUpperInvariant();
user.FirstName = request.FirstName;
user.SecondName = request.SecondName;
user.ProfilePictureUrl = request.ProfilePictureUrl;
var written = await database.SaveChangesAsync(cancellationToken);
if (written > 0)
logger.LogInformation("Synced profile for user {UserId}", request.Id);
return Result.Success();
}
}
}