using Application.Endpoints; using Application.Endpoints.Authorization; using Application.Endpoints.Authorization.Doctor; using Application.Endpoints.Authorization.Patient; using Application.Services.Database.PostgreSQL; using Application.Services.Email; using Application.Services.HashingAlgorithms; using Application.Services.Jwt; using Core.Entities; using Microsoft.AspNetCore.Mvc; namespace API.Controllers; [Route("api/[controller]")] public class AuthorizationController : BaseApiController { private readonly IJwtService _jwtService; private readonly IEmailService _emailService; private readonly IPatientRepository _patientRepository; private readonly IDoctorRepository _doctorRepository; private readonly IHashingAlgorithms _hashingAlgorithms; public AuthorizationController(IEmailService emailService, IJwtService jwtService, IPatientRepository patientRepository, IDoctorRepository doctorRepository, IHashingAlgorithms hashingAlgorithms) { _jwtService = jwtService; _emailService = emailService; _patientRepository = patientRepository; _doctorRepository = doctorRepository; _hashingAlgorithms = hashingAlgorithms; } [HttpPost("login")] public async Task> Login(UserLoginModel dto) { BaseResponse? response = null; var loginInfo = new LoginDto(); loginInfo.Email = dto.Email; loginInfo.Password = dto.Password; switch (dto.UserType) { case "doctor": var handlerDoctor = new DoctorLoginHandler(_doctorRepository, _hashingAlgorithms); response = await handlerDoctor.Handle(loginInfo).ConfigureAwait(false); if (response.Data != null) { Doctor patient = (Doctor)response.Data; var authToken = _jwtService.GenerateJwtToken(patient.Email); Console.WriteLine(patient.Email); HttpContext.Response.Headers.Add("Authorization", $"Bearer {authToken}"); } break; case "patient": var handlerPatient = new PatientLoginHandler(_patientRepository, _hashingAlgorithms); response = await handlerPatient.Handle(loginInfo).ConfigureAwait(false); if (response.Data != null) { Patient patient = (Patient)response.Data; var authToken = _jwtService.GenerateJwtToken(patient.Email); HttpContext.Response.Headers.Add("Authorization", $"Bearer {authToken}"); } break; default: return new ActionResult(new BaseResponse { StatusCode = HttpStatusCodes.BadRequest, Message = "Need user type.", Data = null }); } return StatusCode(response.StatusCode, response); } [HttpPost("reset_password")] public async Task> ResetPassword(UserLoginModel dto) { BaseResponse? response = null; var loginInfo = new LoginDto(); loginInfo.Email = dto.Email; loginInfo.Password = dto.Password; switch (dto.UserType) { case "doctor": var handlerDoctor = new DoctorResetPasswordHandler(_doctorRepository, _hashingAlgorithms); response = await handlerDoctor.Handle(loginInfo).ConfigureAwait(false); break; case "patient": var handlerPatient = new PatientResetPasswordHandler(_patientRepository, _hashingAlgorithms); response = await handlerPatient.Handle(loginInfo).ConfigureAwait(false); break; default: return new ActionResult(new BaseResponse { StatusCode = HttpStatusCodes.BadRequest, Message = "Need user type.", Data = null }); } if (response.StatusCode < HttpStatusCodes.BadRequest) { var body = _emailService.GenerateResetCredentialsEmailBody( loginInfo.Email, loginInfo.Password); await _emailService.SendEmailAsync(loginInfo.Email, "Password reset successfully!", body); } return StatusCode(response.StatusCode, response); } [HttpPost("refresh_token")] public async Task> RefreshToken() { var authorizationHeader = Request.Headers["Authorization"].FirstOrDefault(); if (string.IsNullOrEmpty(authorizationHeader) || !authorizationHeader.StartsWith("Bearer ")) return StatusCode(HttpStatusCodes.BadRequest, new BaseResponse { StatusCode = HttpStatusCodes.BadRequest, Message = "Invalid request header format.", Data = null }); var oldToken = authorizationHeader.Substring("Bearer ".Length).Trim(); if (!_jwtService.ValidateJwtToken(oldToken)) return StatusCode(HttpStatusCodes.Unauthorized, new BaseResponse { StatusCode = HttpStatusCodes.Unauthorized, Message = "Invalid JWT token.", Data = null }); var newToken = _jwtService.RefreshToken(oldToken); return StatusCode(HttpStatusCodes.OK, new BaseResponse { StatusCode = HttpStatusCodes.OK, Message = "Token refreshed successfully.", Data = new { Token = newToken } }); } }