247 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			247 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System.Net;
 | 
						|
using Marco.Pms.DataAccess.Data;
 | 
						|
using Marco.Pms.Model.Authentication;
 | 
						|
using Marco.Pms.Model.Dtos;
 | 
						|
using Marco.Pms.Model.Dtos.Util;
 | 
						|
using Marco.Pms.Model.Employees;
 | 
						|
using Marco.Pms.Model.Entitlements;
 | 
						|
using Marco.Pms.Model.Utilities;
 | 
						|
using MarcoBMS.Services.Helpers;
 | 
						|
using MarcoBMS.Services.Service;
 | 
						|
using Microsoft.AspNetCore.Identity;
 | 
						|
using Microsoft.AspNetCore.Mvc;
 | 
						|
using Microsoft.EntityFrameworkCore;
 | 
						|
 | 
						|
namespace MarcoBMS.Services.Controllers
 | 
						|
{
 | 
						|
    [ApiController]
 | 
						|
    [Route("api/[controller]")]
 | 
						|
    public class AuthController : ControllerBase
 | 
						|
    {
 | 
						|
        private readonly UserManager<ApplicationUser> _userManager;
 | 
						|
        private readonly ApplicationDbContext _context;
 | 
						|
        private readonly JwtSettings _jwtSettings;
 | 
						|
        private readonly RefreshTokenService _refreshTokenService;
 | 
						|
        private readonly IEmailSender _emailSender;
 | 
						|
        private readonly IConfiguration _configuration;
 | 
						|
        private readonly EmployeeHelper _employeeHelper;
 | 
						|
        //string tenentId = "1";
 | 
						|
        public AuthController(UserManager<ApplicationUser> userManager, ApplicationDbContext context, JwtSettings jwtSettings, RefreshTokenService refreshTokenService,
 | 
						|
            IEmailSender emailSender, IConfiguration configuration, EmployeeHelper employeeHelper)
 | 
						|
        {
 | 
						|
            _userManager = userManager;
 | 
						|
            _jwtSettings = jwtSettings;
 | 
						|
            _refreshTokenService = refreshTokenService;
 | 
						|
            _emailSender = emailSender;
 | 
						|
            _configuration = configuration;
 | 
						|
            _employeeHelper = employeeHelper;
 | 
						|
            _context = context;
 | 
						|
        }
 | 
						|
 | 
						|
        [HttpPost("login")]
 | 
						|
        public async Task<IActionResult> Login([FromBody] LoginDto loginDto)
 | 
						|
        {
 | 
						|
            var user = await _context.ApplicationUsers.FirstOrDefaultAsync(u => u.Email == loginDto.Username || u.PhoneNumber == loginDto.Username);
 | 
						|
 | 
						|
            if (user != null)
 | 
						|
            {
 | 
						|
                if (!user.IsActive)
 | 
						|
                {
 | 
						|
                    return BadRequest(ApiResponse<object>.ErrorResponse("User is In Active", "User is In Active", 400));
 | 
						|
                }
 | 
						|
                if (!user.EmailConfirmed)
 | 
						|
                {
 | 
						|
                    return BadRequest(ApiResponse<object>.ErrorResponse("Your email is not verified, Please verify your email", "Your email is not verified, Please verify your email", 400));
 | 
						|
                }
 | 
						|
                if (await _userManager.CheckPasswordAsync(user, loginDto.Password ?? string.Empty))
 | 
						|
                {
 | 
						|
                    Employee emp = await _employeeHelper.GetEmployeeByApplicationUserID(user.Id);
 | 
						|
                    //var refreshToken = GenerateRefreshToken();
 | 
						|
                    if (user.UserName == null) return NotFound(ApiResponse<object>.ErrorResponse("UserName Not found", "UserName Not found", 404)); ;
 | 
						|
 | 
						|
                    var token = _refreshTokenService.GenerateJwtToken(user.UserName, emp.TenantId, _jwtSettings);
 | 
						|
 | 
						|
                    var refreshToken = await _refreshTokenService.CreateRefreshToken(user.Id, emp.TenantId.ToString(), _jwtSettings);
 | 
						|
 | 
						|
                    return Ok(ApiResponse<object>.SuccessResponse(new { token = token, refreshToken = refreshToken }, "User logged in successfully.", 200));
 | 
						|
                }
 | 
						|
 | 
						|
            }
 | 
						|
 | 
						|
            return Unauthorized(ApiResponse<object>.ErrorResponse("Invalid username or password.", "Invalid username or password.", 401));
 | 
						|
        }
 | 
						|
 | 
						|
        [HttpPost("logout")]
 | 
						|
        public async Task<IActionResult> Logout([FromBody] LogoutDto logoutDto)
 | 
						|
        {
 | 
						|
            if (string.IsNullOrEmpty(logoutDto.RefreshToken))
 | 
						|
            {
 | 
						|
                return BadRequest(ApiResponse<object>.ErrorResponse("Refresh token is required", "Refresh token is required", 400));
 | 
						|
 | 
						|
            }
 | 
						|
 | 
						|
            try
 | 
						|
            {
 | 
						|
                // Revoke the refresh token
 | 
						|
                bool isRevoked = await _refreshTokenService.RevokeRefreshTokenAsync(logoutDto.RefreshToken);
 | 
						|
 | 
						|
                if (!isRevoked)
 | 
						|
                    return Unauthorized(ApiResponse<object>.ErrorResponse("Invalid or expired refresh token", "Invalid or expired refresh token", 401));
 | 
						|
 | 
						|
 | 
						|
                // Optional: Blacklist the access token (JWT)
 | 
						|
                string jwtToken = HttpContext.Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
 | 
						|
                if (!string.IsNullOrEmpty(jwtToken))
 | 
						|
                {
 | 
						|
                    await _refreshTokenService.BlacklistJwtTokenAsync(jwtToken);
 | 
						|
                }
 | 
						|
                return Ok(ApiResponse<object>.SuccessResponse(new { }, "Logged out successfully", 200));
 | 
						|
            }
 | 
						|
            catch (Exception ex)
 | 
						|
            {
 | 
						|
                // _logger.LogError(ex, "Error during logout");
 | 
						|
                return BadRequest(ApiResponse<object>.ErrorResponse("Internal server error", ex.Message, 500));
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        [HttpPost("refresh-token")]
 | 
						|
        public async Task<IActionResult> RefreshToken([FromBody] RefreshTokenDto refreshTokenDto)
 | 
						|
        {
 | 
						|
            var refreshToken = await _refreshTokenService.GetRefreshToken(refreshTokenDto.RefreshToken);
 | 
						|
            if (refreshToken == null || refreshToken.ExpiryDate < DateTime.UtcNow)
 | 
						|
            {
 | 
						|
                return Unauthorized(ApiResponse<object>.ErrorResponse("Invalid or expired refresh token.", "Invalid or expired refresh token.", 401));
 | 
						|
            }
 | 
						|
 | 
						|
            // Mark token as used
 | 
						|
            await _refreshTokenService.MarkRefreshTokenAsUsed(refreshToken);
 | 
						|
 | 
						|
            // Generate new JWT token and refresh token
 | 
						|
            var user = await _userManager.FindByIdAsync(refreshToken.UserId ?? string.Empty);
 | 
						|
            if (user == null)
 | 
						|
                return BadRequest(ApiResponse<object>.ErrorResponse("Invalid request.", "Invalid request.", 400));
 | 
						|
 | 
						|
            Employee emp = await _employeeHelper.GetEmployeeByApplicationUserID(user.Id);
 | 
						|
 | 
						|
            if (user.UserName == null) return NotFound(ApiResponse<object>.ErrorResponse("UserName Not found", "UserName Not found", 404));
 | 
						|
 | 
						|
            var newJwtToken = _refreshTokenService.GenerateJwtToken(user.UserName, emp.TenantId, _jwtSettings);
 | 
						|
            var newRefreshToken = await _refreshTokenService.CreateRefreshToken(user.Id, emp.TenantId.ToString(), _jwtSettings);
 | 
						|
 | 
						|
            return Ok(ApiResponse<object>.SuccessResponse(new { token = newJwtToken, refreshToken = newRefreshToken }, "User refresh token generated successfully.", 200));
 | 
						|
        }
 | 
						|
 | 
						|
        [HttpPost("forgot-password")]
 | 
						|
        public async Task<IActionResult> ForgotPassword([FromBody] ForgotPasswordDto forgotPasswordDto)
 | 
						|
        {
 | 
						|
            var user = await _userManager.FindByEmailAsync(forgotPasswordDto.Email);
 | 
						|
            if (user == null)
 | 
						|
                return NotFound(ApiResponse<object>.ErrorResponse("User not found.", "User not found.", 404));
 | 
						|
 | 
						|
            /* SEND USER REGISTRATION MAIL*/
 | 
						|
            var token = await _userManager.GeneratePasswordResetTokenAsync(user);
 | 
						|
            var resetLink = $"{_configuration["AppSettings:WebFrontendUrl"]}/reset-password?token={WebUtility.UrlEncode(token)}";
 | 
						|
 | 
						|
            if (user.Email == null) return NotFound(ApiResponse<object>.ErrorResponse("Email Not found", "Email Not found", 404));
 | 
						|
 | 
						|
            await _emailSender.SendResetPasswordEmail(user.Email, "", resetLink);
 | 
						|
 | 
						|
 | 
						|
            return Ok(ApiResponse<object>.SuccessResponse(true, "Password reset link sent.", 200));
 | 
						|
        }
 | 
						|
 | 
						|
        [HttpPost("reset-password")]
 | 
						|
        public async Task<IActionResult> ResetPassword([FromBody] ResetPasswordDto model)
 | 
						|
        {
 | 
						|
            var user = await _userManager.FindByEmailAsync(model.Email ?? string.Empty);
 | 
						|
            if (user == null)
 | 
						|
                return BadRequest(ApiResponse<object>.ErrorResponse("Invalid request.", "Invalid request.", 400));
 | 
						|
 | 
						|
            // var isTokenValid = await _userManager.VerifyUserTokenAsync(user,UserManager<ApplicationUser>.ResetPasswordTokenPurpose, model.ResetCode);
 | 
						|
            var isTokenValid = await _userManager.VerifyUserTokenAsync(
 | 
						|
                    user,
 | 
						|
                    TokenOptions.DefaultProvider, // This is the token provider
 | 
						|
                    UserManager<ApplicationUser>.ResetPasswordTokenPurpose,
 | 
						|
                   WebUtility.UrlDecode(model.Token)
 | 
						|
                );
 | 
						|
            string token = "";
 | 
						|
 | 
						|
            if (!isTokenValid)
 | 
						|
            {
 | 
						|
                var isDecodedTokenValid = await _userManager.VerifyUserTokenAsync(
 | 
						|
                    user,
 | 
						|
                    TokenOptions.DefaultProvider, // This is the token provider
 | 
						|
                    UserManager<ApplicationUser>.ResetPasswordTokenPurpose,
 | 
						|
                   model.Token
 | 
						|
                );
 | 
						|
                if (!isDecodedTokenValid)
 | 
						|
                    return BadRequest(ApiResponse<object>.ErrorResponse("Invalid request.", "Invalid request.", 400));
 | 
						|
 | 
						|
                token = model.Token;
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                token = WebUtility.UrlDecode(model.Token);
 | 
						|
            }
 | 
						|
 | 
						|
 | 
						|
            var result = await _userManager.ResetPasswordAsync(user, token, model.NewPassword ?? string.Empty);
 | 
						|
            if (!result.Succeeded)
 | 
						|
            {
 | 
						|
                var errors = result.Errors.Select(e => e.Description).ToList();
 | 
						|
                return BadRequest(ApiResponse<object>.ErrorResponse("Failed to Change password", errors, 400));
 | 
						|
            }
 | 
						|
 | 
						|
            try
 | 
						|
            {
 | 
						|
                Employee emp = await _employeeHelper.GetEmployeeByApplicationUserID(user.Id);
 | 
						|
                await _emailSender.SendResetPasswordSuccessEmail(user.Email ?? string.Empty, emp.FirstName + " " + emp.LastName);
 | 
						|
            }
 | 
						|
            catch (Exception ex)
 | 
						|
            {
 | 
						|
                return BadRequest(ApiResponse<object>.ErrorResponse(ex.Message, ex.Message, 400));
 | 
						|
            }
 | 
						|
 | 
						|
 | 
						|
            return Ok(ApiResponse<object>.SuccessResponse(result.Succeeded, "Password reset successfully.", 200));
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
 | 
						|
        [HttpPost("sendmail")]
 | 
						|
        public async Task<IActionResult> SendEmail([FromBody] EmailDot emailDot)
 | 
						|
        {
 | 
						|
 | 
						|
 | 
						|
 | 
						|
            var user = await _userManager.FindByEmailAsync(emailDot.ToEmail ?? string.Empty);
 | 
						|
            if (user == null)
 | 
						|
            {
 | 
						|
                return NotFound(ApiResponse<object>.ErrorResponse("User not found.", "User not found.", 404));
 | 
						|
            }
 | 
						|
 | 
						|
            /* New User*/
 | 
						|
            //var token = await _userManager.GeneratePasswordResetTokenAsync(user);
 | 
						|
            //var resetLink = $"{_configuration["AppSettings:WebFrontendUrl"]}/reset-password?token={WebUtility.UrlEncode(token)}";
 | 
						|
 | 
						|
            //await _emailSender.SendResetPasswordEmailOnRegister(emailDot.ToEmail, "Vikas", resetLink);
 | 
						|
 | 
						|
 | 
						|
            /* Forget password*/
 | 
						|
            // var token = await _userManager.GeneratePasswordResetTokenAsync(user);
 | 
						|
 | 
						|
            var token = await _userManager.GenerateUserTokenAsync(user, TokenOptions.DefaultProvider, "ResetPassword");
 | 
						|
 | 
						|
            var isTokenValid = await _userManager.VerifyUserTokenAsync(user, TokenOptions.DefaultProvider, "ResetPassword", token);
 | 
						|
 | 
						|
            var resetLink = $"{_configuration["AppSettings:WebFrontendUrl"]}/reset-password?token={WebUtility.UrlEncode(token)}";
 | 
						|
 | 
						|
            if (user.Email == null) return NotFound(ApiResponse<object>.ErrorResponse("Email Not found", "Email Not found", 404));
 | 
						|
 | 
						|
            await _emailSender.SendResetPasswordEmail(user.Email, "", resetLink);
 | 
						|
 | 
						|
            return Ok(ApiResponse<object>.SuccessResponse(new { }, "Password reset link sent.", 200));
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |