using Data.SeaHavenIndustries; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; using Api.SeaHavenIndustries.DTOs; using Api.SeaHavenIndustries.Helper; using Microsoft.EntityFrameworkCore; namespace Api.SeaHavenIndustries.Controllers { [ApiController] [Route("api/Authentication")] public class AuthenticationController : Controller { private readonly UserManager _userManager; private readonly IConfiguration _configuration; private readonly ApplicationDbContext _db; private readonly SendMessage _sendMessage; public AuthenticationController(UserManager userManager, IConfiguration configuration, ApplicationDbContext db, SendMessage sendMessage) { _userManager = userManager; _configuration = configuration; _db = db; _sendMessage = sendMessage; } [AllowAnonymous] [HttpPost] [Route("login")] public async Task Login([FromBody] LoginModel model) { try { var user = await _userManager.FindByNameAsync(model.Username ?? ""); if (user != null && user.IsDeleted != true && await _userManager.CheckPasswordAsync(user, model.Password ?? "")) { // Standard login without 2FA var userRoles = await _userManager.GetRolesAsync(user); var authClaims = new List { new Claim(ClaimTypes.Name, user.UserName ?? ""), new Claim(ClaimTypes.NameIdentifier, user.Id), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) }; foreach (var userRole in userRoles) { authClaims.Add(new Claim(ClaimTypes.Role, userRole)); } var token = GetToken(authClaims); return Ok(new { token = new JwtSecurityTokenHandler().WriteToken(token), expiration = token.ValidTo, email = user.Email, userRoles = userRoles.FirstOrDefault(), phoneNumber = user.PhoneNumber, fullname = user.FirstName + " " + user.LastName, id = user.Id }); } // Invalid credentials return Unauthorized(); } catch (Exception ex) { return StatusCode(500, ex.Message); } } [Route("ChangePassword")] [HttpPost] public async Task ChangePassword(ChangePasswords usermodel) { var userid = User.FindFirstValue(ClaimTypes.NameIdentifier) ?? ""; var user = await _userManager.FindByIdAsync(userid); var result = await _userManager.ChangePasswordAsync(user, usermodel.Currentpassword ?? "", usermodel.Confirmpassword ?? ""); if (result.Succeeded) { return Ok(new Response { Status = "Success ", Message = "Password successfully changed" }); } else return BadRequest(new Response { Status = "Old Password is incorrect" }); } private JwtSecurityToken GetToken(List authClaims) { var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:Secret"] ?? "")); var token = new JwtSecurityToken( issuer: _configuration["JWT:ValidIssuer"], audience: _configuration["JWT:ValidAudience"], expires: DateTime.Now.AddDays(10), claims: authClaims, signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256) ); return token; } [HttpPost] [Route("UpdateProfile")] public async Task UserProfileUpdate([FromForm] User_DTO model) { try { var userid = User.FindFirstValue(ClaimTypes.NameIdentifier) ?? ""; ApplicationUser appuser = _db.Users.AsNoTracking().Where(u => u.Id == userid).FirstOrDefault() ?? new ApplicationUser(); appuser.FirstName = model.Name; appuser.Email = model.Email; appuser.Contact = model.Contact; _db.Users.Update(appuser); await _db.SaveChangesAsync(); return Ok(new DataResponse { Message = "Introduction Updated Successfully", Status = "200", Data = _db.Users.Where(u => u.Id == userid).Select(s => new { s.FirstName, //s.Location, s.Email, s.Contact }).FirstOrDefault() }); } catch (Exception ex) { return BadRequest(new Response { Status = "Error", Message = ex.Message }); } } #region Forget Password Area [AllowAnonymous] [HttpPost()] [Route("ForgetPassword")] public async Task ForgetPassword(string Email) { var user = await _db.Users.Where(u => u.Email.ToLower().Trim() == Email.ToLower().ToLower()).FirstOrDefaultAsync(); if (user != null) { if (_db.ForgetPasswordCodes.Where(u => u.Email.ToLower().Trim() == Email.ToLower().Trim()).Any()) { _db.ForgetPasswordCodes.Remove(_db.ForgetPasswordCodes.Where(u => u.Email.ToLower().Trim() == Email.ToLower().Trim()).FirstOrDefault()); _db.SaveChanges(); } ForgetPasswordCode forgetPasswordCode = new ForgetPasswordCode(); forgetPasswordCode.Email = user.Email ?? ""; forgetPasswordCode.UserId = user.Id; forgetPasswordCode.Code = GenerateRandomNo(); _db.ForgetPasswordCodes.Add(forgetPasswordCode); _db.SaveChanges(); string body = $"Your Password Reset Code is: " + forgetPasswordCode.Code; await _sendMessage.SendEMail(user.Email, "Forget Password Request.", body); return Ok(new Response { Status = "Success ", Message = "Please check your email for code" }); } else { return BadRequest(new Response { Status = "Error", Message = "No such email is registered" }); } } //need email and code [AllowAnonymous] [HttpPost()] [Route("VerificationCode")] public async Task VerificationCode(string code) { try { if (await _db.ForgetPasswordCodes.Where(u => u.Code == code).AnyAsync()) { return Ok(new Response { Status = "Success ", Message = "Code Matched" }); } else { return BadRequest(new Response { Status = "Error", Message = "Code Not Matched" }); } } catch (Exception ex) { return BadRequest(new Response { Status = "Error", Message = "Error: " + ex.Message }); } } // need email, password and code [AllowAnonymous] [HttpPost()] [Route("ResetPassword")] public async Task ResetPassword(ForgetPassword_Dto fpdto) { try { if (_db.ForgetPasswordCodes.Where(u => u.Email.ToLower().Trim() == fpdto.Email.ToLower().Trim() && u.Code == fpdto.Code.Trim()).Any()) { var GetUser = _db.ForgetPasswordCodes.Where(u => u.Email.ToLower().Trim() == fpdto.Email.ToLower().Trim()).FirstOrDefault(); var user = await _userManager.FindByIdAsync(GetUser.UserId); var token = await _userManager.GeneratePasswordResetTokenAsync(user); var result = await _userManager.ResetPasswordAsync(user, token, fpdto.Password); return Ok(new Response { Status = "Success ", Message = "password changed" }); } else { return BadRequest(new Response { Status = "Error", Message = "Your email or code not found please check" }); } } catch (Exception ex) { return BadRequest(new Response { Status = "Error", Message = "Error: " + ex.Message }); } } private Random _random = new Random(); private string GenerateRandomNo() { return _random.Next(0, 999999).ToString("D6"); } #endregion } }