This commit is contained in:
lumijiez
2025-06-09 00:45:42 +03:00
parent ab9b80b74f
commit a695e1cce6
19 changed files with 464 additions and 173 deletions

View File

@@ -15,28 +15,29 @@ public class UserConfiguration : IEntityTypeConfiguration<User>
builder.Property(u => u.Email)
.IsRequired()
.HasMaxLength(256);
builder.Property(u => u.FirstName)
builder.Property(u => u.Name)
.IsRequired()
.HasMaxLength(100);
builder.Property(u => u.LastName)
builder.Property(u => u.Nickname)
.IsRequired()
.HasMaxLength(100);
builder.Property(u => u.EmailVerified)
.IsRequired()
.HasMaxLength(100);
builder.Property(u => u.FullName)
.HasMaxLength(100);
builder.Property(u => u.PhoneNumber)
.HasMaxLength(20);
builder.Property(u => u.DateOfBirth)
.HasColumnType("date");
builder.Property(u => u.IsActive)
.IsRequired()
.HasDefaultValue(true);
builder.Property(u => u.LastLoginAt)
.HasColumnType("datetime2");
builder.HasIndex(u => u.Email)
.IsUnique()
.HasDatabaseName("IX_User_Email");
@@ -50,7 +51,6 @@ public class UserConfiguration : IEntityTypeConfiguration<User>
.HasPrincipalKey(u => u.Id)
.OnDelete(DeleteBehavior.Cascade);
builder.Ignore(u => u.FullName);
builder.Ignore(u => u.DefaultAddress);
builder.Ignore(u => u.Roles);
}

View File

