user create command and user repo

This commit is contained in:
2026-02-04 22:18:05 +01:00
parent b73fd8eb05
commit 01f25fb093
10 changed files with 136 additions and 5 deletions

View File

@@ -6,4 +6,8 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.2" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,6 @@
using AipsCore.Application.Abstract.Command;
using AipsCore.Domain.Models.User.ValueObjects;
namespace AipsCore.Application.Models.User.Command;
public record CreateUserCommand(string Username, string Email) : ICommand<UserId>, ICommand;

View File

@@ -0,0 +1,23 @@
using AipsCore.Application.Abstract.Command;
using AipsCore.Domain.Common.ValueObjects;
using AipsCore.Domain.Models.User.External;
using AipsCore.Domain.Models.User.ValueObjects;
namespace AipsCore.Application.Models.User.Command.Handler;
public class CreateUserCommandHandler : ICommandHandler<CreateUserCommand>
{
private readonly IUserRepository _userRepository;
public CreateUserCommandHandler(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public async Task Handle(CreateUserCommand command, CancellationToken cancellationToken = default)
{
var user = Domain.Models.User.User.Create(command.Email, command.Username);
await _userRepository.Save(user, cancellationToken);
}
}

View File

@@ -2,6 +2,7 @@
using AipsCore.Domain.Abstract.Rule;
using AipsCore.Domain.Abstract.ValueObject;
using AipsCore.Domain.Common.Validation;
using AipsCore.Domain.Common.Validation.Rules;
namespace AipsCore.Domain.Common.ValueObjects;
@@ -17,6 +18,8 @@ public record DomainId : AbstractValueObject
protected override ICollection<IRule> GetValidationRules()
{
return [];
return [
new MinLengthRule(IdValue, 5)
];
}
}

View File

@@ -0,0 +1,9 @@
using AipsCore.Domain.Models.User.ValueObjects;
namespace AipsCore.Domain.Models.User.External;
public interface IUserRepository
{
Task<User?> Get(UserId userId, CancellationToken cancellationToken = default);
Task Save(User user, CancellationToken cancellationToken = default);
}

View File

@@ -15,4 +15,19 @@ public class User
Email = email;
Username = username;
}
public static User Create(string id, string email, string username)
{
var userIdVo = new UserId(id);
var usernameVo = new Username(username);
var emailVo = new Email(email);
return new User( userIdVo, emailVo, usernameVo);
}
public static User Create(string email, string username)
{
var usernameVo = new Username(username);
var emailVo = new Email(email);
return new User( UserId.Any(), emailVo, usernameVo);
}
}

View File

@@ -2,4 +2,7 @@
namespace AipsCore.Domain.Models.User.ValueObjects;
public record UserId(string IdValue) : DomainId(IdValue);
public record UserId(string IdValue) : DomainId(IdValue)
{
public static UserId Any() => new(Guid.NewGuid().ToString());
}

View File

@@ -1,6 +1,9 @@
namespace AipsCore.Infrastructure.Db;
using AipsCore.Infrastructure.Entities;
using Microsoft.EntityFrameworkCore;
public class AipsDbContext
namespace AipsCore.Infrastructure.Db;
public class AipsDbContext : DbContext
{
public DbSet<User> Users { get; set; }
}

View File

@@ -0,0 +1,12 @@
using System.ComponentModel.DataAnnotations;
namespace AipsCore.Infrastructure.Entities;
public class User
{
[Key]
public Guid Id { get; set; }
[Required] [MaxLength(255)] public string Username { get; set; } = null!;
[Required] [MaxLength(255)] public string Email { get; set; } = null!;
}

View File

@@ -0,0 +1,53 @@
using AipsCore.Domain.Common.ValueObjects;
using AipsCore.Domain.Models.User;
using AipsCore.Domain.Models.User.External;
using AipsCore.Domain.Models.User.ValueObjects;
using AipsCore.Infrastructure.Db;
namespace AipsCore.Infrastructure.Repositories;
public class UserRepository : IUserRepository
{
private readonly AipsDbContext _context;
public UserRepository(AipsDbContext context)
{
_context = context;
}
public async Task<User?> Get(UserId userId, CancellationToken cancellationToken = default)
{
var userEntity = await _context.Users.FindAsync([new Guid(userId.IdValue), cancellationToken], cancellationToken: cancellationToken);
if (userEntity is null) return null;
return User.Create(
userEntity.Id.ToString(),
userEntity.Email,
userEntity.Username);
}
public async Task Save(User user, CancellationToken cancellationToken = default)
{
var userEntity = await _context.Users.FindAsync([new Guid(user.Id.IdValue), cancellationToken], cancellationToken: cancellationToken);
if (userEntity is not null)
{
userEntity.Email = user.Email.EmailValue;
userEntity.Username = user.Username.UsernameValue;
_context.Users.Update(userEntity);
}
else
{
userEntity = new Entities.User()
{
Id = new Guid(user.Id.IdValue),
Email = user.Email.EmailValue,
Username = user.Username.UsernameValue,
};
_context.Users.Add(userEntity);
}
}
}