TheInfinityIQ_GCP/src/gcp-backend/GCP.Api/Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs
#nullable disable

using System.ComponentModel.DataAnnotations;

using GCP.Api.Data.Entities;

using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace GCP.Api.Areas.Identity.Pages.Account
{
	public class LoginWith2faModel : PageModel
	{
		private readonly SignInManager<User> _signInManager;
		private readonly UserManager<User> _userManager;
		private readonly ILogger<LoginWith2faModel> _logger;

		public LoginWith2faModel(
			SignInManager<User> signInManager,
			UserManager<User> userManager,
			ILogger<LoginWith2faModel> logger)
		{
			_signInManager = signInManager;
			_userManager = userManager;
			_logger = logger;
		}

		[BindProperty]
		public InputModel Input { get; set; }

		public bool RememberMe { get; set; }
		public string ReturnUrl { get; set; }

		public class InputModel
		{
			[Required]
			[StringLength(7, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
			[DataType(DataType.Text)]
			[Display(Name = "Authenticator code")]
			public string TwoFactorCode { get; set; }

			[Display(Name = "Remember this machine")]
			public bool RememberMachine { get; set; }
		}

		public async Task<IActionResult> OnGetAsync(bool rememberMe, string returnUrl = null)
		{
			// Ensure the user has gone through the username & password screen first
			var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();

			if (user is null)
			{
				throw new InvalidOperationException($"Unable to load two-factor authentication user.");
			}

			ReturnUrl = returnUrl;
			RememberMe = rememberMe;

			return Page();
		}

		public async Task<IActionResult> OnPostAsync(bool rememberMe, string returnUrl = null)
		{
			if (!ModelState.IsValid)
			{
				return Page();
			}

			returnUrl ??= Url.Content("~/");

			var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
			if (user is null)
			{
				throw new InvalidOperationException($"Unable to load two-factor authentication user.");
			}

			var authenticatorCode = Input.TwoFactorCode.Replace(" ", string.Empty).Replace("-", string.Empty);

			var result = await _signInManager.TwoFactorAuthenticatorSignInAsync(authenticatorCode, rememberMe, Input.RememberMachine);

			var userId = await _userManager.GetUserIdAsync(user);

			if (result.Succeeded)
			{
				_logger.LogInformation("User with ID '{UserId}' logged in with 2fa.", user.Id);
				return LocalRedirect(returnUrl);
			}
			else if (result.IsLockedOut)
			{
				_logger.LogWarning("User with ID '{UserId}' account locked out.", user.Id);
				return RedirectToPage("./Lockout");
			}
			else
			{
				_logger.LogWarning("Invalid authenticator code entered for user with ID '{UserId}'.", user.Id);
				ModelState.AddModelError(string.Empty, "Invalid authenticator code.");
				return Page();
			}
		}
	}
}
