From fd6603ee070225caf9318fd716c00ce26d312642 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 12 Jan 2021 10:19:58 -0800 Subject: [PATCH] Invite views --- bookwyrm/templates/manage_invites.html | 2 +- bookwyrm/tests/test_views.py | 26 ------------ bookwyrm/tests/views/test_invite.py | 48 +++++++++++++++++++++ bookwyrm/urls.py | 7 ++-- bookwyrm/view_actions.py | 17 -------- bookwyrm/views/__init__.py | 1 + bookwyrm/views/invite.py | 58 ++++++++++++++++++++++++++ bookwyrm/vviews.py | 53 +---------------------- 8 files changed, 112 insertions(+), 100 deletions(-) create mode 100644 bookwyrm/tests/views/test_invite.py create mode 100644 bookwyrm/views/invite.py diff --git a/bookwyrm/templates/manage_invites.html b/bookwyrm/templates/manage_invites.html index 14808490..a29ee5e4 100644 --- a/bookwyrm/templates/manage_invites.html +++ b/bookwyrm/templates/manage_invites.html @@ -27,7 +27,7 @@

Generate New Invite

-
+ {% csrf_token %}
diff --git a/bookwyrm/tests/test_views.py b/bookwyrm/tests/test_views.py index 6cbd67d8..9729b0f1 100644 --- a/bookwyrm/tests/test_views.py +++ b/bookwyrm/tests/test_views.py @@ -274,32 +274,6 @@ class Views(TestCase): self.assertEqual(result.status_code, 200) - def test_invite_page(self): - ''' there are so many views, this just makes sure it LOADS ''' - models.SiteInvite.objects.create(code='hi', user=self.local_user) - request = self.factory.get('') - request.user = AnonymousUser - # why?? this is annoying. - request.user.is_authenticated = False - with patch('bookwyrm.models.site.SiteInvite.valid') as invite: - invite.return_value = True - result = views.invite_page(request, 'hi') - self.assertIsInstance(result, TemplateResponse) - self.assertEqual(result.template_name, 'invite.html') - self.assertEqual(result.status_code, 200) - - - def test_manage_invites(self): - ''' there are so many views, this just makes sure it LOADS ''' - request = self.factory.get('') - request.user = self.local_user - request.user.is_superuser = True - result = views.manage_invites(request) - self.assertIsInstance(result, TemplateResponse) - self.assertEqual(result.template_name, 'manage_invites.html') - self.assertEqual(result.status_code, 200) - - def test_notifications_page(self): ''' there are so many views, this just makes sure it LOADS ''' request = self.factory.get('') diff --git a/bookwyrm/tests/views/test_invite.py b/bookwyrm/tests/views/test_invite.py new file mode 100644 index 00000000..57b7a34a --- /dev/null +++ b/bookwyrm/tests/views/test_invite.py @@ -0,0 +1,48 @@ +''' test for app action functionality ''' +from unittest.mock import patch + +from django.contrib.auth.models import AnonymousUser +from django.template.response import TemplateResponse +from django.test import TestCase +from django.test.client import RequestFactory + +from bookwyrm import models +from bookwyrm import views + + +class InviteViews(TestCase): + ''' every response to a get request, html or json ''' + 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') + + + def test_invite_page(self): + ''' there are so many views, this just makes sure it LOADS ''' + view = views.Invite.as_view() + models.SiteInvite.objects.create(code='hi', user=self.local_user) + request = self.factory.get('') + request.user = AnonymousUser + # why?? this is annoying. + request.user.is_authenticated = False + with patch('bookwyrm.models.site.SiteInvite.valid') as invite: + invite.return_value = True + result = view(request, 'hi') + self.assertIsInstance(result, TemplateResponse) + self.assertEqual(result.template_name, 'invite.html') + self.assertEqual(result.status_code, 200) + + + def test_manage_invites(self): + ''' there are so many views, this just makes sure it LOADS ''' + view = views.ManageInvites.as_view() + request = self.factory.get('') + request.user = self.local_user + request.user.is_superuser = True + result = view(request) + self.assertIsInstance(result, TemplateResponse) + self.assertEqual(result.template_name, 'manage_invites.html') + self.assertEqual(result.status_code, 200) diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index d93570f6..c2e3ef36 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -51,11 +51,11 @@ urlpatterns = [ views.PasswordReset.as_view()), re_path(r'^change-password/?$', views.ChangePassword), + #invites + re_path(r'^invite/?$', views.ManageInvites.as_view()), + re_path(r'^invite/(?P[A-Za-z0-9]+)/?$', views.Invite.as_view()), re_path(r'^about/?$', vviews.about_page), - re_path(r'^invite/?$', vviews.manage_invites), - re_path(r'^invite/(?P[A-Za-z0-9]+)/?$', vviews.invite_page), - path('', vviews.home), re_path(r'^(?Phome|local|federated)/?$', vviews.home_tab), re_path(r'^discover/?$', vviews.discover_page), @@ -141,6 +141,5 @@ urlpatterns = [ re_path(r'^clear-notifications/?$', actions.clear_notifications), - re_path(r'^create-invite/?$', actions.create_invite), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/bookwyrm/view_actions.py b/bookwyrm/view_actions.py index 7977498b..8af68e06 100644 --- a/bookwyrm/view_actions.py +++ b/bookwyrm/view_actions.py @@ -653,23 +653,6 @@ def retry_import(request): goodreads_import.start_import(job) return redirect('/import-status/%d' % job.id) - -@login_required -@require_POST -@permission_required('bookwyrm.create_invites', raise_exception=True) -def create_invite(request): - ''' creates a user invite database entry ''' - form = forms.CreateInviteForm(request.POST) - if not form.is_valid(): - return HttpResponseBadRequest("ERRORS : %s" % (form.errors,)) - - invite = form.save(commit=False) - invite.user = request.user - invite.save() - - return redirect('/invite') - - def update_readthrough(request, book=None, create=True): ''' updates but does not save dates on a readthrough ''' try: diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py index 0adf771f..5d2fda52 100644 --- a/bookwyrm/views/__init__.py +++ b/bookwyrm/views/__init__.py @@ -1,3 +1,4 @@ ''' make sure all our nice views are available ''' from .authentication import Login, Register, Logout from .password import PasswordResetRequest, PasswordReset, ChangePassword +from .invite import ManageInvites, Invite diff --git a/bookwyrm/views/invite.py b/bookwyrm/views/invite.py new file mode 100644 index 00000000..56485861 --- /dev/null +++ b/bookwyrm/views/invite.py @@ -0,0 +1,58 @@ +''' invites when registration is closed ''' +from django.contrib.auth.decorators import login_required, permission_required +from django.http import HttpResponseBadRequest +from django.shortcuts import get_object_or_404, redirect +from django.template.response import TemplateResponse +from django.utils.decorators import method_decorator +from django.views import View + +from bookwyrm import forms, models + + +# pylint: disable= no-self-use +@method_decorator(login_required, name='dispatch') +@method_decorator( + permission_required('bookwyrm.create_invites', raise_exception=True), + name='dispatch') +class ManageInvites(View): + ''' create invites ''' + def get(self, request): + ''' invite management page ''' + data = { + 'title': 'Invitations', + 'invites': models.SiteInvite.objects.filter( + user=request.user).order_by('-created_date'), + 'form': forms.CreateInviteForm(), + } + return TemplateResponse(request, 'manage_invites.html', data) + + def post(self, request): + ''' creates an invite database entry ''' + form = forms.CreateInviteForm(request.POST) + if not form.is_valid(): + return HttpResponseBadRequest("ERRORS : %s" % (form.errors,)) + + invite = form.save(commit=False) + invite.user = request.user + invite.save() + + return redirect('/invite') + + +class Invite(View): + ''' use an invite to register ''' + def get(self, request, code): + ''' endpoint for using an invites ''' + if request.user.is_authenticated: + return redirect('/') + invite = get_object_or_404(models.SiteInvite, code=code) + + data = { + 'title': 'Join', + 'register_form': forms.RegisterForm(), + 'invite': invite, + 'valid': invite.valid() if invite else True, + } + return TemplateResponse(request, 'invite.html', data) + + # post handling is in views.authentication.Register diff --git a/bookwyrm/vviews.py b/bookwyrm/vviews.py index 66b26615..17ff8806 100644 --- a/bookwyrm/vviews.py +++ b/bookwyrm/vviews.py @@ -8,7 +8,7 @@ from django.db.models import Avg, Q, Max from django.db.models.functions import Greatest from django.http import HttpResponseNotFound, JsonResponse from django.core.exceptions import PermissionDenied -from django.shortcuts import get_object_or_404, redirect +from django.shortcuts import get_object_or_404 from django.template.response import TemplateResponse from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_GET @@ -332,57 +332,6 @@ def about_page(request): return TemplateResponse(request, 'about.html', data) - - -@require_GET -def password_reset(request, code): - ''' endpoint for sending invites ''' - if request.user.is_authenticated: - return redirect('/') - try: - reset_code = models.PasswordReset.objects.get(code=code) - if not reset_code.valid(): - raise PermissionDenied - except models.PasswordReset.DoesNotExist: - raise PermissionDenied - - return TemplateResponse( - request, - 'password_reset.html', - {'title': 'Reset Password', 'code': reset_code.code} - ) - - -@require_GET -def invite_page(request, code): - ''' endpoint for sending invites ''' - if request.user.is_authenticated: - return redirect('/') - invite = get_object_or_404(models.SiteInvite, code=code) - - data = { - 'title': 'Join', - 'register_form': forms.RegisterForm(), - 'invite': invite, - 'valid': invite.valid() if invite else True, - } - return TemplateResponse(request, 'invite.html', data) - - -@login_required -@permission_required('bookwyrm.create_invites', raise_exception=True) -@require_GET -def manage_invites(request): - ''' invite management page ''' - data = { - 'title': 'Invitations', - 'invites': models.SiteInvite.objects.filter( - user=request.user).order_by('-created_date'), - 'form': forms.CreateInviteForm(), - } - return TemplateResponse(request, 'manage_invites.html', data) - - @login_required @require_GET def notifications_page(request):