using FlatRender.IdentitySvc.Application.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace FlatRender.IdentitySvc.Controllers; /// Service-to-service endpoints (render-svc → identity). Auth via shared service token, /// reachable only on the internal network (the gateway does not route /v1/internal). [ApiController] [AllowAnonymous] [Route("v1/internal")] public class InternalController(AdminService svc, IConfiguration config) : ControllerBase { public record ChargeReq(Guid UserId); private bool ServiceTokenValid() { var expected = config["ServiceToken"] ?? Environment.GetEnvironmentVariable("SERVICE_TOKEN") ?? "internal-service-secret"; var got = Request.Headers["X-Service-Token"].ToString(); if (string.IsNullOrEmpty(got)) { var auth = Request.Headers["Authorization"].ToString(); if (auth.StartsWith("Bearer ", StringComparison.Ordinal)) got = auth[7..]; } return !string.IsNullOrEmpty(got) && got == expected; } [HttpPost("render-charge/consume")] public async Task Consume([FromBody] ChargeReq req) { if (!ServiceTokenValid()) return Unauthorized(); var (allowed, remaining) = await svc.ConsumeRenderChargeAsync(req.UserId); return Ok(new { allowed, remaining }); } [HttpPost("render-charge/refund")] public async Task Refund([FromBody] ChargeReq req) { if (!ServiceTokenValid()) return Unauthorized(); await svc.RefundRenderChargeAsync(req.UserId); return Ok(new { ok = true }); } }