using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.WebUtilities; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using MTWorkHR.Application.Identity; using MTWorkHR.Application.Mapper; using MTWorkHR.Application.Models; using MTWorkHR.Application.Services; using MTWorkHR.Application.Models.Email; using MTWorkHR.Core.Global; using MTWorkHR.Core.IRepositories; using MTWorkHR.Core.UnitOfWork; using MTWorkHR.Identity.Entities; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using NeomtechERP.Auth.Core.Global; using Microsoft.AspNetCore.Identity.UI.Services; using IEmailSender = MTWorkHR.Application.Services.IEmailSender; using System.Security.Policy; using MTWorkHR.Application.Services.Interfaces; namespace MTWorkHR.Identity.Services { public class UserService : IUserService { private readonly RoleManager _roleManager; private readonly ApplicationUserManager _userManager; private readonly IUnitOfWork _unitOfWork; private readonly IUserRoleRepository> _userRole; private readonly AppSettingsConfiguration _configuration; private readonly IEmailSender _emailSender; private readonly GlobalInfo _globalInfo; private readonly IFileService _fileService; public UserService(ApplicationUserManager userManager, IUnitOfWork unitOfWork , RoleManager roleManager, GlobalInfo globalInfo, AppSettingsConfiguration configuration, IEmailSender emailSender , IUserRoleRepository> userRole, IFileService fileService) { _userManager = userManager; _unitOfWork = unitOfWork; _roleManager = roleManager; _userRole = userRole; _configuration = configuration; _emailSender = emailSender; _globalInfo = globalInfo; _fileService = fileService; } public async Task GetById(string userId) { var employee = await _userManager.FindByIdAsync(userId); return new UserDto { Email = employee.Email, FirstName = employee.FirstName, LastName = employee.LastName, Id = employee.Id }; } public async Task> GetAll() { var employees = await _userManager.GetUsersInRoleAsync("Employee"); return employees.Select( e=> new UserDto { Email = e.Email, FirstName = e.FirstName, LastName = e.LastName, Id = e.Id }).ToList(); } public async Task Delete(string id) { var user = await _userManager.FindByIdAsync(id); if (user != null) { user.IsDeleted = true; await _userManager.UpdateAsync(user); } } public async Task Create(UserDto input) { var emailExists = await _userManager.FindByEmailAsync(input.Email); if (emailExists != null) throw new AppException(ExceptionEnum.RecordAlreadyExist); var phoneExists = await _userManager.FindByAnyAsync(input.PhoneNumber); if (phoneExists != null) throw new AppException(ExceptionEnum.RecordAlreadyExist); var userExists = await _userManager.FindByAnyAsync(input.UserName); if (userExists != null) throw new AppException(ExceptionEnum.RecordAlreadyExist); //loop for given list of attachment, and move each file from Temp path to Actual path if (!_fileService.CopyFileToActualFolder(input.UserAttachments.ToList())) throw new AppException(ExceptionEnum.CouldNotMoveFiles); var user = MapperObject.Mapper.Map(input); _unitOfWork.BeginTran(); //saving user var result = await _userManager.CreateAsync(user); if (!result.Succeeded) throw new AppException(ExceptionEnum.RecordCreationFailed); input.Id = user.Id; //saving userRoles var userRoles = MapperObject.Mapper.Map>>(input.UserRoles); foreach (var role in userRoles) { role.UserId = user.Id; if ((await _roleManager.FindByIdAsync(role.RoleId)) == null) throw new AppException(ExceptionEnum.RecordNotExist); } await _userRole.AddRangeAsync(userRoles); await _unitOfWork.CompleteAsync(); _unitOfWork.CommitTran(); try { var resultPassReset = await GetResetPasswordURL(user.Id); var sendMailResult = await _emailSender.SendEmail(new EmailMessage { Subject = "Register Confirmation", To = input.Email, Body = "Please Set Your Password (this link will expired after 24 hours)" , url = resultPassReset.Item1, userId = user.Id } ); if (!sendMailResult) { throw new AppException("User created, but could not send the email!"); } } catch { throw new AppException("User created, but could not send the email!"); } return input; } private async Task> GetResetPasswordURL(string userId) { var user = await _userManager.Users.FirstOrDefaultAsync(x => (!x.IsDeleted) && x.Id.Equals(userId)); if (user == null) throw new AppException(ExceptionEnum.RecordNotExist); string code = await _userManager.GeneratePasswordResetTokenAsync(user); var route = "auth/forgetpassword"; var origin = _configuration.JwtSettings.Audience; var endpointUri = new Uri(string.Concat($"{origin}/", route)); var userURL = QueryHelpers.AddQueryString(endpointUri.ToString(), "userId", user.Id); var passwordResetURL = QueryHelpers.AddQueryString(userURL.ToString(), "token", code); return new Tuple ( passwordResetURL, user.Email); } public Task Update(UserDto input) { throw new NotImplementedException(); } public Task UpdateWithoutChildren(UserDto input) { throw new NotImplementedException(); } public async Task IsExpiredToken(ForgetPasswordDto input) { var user = await _userManager.Users.IgnoreQueryFilters().FirstOrDefaultAsync(x => x.Id == input.UserId); if (user == null) throw new AppException(ExceptionEnum.RecordNotExist); var purpose = UserManager.ResetPasswordTokenPurpose; var result = await _userManager.VerifyUserTokenAsync(user, "Default", purpose, input.Token); return !result; } public async Task ForgetPassword(ForgetPasswordDto model) { var user = await _userManager.Users.IgnoreQueryFilters().FirstOrDefaultAsync(x => x.Id == model.UserId); if (user == null) throw new AppException(ExceptionEnum.RecordNotExist); var result = await _userManager.ResetPasswordAsync(user, model.Token, model.Password); return result.Succeeded; } public async Task ResetPassword(ResetPasswordDto input) { var user = await _userManager.FindByIdAsync(_globalInfo.UserId); if (user == null) throw new AppException(ExceptionEnum.RecordNotExist); if (!await _userManager.CheckPasswordAsync(user, input.OldPassword)) throw new AppException(ExceptionEnum.WrongCredentials); var token = await _userManager.GeneratePasswordResetTokenAsync(user); var result = await _userManager.ResetPasswordAsync(user, token, input.NewPassword); if (!result.Succeeded) throw new AppException(ExceptionEnum.RecordUpdateFailed); return true; } public async Task ForgetPasswordMail(string userId) { var resultPassReset = await GetResetPasswordURL(userId); await _emailSender.SendEmail(new EmailMessage { Subject = "Register Confirmation", To = resultPassReset.Item2, Body = "Forget Your Password, link will expired after 24 hours", url = resultPassReset.Item1, userId = userId }); } public async Task StopUser(string userId) { var entity = await _userManager.Users.FirstOrDefaultAsync(x => x.Id == userId); if (entity == null) throw new AppException(ExceptionEnum.RecordNotExist); if (!entity.IsStopped) { entity.IsStopped = true; await _unitOfWork.CompleteAsync(); } } public async Task ActiveUser(string userId) { var entity = await _userManager.Users.FirstOrDefaultAsync(x => x.Id == userId); if (entity == null) throw new AppException(ExceptionEnum.RecordNotExist); entity.IsStopped = false; entity.AccessFailedCount = 0; entity.LockoutEnabled = false; entity.LockoutEnd = null; await _unitOfWork.CompleteAsync(); } } }