From 20662a90dd2e2aee18d7095d741c0c741585b585 Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Fri, 13 Mar 2020 17:04:39 +0000 Subject: [PATCH] Generate Reject activities. Work on checking incoming / outgoing will work alone. --- fedireads/activitypub/__init__.py | 2 +- fedireads/activitypub/follow.py | 24 ++++++++++++++++-- fedireads/incoming.py | 41 ++++++++++++++++++------------- fedireads/outgoing.py | 13 ++++++---- fedireads/view_actions.py | 21 ++++++++-------- 5 files changed, 66 insertions(+), 35 deletions(-) diff --git a/fedireads/activitypub/__init__.py b/fedireads/activitypub/__init__.py index 50424b8fe..05ac4aedc 100644 --- a/fedireads/activitypub/__init__.py +++ b/fedireads/activitypub/__init__.py @@ -3,6 +3,6 @@ from .actor import get_actor from .collection import get_outbox, get_outbox_page, get_add, get_remove, \ get_following, get_followers from .create import get_create -from .follow import get_follow_request, get_unfollow, get_accept +from .follow import get_follow_request, get_unfollow, get_accept, get_reject from .status import get_review, get_review_article, get_status, get_replies, \ get_favorite, get_add_tag, get_remove_tag, get_replies_page diff --git a/fedireads/activitypub/follow.py b/fedireads/activitypub/follow.py index 0c5d39382..04a71ef40 100644 --- a/fedireads/activitypub/follow.py +++ b/fedireads/activitypub/follow.py @@ -32,13 +32,33 @@ def get_unfollow(relationship): } -def get_accept(user, request_activity): +def get_accept(user, relationship): ''' accept a follow request ''' return { '@context': 'https://www.w3.org/ns/activitystreams', 'id': '%s#accepts/follows/' % user.absolute_id, 'type': 'Accept', 'actor': user.actor, - 'object': request_activity, + 'object': { + 'id': relationship.relationship_id, + 'type': 'Follow', + 'actor': relationship.user_subject.actor, + 'object': relationship.user_object.actor, + } } + +def get_reject(user, relationship): + ''' reject a follow request ''' + return { + '@context': 'https://www.w3.org/ns/activitystreams', + 'id': '%s#rejects/follows/' % user.absolute_id, + 'type': 'Reject', + 'actor': user.actor, + 'object': { + 'id': relationship.relationship_id, + 'type': 'Follow', + 'actor': relationship.user_subject.actor, + 'object': relationship.user_object.actor, + } + } diff --git a/fedireads/incoming.py b/fedireads/incoming.py index ee0e12e07..2d3b1bdb8 100644 --- a/fedireads/incoming.py +++ b/fedireads/incoming.py @@ -54,6 +54,8 @@ def shared_inbox(request): elif activity['type'] == 'Add': response = handle_incoming_add(activity) + elif activity['type'] == 'Reject': + response = handle_incoming_follow_reject(activity) # TODO: Add, Undo, Remove, etc @@ -218,7 +220,7 @@ def handle_incoming_follow(activity): user = get_or_create_remote_user(activity['actor']) # TODO: allow users to manually approve requests try: - models.UserFollowRequest.objects.create( + request = models.UserFollowRequest.objects.create( user_subject=user, user_object=to_follow, relationship_id=activity['id'] @@ -231,7 +233,7 @@ def handle_incoming_follow(activity): if not to_follow.manually_approves_followers: create_notification(to_follow, 'FOLLOW', related_user=user) - outgoing.handle_outgoing_accept(user, to_follow, activity) + outgoing.handle_outgoing_accept(user, to_follow, request) else: create_notification(to_follow, 'FOLLOW_REQUEST', related_user=user) return HttpResponse() @@ -260,10 +262,29 @@ def handle_incoming_follow_accept(activity): # figure out who they are accepter = get_or_create_remote_user(activity['actor']) - accepter.followers.add(requester) + try: + request = models.UserFollowRequest.objects.get(user_subject=requester, user_object=accepter) + request.delete() + except models.UserFollowRequest.DoesNotExist: + pass + else: + accepter.followers.add(requester) return HttpResponse() +def handle_incoming_follow_reject(activity): + ''' someone is rejecting a follow request ''' + requester = models.User.objects.get(actor=activity['object']['actor']) + rejecter = get_or_create_remote_user(activity['actor']) + + try: + request = models.UserFollowRequest.objects.get(user_subject=requester, user_object=rejecter) + request.delete() + except models.UserFollowRequest.DoesNotExist: + pass + + return HttpResponse() + def handle_incoming_create(activity): ''' someone did something, good on them ''' user = get_or_create_remote_user(activity['actor']) @@ -331,17 +352,3 @@ def handle_incoming_add(activity): return HttpResponse() return HttpResponse() return HttpResponseNotFound() - - -def handle_incoming_accept(activity): - ''' someone is accepting a follow request ''' - # our local user - user = models.User.objects.get(actor=activity['actor']) - # the person our local user wants to follow, who said yes - followed = get_or_create_remote_user(activity['object']['actor']) - - # save this relationship in the db - followed.followers.add(user) - - return HttpResponse() - diff --git a/fedireads/outgoing.py b/fedireads/outgoing.py index 75e8d7340..6a66c5f6d 100644 --- a/fedireads/outgoing.py +++ b/fedireads/outgoing.py @@ -99,20 +99,23 @@ def handle_outgoing_unfollow(user, to_unfollow): raise(error['error']) -def handle_outgoing_accept(user, to_follow, request_activity): +def handle_outgoing_accept(user, to_follow, follow_request): ''' send an acceptance message to a follow request ''' with transaction.atomic(): - follow_request = models.UserFollowRequest.objects.get( - relationship_id=request_activity['id'] - ) relationship = models.UserFollows.from_request(follow_request) follow_request.delete() relationship.save() - activity = activitypub.get_accept(to_follow, request_activity) + activity = activitypub.get_accept(to_follow, follow_request) recipient = get_recipients(to_follow, 'direct', direct_recipients=[user]) broadcast(to_follow, activity, recipient) +def handle_outgoing_reject(user, to_follow, relationship): + relationship.delete() + + activity = activitypub.get_reject(to_follow, relationship) + recipient = get_recipients(to_follow, 'direct', direct_recipients=[user]) + broadcast(to_follow, activity, recipient) def handle_shelve(user, book, shelf): ''' a local user is getting a book put on their shelf ''' diff --git a/fedireads/view_actions.py b/fedireads/view_actions.py index d173c80ba..a1e34d979 100644 --- a/fedireads/view_actions.py +++ b/fedireads/view_actions.py @@ -171,13 +171,15 @@ def accept_follow_request(request): except models.User.DoesNotExist: return HttpResponseBadRequest() - follow_request = models.UserFollowRequest.objects.get(user_subject=requester, user_object=request.user) - # We don't keep a full copy of the follow request, but a minimal copy is good enough for now. - follow_activity = {'id': follow_request.relationship_id} - outgoing.handle_outgoing_accept(requester, request.user, follow_activity) - user_slug = requester.localname if requester.localname \ - else requester.username - return redirect('/user/%s' % user_slug) + try: + follow_request = models.UserFollowRequest.objects.get(user_subject=requester, user_object=request.user) + except models.UserFollowRequest.DoesNotExist: + # Request already dealt with. + pass + else: + outgoing.handle_outgoing_accept(requester, request.user, follow_request) + + return redirect('/user/%s' % request.user.localname) @login_required def delete_follow_request(request): @@ -189,9 +191,8 @@ def delete_follow_request(request): try: follow_request = models.UserFollowRequest.objects.get(user_subject=requester, user_object=request.user) - follow_request.delete() - # Generate a Reject activity here. except models.UserFollowRequest.DoesNotExist: - pass + return HttpResponseBadRequest() + outgoing.handle_outgoing_reject(requester, request.user, follow_request) return redirect('/user/%s' % request.user.localname)