293 lines
12 KiB
C#
293 lines
12 KiB
C#
using CPRNIMS.Domain.Contracts.Account;
|
|
using CPRNIMS.Domain.Services;
|
|
using CPRNIMS.Infrastructure.Entities.Account;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Identity;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using CPRNIMS.Infrastructure.Models.Common;
|
|
using CPRNIMS.Infrastructure.Helper;
|
|
using CPRNIMS.Infrastructure.Entities.Common;
|
|
using CPRNIMS.Infrastructure.ViewModel.Common;
|
|
using CPRNIMS.Infrastructure.Dto.Account;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace CPRNIMS.WebApi.Controllers.Account
|
|
{
|
|
public class AnonController : Base.BaseController
|
|
{
|
|
private readonly SMTPHelper _smtpHelper;
|
|
private readonly IForgotPassword _forgotPassword;
|
|
private readonly UserManager<ApplicationUser> _userManager;
|
|
private readonly SignInManager<ApplicationUser> _signInManager;
|
|
private readonly IConfiguration _config;
|
|
|
|
public AnonController(ErrorMessageService errorMessageService,
|
|
IWebHostEnvironment webHostEnvironment,
|
|
SMTPHelper sMTPHelper, IConfiguration configuration,
|
|
IForgotPassword forgotPassword,
|
|
IDepartment department ,
|
|
SignInManager<ApplicationUser> signInManager,
|
|
UserManager<ApplicationUser> userManager
|
|
)
|
|
: base(errorMessageService, webHostEnvironment, configuration)
|
|
{
|
|
_config = configuration;
|
|
_smtpHelper = sMTPHelper;
|
|
_forgotPassword = forgotPassword;
|
|
_userManager = userManager;
|
|
_signInManager = signInManager;
|
|
}
|
|
[AllowAnonymous]
|
|
[HttpPost("Login")]
|
|
public async Task<IActionResult> Login([FromBody] LoginRequest model,
|
|
[FromServices] IAccount tokenService)
|
|
{
|
|
try
|
|
{
|
|
var user = await _userManager.FindByNameAsync(model.UserName.ToLower());
|
|
if (user == null)
|
|
return BadRequest(new ResponseObject
|
|
{
|
|
success = false,
|
|
messCode = 0,
|
|
message = "Invalid username or password."
|
|
});
|
|
|
|
var signInResult = await _signInManager.CheckPasswordSignInAsync(user, model.Password, false);
|
|
|
|
if (signInResult.Succeeded)
|
|
{
|
|
await HandleSuccessfulLogin(user);
|
|
|
|
var token = await tokenService.CreateToken(user);
|
|
return Ok(new
|
|
{
|
|
token,
|
|
expiresAt= DateTime.UtcNow.AddMinutes(30),
|
|
userId = user.Id,
|
|
userName = user.UserName,
|
|
fullName = user.FullName,
|
|
email = user.Email,
|
|
phoneNumber = user.PhoneNumber,
|
|
company = user.Company,
|
|
success = true,
|
|
messCode = 1,
|
|
message = "Success"
|
|
});
|
|
}
|
|
|
|
return await HandleFailedLogin(user, signInResult);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var message = ex.InnerException?.Message ?? ex.Message;
|
|
return BadRequest(new ResponseObject
|
|
{
|
|
success = false,
|
|
messCode = 0,
|
|
message = message
|
|
});
|
|
}
|
|
}
|
|
protected async Task HandleSuccessfulLogin(ApplicationUser user)
|
|
{
|
|
// Unlock if necessary
|
|
if (user.LockoutEnabled || user.LockoutEnd != null)
|
|
{
|
|
await _userManager.SetLockoutEnabledAsync(user, false);
|
|
user.LockoutEnd = null;
|
|
await _userManager.UpdateAsync(user);
|
|
}
|
|
|
|
// Reset failed attempts
|
|
await _userManager.ResetAccessFailedCountAsync(user);
|
|
}
|
|
protected async Task<IActionResult> HandleFailedLogin(ApplicationUser user,
|
|
Microsoft.AspNetCore.Identity.SignInResult signInResult)
|
|
{
|
|
// Increment failed attempts
|
|
await _userManager.AccessFailedAsync(user);
|
|
|
|
if (user.AccessFailedCount > 3 || signInResult.IsLockedOut)
|
|
{
|
|
await _userManager.SetLockoutEnabledAsync(user, true);
|
|
await _userManager.SetLockoutEndDateAsync(user, DateTime.Now.AddMinutes(30));
|
|
|
|
return BadRequest(new ResponseObject
|
|
{
|
|
success = false,
|
|
messCode = 0,
|
|
message = "Account is locked. Please try again after 30 minutes or contact support."
|
|
});
|
|
}
|
|
|
|
return BadRequest(new ResponseObject
|
|
{
|
|
success = false,
|
|
messCode = 0,
|
|
message = "Invalid username or password, please double check!"
|
|
});
|
|
}
|
|
[AllowAnonymous]
|
|
[HttpPost("ValidateOTP")]
|
|
public async Task<IActionResult> ValidateOTP([FromBody] EmailMessageDetailsVM viewModel)
|
|
{
|
|
try
|
|
{
|
|
var otpModel = new Otps
|
|
{
|
|
OTP = viewModel.OTP,
|
|
Email = viewModel.Email,
|
|
|
|
};
|
|
if (String.IsNullOrEmpty(otpModel.Email) || String.IsNullOrEmpty(otpModel.OTP))
|
|
{
|
|
return NotFound();
|
|
}
|
|
var isEmailExist = await _userManager.FindByEmailAsync(otpModel.Email.ToLower());
|
|
if (isEmailExist != null)
|
|
{
|
|
bool isOTPValid = await _forgotPassword.ValidateOTP(otpModel);
|
|
if (isOTPValid)
|
|
{
|
|
return Ok(new ResponseObject { messCode = 1, message = "You may proceed now." });
|
|
}
|
|
return Ok(new ResponseObject { messCode = 0, message = "Your OTP is invalid!." });
|
|
}
|
|
return NotFound();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var message = ex.InnerException?.ToString() ?? ex.Message.ToString();
|
|
await PostErrorMessage(message, "ForgotPassWebApi");
|
|
throw;
|
|
}
|
|
}
|
|
[AllowAnonymous]
|
|
[HttpPost("GetUserByEmail")]
|
|
public async Task<IActionResult> GetUserByEmail([FromBody] EmailMessageDetailsVM model)
|
|
{
|
|
try
|
|
{
|
|
if (string.IsNullOrEmpty(model.Email))
|
|
{
|
|
return NotFound();
|
|
}
|
|
var isEmailExist = await _userManager.FindByEmailAsync(model.Email.ToLower());
|
|
if (isEmailExist != null)
|
|
{
|
|
var otpGenerated = _smtpHelper.GenerateOTP();
|
|
var otpDetails = new Otps
|
|
{
|
|
OTP = otpGenerated,
|
|
Email = model.Email,
|
|
CreatedBy = model.Email,
|
|
CreatedDate = DateTime.Now,
|
|
UpdatedBy = model.Email,
|
|
UpdatedDate = DateTime.Now,
|
|
};
|
|
bool isOTPExpired = await _forgotPassword.ValidateOTP(otpDetails);
|
|
if (isOTPExpired)
|
|
{
|
|
otpGenerated = _smtpHelper.GenerateOTP();
|
|
}
|
|
otpDetails.OTP = otpGenerated;
|
|
var message = EMailTemplate("Content/SMTPEmailContent", "ForgotPassword.cshtml");
|
|
message = message.Replace("@ViewBag.FullName", isEmailExist.FullName);
|
|
message = message.Replace("@ViewBag.OTPCode", otpGenerated);
|
|
var messageDetails = new EmailMessageDetailsVM
|
|
{
|
|
Message = message,
|
|
Subject = "CLMS - OTP code for password reset",
|
|
SenderEmail = _config["SMTP:SenderEmail"],
|
|
DisplayName = _config["SMTP:DisplayName"],
|
|
Recipient = model.Email,
|
|
Bcc = _config["SMTP:CC"],
|
|
CC = _config["SMTP:CC"],
|
|
NewPassword = _config["SMTP:Password"],
|
|
OutGoingPort = 587,
|
|
Server = _config["SMTP:Server"],
|
|
UserName = _config["SMTP:UserName"]
|
|
};
|
|
await _forgotPassword.SaveUpdateOTPAsync(otpDetails, true);
|
|
await _forgotPassword.SaveUpdateOTPAsync(otpDetails, false);
|
|
await _smtpHelper.SendEmailAsync(messageDetails);
|
|
|
|
return Ok(new ResponseObject { messCode = 1, message = "You may proceed now." });
|
|
}
|
|
return NotFound();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var message = ex.InnerException?.ToString() ?? ex.Message.ToString();
|
|
await PostErrorMessage(message, "ForgotPassWebApi");
|
|
throw;
|
|
}
|
|
}
|
|
[AllowAnonymous]
|
|
[HttpPut("ChangePassword")]
|
|
public async Task<IActionResult> ChangePassword([FromBody] EmailMessageDetailsVM model)
|
|
{
|
|
try
|
|
{
|
|
var isEmailExist = await _userManager.FindByEmailAsync(model?.Email);
|
|
//If this email is exist then go to 2nd validation
|
|
if (isEmailExist != null)
|
|
{
|
|
var passwordToken = "";
|
|
|
|
// Check if the Password field is not empty
|
|
if (!string.IsNullOrEmpty(model.PasswordHash))
|
|
{
|
|
// Change the user's password
|
|
passwordToken = await _userManager.GeneratePasswordResetTokenAsync(isEmailExist);
|
|
var passwordChangeResult = await _userManager.ResetPasswordAsync(isEmailExist, passwordToken, model.PasswordHash);
|
|
|
|
if (!passwordChangeResult.Succeeded)
|
|
{
|
|
string passwordErrorMessage = passwordChangeResult.Errors?.FirstOrDefault().Description;
|
|
return StatusCode(StatusCodes.Status500InternalServerError, new ResponseObject { messCode = 0, message = passwordErrorMessage });
|
|
}
|
|
}
|
|
|
|
var otps = new Otps
|
|
{
|
|
Email = model.Email,
|
|
OTP = model.OTP
|
|
};
|
|
bool isOTPValid = await _forgotPassword.ValidateOTP(otps);
|
|
if (isOTPValid != true)
|
|
{
|
|
return NotFound(new ResponseObject { IsValid = false, message = "Your OTP is invalid or expired!." });
|
|
}
|
|
else
|
|
{
|
|
isEmailExist.UpdatedDate = DateTime.Now;
|
|
isEmailExist.UpdatedBy = model.Email;
|
|
isEmailExist.LockoutEnabled = false;
|
|
isEmailExist.LockoutEnd = null;
|
|
isEmailExist.AccessFailedCount = 0;
|
|
var result = await _userManager.UpdateAsync(isEmailExist);
|
|
if (!result.Succeeded)
|
|
{
|
|
string errorMessage = result.Errors.FirstOrDefault()?.Description;
|
|
return StatusCode(StatusCodes.Status500InternalServerError, new ResponseObject { messCode = 0, message = errorMessage });
|
|
}
|
|
|
|
await _forgotPassword.SaveUpdateOTPAsync(otps, true);
|
|
return Ok(new ResponseObject { messCode = 1, message = "Your password has been reset successfully!, please check your email." });
|
|
}
|
|
}
|
|
|
|
return NotFound(new ResponseObject { messCode = 0, message = "Email not exist!" });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var message = ex.InnerException?.ToString() ?? ex.Message.ToString();
|
|
await PostErrorMessage(message, "ForgotPassWebApi");
|
|
throw;
|
|
}
|
|
}
|
|
}
|
|
}
|