BCards/src/BCards.Web/Middleware/PlanLimitationMiddleware.cs
2025-06-24 23:25:02 -03:00

127 lines
4.8 KiB
C#

using BCards.Web.Services;
using BCards.Web.Repositories;
using System.Security.Claims;
namespace BCards.Web.Middleware;
public class PlanLimitationMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<PlanLimitationMiddleware> _logger;
public PlanLimitationMiddleware(RequestDelegate next, ILogger<PlanLimitationMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context, IServiceProvider serviceProvider)
{
// Only check for authenticated users on specific endpoints
if (context.User.Identity?.IsAuthenticated == true && ShouldCheckLimitations(context))
{
using var scope = serviceProvider.CreateScope();
var authService = scope.ServiceProvider.GetRequiredService<IAuthService>();
var subscriptionRepository = scope.ServiceProvider.GetRequiredService<ISubscriptionRepository>();
var userPageRepository = scope.ServiceProvider.GetRequiredService<IUserPageRepository>();
try
{
var user = await authService.GetCurrentUserAsync(context.User);
if (user != null)
{
var subscription = await subscriptionRepository.GetByUserIdAsync(user.Id);
var limitations = GetPlanLimitations(subscription?.PlanType ?? "free");
// Check specific limitations based on the request
if (IsLinkCreationRequest(context))
{
var userPage = await userPageRepository.GetByUserIdAsync(user.Id);
var currentLinksCount = userPage?.Links?.Count(l => l.IsActive) ?? 0;
if (limitations.MaxLinks != -1 && currentLinksCount >= limitations.MaxLinks)
{
context.Response.StatusCode = 403;
await context.Response.WriteAsync("Limite de links atingido. Faça upgrade do seu plano.");
return;
}
}
// Add limitations to context for use in controllers
context.Items["PlanLimitations"] = limitations;
context.Items["CurrentSubscription"] = subscription;
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error checking plan limitations for user");
// Continue without blocking the request
}
}
await _next(context);
}
private static bool ShouldCheckLimitations(HttpContext context)
{
var path = context.Request.Path.Value?.ToLowerInvariant() ?? "";
return path.StartsWith("/admin/") ||
path.StartsWith("/api/") ||
(context.Request.Method == "POST" && path.Contains("/editpage"));
}
private static bool IsLinkCreationRequest(HttpContext context)
{
var path = context.Request.Path.Value?.ToLowerInvariant() ?? "";
return context.Request.Method == "POST" &&
(path.Contains("/editpage") || path.Contains("/addlink"));
}
private static Models.PlanLimitations GetPlanLimitations(string planType)
{
return planType.ToLower() switch
{
"basic" => new Models.PlanLimitations
{
MaxLinks = 5,
AllowCustomThemes = false,
AllowAnalytics = true,
AllowCustomDomain = false,
AllowMultipleDomains = false,
PrioritySupport = false,
PlanType = "basic"
},
"professional" => new Models.PlanLimitations
{
MaxLinks = 15,
AllowCustomThemes = false,
AllowAnalytics = true,
AllowCustomDomain = true,
AllowMultipleDomains = false,
PrioritySupport = false,
PlanType = "professional"
},
"premium" => new Models.PlanLimitations
{
MaxLinks = -1, // Unlimited
AllowCustomThemes = true,
AllowAnalytics = true,
AllowCustomDomain = true,
AllowMultipleDomains = true,
PrioritySupport = true,
PlanType = "premium"
},
_ => new Models.PlanLimitations
{
MaxLinks = 5,
AllowCustomThemes = false,
AllowAnalytics = false,
AllowCustomDomain = false,
AllowMultipleDomains = false,
PrioritySupport = false,
PlanType = "free"
}
};
}
}