using Nuuru.Server.Services; namespace Nuuru.Server.Middleware { public class PowCheckMiddleware { private readonly RequestDelegate _next; public PowCheckMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context, IPowService powService) { if (!powService.IsEnabled) { await _next(context); return; } var path = context.Request.Path.Value ?? string.Empty; // Only gate API requests if (!path.StartsWith("/api/", StringComparison.OrdinalIgnoreCase)) { await _next(context); return; } // Skip POW endpoints themselves if (path.StartsWith("/api/pow/", StringComparison.OrdinalIgnoreCase)) { await _next(context); return; } // Skip SignalR hubs if (path.StartsWith("/api/hubs/", StringComparison.OrdinalIgnoreCase)) { await _next(context); return; } // Skip SSR requests (Node.js server) if (powService.IsSsrRequest(context)) { await _next(context); return; } // Validate pow_token cookie var token = context.Request.Cookies["pow_token"]; var clientIp = context.Connection.RemoteIpAddress?.ToString() ?? "unknown"; if (!string.IsNullOrEmpty(token) && powService.ValidateCookieToken(token, clientIp)) { await _next(context); return; } // POW required context.Response.StatusCode = 449; context.Response.ContentType = "application/json"; await context.Response.WriteAsJsonAsync(new { error = "pow_required" }); } } }