@@ -12,7 +12,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace Imprink.Infrastructure.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20250607211109_InitialSetup")]
[Migration("20250608204903_InitialSetup")]
partial class InitialSetup
{
/// <inheritdoc />
@@ -766,16 +766,16 @@ namespace Imprink.Infrastructure.Migrations
.HasMaxLength(450)
.HasColumnType("nvarchar(450)");
b.Property<DateTime?>("DateOfBirth")
.HasColumnType("date");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("FirstName")
.IsRequired()
b.Property<bool>("EmailVerified")
.HasMaxLength(100)
.HasColumnType("bit");
b.Property<string>("FullName")
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
@@ -784,10 +784,12 @@ namespace Imprink.Infrastructure.Migrations
.HasColumnType("bit")
.HasDefaultValue(true);
b.Property<DateTime?>("LastLoginAt")
.HasColumnType("datetime2");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<string>("LastName")
b.Property<string>("Nickname")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");

View File

@@ -81,13 +81,13 @@ namespace Imprink.Infrastructure.Migrations
columns: table => new
{
Id = table.Column<string>(type: "nvarchar(450)", maxLength: 450, nullable: false),
Name = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
Nickname = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
Email = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
FirstName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
LastName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
EmailVerified = table.Column<bool>(type: "bit", maxLength: 100, nullable: false),
FullName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
PhoneNumber = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
DateOfBirth = table.Column<DateTime>(type: "date", nullable: true),
IsActive = table.Column<bool>(type: "bit", nullable: false, defaultValue: true),
LastLoginAt = table.Column<DateTime>(type: "datetime2", nullable: true)
IsActive = table.Column<bool>(type: "bit", nullable: false, defaultValue: true)
},
constraints: table =>
{

View File

@@ -763,16 +763,16 @@ namespace Imprink.Infrastructure.Migrations
.HasMaxLength(450)
.HasColumnType("nvarchar(450)");
b.Property<DateTime?>("DateOfBirth")
.HasColumnType("date");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("FirstName")
.IsRequired()
b.Property<bool>("EmailVerified")
.HasMaxLength(100)
.HasColumnType("bit");
b.Property<string>("FullName")
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
@@ -781,10 +781,12 @@ namespace Imprink.Infrastructure.Migrations
.HasColumnType("bit")
.HasDefaultValue(true);
b.Property<DateTime?>("LastLoginAt")
.HasColumnType("datetime2");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<string>("LastName")
b.Property<string>("Nickname")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");

View File

@@ -1,3 +1,4 @@
using Imprink.Domain.Common.Models;
using Imprink.Domain.Entities.Users;
using Imprink.Domain.Repositories;
using Imprink.Infrastructure.Database;
@@ -7,6 +8,37 @@ namespace Imprink.Infrastructure.Repositories;
public class UserRepository(ApplicationDbContext context) : IUserRepository
{
public async Task<bool> UpdateOrCreateUserAsync(Auth0User user, CancellationToken cancellationToken = default)
{
var userToUpdate = await context.Users
.Where(u => u.Id.Equals(user.Sub))
.FirstOrDefaultAsync(cancellationToken);
if (userToUpdate == null)
{
var newUser = new User
{
Id = user.Sub,
Email = user.Email,
EmailVerified = user.EmailVerified,
Name = user.Name,
Nickname = user.Nickname,
IsActive = true
};
context.Users.Add(newUser);
}
else
{
userToUpdate.Email = user.Email;
userToUpdate.Name = user.Name;
userToUpdate.Nickname = user.Nickname;
userToUpdate.EmailVerified = user.EmailVerified;
}
return true;
}
public async Task<User?> GetUserByIdAsync(string userId, CancellationToken cancellationToken = default)
{
return await context.Users
@@ -92,26 +124,6 @@ public class UserRepository(ApplicationDbContext context) : IUserRepository
return true;
}
public async Task UpdateLastLoginAsync(string userId, DateTime loginTime, CancellationToken cancellationToken = default)
{
var user = await context.Users.FindAsync(new object[] { userId }, cancellationToken);
if (user != null)
{
user.LastLoginAt = loginTime;
await context.SaveChangesAsync(cancellationToken);
}
}
public async Task<IEnumerable<User>> SearchUsersAsync(string searchTerm, CancellationToken cancellationToken = default)
{
return await context.Users
.AsNoTracking()
.Where(u => u.Email.Contains(searchTerm) ||
u.FirstName.Contains(searchTerm) ||
u.LastName.Contains(searchTerm))
.ToListAsync(cancellationToken);
}
public async Task<IEnumerable<User>> GetUsersByRoleAsync(Guid roleId, CancellationToken cancellationToken = default)
{
return await context.Users
@@ -120,54 +132,6 @@ public class UserRepository(ApplicationDbContext context) : IUserRepository
.ToListAsync(cancellationToken);
}
public async Task<(IEnumerable<User> Users, int TotalCount)> GetUsersPagedAsync(
int pageNumber,
int pageSize,
string? searchTerm = null,
bool? isActive = null,
CancellationToken cancellationToken = default)
{
var query = context.Users.AsNoTracking();
if (!string.IsNullOrEmpty(searchTerm))
{
query = query.Where(u => u.Email.Contains(searchTerm) ||
u.FirstName.Contains(searchTerm) ||
u.LastName.Contains(searchTerm));
}
if (isActive.HasValue)
{
query = query.Where(u => u.IsActive == isActive.Value);
}
var totalCount = await query.CountAsync(cancellationToken);
var users = await query
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
.ToListAsync(cancellationToken);
return (users, totalCount);
}
public async Task<User?> GetUserWithAddressesAsync(string userId, CancellationToken cancellationToken = default)
{
return await context.Users
.AsNoTracking()
.Include(u => u.Addresses)
.FirstOrDefaultAsync(u => u.Id == userId, cancellationToken);
}
public async Task<User?> GetUserWithRolesAsync(string userId, CancellationToken cancellationToken = default)
{
return await context.Users
.AsNoTracking()
.Include(u => u.UserRoles)
.ThenInclude(ur => ur.Role)
.FirstOrDefaultAsync(u => u.Id == userId, cancellationToken);
}
public async Task<User?> GetUserWithAllRelatedDataAsync(string userId, CancellationToken cancellationToken = default)
{
return await context.Users

View File

@@ -1,6 +1,7 @@
using Imprink.Application;
using Imprink.Domain.Repositories;
using Imprink.Infrastructure.Database;
using Microsoft.Identity.Client;
namespace Imprink.Infrastructure;
@@ -8,11 +9,13 @@ public class UnitOfWork(
ApplicationDbContext context,
IProductRepository productRepository,
IProductVariantRepository productVariantRepository,
ICategoryRepository categoryRepository) : IUnitOfWork
ICategoryRepository categoryRepository,
IUserRepository userRepository) : IUnitOfWork
{
public IProductRepository ProductRepository => productRepository;
public IProductVariantRepository ProductVariantRepository => productVariantRepository;
public ICategoryRepository CategoryRepository => categoryRepository;
public IUserRepository UserRepository => userRepository;
public async Task SaveAsync(CancellationToken cancellationToken = default)
{