Files
blazor-saas-hrm/Features/Account/Register/Cqrs/RegisterHandler.cs
T
2026-07-21 14:22:06 +07:00

131 lines
4.8 KiB
C#

using Indotalent.Data.Entities;
using Indotalent.Infrastructure.Authorization.Identity;
using Indotalent.Infrastructure.Database;
using MediatR;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.EntityFrameworkCore;
using System.Text;
namespace Indotalent.Features.Account.Register.Cqrs;
public class CreateUserRequest
{
public string FullName { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
public bool IsActive { get; set; } = true;
public bool EmailConfirmed { get; set; } = false;
}
public class CreateUserResponse
{
public string? Id { get; set; }
public string? Email { get; set; }
}
public record CreateUserCommand(CreateUserRequest Data) : IRequest<CreateUserResponse>;
public class RegisterHandler : IRequestHandler<CreateUserCommand, CreateUserResponse>
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly IEmailSender<ApplicationUser> _emailSender;
private readonly IConfiguration _configuration;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly AppDbContext _context;
public RegisterHandler(
UserManager<ApplicationUser> userManager,
IEmailSender<ApplicationUser> emailSender,
IConfiguration configuration,
IHttpContextAccessor httpContextAccessor,
AppDbContext context)
{
_userManager = userManager;
_emailSender = emailSender;
_configuration = configuration;
_httpContextAccessor = httpContextAccessor;
_context = context;
}
public async Task<CreateUserResponse> Handle(CreateUserCommand request, CancellationToken cancellationToken)
{
var user = new ApplicationUser
{
UserName = request.Data.Email,
Email = request.Data.Email,
FullName = request.Data.FullName,
IsActive = request.Data.IsActive,
EmailConfirmed = request.Data.EmailConfirmed,
};
var result = await _userManager.CreateAsync(user, request.Data.Password);
if (!result.Succeeded)
{
var errors = result.Errors.Select(x => x.Description).ToList();
throw new Exception(string.Join(", ", errors));
}
// Assign default roles: Member and TenantAdmin (but not Admin)
var rolesToAdd = new List<string> { ApplicationRoles.Member, ApplicationRoles.TenantAdmin };
await _userManager.AddToRolesAsync(user, rolesToAdd);
// Create default tenant for the new user
var tenant = new Data.Entities.Tenant
{
Name = "Default Tenant",
Description = $"Default tenant for {request.Data.Email}",
EmailAddress = request.Data.Email,
IsActive = true
};
_context.Tenant.Add(tenant);
await _context.SaveChangesAsync(cancellationToken);
// Create TenantUser linking the user to the default tenant
var tenantUser = new Data.Entities.TenantUser
{
TenantId = tenant.Id,
UserId = user.Id,
Summary = $"Default tenant assignment for {request.Data.FullName}",
IsActive = true
};
_context.TenantUser.Add(tenantUser);
await _context.SaveChangesAsync(cancellationToken);
var requireConfirmation = _configuration.GetValue<bool>("IdentitySettings:SignIn:RequireConfirmedAccount");
if (requireConfirmation)
{
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var requestHttp = _httpContextAccessor.HttpContext?.Request;
var scheme = requestHttp?.Scheme ?? "https";
var host = requestHttp?.Host.Value ?? "localhost:8080";
var callbackUrl = $"{scheme}://{host}/account/confirm-email?userId={user.Id}&code={code}";
var message = $@"
<div style=""font-family: Arial, sans-serif;"">
<h3>Welcome, {user.FullName}!</h3>
<p>Please confirm your account by clicking the link below:</p>
<p><a href=""{callbackUrl}"" style=""color: #2196F3; font-weight: bold; text-decoration: underline;"">Confirm Account</a></p>
<br/>
<p style=""font-size: 0.8em; color: #666;"">If the link doesn't work, copy and paste this URL into your browser:</p>
<p style=""font-size: 0.8em; color: #666;"">{callbackUrl}</p>
</div>";
await _emailSender.SendConfirmationLinkAsync(user, user.Email!, message);
}
return new CreateUserResponse
{
Id = user.Id,
Email = user.Email
};
}
}