242 lines
8.5 KiB
C#
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 });
|
|
}
|
|
}
|
|
} |