using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.RateLimiting; using Nuuru.Server.Services; namespace Nuuru.Server.Controllers { [ApiController] [Route("api/pow")] [AllowAnonymous] [EnableRateLimiting("pow")] public class PowController : ControllerBase { private readonly IPowService _powService; public PowController(IPowService powService) { _powService = powService; } [HttpGet("challenge")] public IActionResult GetChallenge() { var challenge = _powService.IssueChallenge(); return Ok(challenge); } [HttpPost("verify")] public IActionResult Verify([FromBody] PowVerifyRequest request) { if (string.IsNullOrWhiteSpace(request.ChallengeId) || string.IsNullOrWhiteSpace(request.Challenge) || string.IsNullOrWhiteSpace(request.Nonce)) return BadRequest(new { error = "Missing challengeId, challenge, or nonce" }); var valid = _powService.ValidateSolution(request.ChallengeId, request.Challenge, request.Nonce); if (!valid) return BadRequest(new { error = "Invalid solution" }); var clientIp = HttpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown"; var token = _powService.IssueCookieToken(clientIp); Response.Cookies.Append("pow_token", token, new CookieOptions { HttpOnly = true, Secure = true, SameSite = SameSiteMode.Lax, Path = "/", MaxAge = TimeSpan.FromDays(1), }); return Ok(new { success = true }); } } public class PowVerifyRequest { public string ChallengeId { get; set; } = string.Empty; public string Challenge { get; set; } = string.Empty; public string Nonce { get; set; } = string.Empty; } }