QrRapido/Controllers/AccountController.cs
Ricardo Carneiro 2ccd35bb7d
Some checks failed
Deploy QR Rapido / test (push) Successful in 4m58s
Deploy QR Rapido / build-and-push (push) Failing after 1m39s
Deploy QR Rapido / deploy-staging (push) Has been skipped
Deploy QR Rapido / deploy-production (push) Has been skipped
first commit
2025-07-28 11:46:48 -03:00

242 lines
8.5 KiB
C#

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.Google;
using Microsoft.AspNetCore.Authentication.MicrosoftAccount;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using QRRapidoApp.Models.ViewModels;
using QRRapidoApp.Services;
using System.Security.Claims;
namespace QRRapidoApp.Controllers
{
public class AccountController : Controller
{
private readonly IUserService _userService;
private readonly AdDisplayService _adDisplayService;
private readonly ILogger<AccountController> _logger;
public AccountController(IUserService userService, AdDisplayService adDisplayService, ILogger<AccountController> logger)
{
_userService = userService;
_adDisplayService = adDisplayService;
_logger = logger;
}
[HttpGet]
public IActionResult Login(string returnUrl = "/")
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
[HttpGet]
public IActionResult LoginGoogle(string returnUrl = "/")
{
var properties = new AuthenticationProperties
{
RedirectUri = Url.Action("GoogleCallback"),
Items = { { "returnUrl", returnUrl } }
};
return Challenge(properties, GoogleDefaults.AuthenticationScheme);
}
[HttpGet]
public IActionResult LoginMicrosoft(string returnUrl = "/")
{
var properties = new AuthenticationProperties
{
RedirectUri = Url.Action("MicrosoftCallback"),
Items = { { "returnUrl", returnUrl } }
};
return Challenge(properties, MicrosoftAccountDefaults.AuthenticationScheme);
}
[HttpGet]
public async Task<IActionResult> GoogleCallback()
{
return await HandleExternalLoginCallbackAsync(GoogleDefaults.AuthenticationScheme);
}
[HttpGet]
public async Task<IActionResult> MicrosoftCallback()
{
return await HandleExternalLoginCallbackAsync(MicrosoftAccountDefaults.AuthenticationScheme);
}
private async Task<IActionResult> HandleExternalLoginCallbackAsync(string scheme)
{
try
{
var result = await HttpContext.AuthenticateAsync(scheme);
if (!result.Succeeded)
{
_logger.LogWarning($"External authentication failed for scheme {scheme}");
return RedirectToAction("Login");
}
var email = result.Principal?.FindFirst(ClaimTypes.Email)?.Value;
var name = result.Principal?.FindFirst(ClaimTypes.Name)?.Value;
var providerId = result.Principal?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(providerId))
{
_logger.LogWarning($"Missing required claims from {scheme} authentication");
return RedirectToAction("Login");
}
// Find or create user
var user = await _userService.GetUserByProviderAsync(scheme, providerId);
if (user == null)
{
user = await _userService.CreateUserAsync(email, name ?? email, scheme, providerId);
}
else
{
await _userService.UpdateLastLoginAsync(user.Id);
}
// Create application claims
var claims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, user.Id),
new Claim(ClaimTypes.Email, user.Email),
new Claim(ClaimTypes.Name, user.Name),
new Claim("Provider", user.Provider),
new Claim("IsPremium", user.IsPremium.ToString())
};
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
var authProperties = new AuthenticationProperties
{
IsPersistent = true,
ExpiresUtc = DateTimeOffset.UtcNow.AddDays(30)
};
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity), authProperties);
var returnUrl = result.Properties?.Items["returnUrl"] ?? "/";
return Redirect(returnUrl);
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error in external login callback for {scheme}");
return RedirectToAction("Login");
}
}
[HttpPost]
[Authorize]
public async Task<IActionResult> Logout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return RedirectToAction("Index", "Home");
}
[HttpGet]
[Authorize]
public async Task<IActionResult> Profile()
{
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (string.IsNullOrEmpty(userId))
{
return RedirectToAction("Login");
}
var user = await _userService.GetUserAsync(userId);
if (user == null)
{
return RedirectToAction("Login");
}
ViewBag.QRHistory = await _userService.GetUserQRHistoryAsync(userId, 10);
ViewBag.MonthlyQRCount = await _userService.GetQRCountThisMonthAsync(userId);
ViewBag.IsPremium = await _adDisplayService.HasValidPremiumSubscription(userId);
return View(user);
}
[HttpGet]
public async Task<IActionResult> AdFreeStatus()
{
var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (string.IsNullOrEmpty(userId))
{
return Json(new AdFreeStatusViewModel
{
IsAdFree = false,
TimeRemaining = 0,
IsPremium = false
});
}
var shouldShowAds = await _adDisplayService.ShouldShowAds(userId);
var isPremium = await _adDisplayService.HasValidPremiumSubscription(userId);
var expiryDate = await _adDisplayService.GetAdFreeExpiryDate(userId);
var status = await _adDisplayService.GetAdFreeStatusAsync(userId);
return Json(new AdFreeStatusViewModel
{
IsAdFree = !shouldShowAds,
TimeRemaining = isPremium ? int.MaxValue : 0,
IsPremium = isPremium,
ExpiryDate = expiryDate,
SessionType = status
});
}
[HttpPost]
[Authorize]
public async Task<IActionResult> ExtendAdFreeTime(int minutes)
{
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
// Método removido - sem extensão de tempo ad-free
return Json(new { success = false, message = "Feature not available" });
}
[HttpGet]
[Authorize]
public async Task<IActionResult> History()
{
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (string.IsNullOrEmpty(userId))
{
return RedirectToAction("Login");
}
var history = await _userService.GetUserQRHistoryAsync(userId, 50);
return View(history);
}
[HttpPost]
[Authorize]
public async Task<IActionResult> UpdatePreferences(string language)
{
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (string.IsNullOrEmpty(userId))
{
return Json(new { success = false });
}
try
{
var user = await _userService.GetUserAsync(userId);
if (user != null)
{
user.PreferredLanguage = language;
await _userService.UpdateUserAsync(user);
return Json(new { success = true });
}
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error updating preferences for user {userId}");
}
return Json(new { success = false });
}
}
}