[backend/federation] Handle reject activity

This commit is contained in:
Laura Hausmann 2024-02-06 21:07:51 +01:00
parent 333ef6f7cd
commit e0b6fa3bff
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
3 changed files with 34 additions and 6 deletions

View file

@ -43,11 +43,14 @@ public class ActivityHandlerService(
}
case ASActivity.Types.Accept: {
if (activity.Object is { } obj) return AcceptAsync(obj, activity.Actor);
throw GracefulException.UnprocessableEntity("Follow activity object is invalid");
throw GracefulException.UnprocessableEntity("Accept activity object is invalid");
}
case ASActivity.Types.Reject: {
if (activity.Object is { } obj) return RejectAsync(obj, activity.Actor);
throw GracefulException.UnprocessableEntity("Reject activity object is invalid");
}
case ASActivity.Types.Undo: {
//TODO: implement the rest
//TODO: test if this actually works
if (activity.Object is ASActivity { Type: ASActivity.Types.Follow, Object: not null } undoActivity)
return UnfollowAsync(undoActivity.Object, activity.Actor);
throw new NotImplementedException("Unsupported undo operation");
@ -119,6 +122,7 @@ public class ActivityHandlerService(
}
private async Task UnfollowAsync(ASObject followeeActor, ASObject followerActor) {
//TODO: send reject? or do we not want to copy that part of the old ap core
var follower = await userResolver.ResolveAsync(followerActor.Id);
var followee = await userResolver.ResolveAsync(followeeActor.Id);
@ -129,7 +133,7 @@ public class ActivityHandlerService(
private async Task AcceptAsync(ASObject obj, ASObject actor) {
var prefix = $"https://{config.Value.WebDomain}/follows/";
if (!obj.Id.StartsWith(prefix))
throw GracefulException.UnprocessableEntity($"Object id '{obj.Id}' not a valid follow request");
throw GracefulException.UnprocessableEntity($"Object id '{obj.Id}' not a valid follow request id");
var resolvedActor = await userResolver.ResolveAsync(actor.Id);
var ids = obj.Id[prefix.Length..].TrimEnd('/').Split("/");
@ -161,4 +165,19 @@ public class ActivityHandlerService(
await db.AddAsync(following);
await db.SaveChangesAsync();
}
private async Task RejectAsync(ASObject obj, ASObject actor) {
if (obj is not ASFollow { Actor: not null } follow)
throw GracefulException.UnprocessableEntity("Refusing to reject object with invalid follow object");
var resolvedActor = await userResolver.ResolveAsync(actor.Id);
var resolvedFollower = await userResolver.ResolveAsync(follow.Actor.Id);
if (resolvedFollower is not { Host: null })
throw GracefulException.UnprocessableEntity("Refusing to reject remote follow");
await db.FollowRequests.Where(p => p.Followee == resolvedActor && p.Follower == resolvedFollower)
.ExecuteDeleteAsync();
await db.Followings.Where(p => p.Followee == resolvedActor && p.Follower == resolvedFollower)
.ExecuteDeleteAsync();
}
}

View file

@ -27,6 +27,14 @@ public class ASActivity : ASObject {
}
}
public class ASCreate : ASActivity {
public ASCreate() => Type = Types.Create;
}
public class ASDelete : ASActivity {
public ASDelete() => Type = Types.Delete;
}
public class ASFollow : ASActivity {
public ASFollow() => Type = Types.Follow;
}

View file

@ -23,12 +23,13 @@ public class ASObject {
ASActor.Types.Organization => token.ToObject<ASActor>(),
ASActor.Types.Application => token.ToObject<ASActor>(),
ASNote.Types.Note => token.ToObject<ASNote>(),
ASActivity.Types.Create => token.ToObject<ASActivity>(),
ASActivity.Types.Delete => token.ToObject<ASActivity>(),
ASActivity.Types.Create => token.ToObject<ASCreate>(),
ASActivity.Types.Delete => token.ToObject<ASDelete>(),
ASActivity.Types.Follow => token.ToObject<ASFollow>(),
ASActivity.Types.Unfollow => token.ToObject<ASUnfollow>(),
ASActivity.Types.Accept => token.ToObject<ASAccept>(),
ASActivity.Types.Undo => token.ToObject<ASActivity>(),
ASActivity.Types.Reject => token.ToObject<ASReject>(),
ASActivity.Types.Undo => token.ToObject<ASUndo>(),
ASActivity.Types.Like => token.ToObject<ASActivity>(),
_ => token.ToObject<ASObject>()
},