diff --git a/bookwyrm/forms.py b/bookwyrm/forms.py
index 0a69dbe0..d330211c 100644
--- a/bookwyrm/forms.py
+++ b/bookwyrm/forms.py
@@ -3,6 +3,7 @@ import datetime
from collections import defaultdict
from django import forms
+from django.core.exceptions import ValidationError
from django.forms import ModelForm, PasswordInput, widgets
from django.forms.widgets import Textarea
from django.utils import timezone
@@ -203,6 +204,13 @@ class ExpiryWidget(widgets.Select):
class InviteRequestForm(CustomForm):
+ def clean(self):
+ """ make sure the email isn't in use by a registered user """
+ cleaned_data = super().clean()
+ email = cleaned_data.get("email")
+ if email and models.User.objects.filter(email=email).exists():
+ self.add_error("email", _("A user with this email already exists."))
+
class Meta:
model = models.InviteRequest
fields = ["email"]
diff --git a/bookwyrm/templates/discover/landing_layout.html b/bookwyrm/templates/discover/landing_layout.html
index 5cfa1fd3..8e507531 100644
--- a/bookwyrm/templates/discover/landing_layout.html
+++ b/bookwyrm/templates/discover/landing_layout.html
@@ -45,9 +45,33 @@
+ {% trans "Thank you! Your request has been received." %}
+
+ {% else %}
+ {% trans "Allow registration:" %}
{{ site_form.allow_registration }}
+
+ {% trans "Allow invite requests:" %}
+ {{ site_form.allow_invite_requests }}
+
{% trans "Registration closed text:" %}
{{ site_form.registration_closed_text }}
diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py
index c24b83f7..ca58d300 100644
--- a/bookwyrm/urls.py
+++ b/bookwyrm/urls.py
@@ -54,6 +54,9 @@ urlpatterns = [
re_path(
r"^settings/invites/?$", views.ManageInvites.as_view(), name="settings-invites"
),
+ re_path(
+ r"^invite-request/?$", views.InviteRequest.as_view(), name="invite-request"
+ ),
re_path(r"^invite/(?P[A-Za-z0-9]+)/?$", views.Invite.as_view()),
# moderation
re_path(r"^settings/reports/?$", views.Reports.as_view(), name="settings-reports"),
diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py
index e98cb24a..119fc492 100644
--- a/bookwyrm/views/__init__.py
+++ b/bookwyrm/views/__init__.py
@@ -13,7 +13,7 @@ from .goal import Goal, hide_goal
from .import_data import Import, ImportStatus
from .inbox import Inbox
from .interaction import Favorite, Unfavorite, Boost, Unboost
-from .invite import ManageInvites, Invite
+from .invite import ManageInvites, Invite, InviteRequest
from .isbn import Isbn
from .landing import About, Home, Discover
from .list import Lists, List, Curate, UserLists
diff --git a/bookwyrm/views/helpers.py b/bookwyrm/views/helpers.py
index 20332cbd..c62856ba 100644
--- a/bookwyrm/views/helpers.py
+++ b/bookwyrm/views/helpers.py
@@ -2,7 +2,7 @@
import re
from requests import HTTPError
from django.core.exceptions import FieldError
-from django.db.models import Q
+from django.db.models import Max, Q
from bookwyrm import activitypub, models
from bookwyrm.connectors import ConnectorException, get_data
@@ -216,3 +216,20 @@ def is_blocked(viewer, user):
if viewer.is_authenticated and viewer in user.blocks.all():
return True
return False
+
+
+def get_discover_books():
+ """ list of books for the discover page """
+ return list(
+ set(
+ models.Edition.objects.filter(
+ review__published_date__isnull=False,
+ review__deleted=False,
+ review__user__local=True,
+ review__privacy__in=["public", "unlisted"],
+ )
+ .exclude(cover__exact="")
+ .annotate(Max("review__published_date"))
+ .order_by("-review__published_date__max")[:6]
+ )
+ )
diff --git a/bookwyrm/views/invite.py b/bookwyrm/views/invite.py
index 1f1ccaf1..0f5a65b6 100644
--- a/bookwyrm/views/invite.py
+++ b/bookwyrm/views/invite.py
@@ -9,6 +9,7 @@ from django.views import View
from bookwyrm import forms, models
from bookwyrm.settings import PAGE_LENGTH
+from . import helpers
# pylint: disable= no-self-use
@@ -77,3 +78,22 @@ class Invite(View):
return TemplateResponse(request, "invite.html", data)
# post handling is in views.authentication.Register
+
+
+class InviteRequest(View):
+ """ prospective users sign up here """
+
+ def post(self, request):
+ """ create a request """
+ form = forms.InviteRequestForm(request.POST)
+ received = False
+ if form.is_valid():
+ received = True
+ form.save()
+
+ data = {
+ "request_form": form,
+ "request_received": received,
+ "books": helpers.get_discover_books(),
+ }
+ return TemplateResponse(request, "discover/discover.html", data)
diff --git a/bookwyrm/views/landing.py b/bookwyrm/views/landing.py
index 2c4a5147..86f7d3e9 100644
--- a/bookwyrm/views/landing.py
+++ b/bookwyrm/views/landing.py
@@ -1,10 +1,10 @@
""" non-interactive pages """
-from django.db.models import Max
from django.template.response import TemplateResponse
from django.views import View
from bookwyrm import forms, models
from .feed import Feed
+from . import helpers
# pylint: disable= no-self-use
@@ -33,20 +33,9 @@ class Discover(View):
def get(self, request):
""" tiled book activity page """
- books = (
- models.Edition.objects.filter(
- review__published_date__isnull=False,
- review__deleted=False,
- review__user__local=True,
- review__privacy__in=["public", "unlisted"],
- )
- .exclude(cover__exact="")
- .annotate(Max("review__published_date"))
- .order_by("-review__published_date__max")[:6]
- )
-
data = {
"register_form": forms.RegisterForm(),
- "books": list(set(books)),
+ "request_form": forms.InviteRequestForm(),
+ "books": helpers.get_discover_books(),
}
return TemplateResponse(request, "discover/discover.html", data)