New way to interact with AspNet users

This commit is contained in:
Dominic Villemure
2024-04-09 23:38:26 -04:00
parent 47121b0539
commit 49a10198e4
13 changed files with 476 additions and 77 deletions

View File

@@ -5,8 +5,5 @@ namespace Hutopy.Application.Common.Interfaces;
public interface IApplicationDbContext
{
DbSet<FutureCreator> FutureCreators { get; }
DbSet<User> DomainUsers { get; }
Task<int> SaveChangesAsync(CancellationToken cancellationToken);
}

View File

@@ -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<Guid>
@@ -14,26 +17,24 @@ public record CreateUserCommand : IRequest<Guid>
public class CreateUserCommandHandler : IRequestHandler<CreateUserCommand, Guid>
{
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<Guid> 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();
}
}
}

View File

@@ -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; }
}

View File

@@ -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<UserModel?> FindUserByIdAsync(string id);
Task<UserModel?> FindUserByEmailAsync(string id);
}

View File

@@ -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; }
}

View File

@@ -13,8 +13,6 @@ public class ApplicationDbContext(
{
public DbSet<FutureCreator> FutureCreators => Set<FutureCreator>();
public DbSet<User> DomainUsers => Set<User>();
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);

View File

@@ -17,7 +17,7 @@ public static class InitializerExtensions
var initializer = scope.ServiceProvider.GetRequiredService<ApplicationDbContextInitializer>();
await initializer.InitialiseAsync();
// await initializer.InitialiseAsync();
await initializer.SeedAsync();
}

View File

@@ -0,0 +1,334 @@
// <auto-generated />
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
{
/// <inheritdoc />
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<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<DateTimeOffset>("Created")
.HasColumnType("datetimeoffset");
b.Property<string>("CreatedBy")
.HasColumnType("nvarchar(max)");
b.Property<string>("EmailAddress")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("FirstName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<DateTimeOffset>("LastModified")
.HasColumnType("datetimeoffset");
b.Property<string>("LastModifiedBy")
.HasColumnType("nvarchar(max)");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PhoneNumber")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("ReasonToJoin")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("SocialNetworkAccount")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("FutureCreators");
});
modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<int>("AccessFailedCount")
.HasColumnType("int");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("bit");
b.Property<string>("FirstName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<bool>("LockoutEnabled")
.HasColumnType("bit");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("datetimeoffset");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");
b.Property<string>("PhoneNumber")
.HasColumnType("nvarchar(max)");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("bit");
b.Property<string>("SecurityStamp")
.HasColumnType("nvarchar(max)");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("bit");
b.Property<string>("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<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("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<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderKey")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderDisplayName")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("RoleId")
.HasColumnType("nvarchar(450)");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property<string>("Name")
.HasColumnType("nvarchar(450)");
b.Property<string>("Value")
.HasColumnType("nvarchar(max)");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", 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<string>", b =>
{
b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,64 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Hutopy.Infrastructure.Data.Migrations
{
/// <inheritdoc />
public partial class RemovedDomainUserAddFirstNameLastNameToApplicationUser : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "DomainUsers");
migrationBuilder.AddColumn<string>(
name: "FirstName",
table: "AspNetUsers",
type: "nvarchar(max)",
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "LastName",
table: "AspNetUsers",
type: "nvarchar(max)",
nullable: false,
defaultValue: "");
}
/// <inheritdoc />
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<Guid>(type: "uniqueidentifier", nullable: false),
Created = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
CreatedBy = table.Column<string>(type: "nvarchar(max)", nullable: true),
EmailAddress = table.Column<string>(type: "nvarchar(max)", nullable: false),
FirstName = table.Column<string>(type: "nvarchar(max)", nullable: false),
IdentityUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
LastModified = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
LastModifiedBy = table.Column<string>(type: "nvarchar(max)", nullable: true),
LastName = table.Column<string>(type: "nvarchar(max)", nullable: false),
UserName = table.Column<string>(type: "nvarchar(max)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_DomainUsers", x => x.Id);
});
}
}
}

View File

@@ -69,48 +69,6 @@ namespace Hutopy.Infrastructure.Data.Migrations
b.ToTable("FutureCreators");
});
modelBuilder.Entity("Hutopy.Domain.Entities.User", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<DateTimeOffset>("Created")
.HasColumnType("datetimeoffset");
b.Property<string>("CreatedBy")
.HasColumnType("nvarchar(max)");
b.Property<string>("EmailAddress")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("FirstName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<Guid>("IdentityUserId")
.HasColumnType("uniqueidentifier");
b.Property<DateTimeOffset>("LastModified")
.HasColumnType("datetimeoffset");
b.Property<string>("LastModifiedBy")
.HasColumnType("nvarchar(max)");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("UserName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("DomainUsers");
});
modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b =>
{
b.Property<string>("Id")
@@ -130,6 +88,14 @@ namespace Hutopy.Infrastructure.Data.Migrations
b.Property<bool>("EmailConfirmed")
.HasColumnType("bit");
b.Property<string>("FirstName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<bool>("LockoutEnabled")
.HasColumnType("bit");

View File

@@ -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;
}

View File

@@ -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<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager) : IUserService
public class UserService(UserManager<ApplicationUser> userManager) : IUserService
{
private readonly UserManager<ApplicationUser> _userManager = userManager;
private readonly SignInManager<ApplicationUser> _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<ApplicationUser> userManager, SignInManager
throw new InvalidOperationException(response.Errors.First().Description);
}
}
public async Task<UserModel?> 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<UserModel?> 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;
}
}

View File

@@ -15,7 +15,7 @@ public class Users : EndpointGroupBase
public async Task<Guid> 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);
}
}