50 lines
1.6 KiB
C#
50 lines
1.6 KiB
C#
using ClaudeDo.Data.Repositories;
|
|
using ClaudeDo.Worker.Runner;
|
|
using Microsoft.AspNetCore.Http;
|
|
|
|
namespace ClaudeDo.Worker.Planning;
|
|
|
|
public sealed class PlanningTokenAuthMiddleware
|
|
{
|
|
private readonly RequestDelegate _next;
|
|
|
|
public PlanningTokenAuthMiddleware(RequestDelegate next) => _next = next;
|
|
|
|
public async Task InvokeAsync(HttpContext ctx, TaskRepository tasks, TaskRunTokenRegistry runTokens)
|
|
{
|
|
if (!ctx.Request.Path.StartsWithSegments("/mcp"))
|
|
{
|
|
await _next(ctx);
|
|
return;
|
|
}
|
|
|
|
var auth = ctx.Request.Headers["Authorization"].ToString();
|
|
if (!auth.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
ctx.Response.StatusCode = 401;
|
|
await ctx.Response.WriteAsync("Missing bearer token");
|
|
return;
|
|
}
|
|
|
|
var token = auth.Substring("Bearer ".Length).Trim();
|
|
|
|
var parent = await tasks.FindByPlanningTokenAsync(token, ctx.RequestAborted);
|
|
if (parent is not null && parent.PlanningPhase == ClaudeDo.Data.Models.PlanningPhase.Active)
|
|
{
|
|
ctx.Items["PlanningContext"] = new PlanningMcpContext { ParentTaskId = parent.Id };
|
|
await _next(ctx);
|
|
return;
|
|
}
|
|
|
|
if (runTokens.TryResolve(token, out var callerTaskId))
|
|
{
|
|
ctx.Items["TaskRunContext"] = new TaskRunMcpContext { CallerTaskId = callerTaskId };
|
|
await _next(ctx);
|
|
return;
|
|
}
|
|
|
|
ctx.Response.StatusCode = 401;
|
|
await ctx.Response.WriteAsync("Invalid or expired token");
|
|
}
|
|
}
|