[backend/federation] Enforce note visibility checks in AP controller

This commit is contained in:
Laura Hausmann 2024-02-12 05:09:06 +01:00
parent c5d773e46a
commit a1fbe6f9b5
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
4 changed files with 24 additions and 4 deletions

View file

@ -28,7 +28,11 @@ public class ActivityPubController : Controller {
[ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(ErrorResponse))] [ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(ErrorResponse))]
public async Task<IActionResult> GetNote(string id, [FromServices] DatabaseContext db, public async Task<IActionResult> GetNote(string id, [FromServices] DatabaseContext db,
[FromServices] NoteRenderer noteRenderer) { [FromServices] NoteRenderer noteRenderer) {
var note = await db.Notes.IncludeCommonProperties().FirstOrDefaultAsync(p => p.Id == id); var actor = HttpContext.GetActor();
var note = await db.Notes
.IncludeCommonProperties()
.EnsureVisibleFor(actor)
.FirstOrDefaultAsync(p => p.Id == id);
if (note == null) return NotFound(); if (note == null) return NotFound();
var rendered = await noteRenderer.RenderAsync(note); var rendered = await noteRenderer.RenderAsync(note);
var compacted = LdHelpers.Compact(rendered); var compacted = LdHelpers.Compact(rendered);

View file

@ -13,8 +13,8 @@ public class NoteRenderer(IOptions<Config.InstanceSection> config, MfmConverter
public async Task<ASNote> RenderAsync(Note note, List<Note.MentionedUser>? mentions = null) { public async Task<ASNote> RenderAsync(Note note, List<Note.MentionedUser>? mentions = null) {
var id = $"https://{config.Value.WebDomain}/notes/{note.Id}"; var id = $"https://{config.Value.WebDomain}/notes/{note.Id}";
var userId = $"https://{config.Value.WebDomain}/users/{note.User.Id}"; var userId = $"https://{config.Value.WebDomain}/users/{note.User.Id}";
var replyId = note.ReplyId != null var replyId = note.Reply != null
? new ASObjectBase($"https://{config.Value.WebDomain}/notes/{note.ReplyId}") ? new ASObjectBase(note.Reply.Uri ?? $"https://{config.Value.WebDomain}/notes/{note.ReplyId}")
: null; : null;
mentions ??= await db.Users mentions ??= await db.Users

View file

@ -65,7 +65,7 @@ public class AuthenticateAttribute(params string[] scopes) : Attribute {
public readonly string[] Scopes = scopes; public readonly string[] Scopes = scopes;
} }
public static class HttpContextExtensions { public static partial class HttpContextExtensions {
private const string Key = "session"; private const string Key = "session";
private const string MastodonKey = "masto-session"; private const string MastodonKey = "masto-session";

View file

@ -2,6 +2,7 @@ using System.Diagnostics.CodeAnalysis;
using System.Net; using System.Net;
using Iceshrimp.Backend.Core.Configuration; using Iceshrimp.Backend.Core.Configuration;
using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Database;
using Iceshrimp.Backend.Core.Database.Tables;
using Iceshrimp.Backend.Core.Federation.Cryptography; using Iceshrimp.Backend.Core.Federation.Cryptography;
using Iceshrimp.Backend.Core.Services; using Iceshrimp.Backend.Core.Services;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@ -65,6 +66,8 @@ public class AuthorizedFetchMiddleware(
//TODO: re-fetch key once if signature validation fails, to properly support key rotation //TODO: re-fetch key once if signature validation fails, to properly support key rotation
//TODO: Check for LD signature as well //TODO: Check for LD signature as well
ctx.SetActor(key.User);
} }
await next(ctx); await next(ctx);
@ -74,3 +77,16 @@ public class AuthorizedFetchMiddleware(
public class AuthorizedFetchAttribute(bool forceBody = false) : Attribute { public class AuthorizedFetchAttribute(bool forceBody = false) : Attribute {
public bool ForceBody { get; } = forceBody; public bool ForceBody { get; } = forceBody;
} }
public static partial class HttpContextExtensions {
private const string ActorKey = "auth-fetch-user";
internal static void SetActor(this HttpContext ctx, User actor) {
ctx.Items.Add(ActorKey, actor);
}
public static User? GetActor(this HttpContext ctx) {
ctx.Items.TryGetValue(ActorKey, out var actor);
return actor as User;
}
}