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 _logger; public PlanLimitationMiddleware(RequestDelegate next, ILogger 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(); var subscriptionRepository = scope.ServiceProvider.GetRequiredService(); var userPageRepository = scope.ServiceProvider.GetRequiredService(); 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" } }; } }