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