QrRapido/Controllers/QRController.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

216 lines
7.6 KiB
C#

using Microsoft.AspNetCore.Mvc;
using QRRapidoApp.Models.ViewModels;
using QRRapidoApp.Services;
using System.Diagnostics;
using System.Security.Claims;
using System.Text;
namespace QRRapidoApp.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class QRController : ControllerBase
{
private readonly IQRCodeService _qrService;
private readonly IUserService _userService;
private readonly AdDisplayService _adService;
private readonly ILogger<QRController> _logger;
public QRController(IQRCodeService qrService, IUserService userService, AdDisplayService adService, ILogger<QRController> logger)
{
_qrService = qrService;
_userService = userService;
_adService = adService;
_logger = logger;
}
[HttpPost("GenerateRapid")]
public async Task<IActionResult> GenerateRapid([FromBody] QRGenerationRequest request)
{
var stopwatch = Stopwatch.StartNew();
try
{
// Quick validations
if (string.IsNullOrWhiteSpace(request.Content))
{
return BadRequest(new { error = "Conteúdo é obrigatório", success = false });
}
if (request.Content.Length > 4000) // Limit to maintain speed
{
return BadRequest(new { error = "Conteúdo muito longo. Máximo 4000 caracteres.", success = false });
}
// Check user status
var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
var user = await _userService.GetUserAsync(userId);
// Rate limiting for free users
if (!await CheckRateLimitAsync(userId, user))
{
return StatusCode(429, new
{
error = "Limite de QR codes atingido",
upgradeUrl = "/Premium/Upgrade",
success = false
});
}
// Configure optimizations based on user
request.IsPremium = user?.IsPremium == true;
request.OptimizeForSpeed = true;
// Generate QR code
var result = await _qrService.GenerateRapidAsync(request);
if (!result.Success)
{
return StatusCode(500, new { error = result.ErrorMessage, success = false });
}
// Update counter for free users
if (!request.IsPremium && userId != null)
{
var remaining = await _userService.DecrementDailyQRCountAsync(userId);
result.RemainingQRs = remaining;
}
// Save to history if user is logged in (fire and forget)
if (userId != null)
{
_ = Task.Run(async () =>
{
try
{
await _userService.SaveQRToHistoryAsync(userId, result);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error saving QR to history");
}
});
}
stopwatch.Stop();
// Performance logging
_logger.LogInformation($"QR Rapido generated in {stopwatch.ElapsedMilliseconds}ms " +
$"(service: {result.GenerationTimeMs}ms, " +
$"cache: {result.FromCache}, " +
$"user: {(request.IsPremium ? "premium" : "free")})");
return Ok(result);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in rapid QR code generation");
return StatusCode(500, new { error = "Erro interno do servidor", success = false });
}
}
[HttpGet("Download/{qrId}")]
public async Task<IActionResult> Download(string qrId, string format = "png")
{
try
{
var qrData = await _userService.GetQRDataAsync(qrId);
if (qrData == null)
{
return NotFound();
}
var contentType = format.ToLower() switch
{
"svg" => "image/svg+xml",
"pdf" => "application/pdf",
_ => "image/png"
};
var fileName = $"qrrapido-{DateTime.Now:yyyyMMdd-HHmmss}.{format}";
if (format.ToLower() == "svg")
{
var svgContent = await _qrService.ConvertToSvgAsync(qrData.QRCodeBase64);
return File(svgContent, contentType, fileName);
}
else if (format.ToLower() == "pdf")
{
var pdfContent = await _qrService.ConvertToPdfAsync(qrData.QRCodeBase64, qrData.Size);
return File(pdfContent, contentType, fileName);
}
var imageBytes = Convert.FromBase64String(qrData.QRCodeBase64);
return File(imageBytes, contentType, fileName);
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error downloading QR {qrId}");
return StatusCode(500);
}
}
[HttpPost("SaveToHistory")]
public async Task<IActionResult> SaveToHistory([FromBody] SaveToHistoryRequest request)
{
try
{
var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (string.IsNullOrEmpty(userId))
{
return Unauthorized();
}
var qrData = await _userService.GetQRDataAsync(request.QrId);
if (qrData == null)
{
return NotFound();
}
// QR is already saved when generated, just return success
return Ok(new { success = true, message = "QR Code salvo no histórico!" });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error saving QR to history");
return StatusCode(500, new { error = "Erro ao salvar no histórico." });
}
}
[HttpGet("History")]
public async Task<IActionResult> GetHistory(int limit = 20)
{
try
{
var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (string.IsNullOrEmpty(userId))
{
return Unauthorized();
}
var history = await _userService.GetUserQRHistoryAsync(userId, limit);
return Ok(history);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting QR history");
return StatusCode(500);
}
}
private async Task<bool> CheckRateLimitAsync(string? userId, Models.User? user)
{
if (user?.IsPremium == true) return true;
var dailyLimit = userId != null ? 50 : 10; // Logged in: 50/day, Anonymous: 10/day
var currentCount = await _userService.GetDailyQRCountAsync(userId);
return currentCount < dailyLimit;
}
}
public class SaveToHistoryRequest
{
public string QrId { get; set; } = string.Empty;
}
}