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):