From 6e7d23c1aec60317e7989aaf5cafa08112d49cc0 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Sun, 28 Nov 2021 20:09:29 +1100 Subject: [PATCH] add remote follow button --- bookwyrm/templates/user/layout.html | 3 +++ bookwyrm/urls.py | 3 ++- bookwyrm/views/__init__.py | 2 +- bookwyrm/views/follow.py | 34 +++++++++++++++-------------- bookwyrm/views/helpers.py | 27 +++++++++++++++++++++++ 5 files changed, 51 insertions(+), 18 deletions(-) diff --git a/bookwyrm/templates/user/layout.html b/bookwyrm/templates/user/layout.html index d7557ae7b..03e3dfce8 100755 --- a/bookwyrm/templates/user/layout.html +++ b/bookwyrm/templates/user/layout.html @@ -39,6 +39,9 @@ {% if not is_self and request.user.is_authenticated %} {% include 'snippets/follow_button.html' with user=user %} {% endif %} + {% if not is_self %} + {% include 'ostatus/remote_follow_button.html' with user=user %} + {% endif %} {% if is_self and user.follower_requests.all %}
diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index 79e6e2a98..48fe0f6cc 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -451,6 +451,7 @@ urlpatterns = [ re_path(r"^unfollow/?$", views.unfollow, name="unfollow"), re_path(r"^accept-follow-request/?$", views.accept_follow_request), re_path(r"^delete-follow-request/?$", views.delete_follow_request), - # re_path(r"^ostatus_follow/?$", views.remote_follow), + re_path(r"^ostatus_follow/?$", views.remote_follow, name="remote-follow"), + re_path(r"^remote_follow/?$", views.remote_follow_page, name="remote-follow-page"), re_path(r"^ostatus_success/?$", views.ostatus_follow_success, name="ostatus-success"), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py index 034b1830a..3b5bf8232 100644 --- a/bookwyrm/views/__init__.py +++ b/bookwyrm/views/__init__.py @@ -58,7 +58,7 @@ from .author import Author, EditAuthor from .directory import Directory from .discover import Discover from .feed import DirectMessage, Feed, Replies, Status -from .follow import follow, unfollow, ostatus_follow_request, ostatus_follow_success +from .follow import follow, unfollow, ostatus_follow_request, ostatus_follow_success, remote_follow, remote_follow_page from .follow import accept_follow_request, delete_follow_request from .get_started import GetStartedBooks, GetStartedProfile, GetStartedUsers from .goal import Goal, hide_goal diff --git a/bookwyrm/views/follow.py b/bookwyrm/views/follow.py index 471fe3079..ce0238d67 100644 --- a/bookwyrm/views/follow.py +++ b/bookwyrm/views/follow.py @@ -8,7 +8,7 @@ from django.template.response import TemplateResponse from django.views.decorators.http import require_POST from bookwyrm import models -from .helpers import get_user_from_username, handle_remote_webfinger +from .helpers import get_user_from_username, handle_remote_webfinger, subscribe_remote_webfinger @login_required @@ -134,33 +134,35 @@ def ostatus_follow_success(request): } return TemplateResponse(request, "ostatus/success.html", data) -@login_required -@require_POST -def remote_follow(request): - """complete an incoming remote follow request""" +def remote_follow_page(request): + """Display remote follow page""" # this is triggered from remote follow form # attempt the follow request # on success [[return success page]] # on fail return [[ostatus_error]] + user = get_user_from_username(request.user, request.GET.get("user")) + data = { + "user": user + } + return TemplateResponse(request, "ostatus/remote_follow.html", data) +@require_POST +def remote_follow(request): + """direct user to follow from remote account using ostatus subscribe protocol""" + remote_user = request.POST.get("remote_user") + template = subscribe_remote_webfinger(remote_user) + url = template.replace("{uri}", request.POST.get("user")) + return redirect(url) """ REQUEST TO FOLLOW FROM REMOTE ACCOUNT 1. click remote follow button [default checked option to open new window] 2. popup new small window -3. enter user acct to follow from (user@domain.tld) and submit form -5. GET {base_url}/.well-known/webfinger/?resource=acct:{user@domain.tld} -6. parse json for links -6.1 rel="http://ostatus.org/schema/1.0/subscribe" and return 'template' -6.2 rel="self" and return href -7. replace '{uri}' in the returned string with self.href -8. GET the URI at 6.1 + REQUEST TO FOLLOW FROM LOCAL ACCOUNT -1. receive request to /ostatus_subscribe?acct={uri} -2. check user is logged in and present confirmation screen (remote_follow_request) -3. On confirmation, 3. parse user into info needed for a normal follow -4. send follow request, on 200 response display success else display error (remote_follow) + +4. send follow request, on 200 response display success else display error 5. Include button inviting to close window """ diff --git a/bookwyrm/views/helpers.py b/bookwyrm/views/helpers.py index f28d01023..607181489 100644 --- a/bookwyrm/views/helpers.py +++ b/bookwyrm/views/helpers.py @@ -84,6 +84,33 @@ def handle_remote_webfinger(query): return None return user +def subscribe_remote_webfinger(query): + """get subscribe template from other servers""" + template = None + + # usernames could be @user@domain or user@domain + if not query: + return None + + if query[0] == "@": + query = query[1:] + + try: + domain = query.split("@")[1] + except IndexError: + return None + + url = f"https://{domain}/.well-known/webfinger?resource=acct:{query}" + try: + data = get_data(url) + except (ConnectorException, HTTPError): + return None + + for link in data.get("links"): + if link.get("rel") == "http://ostatus.org/schema/1.0/subscribe": + template = link["template"] + + return template def get_edition(book_id): """look up a book in the db and return an edition"""