using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using PlotLine.Models; using PlotLine.Services; using PlotLine.ViewModels; namespace PlotLine.Controllers; public sealed class AccountController(IAuthService authService) : Controller { [HttpGet] [AllowAnonymous] public IActionResult Register(string? returnUrl = null) { return View(new RegisterViewModel()); } [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task Register(RegisterViewModel model) { if (!ModelState.IsValid) { return View(model); } RegistrationResult result; try { result = await authService.RegisterAsync(model); } catch { ModelState.AddModelError(string.Empty, "Your account could not be created because the verification email could not be sent. Please try again later."); return View(model); } if (!result.Success) { ModelState.AddModelError(string.Empty, result.ErrorMessage ?? "Registration could not be completed."); return View(model); } TempData["AuthMessage"] = "Your account has been created. Check your email to verify your address before signing in. If it does not arrive, use the resend verification email link below."; return RedirectToAction(nameof(Login)); } [HttpGet] [AllowAnonymous] public IActionResult Login(string? returnUrl = null) { return View(new LoginViewModel { ReturnUrl = returnUrl }); } [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task Login(LoginViewModel model) { if (!ModelState.IsValid) { return View(model); } var result = await authService.LoginAsync(model); if (!result.Success) { ModelState.AddModelError(string.Empty, result.ErrorMessage ?? "Login could not be completed."); return View(model); } if (!string.IsNullOrWhiteSpace(model.ReturnUrl) && Url.IsLocalUrl(model.ReturnUrl)) { return LocalRedirect(model.ReturnUrl); } return RedirectToAction("Index", "Home"); } [HttpPost] [ValidateAntiForgeryToken] public async Task Logout() { await authService.LogoutAsync(); return RedirectToAction("Index", "Home"); } [HttpGet] [AllowAnonymous] public IActionResult AccessDenied() { return View(); } [HttpGet] [AllowAnonymous] public async Task VerifyEmail(Guid token) { if (token == Guid.Empty) { return View(new AccountStatusViewModel { Success = false, Title = "Verification link problem", Message = "This verification link is not valid." }); } var result = await authService.VerifyEmailAsync(token); if (result.Success) { return RedirectToAction(nameof(VerifyEmailConfirmation)); } return View(new AccountStatusViewModel { Success = false, Title = "Verification link problem", Message = result.ErrorMessage ?? "This verification link could not be used." }); } [HttpGet] [AllowAnonymous] public IActionResult VerifyEmailConfirmation() { return View(); } [HttpGet] [AllowAnonymous] public IActionResult ForgotPassword() { return View(new ForgotPasswordViewModel()); } [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task ForgotPassword(ForgotPasswordViewModel model) { if (!ModelState.IsValid) { return View(model); } try { var result = await authService.ForgotPasswordAsync(model); if (!result.Success) { ModelState.AddModelError(string.Empty, "We could not send a password reset email right now. Please try again later."); return View(model); } } catch { ModelState.AddModelError(string.Empty, "We could not send a password reset email right now. Please try again later."); return View(model); } TempData["AuthMessage"] = "If an account exists for that email address, a password reset link has been sent."; return RedirectToAction(nameof(Login)); } [HttpGet] [AllowAnonymous] public IActionResult ResetPassword(Guid token) { if (token == Guid.Empty) { return View(new ResetPasswordViewModel()); } return View(new ResetPasswordViewModel { Token = token }); } [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task ResetPassword(ResetPasswordViewModel model) { if (!ModelState.IsValid) { return View(model); } var result = await authService.ResetPasswordAsync(model); if (!result.Success) { ModelState.AddModelError(string.Empty, result.ErrorMessage ?? "Your password could not be reset."); return View(model); } TempData["AuthMessage"] = "Your password has been reset. You can now log in."; return RedirectToAction(nameof(Login)); } [HttpGet] [AllowAnonymous] public IActionResult ResendVerificationEmail() { return View(new ResendVerificationEmailViewModel()); } [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task ResendVerificationEmail(ResendVerificationEmailViewModel model) { if (!ModelState.IsValid) { return View(model); } var result = await authService.ResendVerificationEmailAsync(model.Email); if (!result.Success) { ModelState.AddModelError(string.Empty, result.ErrorMessage ?? "We could not send the verification email right now. Please try again in a few minutes."); return View(model); } TempData["AuthMessage"] = "If an unverified account exists for that email address, a new verification email has been sent."; return View(new ResendVerificationEmailViewModel()); } }