using System.Security.Claims; using Microsoft.AspNetCore.Mvc; namespace backend.Pairing; public record IssueCodeRequest(string Name); public record PairRequest(string Code, string Hostname, string Client_version); public static class PairingEndpoints { public static IEndpointRouteBuilder MapPairingEndpoints(this IEndpointRouteBuilder app) { app.MapPost("/api/pair-code", async ( [FromBody] IssueCodeRequest req, PairingService svc, HttpContext http, CancellationToken ct) => { var uidStr = http.User.FindFirstValue(ClaimTypes.NameIdentifier); if (!Guid.TryParse(uidStr, out var uid)) return Results.Unauthorized(); if (string.IsNullOrWhiteSpace(req.Name)) return Results.BadRequest(new { error = "name is required" }); var pc = await svc.IssueAsync(uid, req.Name.Trim(), ct); return Results.Ok(new { code = pc.Code, expires_at = pc.ExpiresAt }); }).RequireAuthorization(); app.MapPost("/api/pair", async ( [FromBody] PairRequest req, PairingService svc, HttpContext http, CancellationToken ct) => { var result = await svc.ConsumeAsync(req.Code, ct); if (result is null) return Results.NotFound(new { error = "code invalid or expired" }); var scheme = http.Request.Scheme == "https" ? "wss" : "ws"; var host = http.Request.Host.ToString(); return Results.Ok(new { device_id = result.DeviceId, device_token = result.DeviceToken, backend_ws = $"{scheme}://{host}/device", }); }); return app; } }