Request invite flow

This commit is contained in:
Mouse Reeve 2021-03-20 19:14:41 -07:00
parent 4d07cb1eb5
commit d15396eb26
8 changed files with 81 additions and 16 deletions

View file

@ -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"]

View file

@ -45,9 +45,33 @@
<form name="register" method="post" action="/register">
{% include 'snippets/register_form.html' %}
</form>
{% else %}
<h2 class="title">{% trans "This instance is closed" %}</h2>
<p>{{ site.registration_closed_text | safe}}</p>
{% if site.allow_invite_requests %}
{% if request_received %}
<p>
{% trans "Thank you! Your request has been received." %}
</p>
{% else %}
<h3>{% trans "Request an Invitation" %}</h3>
<form name="invite-request" action="{% url 'invite-request' %}" method="post">
{% csrf_token %}
<div class="block">
<label for="id_request_email" class="label">{% trans "Email address:" %}</label>
<input type="email" name="email" maxlength="255" class="input" required="" id="id_request_email">
{% for error in request_form.email.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
</div>
<button type="submit" class="button is-link">{% trans "Submit" %}</button>
</form>
{% endif %}
{% endif %}
{% endif %}
</div>
{% else %}

View file

@ -79,6 +79,10 @@
<label class="label" for="id_allow_registration">{% trans "Allow registration:" %}
{{ site_form.allow_registration }}
</div>
<div class="control">
<label class="label" for="id_allow_invite_requests">{% trans "Allow invite requests:" %}
{{ site_form.allow_invite_requests }}
</div>
<div class="control">
<label class="label" for="id_registration_closed_text">{% trans "Registration closed text:" %}</label>
{{ site_form.registration_closed_text }}

View file

@ -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<code>[A-Za-z0-9]+)/?$", views.Invite.as_view()),
# moderation
re_path(r"^settings/reports/?$", views.Reports.as_view(), name="settings-reports"),

View file

@ -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

View file

@ -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]
)
)

View file

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

View file

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