[backend/federation] Enforce JSON-LD profile for activities (and make them acceptable to begin with)

This commit is contained in:
Laura Hausmann 2024-02-17 16:17:39 +01:00
parent 6044cdb52c
commit 2b141f8084
No known key found for this signature in database
GPG key ID: D044E84C5BE01605

View file

@ -1,3 +1,4 @@
using System.Net.Http.Headers;
using Iceshrimp.Backend.Core.Database.Tables; using Iceshrimp.Backend.Core.Database.Tables;
using Iceshrimp.Backend.Core.Federation.ActivityStreams; using Iceshrimp.Backend.Core.Federation.ActivityStreams;
using Iceshrimp.Backend.Core.Federation.ActivityStreams.Types; using Iceshrimp.Backend.Core.Federation.ActivityStreams.Types;
@ -10,6 +11,11 @@ namespace Iceshrimp.Backend.Core.Federation.ActivityPub;
public class ActivityFetcherService(HttpClient client, HttpRequestService httpRqSvc, SystemUserService systemUserSvc) public class ActivityFetcherService(HttpClient client, HttpRequestService httpRqSvc, SystemUserService systemUserSvc)
{ {
private static readonly IReadOnlyCollection<string> AcceptableActivityTypes =
[
"application/activity+json", "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
];
private static readonly JsonSerializerSettings JsonSerializerSettings = new(); private static readonly JsonSerializerSettings JsonSerializerSettings = new();
//FIXME: not doing this breaks ld signatures, but doing this breaks mapping the object to datetime properties //FIXME: not doing this breaks ld signatures, but doing this breaks mapping the object to datetime properties
//new() { DateParseHandling = DateParseHandling.None }; //new() { DateParseHandling = DateParseHandling.None };
@ -22,12 +28,11 @@ public class ActivityFetcherService(HttpClient client, HttpRequestService httpRq
public async Task<IEnumerable<ASObject>> FetchActivityAsync(string url, User actor, UserKeypair keypair) public async Task<IEnumerable<ASObject>> FetchActivityAsync(string url, User actor, UserKeypair keypair)
{ {
var request = httpRqSvc.GetSigned(url, ["application/activity+json"], actor, keypair); var request = httpRqSvc.GetSigned(url, AcceptableActivityTypes, actor, keypair);
var response = await client.SendAsync(request); var response = await client.SendAsync(request);
if (!response.IsSuccessStatusCode) return []; if (!response.IsSuccessStatusCode) return [];
if (response.Content.Headers.ContentType?.MediaType if (!IsValidActivityContentType(response.Content.Headers.ContentType))
is not "application/activity+json" and not "application/ld+json")
return []; return [];
var finalUri = response.RequestMessage?.RequestUri ?? var finalUri = response.RequestMessage?.RequestUri ??
@ -48,6 +53,17 @@ public class ActivityFetcherService(HttpClient client, HttpRequestService httpRq
return activities; return activities;
} }
private static bool IsValidActivityContentType(MediaTypeHeaderValue? headersContentType) =>
headersContentType switch
{
{ MediaType: "application/activity+json" } => true,
{ MediaType: "application/ld+json" } when headersContentType.Parameters.Any(p => p is
{
Name: "profile", Value: "https://www.w3.org/ns/activitystreams"
}) => true,
_ => false
};
public async Task<ASActor> FetchActorAsync(string uri, User actor, UserKeypair keypair) public async Task<ASActor> FetchActorAsync(string uri, User actor, UserKeypair keypair)
{ {
var activity = await FetchActivityAsync(uri, actor, keypair); var activity = await FetchActivityAsync(uri, actor, keypair);