using System.Security.Claims; using System.Text; using System.Text.Json; using Eshop.Application.Auth; using Eshop.Web.ViewModels; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace Eshop.Web.Controllers; public class AuthController : Controller { private readonly ILogger _logger; private readonly IAuthenticationService _authenticationService; private readonly IUserAccountService _userAccountService; public AuthController( ILogger logger, IAuthenticationService authenticationService, IUserAccountService userAccountService) { _logger = logger; _authenticationService = authenticationService; _userAccountService = userAccountService; } #region HttpGet [HttpGet] [AllowAnonymous] public IActionResult Login(string? returnUrl) { if (User.Identity?.IsAuthenticated == true) return RedirectToAction("Index", "Home"); return View(new AuthLoginViewModel { ReturnUrl = returnUrl }); } [HttpGet] [AllowAnonymous] public IActionResult Register(string? returnUrl) { if (User.Identity?.IsAuthenticated == true) return RedirectToAction("Index", "Home"); return View(new AuthRegisterViewModel { ReturnUrl = returnUrl }); } [HttpGet] public IActionResult AccessDenied() => View(); [HttpGet] [Authorize] public async Task Profile() { var userId = GetCurrentUserId(); if (userId is null) return RedirectToAction("Login"); var profile = await _userAccountService.GetProfileAsync(userId); if (profile is null) return RedirectToAction("Login"); return View(new ProfileViewModel { UserName = profile.UserName, Email = profile.Email, }); } #endregion #region HttpPost [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task Login(AuthLoginViewModel model) { if (!ModelState.IsValid) return View(model); var result = await _authenticationService.SignInAsync( model.EmailOrUsername, model.Password, model.RememberMe); if (!result.Succeeded) { ModelState.AddModelError(string.Empty, "Invalid credentials."); return View(model); } if (!string.IsNullOrEmpty(model.ReturnUrl) && Url.IsLocalUrl(model.ReturnUrl)) return Redirect(model.ReturnUrl); return RedirectToAction("Index", "Home"); } [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task Register(AuthRegisterViewModel model) { if (!ModelState.IsValid) return View(model); var result = await _userAccountService.RegisterAsync( model.UserName, model.Email, model.Password); if (!result.Success) { foreach (var error in result.Errors) ModelState.AddModelError(string.Empty, error); return View(model); } _logger.LogInformation("User {UserName} registered.", model.UserName); if (!string.IsNullOrEmpty(model.ReturnUrl) && Url.IsLocalUrl(model.ReturnUrl)) return Redirect(model.ReturnUrl); return RedirectToAction("Login"); } [HttpPost] [Authorize] [ValidateAntiForgeryToken] public async Task Profile(ProfileViewModel model) { if (!ModelState.IsValid) return View(model); var userId = GetCurrentUserId(); if (userId is null) return RedirectToAction("Login"); var result = await _userAccountService.UpdateProfileAsync( userId, new UpdateProfileRequest( model.UserName, model.Email, model.CurrentPassword, model.NewPassword)); if (!result.Success) { foreach (var error in result.Errors) ModelState.AddModelError(string.Empty, error); return View(model); } TempData["SuccessMessage"] = "Profile updated successfully."; return RedirectToAction("Profile"); } [HttpPost] [ValidateAntiForgeryToken] public async Task Logout() { await _authenticationService.SignOutAsync(); return RedirectToAction("Index", "Home"); } [HttpPost] [Authorize] [ValidateAntiForgeryToken] public async Task DeleteAccount() { var userId = GetCurrentUserId(); if (userId is null) return RedirectToAction("Login"); var result = await _userAccountService.DeleteAccountAsync(userId); if (!result.Success) { foreach (var error in result.Errors) ModelState.AddModelError(string.Empty, error); return RedirectToAction("Profile"); } _logger.LogInformation("User {UserId} deleted their account.", userId); return RedirectToAction("Register"); } [HttpGet] [Authorize] public async Task DownloadData() { var userId = GetCurrentUserId(); if (userId is null) return RedirectToAction("Login"); var data = await _userAccountService.ExportUserDataAsync(userId); if (data is null) return RedirectToAction("Login"); var export = new { data.Id, data.UserName, data.Email, Roles = data.Roles, data.ExportDate, }; var json = JsonSerializer.Serialize(export, new JsonSerializerOptions { WriteIndented = true }); var bytes = Encoding.UTF8.GetBytes(json); return File(bytes, "application/json", $"user_data_{data.UserName}.json"); } #endregion private string? GetCurrentUserId() => User.FindFirstValue(ClaimTypes.NameIdentifier); }