From 139416d9c37762e51b7b07a4e2969bcfbf2a3aa1 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 13 Mar 2021 10:58:54 -0800 Subject: [PATCH] Moves federation info endpoints into views module --- bookwyrm/tests/views/test_user.py | 1 - bookwyrm/tests/views/test_wellknown.py | 84 ++++++++++++++++++++++++++ bookwyrm/urls.py | 12 ++-- bookwyrm/views/__init__.py | 3 +- bookwyrm/{ => views}/wellknown.py | 31 ++++------ 5 files changed, 103 insertions(+), 28 deletions(-) create mode 100644 bookwyrm/tests/views/test_wellknown.py rename bookwyrm/{ => views}/wellknown.py (86%) diff --git a/bookwyrm/tests/views/test_user.py b/bookwyrm/tests/views/test_user.py index 596ea8bf7..426c1a791 100644 --- a/bookwyrm/tests/views/test_user.py +++ b/bookwyrm/tests/views/test_user.py @@ -5,7 +5,6 @@ from PIL import Image from django.contrib.auth.models import AnonymousUser from django.core.files.base import ContentFile -from django.core.files.uploadedfile import SimpleUploadedFile from django.template.response import TemplateResponse from django.test import TestCase from django.test.client import RequestFactory diff --git a/bookwyrm/tests/views/test_wellknown.py b/bookwyrm/tests/views/test_wellknown.py new file mode 100644 index 000000000..f408460f5 --- /dev/null +++ b/bookwyrm/tests/views/test_wellknown.py @@ -0,0 +1,84 @@ +""" test for app action functionality """ +import json +from unittest.mock import patch + +from django.contrib.auth.models import AnonymousUser +from django.http import JsonResponse +from django.test import TestCase +from django.test.client import RequestFactory + +from bookwyrm import models, views + + +class UserViews(TestCase): + """ view user and edit profile """ + + def setUp(self): + """ we need basic test data and mocks """ + self.factory = RequestFactory() + self.local_user = models.User.objects.create_user( + "mouse@local.com", + "mouse@mouse.mouse", + "password", + local=True, + localname="mouse", + ) + models.User.objects.create_user( + "rat@local.com", "rat@rat.rat", "password", local=True, localname="rat" + ) + with patch("bookwyrm.models.user.set_remote_server.delay"): + models.User.objects.create_user( + "rat", + "rat@remote.com", + "ratword", + local=False, + remote_id="https://example.com/users/rat", + inbox="https://example.com/users/rat/inbox", + outbox="https://example.com/users/rat/outbox", + ) + models.SiteSettings.objects.create() + self.anonymous_user = AnonymousUser + self.anonymous_user.is_authenticated = False + + def test_webfinger(self): + """ there are so many views, this just makes sure it LOADS """ + request = self.factory.get("", {"resource": "acct:mouse@local.com"}) + request.user = self.anonymous_user + + result = views.webfinger(request) + self.assertIsInstance(result, JsonResponse) + data = json.loads(result.getvalue()) + self.assertEqual(data["subject"], "acct:mouse@local.com") + + def test_nodeinfo_pointer(self): + """ just tells you where nodeinfo is """ + request = self.factory.get("") + request.user = self.anonymous_user + + result = views.nodeinfo_pointer(request) + data = json.loads(result.getvalue()) + self.assertIsInstance(result, JsonResponse) + self.assertTrue("href" in data["links"][0]) + + def test_nodeinfo(self): + """ info about the instance """ + request = self.factory.get("") + request.user = self.anonymous_user + + result = views.nodeinfo(request) + data = json.loads(result.getvalue()) + self.assertIsInstance(result, JsonResponse) + self.assertEqual(data["software"]["name"], "bookwyrm") + self.assertEqual(data["usage"]["users"]["total"], 2) + self.assertEqual(models.User.objects.count(), 3) + + def test_instanceinfo(self): + """ about the instance's user activity """ + request = self.factory.get("") + request.user = self.anonymous_user + + result = views.instance_info(request) + data = json.loads(result.getvalue()) + self.assertIsInstance(result, JsonResponse) + self.assertEqual(data["stats"]["user_count"], 2) + self.assertEqual(models.User.objects.count(), 3) diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index 709981725..b645e943c 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -4,7 +4,7 @@ from django.contrib import admin from django.urls import path, re_path -from bookwyrm import settings, views, wellknown +from bookwyrm import settings, views from bookwyrm.utils import regex user_path = r"^user/(?P%s)" % regex.username @@ -31,11 +31,11 @@ urlpatterns = [ re_path(r"^inbox/?$", views.Inbox.as_view()), re_path(r"%s/inbox/?$" % local_user_path, views.Inbox.as_view()), re_path(r"%s/outbox/?$" % local_user_path, views.Outbox.as_view()), - re_path(r"^.well-known/webfinger/?$", wellknown.webfinger), - re_path(r"^.well-known/nodeinfo/?$", wellknown.nodeinfo_pointer), - re_path(r"^nodeinfo/2\.0/?$", wellknown.nodeinfo), - re_path(r"^api/v1/instance/?$", wellknown.instance_info), - re_path(r"^api/v1/instance/peers/?$", wellknown.peers), + re_path(r"^.well-known/webfinger/?$", views.webfinger), + re_path(r"^.well-known/nodeinfo/?$", views.nodeinfo_pointer), + re_path(r"^nodeinfo/2\.0/?$", views.nodeinfo), + re_path(r"^api/v1/instance/?$", views.instance_info), + re_path(r"^api/v1/instance/peers/?$", views.peers), # polling updates re_path("^api/updates/notifications/?$", views.Updates.as_view()), # authentication diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py index e7f84544d..2c32bc9d6 100644 --- a/bookwyrm/views/__init__.py +++ b/bookwyrm/views/__init__.py @@ -14,6 +14,7 @@ from .import_data import Import, ImportStatus from .inbox import Inbox from .interaction import Favorite, Unfavorite, Boost, Unboost from .invite import ManageInvites, Invite +from .isbn import Isbn from .landing import About, Home, Discover from .list import Lists, List, Curate, UserLists from .notifications import Notifications @@ -32,4 +33,4 @@ from .status import CreateStatus, DeleteStatus from .tag import Tag, AddTag, RemoveTag from .updates import Updates from .user import User, EditUser, Followers, Following -from .isbn import Isbn +from .wellknown import webfinger, nodeinfo_pointer, nodeinfo, instance_info, peers diff --git a/bookwyrm/wellknown.py b/bookwyrm/views/wellknown.py similarity index 86% rename from bookwyrm/wellknown.py rename to bookwyrm/views/wellknown.py index eb0148082..127c7491a 100644 --- a/bookwyrm/wellknown.py +++ b/bookwyrm/views/wellknown.py @@ -4,18 +4,17 @@ from dateutil.relativedelta import relativedelta from django.http import HttpResponseNotFound from django.http import JsonResponse from django.utils import timezone +from django.views.decorators.http import require_GET from bookwyrm import models from bookwyrm.settings import DOMAIN, VERSION +@require_GET def webfinger(request): """ allow other servers to ask about a user """ - if request.method != "GET": - return HttpResponseNotFound() - resource = request.GET.get("resource") - if not resource and not resource.startswith("acct:"): + if not resource or not resource.startswith("acct:"): return HttpResponseNotFound() username = resource.replace("acct:", "") @@ -38,11 +37,9 @@ def webfinger(request): ) -def nodeinfo_pointer(request): +@require_GET +def nodeinfo_pointer(_): """ direct servers to nodeinfo """ - if request.method != "GET": - return HttpResponseNotFound() - return JsonResponse( { "links": [ @@ -55,11 +52,9 @@ def nodeinfo_pointer(request): ) -def nodeinfo(request): +@require_GET +def nodeinfo(_): """ basic info about the server """ - if request.method != "GET": - return HttpResponseNotFound() - status_count = models.Status.objects.filter(user__local=True).count() user_count = models.User.objects.filter(local=True).count() @@ -92,11 +87,9 @@ def nodeinfo(request): ) -def instance_info(request): +@require_GET +def instance_info(_): """ let's talk about your cool unique instance """ - if request.method != "GET": - return HttpResponseNotFound() - user_count = models.User.objects.filter(local=True).count() status_count = models.Status.objects.filter(user__local=True).count() @@ -120,10 +113,8 @@ def instance_info(request): ) -def peers(request): +@require_GET +def peers(_): """ list of federated servers this instance connects with """ - if request.method != "GET": - return HttpResponseNotFound() - names = models.FederatedServer.objects.values_list("server_name", flat=True) return JsonResponse(list(names), safe=False)