diff --git a/src/Application/Common/Interfaces/IApplicationDbContext.cs b/src/Application/Common/Interfaces/IApplicationDbContext.cs index ef5afaa..3615321 100644 --- a/src/Application/Common/Interfaces/IApplicationDbContext.cs +++ b/src/Application/Common/Interfaces/IApplicationDbContext.cs @@ -5,8 +5,5 @@ namespace Hutopy.Application.Common.Interfaces; public interface IApplicationDbContext { DbSet FutureCreators { get; } - - DbSet DomainUsers { get; } - Task SaveChangesAsync(CancellationToken cancellationToken); } diff --git a/src/Application/Users/Commands/CreateUser.cs b/src/Application/Users/Commands/CreateUser.cs index be18e30..07e4cb9 100644 --- a/src/Application/Users/Commands/CreateUser.cs +++ b/src/Application/Users/Commands/CreateUser.cs @@ -1,5 +1,8 @@ -using Hutopy.Application.Common.Interfaces; +using System.Dynamic; +using Hutopy.Application.Common.Interfaces; using Hutopy.Domain.Entities; +using Hutopy.Domain.Interfaces; +using Microsoft.EntityFrameworkCore; namespace Hutopy.Application.Users.Commands; public record CreateUserCommand : IRequest @@ -14,26 +17,24 @@ public record CreateUserCommand : IRequest public class CreateUserCommandHandler : IRequestHandler { private readonly IApplicationDbContext _context; + private readonly IUserService _userService; - public CreateUserCommandHandler(IApplicationDbContext context) + public CreateUserCommandHandler(IApplicationDbContext context, IUserService userService) { _context = context; + _userService = userService; } public async Task Handle(CreateUserCommand request, CancellationToken cancellationToken) { - var entity = new User - { - FirstName = request.FirstName, - LastName = request.LastName, - EmailAddress = request.EmailAddress, - UserName = request.UserName, - }; + // Dont really need the handler for the create. The get will work like this : + var user = await _userService.FindUserByIdAsync("a4baeb4f-e846-45c6-9be2-6655dd8d1baf"); + // var user2 = await _userService.FindUserByEmailAsync("test10@hotmail.com"); - _context.DomainUsers.Add(entity); + var tt = user?.UserName; await _context.SaveChangesAsync(cancellationToken); - return entity.Id; + return Guid.NewGuid(); } -} \ No newline at end of file +} diff --git a/src/Domain/Entities/User.cs b/src/Domain/Entities/User.cs deleted file mode 100644 index d848021..0000000 --- a/src/Domain/Entities/User.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Hutopy.Domain.Entities; - -public class User : BaseAuditableEntity -{ - public Guid IdentityUserId { get; set; } - public required string FirstName { get; set; } - public required string LastName { get; set; } - public required string UserName { get; set; } - public required string EmailAddress { get; set; } -} diff --git a/src/Domain/Interfaces/IUserService.cs b/src/Domain/Interfaces/IUserService.cs index 4048f93..c3bd5ac 100644 --- a/src/Domain/Interfaces/IUserService.cs +++ b/src/Domain/Interfaces/IUserService.cs @@ -1,7 +1,12 @@ -namespace Hutopy.Domain.Interfaces; +using Hutopy.Domain.Models; + +namespace Hutopy.Domain.Interfaces; public interface IUserService { - Task CreateUserAsync(string email, string userName, string password); + Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password); + Task FindUserByIdAsync(string id); + + Task FindUserByEmailAsync(string id); } diff --git a/src/Domain/Models/UserModel.cs b/src/Domain/Models/UserModel.cs new file mode 100644 index 0000000..a010a89 --- /dev/null +++ b/src/Domain/Models/UserModel.cs @@ -0,0 +1,8 @@ +namespace Hutopy.Domain.Models; + +public class UserModel +{ + public string? Id { get; set; } + public string? UserName { get; set; } + public string? Email { get; set; } +} diff --git a/src/Infrastructure/Data/ApplicationDbContext.cs b/src/Infrastructure/Data/ApplicationDbContext.cs index c348dc4..1dd4d94 100644 --- a/src/Infrastructure/Data/ApplicationDbContext.cs +++ b/src/Infrastructure/Data/ApplicationDbContext.cs @@ -13,8 +13,6 @@ public class ApplicationDbContext( { public DbSet FutureCreators => Set(); - public DbSet DomainUsers => Set(); - protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); diff --git a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs index cbabbeb..6a8f886 100644 --- a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs +++ b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs @@ -17,7 +17,7 @@ public static class InitializerExtensions var initializer = scope.ServiceProvider.GetRequiredService(); - await initializer.InitialiseAsync(); + // await initializer.InitialiseAsync(); await initializer.SeedAsync(); } diff --git a/src/Infrastructure/Data/Migrations/20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser.Designer.cs b/src/Infrastructure/Data/Migrations/20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser.Designer.cs new file mode 100644 index 0000000..6df4b5a --- /dev/null +++ b/src/Infrastructure/Data/Migrations/20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser.Designer.cs @@ -0,0 +1,334 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Data.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser")] + partial class RemovedDomainUserAddFirstNameLastNameToApplicationUser + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReasonToJoin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SocialNetworkAccount") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FutureCreators"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Data/Migrations/20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser.cs b/src/Infrastructure/Data/Migrations/20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser.cs new file mode 100644 index 0000000..1fc9b4c --- /dev/null +++ b/src/Infrastructure/Data/Migrations/20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser.cs @@ -0,0 +1,64 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Infrastructure.Data.Migrations +{ + /// + public partial class RemovedDomainUserAddFirstNameLastNameToApplicationUser : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "DomainUsers"); + + migrationBuilder.AddColumn( + name: "FirstName", + table: "AspNetUsers", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "LastName", + table: "AspNetUsers", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "FirstName", + table: "AspNetUsers"); + + migrationBuilder.DropColumn( + name: "LastName", + table: "AspNetUsers"); + + migrationBuilder.CreateTable( + name: "DomainUsers", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Created = table.Column(type: "datetimeoffset", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + EmailAddress = table.Column(type: "nvarchar(max)", nullable: false), + FirstName = table.Column(type: "nvarchar(max)", nullable: false), + IdentityUserId = table.Column(type: "uniqueidentifier", nullable: false), + LastModified = table.Column(type: "datetimeoffset", nullable: false), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastName = table.Column(type: "nvarchar(max)", nullable: false), + UserName = table.Column(type: "nvarchar(max)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_DomainUsers", x => x.Id); + }); + } + } +} diff --git a/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs index 0be5962..3065590 100644 --- a/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs @@ -69,48 +69,6 @@ namespace Hutopy.Infrastructure.Data.Migrations b.ToTable("FutureCreators"); }); - modelBuilder.Entity("Hutopy.Domain.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EmailAddress") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("IdentityUserId") - .HasColumnType("uniqueidentifier"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("UserName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("DomainUsers"); - }); - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => { b.Property("Id") @@ -130,6 +88,14 @@ namespace Hutopy.Infrastructure.Data.Migrations b.Property("EmailConfirmed") .HasColumnType("bit"); + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + b.Property("LockoutEnabled") .HasColumnType("bit"); diff --git a/src/Infrastructure/Identity/ApplicationUser.cs b/src/Infrastructure/Identity/ApplicationUser.cs index badd6ee..0462aff 100644 --- a/src/Infrastructure/Identity/ApplicationUser.cs +++ b/src/Infrastructure/Identity/ApplicationUser.cs @@ -4,4 +4,6 @@ namespace Hutopy.Infrastructure.Identity; public class ApplicationUser : IdentityUser { + public string FirstName { get; set; } = string.Empty; + public string LastName { get; set; } = string.Empty; } diff --git a/src/Infrastructure/Services/UserService.cs b/src/Infrastructure/Services/UserService.cs index 444a317..4a55a6e 100644 --- a/src/Infrastructure/Services/UserService.cs +++ b/src/Infrastructure/Services/UserService.cs @@ -1,21 +1,23 @@ using Hutopy.Domain.Interfaces; +using Hutopy.Domain.Models; using Hutopy.Infrastructure.Identity; +using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Identity; namespace Hutopy.Infrastructure.Services; -public class UserService(UserManager userManager, SignInManager signInManager) : IUserService +public class UserService(UserManager userManager) : IUserService { private readonly UserManager _userManager = userManager; - private readonly SignInManager _signInManager = signInManager; - - public async Task CreateUserAsync(string email, string userName, string password) + public async Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password) { var applicationUser = new ApplicationUser { UserName = userName, Email = email, + FirstName = firstName, + LastName = lastName }; //todo: Need to handle errors better for the user. @@ -26,5 +28,37 @@ public class UserService(UserManager userManager, SignInManager throw new InvalidOperationException(response.Errors.First().Description); } } + + public async Task FindUserByIdAsync(string id) + { + var response = await _userManager.FindByIdAsync(id); + + if (response == null) return null; + + var userModel = new UserModel() + { + Id = response.Id, + UserName = response.UserName, + Email = response.Email + }; + + return userModel; + } + + public async Task FindUserByEmailAsync(string email) + { + var response = await _userManager.FindByEmailAsync(email); + + if (response == null) return null; + + var userModel = new UserModel() + { + Id = response.Id, + UserName = response.UserName, + Email = response.Email + }; + + return userModel; + } } diff --git a/src/Web/Endpoints/Users.cs b/src/Web/Endpoints/Users.cs index 63749c4..38ccb1e 100644 --- a/src/Web/Endpoints/Users.cs +++ b/src/Web/Endpoints/Users.cs @@ -15,7 +15,7 @@ public class Users : EndpointGroupBase public async Task CreateUser(ISender sender, CreateUserCommand command, IUserService userService) { - await userService.CreateUserAsync(command.EmailAddress, command.UserName, command.Password); + await userService.CreateUserAsync(command.EmailAddress, command.UserName, command.FirstName, command.LastName, command.Password); return await sender.Send(command); } }