163 lines
5.8 KiB
C#
163 lines
5.8 KiB
C#
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using QRRapidoApp.Models;
|
|
using QRRapidoApp.Services;
|
|
using System.Security.Claims;
|
|
|
|
namespace QRRapidoApp.Controllers
|
|
{
|
|
[Authorize]
|
|
[Route("Developer")]
|
|
[Route("es/Developer")]
|
|
[Route("en/Developer")]
|
|
public class DeveloperController : Controller
|
|
{
|
|
private readonly IUserService _userService;
|
|
private readonly StripeService _stripeService;
|
|
private readonly ILogger<DeveloperController> _logger;
|
|
|
|
public DeveloperController(
|
|
IUserService userService,
|
|
StripeService stripeService,
|
|
ILogger<DeveloperController> logger)
|
|
{
|
|
_userService = userService;
|
|
_stripeService = stripeService;
|
|
_logger = logger;
|
|
}
|
|
|
|
[HttpGet("")]
|
|
public async Task<IActionResult> Index()
|
|
{
|
|
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
|
if (string.IsNullOrEmpty(userId)) return Unauthorized();
|
|
|
|
var user = await _userService.GetUserAsync(userId);
|
|
if (user == null) return NotFound();
|
|
|
|
ViewBag.Culture = GetCulture();
|
|
return View(user);
|
|
}
|
|
|
|
[HttpPost("GenerateKey")]
|
|
[ValidateAntiForgeryToken]
|
|
public async Task<IActionResult> GenerateKey(string keyName)
|
|
{
|
|
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
|
if (string.IsNullOrEmpty(userId)) return Unauthorized();
|
|
|
|
if (string.IsNullOrWhiteSpace(keyName) || keyName.Length > 50)
|
|
{
|
|
TempData["Error"] = "Nome da chave inválido (máx. 50 caracteres).";
|
|
return Redirect(GetDevUrl());
|
|
}
|
|
|
|
var user = await _userService.GetUserAsync(userId);
|
|
if (user == null) return NotFound();
|
|
|
|
if (user.ApiKeys.Count(k => k.IsActive) >= 5)
|
|
{
|
|
TempData["Error"] = "Limite de 5 chaves ativas atingido. Revogue uma antes de criar outra.";
|
|
return Redirect(GetDevUrl());
|
|
}
|
|
|
|
var (rawKey, prefix) = await _userService.GenerateApiKeyAsync(userId, keyName.Trim());
|
|
|
|
_logger.LogInformation("API key '{Prefix}' generated for user {UserId}", prefix, userId);
|
|
|
|
TempData["NewKey"] = rawKey;
|
|
TempData["NewKeyName"] = keyName.Trim();
|
|
return RedirectToAction(nameof(Index));
|
|
}
|
|
|
|
[HttpGet("Pricing")]
|
|
public async Task<IActionResult> Pricing()
|
|
{
|
|
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
|
User? user = null;
|
|
if (!string.IsNullOrEmpty(userId))
|
|
user = await _userService.GetUserAsync(userId);
|
|
|
|
ViewBag.CurrentTier = user?.ApiSubscription?.EffectiveTier ?? ApiPlanTier.Free;
|
|
ViewBag.Culture = GetCulture();
|
|
return View();
|
|
}
|
|
|
|
[HttpPost("SubscribeApi")]
|
|
[ValidateAntiForgeryToken]
|
|
public async Task<IActionResult> SubscribeApi(string planTier)
|
|
{
|
|
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
|
if (string.IsNullOrEmpty(userId)) return Unauthorized();
|
|
|
|
if (!Enum.TryParse<ApiPlanTier>(planTier, out var tier) ||
|
|
tier == ApiPlanTier.Free ||
|
|
tier == ApiPlanTier.Enterprise)
|
|
{
|
|
TempData["Error"] = "Plano inválido selecionado.";
|
|
return Redirect(GetDevUrl("Pricing"));
|
|
}
|
|
|
|
try
|
|
{
|
|
var baseUrl = $"{Request.Scheme}://{Request.Host}";
|
|
var checkoutUrl = await _stripeService.CreateApiSubscriptionCheckoutAsync(userId, tier, baseUrl);
|
|
return Redirect(checkoutUrl);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error creating API subscription checkout for user {UserId}", userId);
|
|
TempData["Error"] = "Erro ao criar sessão de pagamento. Tente novamente.";
|
|
return Redirect(GetDevUrl("Pricing"));
|
|
}
|
|
}
|
|
|
|
[HttpPost("RevokeKey")]
|
|
[ValidateAntiForgeryToken]
|
|
public async Task<IActionResult> RevokeKey(string prefix)
|
|
{
|
|
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
|
if (string.IsNullOrEmpty(userId)) return Unauthorized();
|
|
|
|
if (string.IsNullOrWhiteSpace(prefix))
|
|
{
|
|
TempData["Error"] = "Chave inválida.";
|
|
return Redirect(GetDevUrl());
|
|
}
|
|
|
|
var revoked = await _userService.RevokeApiKeyAsync(userId, prefix);
|
|
|
|
if (revoked)
|
|
{
|
|
_logger.LogInformation("API key '{Prefix}' revoked by user {UserId}", prefix, userId);
|
|
TempData["Success"] = "Chave revogada com sucesso.";
|
|
}
|
|
else
|
|
{
|
|
TempData["Error"] = "Chave não encontrada ou já inativa.";
|
|
}
|
|
|
|
return RedirectToAction(nameof(Index));
|
|
}
|
|
private string GetCulture()
|
|
{
|
|
var path = Request.Path.Value ?? "";
|
|
if (path.StartsWith("/es/", StringComparison.OrdinalIgnoreCase) ||
|
|
string.Equals(path, "/es", StringComparison.OrdinalIgnoreCase)) return "es";
|
|
if (path.StartsWith("/en/", StringComparison.OrdinalIgnoreCase) ||
|
|
string.Equals(path, "/en", StringComparison.OrdinalIgnoreCase)) return "en";
|
|
return "pt-BR";
|
|
}
|
|
|
|
private string GetDevUrl(string action = "")
|
|
{
|
|
var base_ = GetCulture() switch {
|
|
"es" => "/es/Developer",
|
|
"en" => "/en/Developer",
|
|
_ => "/Developer"
|
|
};
|
|
return string.IsNullOrEmpty(action) ? base_ : $"{base_}/{action}";
|
|
}
|
|
}
|
|
}
|