using MediatR; using cuqmbr.TravelGuide.Application.Common.Persistence; using AutoMapper; using cuqmbr.TravelGuide.Application.Common.Exceptions; using System.Security.Cryptography; using System.Text; using cuqmbr.TravelGuide.Application.Common.Services; using cuqmbr.TravelGuide.Domain.Entities; namespace cuqmbr.TravelGuide.Application .Identity.Accounts.Commands.UpdateAccount; public class UpdateAccountCommandHandler : IRequestHandler { private readonly UnitOfWork _unitOfWork; private readonly IMapper _mapper; private readonly PasswordHasherService _passwordHasher; public UpdateAccountCommandHandler(UnitOfWork unitOfWork, IMapper mapper, PasswordHasherService passwordHasher) { _unitOfWork = unitOfWork; _mapper = mapper; _passwordHasher = passwordHasher; } public async Task Handle( UpdateAccountCommand request, CancellationToken cancellationToken) { var account = await _unitOfWork.AccountRepository .GetOneAsync(e => e.Guid == request.Guid, e => e.AccountRoles, cancellationToken); if (account == null) { throw new NotFoundException(); } account.Username = request.Username ?? account.Username; account.Email = request.Email ?? account.Email; if (request.Password != null) { var salt = RandomNumberGenerator.GetBytes(128 / 8); var hash = await _passwordHasher.HashAsync( Encoding.UTF8.GetBytes(request.Password), salt, cancellationToken); var saltBase64 = Convert.ToBase64String(salt); var hashBase64 = Convert.ToBase64String(hash); account.PasswordHash = hashBase64; account.PasswordSalt = saltBase64; } if (request.Roles != null) { var requestRoleIds = (await _unitOfWork.RoleRepository .GetPageAsync( r => request.Roles.Contains(r.Value), 1, request.Roles.Count, cancellationToken)) .Items .Select(r => r.Id); var accountRoles = account.AccountRoles; var accountRoleIds = accountRoles.Select(ar => ar.RoleId); var commonRoleIds = requestRoleIds.Intersect(accountRoleIds); var newRoleIds = requestRoleIds.Except(accountRoleIds); var combinedRoleIds = commonRoleIds.Union(newRoleIds); account.AccountRoles = combinedRoleIds.Select(rId => new AccountRole() { Id = accountRoles.FirstOrDefault(ar => ar.RoleId == rId)?.Id ?? default, RoleId = rId }) .ToList(); } else { var accountRoleIds = account.AccountRoles.Select(ar => ar.RoleId); var accountRoles = (await _unitOfWork.AccountRoleRepository .GetPageAsync( ar => accountRoleIds.Contains(ar.RoleId), ar => ar.Role, 1, accountRoleIds.Count(), cancellationToken)) .Items; account.AccountRoles = accountRoles.ToList(); } account = await _unitOfWork.AccountRepository.UpdateOneAsync( account, cancellationToken); await _unitOfWork.SaveAsync(cancellationToken); _unitOfWork.Dispose(); return _mapper.Map(account); } }