identity: add proxy controller

This commit is contained in:
sam 2024-05-21 21:21:34 +02:00
parent 727f2f6ba2
commit b95fb76cd4
9 changed files with 446 additions and 10 deletions

View file

@ -0,0 +1,21 @@
using Foxchat.Core.Federation;
using Foxchat.Core.Models;
using Foxchat.Core.Models.Http;
using Foxchat.Identity.Middleware;
using Foxchat.Identity.Services;
using Microsoft.AspNetCore.Mvc;
namespace Foxchat.Identity.Controllers.Proxy;
[Route("/_fox/proxy/guilds")]
public class GuildsProxyController(
ILogger logger,
ChatInstanceResolverService chatInstanceResolverService,
RequestSigningService requestSigningService)
: ProxyControllerBase(logger, chatInstanceResolverService, requestSigningService)
{
[Authorize("chat_client")]
[HttpPost]
public Task<IActionResult> CreateGuild([FromBody] GuildsApi.CreateGuildRequest req) =>
Proxy<Guilds.Guild>(HttpMethod.Post, req);
}

View file

@ -0,0 +1,38 @@
using Foxchat.Core;
using Foxchat.Core.Federation;
using Foxchat.Identity.Middleware;
using Foxchat.Identity.Services;
using Microsoft.AspNetCore.Mvc;
namespace Foxchat.Identity.Controllers.Proxy;
[ApiController]
[ClientAuthenticate]
public class ProxyControllerBase(
ILogger logger,
ChatInstanceResolverService chatInstanceResolverService,
RequestSigningService requestSigningService) : ControllerBase
{
internal async Task<IActionResult> Proxy<TResponse>(HttpMethod method, object? body = null) where TResponse : class
{
var acct = HttpContext.GetAccountOrThrow();
var path = HttpContext.Request.Path.ToString();
if (!path.StartsWith("/_fox/proxy"))
throw new FoxchatError("Proxy<T> used for endpoint that does not start with /_fox/proxy");
path = $"/_fox/chat/{path[12..]}";
if (!HttpContext.Request.Headers.TryGetValue(RequestSigningService.SERVER_HEADER, out var serverHeader))
throw new ApiError.BadRequest($"Invalid or missing {RequestSigningService.SERVER_HEADER} header.");
var server = serverHeader.ToString();
logger.Debug("Proxying {Method} request to {Domain}{Path}", method, server, path);
// Identity instances always initiate federation, so we have to make sure the instance knows about us.
// This also serves as a way to make sure the instance being requested actually exists.
await chatInstanceResolverService.ResolveChatInstanceAsync(serverHeader.ToString());
var resp = await requestSigningService.RequestAsync<TResponse>(method, server, path, acct.Id.ToString(), body);
return Ok(resp);
}
}