diff --git a/dotnet/AipsCore/AipsCore.csproj b/dotnet/AipsCore/AipsCore.csproj index 0e42146..3f0347f 100644 --- a/dotnet/AipsCore/AipsCore.csproj +++ b/dotnet/AipsCore/AipsCore.csproj @@ -6,4 +6,8 @@ enable + + + + diff --git a/dotnet/AipsCore/Application/Models/User/Command/CreateUserCommand.cs b/dotnet/AipsCore/Application/Models/User/Command/CreateUserCommand.cs new file mode 100644 index 0000000..fdb6f36 --- /dev/null +++ b/dotnet/AipsCore/Application/Models/User/Command/CreateUserCommand.cs @@ -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, ICommand; \ No newline at end of file diff --git a/dotnet/AipsCore/Application/Models/User/Command/Handler/CreateUserCommandHandler.cs b/dotnet/AipsCore/Application/Models/User/Command/Handler/CreateUserCommandHandler.cs new file mode 100644 index 0000000..eff3150 --- /dev/null +++ b/dotnet/AipsCore/Application/Models/User/Command/Handler/CreateUserCommandHandler.cs @@ -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 +{ + 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); + } +} \ No newline at end of file diff --git a/dotnet/AipsCore/Domain/Common/ValueObjects/DomainId.cs b/dotnet/AipsCore/Domain/Common/ValueObjects/DomainId.cs index 6f76d85..c638377 100644 --- a/dotnet/AipsCore/Domain/Common/ValueObjects/DomainId.cs +++ b/dotnet/AipsCore/Domain/Common/ValueObjects/DomainId.cs @@ -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 GetValidationRules() { - return []; + return [ + new MinLengthRule(IdValue, 5) + ]; } } \ No newline at end of file diff --git a/dotnet/AipsCore/Domain/Models/User/External/IUserRepository.cs b/dotnet/AipsCore/Domain/Models/User/External/IUserRepository.cs new file mode 100644 index 0000000..c776a74 --- /dev/null +++ b/dotnet/AipsCore/Domain/Models/User/External/IUserRepository.cs @@ -0,0 +1,9 @@ +using AipsCore.Domain.Models.User.ValueObjects; + +namespace AipsCore.Domain.Models.User.External; + +public interface IUserRepository +{ + Task Get(UserId userId, CancellationToken cancellationToken = default); + Task Save(User user, CancellationToken cancellationToken = default); +} \ No newline at end of file diff --git a/dotnet/AipsCore/Domain/Models/User/User.cs b/dotnet/AipsCore/Domain/Models/User/User.cs index 1ca404c..416f102 100644 --- a/dotnet/AipsCore/Domain/Models/User/User.cs +++ b/dotnet/AipsCore/Domain/Models/User/User.cs @@ -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); + } } \ No newline at end of file diff --git a/dotnet/AipsCore/Domain/Models/User/ValueObjects/UserId.cs b/dotnet/AipsCore/Domain/Models/User/ValueObjects/UserId.cs index 022011e..cfc341c 100644 --- a/dotnet/AipsCore/Domain/Models/User/ValueObjects/UserId.cs +++ b/dotnet/AipsCore/Domain/Models/User/ValueObjects/UserId.cs @@ -2,4 +2,7 @@ namespace AipsCore.Domain.Models.User.ValueObjects; -public record UserId(string IdValue) : DomainId(IdValue); \ No newline at end of file +public record UserId(string IdValue) : DomainId(IdValue) +{ + public static UserId Any() => new(Guid.NewGuid().ToString()); +} \ No newline at end of file diff --git a/dotnet/AipsCore/Infrastructure/Db/AipsDbContext.cs b/dotnet/AipsCore/Infrastructure/Db/AipsDbContext.cs index ab85fb3..b39a190 100644 --- a/dotnet/AipsCore/Infrastructure/Db/AipsDbContext.cs +++ b/dotnet/AipsCore/Infrastructure/Db/AipsDbContext.cs @@ -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 Users { get; set; } } \ No newline at end of file diff --git a/dotnet/AipsCore/Infrastructure/Entities/User.cs b/dotnet/AipsCore/Infrastructure/Entities/User.cs new file mode 100644 index 0000000..202f2ca --- /dev/null +++ b/dotnet/AipsCore/Infrastructure/Entities/User.cs @@ -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!; +} \ No newline at end of file diff --git a/dotnet/AipsCore/Infrastructure/Repositories/UserRepository.cs b/dotnet/AipsCore/Infrastructure/Repositories/UserRepository.cs new file mode 100644 index 0000000..8314ac6 --- /dev/null +++ b/dotnet/AipsCore/Infrastructure/Repositories/UserRepository.cs @@ -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 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); + } + } +} \ No newline at end of file