using System.Net; using System.Net.Mail; using GB5Shared.Connection; using GB5Shared.DTO.Framework.Login; using GB5Shared.DTO.Framework.ResponseStandard; using GB5Shared.OTP; using GB5Shared.QueryExecutor; using Google.Rpc; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using static GB5Shared.GB5Constant.Constant; namespace FrameworkSL.Controllers.EMailOTP { [ApiController] [Route("EMailOTP")] public class EMailOTPService : ControllerBase { private readonly EmailOtpRedisService _otpRedis; private readonly EmailOtpSender _emailSender; private readonly IApplicationConnection _ApplicationConnection; private readonly IQueryExecutor _IQueryExecutor; public EMailOTPService(EmailOtpRedisService otpRedis, EmailOtpSender emailSender, IApplicationConnection IApplicationConnection, IQueryExecutor IQueryExecutor) { _otpRedis = otpRedis; _emailSender = emailSender; _ApplicationConnection = IApplicationConnection; _IQueryExecutor = IQueryExecutor; } [HttpPost("ForgotPassword")] public async Task> ForgotPassword([FromBody] ForgotPasswordRequest req) { try { const string sql = @" SELECT m.USERID AS UserId, m.USERCODE AS UserCode, m.USERNAME AS UserName, m.PRIMARYMAIL AS PrimaryMail FROM muser m WHERE m.USERCODE = @usercode; "; var users = await _IQueryExecutor.QueryAsync( req.ConnectionName!, sql, new { usercode = req.UserCode } ); var user = users.FirstOrDefault(); if (user == null) { throw new Exception($"User Not Found {req.UserCode}"); } string? primaryMail = user.PrimaryMail as string; if (string.IsNullOrWhiteSpace(primaryMail)) { throw new Exception($"{req.UserCode} User Has No Primary EMail"); } string email = primaryMail.Trim().ToLower(); var otp = GeneratorOTP.Generate(); await _otpRedis.SaveOtpAsync(email, otp, req.ConnectionName!); await _emailSender.SendAsync(email, otp); return await GB5Shared.ResponseStandard.Response.CreateSuccessResponse($"An OTP has been sent to {email}.", CacheKeyLevel.NOT_REQUIRED, null!); } catch (Exception ex) { return await GB5Shared.ResponseStandard.Response.CreateExceptionError(ex, CacheKeyLevel.NOT_REQUIRED, null!, ex.Message, 500); } } [HttpPost("VerifyEMailOTP")] public async Task> VerifyOtp( ForgotPasswordRequest req) { try { const string sql = @" SELECT m.USERID AS UserId, m.USERCODE AS UserCode, m.USERNAME AS UserName, m.PRIMARYMAIL AS PrimaryMail FROM muser m WHERE m.USERCODE = @usercode; "; var users = await _IQueryExecutor.QueryAsync( req.ConnectionName!, sql, new { usercode = req.UserCode } ); var user = users.FirstOrDefault(); if (user == null) { throw new Exception($"User Not Found {req.UserCode}"); } string? primaryMail = user.PrimaryMail as string; if (string.IsNullOrWhiteSpace(primaryMail)) { throw new Exception($"{req.UserCode} User Has No Primary EMail"); } var valid = await _otpRedis.VerifyOtpAsync(primaryMail, req.EmailOTP!, req.ConnectionName!); if (!valid) { throw new Exception("Invalid or expired OTP"); } return await GB5Shared.ResponseStandard.Response.CreateSuccessResponse("OTP Verified Successfully", CacheKeyLevel.NOT_REQUIRED, null!); } catch (Exception ex) { return await GB5Shared.ResponseStandard.Response.CreateExceptionError(ex, CacheKeyLevel.NOT_REQUIRED, null!, ex.Message, 500); } } [HttpPost("UpdatePassword")] public async Task> UpdatePassword(ForgotPasswordRequest request) { if (string.IsNullOrWhiteSpace(request!.UserCode)) { throw new Exception("User code must be provided."); } if (string.IsNullOrWhiteSpace(request!.Password)) { throw new Exception("New password must be provided."); } if (string.IsNullOrWhiteSpace(request!.ConnectionName)) { throw new Exception("ConnectionName must be provided."); } try { string sql = @" UPDATE MUSER SET PASSWORD = @password WHERE USERCODE = @usercode; "; var parameters = new { password = request!.Password!, usercode = request!.UserCode! }; var rowsAffected = await _IQueryExecutor.QueryAsync( request.ConnectionName!, sql, parameters ); return await GB5Shared.ResponseStandard.Response.CreateSuccessResponse("Password has been updated successfully.", CacheKeyLevel.NOT_REQUIRED, null!); } catch (Exception ex) { return await GB5Shared.ResponseStandard.Response.CreateExceptionError(ex, CacheKeyLevel.NOT_REQUIRED, null!, ex.Message, 500); } } public class ForgotPasswordRequest { public string? Email { get; set; } = ""; public string? EmailOTP { get; set; } = ""; public string? UserCode { get; set; } = ""; public string? ConnectionName { get; set; } = ""; public string? Password { get; set; } } } }