NonInventPurchasingSystem/CPRNIMS.WebApi/Controllers/Account/AnonController.cs
2026-05-20 16:50:48 +08:00

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.AddHours(2),
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;
}
}
}
}