Create default user profile on registration
Implement a `UserWithProfileManager` to automatically create a default user profile upon user registration. This ensures that each user has an associated profile with default values (e.g., `UserName`, `IsAdmin`, `IsDeleted`). Updates the database schema to reflect the change from UserId to UserProfileId in the UserProfileCompanyTableStat and UserProfileProductTableStat entities.
This commit is contained in:
parent
e7ce2c7718
commit
e06700458f
5 changed files with 69 additions and 23 deletions
|
@ -1,8 +1,52 @@
|
||||||
|
using DrinkRateAPI.Contexts;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace DrinkRateAPI.DbEntities;
|
namespace DrinkRateAPI.DbEntities;
|
||||||
|
|
||||||
public class DbApplicationUser : IdentityUser<Guid>
|
public class DbApplicationUser : IdentityUser<Guid>
|
||||||
{
|
{
|
||||||
public virtual DbUserProfile UserProfile { get; set; }
|
public virtual DbUserProfile UserProfile { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UserWithProfileManager : UserManager<DbApplicationUser>
|
||||||
|
{
|
||||||
|
private readonly ApplicationDbContext _context;
|
||||||
|
|
||||||
|
public UserWithProfileManager(
|
||||||
|
IUserStore<DbApplicationUser> store,
|
||||||
|
IOptions<IdentityOptions> optionsAccessor,
|
||||||
|
IPasswordHasher<DbApplicationUser> passwordHasher,
|
||||||
|
IEnumerable<IUserValidator<DbApplicationUser>> userValidators,
|
||||||
|
IEnumerable<IPasswordValidator<DbApplicationUser>> passwordValidators,
|
||||||
|
ILookupNormalizer keyNormalizer,
|
||||||
|
IdentityErrorDescriber errors,
|
||||||
|
IServiceProvider services,
|
||||||
|
ILogger<UserManager<DbApplicationUser>> logger,
|
||||||
|
ApplicationDbContext context)
|
||||||
|
: base(store, optionsAccessor, passwordHasher, userValidators,
|
||||||
|
passwordValidators, keyNormalizer, errors, services, logger)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<IdentityResult> CreateAsync(DbApplicationUser user, string password)
|
||||||
|
{
|
||||||
|
var result = await base.CreateAsync(user, password);
|
||||||
|
if (!result.Succeeded)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
var newProfile = new DbUserProfile
|
||||||
|
{
|
||||||
|
ApplicationUser = user,
|
||||||
|
UserName = $"User_{user.Id}",
|
||||||
|
IsAdmin = false,
|
||||||
|
IsDeleted = false
|
||||||
|
};
|
||||||
|
|
||||||
|
await _context.UserProfiles.AddAsync(newProfile);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -12,8 +12,8 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
namespace DrinkRateAPI.Migrations
|
namespace DrinkRateAPI.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(ApplicationDbContext))]
|
[DbContext(typeof(ApplicationDbContext))]
|
||||||
[Migration("20250809154816_ChangeApplicationUserIdType")]
|
[Migration("20250809165046_UserCreationDemo")]
|
||||||
partial class ChangeApplicationUserIdType
|
partial class UserCreationDemo
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
@ -347,7 +347,7 @@ namespace DrinkRateAPI.Migrations
|
||||||
|
|
||||||
modelBuilder.Entity("DrinkRateAPI.DbEntities.DbUserProfileCompanyTableStat", b =>
|
modelBuilder.Entity("DrinkRateAPI.DbEntities.DbUserProfileCompanyTableStat", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("UserId")
|
b.Property<Guid>("UserProfileId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<Guid>("CompanyTableId")
|
b.Property<Guid>("CompanyTableId")
|
||||||
|
@ -362,7 +362,7 @@ namespace DrinkRateAPI.Migrations
|
||||||
b.Property<int>("RatingCount")
|
b.Property<int>("RatingCount")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
|
|
||||||
b.HasKey("UserId", "CompanyTableId");
|
b.HasKey("UserProfileId", "CompanyTableId");
|
||||||
|
|
||||||
b.HasIndex("CompanyTableId");
|
b.HasIndex("CompanyTableId");
|
||||||
|
|
||||||
|
@ -371,7 +371,7 @@ namespace DrinkRateAPI.Migrations
|
||||||
|
|
||||||
modelBuilder.Entity("DrinkRateAPI.DbEntities.DbUserProfileProductTableStat", b =>
|
modelBuilder.Entity("DrinkRateAPI.DbEntities.DbUserProfileProductTableStat", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("UserId")
|
b.Property<Guid>("UserProfileId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<Guid>("ProductTableId")
|
b.Property<Guid>("ProductTableId")
|
||||||
|
@ -386,7 +386,7 @@ namespace DrinkRateAPI.Migrations
|
||||||
b.Property<int>("RatingCount")
|
b.Property<int>("RatingCount")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
|
|
||||||
b.HasKey("UserId", "ProductTableId");
|
b.HasKey("UserProfileId", "ProductTableId");
|
||||||
|
|
||||||
b.HasIndex("ProductTableId");
|
b.HasIndex("ProductTableId");
|
||||||
|
|
||||||
|
@ -672,7 +672,7 @@ namespace DrinkRateAPI.Migrations
|
||||||
|
|
||||||
b.HasOne("DrinkRateAPI.DbEntities.DbUserProfile", "UserProfile")
|
b.HasOne("DrinkRateAPI.DbEntities.DbUserProfile", "UserProfile")
|
||||||
.WithMany("UserProfileCompanyTableStats")
|
.WithMany("UserProfileCompanyTableStats")
|
||||||
.HasForeignKey("UserId")
|
.HasForeignKey("UserProfileId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
|
@ -691,7 +691,7 @@ namespace DrinkRateAPI.Migrations
|
||||||
|
|
||||||
b.HasOne("DrinkRateAPI.DbEntities.DbUserProfile", "UserProfile")
|
b.HasOne("DrinkRateAPI.DbEntities.DbUserProfile", "UserProfile")
|
||||||
.WithMany("UserProfileProductTableStats")
|
.WithMany("UserProfileProductTableStats")
|
||||||
.HasForeignKey("UserId")
|
.HasForeignKey("UserProfileId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
|
@ -7,7 +7,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
namespace DrinkRateAPI.Migrations
|
namespace DrinkRateAPI.Migrations
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public partial class ChangeApplicationUserIdType : Migration
|
public partial class UserCreationDemo : Migration
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
@ -345,7 +345,7 @@ namespace DrinkRateAPI.Migrations
|
||||||
name: "UserProfileCompanyTableStats",
|
name: "UserProfileCompanyTableStats",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
UserId = table.Column<Guid>(type: "uuid", nullable: false),
|
UserProfileId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
CompanyTableId = table.Column<Guid>(type: "uuid", nullable: false),
|
CompanyTableId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
RatingCount = table.Column<int>(type: "integer", nullable: false),
|
RatingCount = table.Column<int>(type: "integer", nullable: false),
|
||||||
HighestRatingCount = table.Column<int>(type: "integer", nullable: false),
|
HighestRatingCount = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
@ -353,7 +353,7 @@ namespace DrinkRateAPI.Migrations
|
||||||
},
|
},
|
||||||
constraints: table =>
|
constraints: table =>
|
||||||
{
|
{
|
||||||
table.PrimaryKey("PK_UserProfileCompanyTableStats", x => new { x.UserId, x.CompanyTableId });
|
table.PrimaryKey("PK_UserProfileCompanyTableStats", x => new { x.UserProfileId, x.CompanyTableId });
|
||||||
table.ForeignKey(
|
table.ForeignKey(
|
||||||
name: "FK_UserProfileCompanyTableStats_CompanyTables_CompanyTableId",
|
name: "FK_UserProfileCompanyTableStats_CompanyTables_CompanyTableId",
|
||||||
column: x => x.CompanyTableId,
|
column: x => x.CompanyTableId,
|
||||||
|
@ -361,8 +361,8 @@ namespace DrinkRateAPI.Migrations
|
||||||
principalColumn: "Id",
|
principalColumn: "Id",
|
||||||
onDelete: ReferentialAction.Cascade);
|
onDelete: ReferentialAction.Cascade);
|
||||||
table.ForeignKey(
|
table.ForeignKey(
|
||||||
name: "FK_UserProfileCompanyTableStats_UserProfiles_UserId",
|
name: "FK_UserProfileCompanyTableStats_UserProfiles_UserProfileId",
|
||||||
column: x => x.UserId,
|
column: x => x.UserProfileId,
|
||||||
principalTable: "UserProfiles",
|
principalTable: "UserProfiles",
|
||||||
principalColumn: "Id",
|
principalColumn: "Id",
|
||||||
onDelete: ReferentialAction.Cascade);
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
@ -372,7 +372,7 @@ namespace DrinkRateAPI.Migrations
|
||||||
name: "UserProfileProductTableStats",
|
name: "UserProfileProductTableStats",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
UserId = table.Column<Guid>(type: "uuid", nullable: false),
|
UserProfileId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
ProductTableId = table.Column<Guid>(type: "uuid", nullable: false),
|
ProductTableId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
RatingCount = table.Column<int>(type: "integer", nullable: false),
|
RatingCount = table.Column<int>(type: "integer", nullable: false),
|
||||||
HighestRatingCount = table.Column<int>(type: "integer", nullable: false),
|
HighestRatingCount = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
@ -380,7 +380,7 @@ namespace DrinkRateAPI.Migrations
|
||||||
},
|
},
|
||||||
constraints: table =>
|
constraints: table =>
|
||||||
{
|
{
|
||||||
table.PrimaryKey("PK_UserProfileProductTableStats", x => new { x.UserId, x.ProductTableId });
|
table.PrimaryKey("PK_UserProfileProductTableStats", x => new { x.UserProfileId, x.ProductTableId });
|
||||||
table.ForeignKey(
|
table.ForeignKey(
|
||||||
name: "FK_UserProfileProductTableStats_ProductTable_ProductTableId",
|
name: "FK_UserProfileProductTableStats_ProductTable_ProductTableId",
|
||||||
column: x => x.ProductTableId,
|
column: x => x.ProductTableId,
|
||||||
|
@ -388,8 +388,8 @@ namespace DrinkRateAPI.Migrations
|
||||||
principalColumn: "Id",
|
principalColumn: "Id",
|
||||||
onDelete: ReferentialAction.Cascade);
|
onDelete: ReferentialAction.Cascade);
|
||||||
table.ForeignKey(
|
table.ForeignKey(
|
||||||
name: "FK_UserProfileProductTableStats_UserProfiles_UserId",
|
name: "FK_UserProfileProductTableStats_UserProfiles_UserProfileId",
|
||||||
column: x => x.UserId,
|
column: x => x.UserProfileId,
|
||||||
principalTable: "UserProfiles",
|
principalTable: "UserProfiles",
|
||||||
principalColumn: "Id",
|
principalColumn: "Id",
|
||||||
onDelete: ReferentialAction.Cascade);
|
onDelete: ReferentialAction.Cascade);
|
|
@ -344,7 +344,7 @@ namespace DrinkRateAPI.Migrations
|
||||||
|
|
||||||
modelBuilder.Entity("DrinkRateAPI.DbEntities.DbUserProfileCompanyTableStat", b =>
|
modelBuilder.Entity("DrinkRateAPI.DbEntities.DbUserProfileCompanyTableStat", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("UserId")
|
b.Property<Guid>("UserProfileId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<Guid>("CompanyTableId")
|
b.Property<Guid>("CompanyTableId")
|
||||||
|
@ -359,7 +359,7 @@ namespace DrinkRateAPI.Migrations
|
||||||
b.Property<int>("RatingCount")
|
b.Property<int>("RatingCount")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
|
|
||||||
b.HasKey("UserId", "CompanyTableId");
|
b.HasKey("UserProfileId", "CompanyTableId");
|
||||||
|
|
||||||
b.HasIndex("CompanyTableId");
|
b.HasIndex("CompanyTableId");
|
||||||
|
|
||||||
|
@ -368,7 +368,7 @@ namespace DrinkRateAPI.Migrations
|
||||||
|
|
||||||
modelBuilder.Entity("DrinkRateAPI.DbEntities.DbUserProfileProductTableStat", b =>
|
modelBuilder.Entity("DrinkRateAPI.DbEntities.DbUserProfileProductTableStat", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("UserId")
|
b.Property<Guid>("UserProfileId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<Guid>("ProductTableId")
|
b.Property<Guid>("ProductTableId")
|
||||||
|
@ -383,7 +383,7 @@ namespace DrinkRateAPI.Migrations
|
||||||
b.Property<int>("RatingCount")
|
b.Property<int>("RatingCount")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
|
|
||||||
b.HasKey("UserId", "ProductTableId");
|
b.HasKey("UserProfileId", "ProductTableId");
|
||||||
|
|
||||||
b.HasIndex("ProductTableId");
|
b.HasIndex("ProductTableId");
|
||||||
|
|
||||||
|
@ -669,7 +669,7 @@ namespace DrinkRateAPI.Migrations
|
||||||
|
|
||||||
b.HasOne("DrinkRateAPI.DbEntities.DbUserProfile", "UserProfile")
|
b.HasOne("DrinkRateAPI.DbEntities.DbUserProfile", "UserProfile")
|
||||||
.WithMany("UserProfileCompanyTableStats")
|
.WithMany("UserProfileCompanyTableStats")
|
||||||
.HasForeignKey("UserId")
|
.HasForeignKey("UserProfileId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
|
@ -688,7 +688,7 @@ namespace DrinkRateAPI.Migrations
|
||||||
|
|
||||||
b.HasOne("DrinkRateAPI.DbEntities.DbUserProfile", "UserProfile")
|
b.HasOne("DrinkRateAPI.DbEntities.DbUserProfile", "UserProfile")
|
||||||
.WithMany("UserProfileProductTableStats")
|
.WithMany("UserProfileProductTableStats")
|
||||||
.HasForeignKey("UserId")
|
.HasForeignKey("UserProfileId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using DrinkRateAPI.Contexts;
|
using DrinkRateAPI.Contexts;
|
||||||
using DrinkRateAPI.DbEntities;
|
using DrinkRateAPI.DbEntities;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
@ -12,6 +13,7 @@ builder.Services.AddEndpointsApiExplorer();
|
||||||
builder.Services.AddAuthorization();
|
builder.Services.AddAuthorization();
|
||||||
builder.Services.AddIdentityApiEndpoints<DbApplicationUser>()
|
builder.Services.AddIdentityApiEndpoints<DbApplicationUser>()
|
||||||
.AddEntityFrameworkStores<ApplicationDbContext>();
|
.AddEntityFrameworkStores<ApplicationDbContext>();
|
||||||
|
builder.Services.AddScoped<UserManager<DbApplicationUser>, UserWithProfileManager>();
|
||||||
|
|
||||||
builder.Services.AddSwaggerGen(c =>
|
builder.Services.AddSwaggerGen(c =>
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue