Merge pull request #1544 from bookwyrm-social/landing-views

Landing views
This commit is contained in:
Mouse Reeve 2021-10-16 12:17:26 -07:00 committed by GitHub
commit b215316080
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 170 additions and 64 deletions

View file

@ -12,7 +12,7 @@
{% if valid %} {% if valid %}
<div> <div>
<form name="register" method="post" action="/register"> <form name="register" method="post" action="/register">
<input type=hidden name="invite_code" value="{{ invite.code }}"> <input type="hidden" name="invite_code" value="{{ invite.code }}">
{% include 'snippets/register_form.html' %} {% include 'snippets/register_form.html' %}
</form> </form>
</div> </div>

View file

@ -14,19 +14,19 @@
{% if show_confirmed_email %} {% if show_confirmed_email %}
<p class="notification is-success">{% trans "Success! Email address confirmed." %}</p> <p class="notification is-success">{% trans "Success! Email address confirmed." %}</p>
{% endif %} {% endif %}
<form name="login" method="post" action="/login"> <form name="login-confirm" method="post" action="/login">
{% csrf_token %} {% csrf_token %}
{% if show_confirmed_email %}<input type="hidden" name="first_login" value="true">{% endif %} {% if show_confirmed_email %}<input type="hidden" name="first_login" value="true">{% endif %}
<div class="field"> <div class="field">
<label class="label" for="id_localname">{% trans "Username:" %}</label> <label class="label" for="id_localname_confirm">{% trans "Username:" %}</label>
<div class="control"> <div class="control">
{{ login_form.localname }} <input type="text" name="localname" maxlength="255" class="input" required="" id="id_localname_confirm" value="{{ login_form.localname.value|default:'' }}">
</div> </div>
</div> </div>
<div class="field"> <div class="field">
<label class="label" for="id_password">{% trans "Password:" %}</label> <label class="label" for="id_password_confirm">{% trans "Password:" %}</label>
<div class="control"> <div class="control">
{{ login_form.password }} <input type="password" name="password" maxlength="128" class="input" required="" id="id_password_confirm">
</div> </div>
{% for error in login_form.password.errors %} {% for error in login_form.password.errors %}
<p class="help is-danger">{{ error | escape }}</p> <p class="help is-danger">{{ error | escape }}</p>

View file

@ -14,9 +14,9 @@
<form name="password-reset" method="post" action="/password-reset/{{ code }}"> <form name="password-reset" method="post" action="/password-reset/{{ code }}">
{% csrf_token %} {% csrf_token %}
<div class="field"> <div class="field">
<label class="label" for="id_password">{% trans "Password:" %}</label> <label class="label" for="id_new_password">{% trans "Password:" %}</label>
<div class="control"> <div class="control">
<input type="password" name="password" maxlength="128" class="input" required="" id="id_password"> <input type="password" name="password" maxlength="128" class="input" required="" id="id_new_password">
</div> </div>
</div> </div>
<div class="field"> <div class="field">

View file

@ -171,7 +171,7 @@
<input type="text" name="localname" maxlength="150" class="input" required="" id="id_localname" placeholder="{% trans 'username' %}"> <input type="text" name="localname" maxlength="150" class="input" required="" id="id_localname" placeholder="{% trans 'username' %}">
</div> </div>
<div class="column"> <div class="column">
<label class="is-sr-only" for="id_password">{% trans "Username:" %}</label> <label class="is-sr-only" for="id_password">{% trans "Password:" %}</label>
<input type="password" name="password" maxlength="128" class="input" required="" id="id_password" placeholder="{% trans 'password' %}"> <input type="password" name="password" maxlength="128" class="input" required="" id="id_password" placeholder="{% trans 'password' %}">
<p class="help"><a href="{% url 'password-reset' %}">{% trans "Forgot your password?" %}</a></p> <p class="help"><a href="{% url 'password-reset' %}">{% trans "Forgot your password?" %}</a></p>
</div> </div>

View file

@ -0,0 +1 @@
from . import *

View file

@ -8,6 +8,7 @@ from django.test.client import RequestFactory
from bookwyrm import forms, models from bookwyrm import forms, models
from bookwyrm import views from bookwyrm import views
from bookwyrm.tests.validate_html import validate_html
class InviteViews(TestCase): class InviteViews(TestCase):
@ -40,7 +41,7 @@ class InviteViews(TestCase):
invite.return_value = True invite.return_value = True
result = view(request, "hi") result = view(request, "hi")
self.assertIsInstance(result, TemplateResponse) self.assertIsInstance(result, TemplateResponse)
result.render() validate_html(result.render())
self.assertEqual(result.status_code, 200) self.assertEqual(result.status_code, 200)
def test_manage_invites(self): def test_manage_invites(self):
@ -51,7 +52,7 @@ class InviteViews(TestCase):
request.user.is_superuser = True request.user.is_superuser = True
result = view(request) result = view(request)
self.assertIsInstance(result, TemplateResponse) self.assertIsInstance(result, TemplateResponse)
result.render() validate_html(result.render())
self.assertEqual(result.status_code, 200) self.assertEqual(result.status_code, 200)
def test_manage_invites_post(self): def test_manage_invites_post(self):
@ -67,7 +68,7 @@ class InviteViews(TestCase):
result = view(request) result = view(request)
self.assertIsInstance(result, TemplateResponse) self.assertIsInstance(result, TemplateResponse)
result.render() validate_html(result.render())
self.assertEqual(result.status_code, 200) self.assertEqual(result.status_code, 200)
invite = models.SiteInvite.objects.get() invite = models.SiteInvite.objects.get()
@ -83,7 +84,7 @@ class InviteViews(TestCase):
request = self.factory.post("", form.data) request = self.factory.post("", form.data)
result = view(request) result = view(request)
result.render() validate_html(result.render())
req = models.InviteRequest.objects.get() req = models.InviteRequest.objects.get()
self.assertEqual(req.email, "new@user.email") self.assertEqual(req.email, "new@user.email")
@ -97,7 +98,7 @@ class InviteViews(TestCase):
request = self.factory.post("", form.data) request = self.factory.post("", form.data)
result = view(request) result = view(request)
result.render() validate_html(result.render())
# no request created # no request created
self.assertFalse(models.InviteRequest.objects.exists()) self.assertFalse(models.InviteRequest.objects.exists())
@ -110,14 +111,14 @@ class InviteViews(TestCase):
request.user.is_superuser = True request.user.is_superuser = True
result = view(request) result = view(request)
self.assertIsInstance(result, TemplateResponse) self.assertIsInstance(result, TemplateResponse)
result.render() validate_html(result.render())
self.assertEqual(result.status_code, 200) self.assertEqual(result.status_code, 200)
# now with data # now with data
models.InviteRequest.objects.create(email="fish@example.com") models.InviteRequest.objects.create(email="fish@example.com")
result = view(request) result = view(request)
self.assertIsInstance(result, TemplateResponse) self.assertIsInstance(result, TemplateResponse)
result.render() validate_html(result.render())
self.assertEqual(result.status_code, 200) self.assertEqual(result.status_code, 200)
def test_manage_invite_requests_send(self): def test_manage_invite_requests_send(self):

View file

@ -7,6 +7,7 @@ from django.test.client import RequestFactory
from bookwyrm import models from bookwyrm import models
from bookwyrm import views from bookwyrm import views
from bookwyrm.tests.validate_html import validate_html
class LandingViews(TestCase): class LandingViews(TestCase):
@ -38,13 +39,13 @@ class LandingViews(TestCase):
with patch("bookwyrm.activitystreams.ActivityStream.get_activity_stream"): with patch("bookwyrm.activitystreams.ActivityStream.get_activity_stream"):
result = view(request) result = view(request)
self.assertEqual(result.status_code, 200) self.assertEqual(result.status_code, 200)
result.render() validate_html(result.render())
request.user = self.anonymous_user request.user = self.anonymous_user
result = view(request) result = view(request)
self.assertIsInstance(result, TemplateResponse) self.assertIsInstance(result, TemplateResponse)
self.assertEqual(result.status_code, 200) self.assertEqual(result.status_code, 200)
result.render() validate_html(result.render())
def test_about_page(self): def test_about_page(self):
"""there are so many views, this just makes sure it LOADS""" """there are so many views, this just makes sure it LOADS"""
@ -53,7 +54,7 @@ class LandingViews(TestCase):
request.user = self.local_user request.user = self.local_user
result = view(request) result = view(request)
self.assertIsInstance(result, TemplateResponse) self.assertIsInstance(result, TemplateResponse)
result.render() validate_html(result.render())
self.assertEqual(result.status_code, 200) self.assertEqual(result.status_code, 200)
def test_landing(self): def test_landing(self):

View file

@ -7,6 +7,7 @@ from django.test import TestCase
from django.test.client import RequestFactory from django.test.client import RequestFactory
from bookwyrm import forms, models, views from bookwyrm import forms, models, views
from bookwyrm.tests.validate_html import validate_html
# pylint: disable=too-many-public-methods # pylint: disable=too-many-public-methods
@ -41,7 +42,7 @@ class LoginViews(TestCase):
result = login(request) result = login(request)
self.assertIsInstance(result, TemplateResponse) self.assertIsInstance(result, TemplateResponse)
result.render() validate_html(result.render())
self.assertEqual(result.status_code, 200) self.assertEqual(result.status_code, 200)
request.user = self.local_user request.user = self.local_user
@ -58,7 +59,7 @@ class LoginViews(TestCase):
request = self.factory.post("", form.data) request = self.factory.post("", form.data)
request.user = self.anonymous_user request.user = self.anonymous_user
with patch("bookwyrm.views.login.login"): with patch("bookwyrm.views.landing.login.login"):
result = view(request) result = view(request)
self.assertEqual(result.url, "/") self.assertEqual(result.url, "/")
self.assertEqual(result.status_code, 302) self.assertEqual(result.status_code, 302)
@ -72,7 +73,7 @@ class LoginViews(TestCase):
request = self.factory.post("", form.data) request = self.factory.post("", form.data)
request.user = self.anonymous_user request.user = self.anonymous_user
with patch("bookwyrm.views.login.login"): with patch("bookwyrm.views.landing.login.login"):
result = view(request) result = view(request)
self.assertEqual(result.url, "/") self.assertEqual(result.url, "/")
self.assertEqual(result.status_code, 302) self.assertEqual(result.status_code, 302)
@ -86,7 +87,7 @@ class LoginViews(TestCase):
request = self.factory.post("", form.data) request = self.factory.post("", form.data)
request.user = self.anonymous_user request.user = self.anonymous_user
with patch("bookwyrm.views.login.login"): with patch("bookwyrm.views.landing.login.login"):
result = view(request) result = view(request)
self.assertEqual(result.url, "/") self.assertEqual(result.url, "/")
self.assertEqual(result.status_code, 302) self.assertEqual(result.status_code, 302)
@ -100,9 +101,9 @@ class LoginViews(TestCase):
request = self.factory.post("", form.data) request = self.factory.post("", form.data)
request.user = self.anonymous_user request.user = self.anonymous_user
with patch("bookwyrm.views.login.login"): with patch("bookwyrm.views.landing.login.login"):
result = view(request) result = view(request)
result.render() validate_html(result.render())
self.assertEqual(result.status_code, 200) self.assertEqual(result.status_code, 200)
self.assertEqual( self.assertEqual(
result.context_data["login_form"].non_field_errors, result.context_data["login_form"].non_field_errors,

View file

@ -1,12 +1,16 @@
""" test for app action functionality """ """ test for app action functionality """
from datetime import timedelta
from unittest.mock import patch from unittest.mock import patch
from django.contrib.auth.models import AnonymousUser from django.contrib.auth.models import AnonymousUser
from django.core.exceptions import PermissionDenied
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
from django.test import TestCase from django.test import TestCase
from django.test.client import RequestFactory from django.test.client import RequestFactory
from django.utils import timezone
from bookwyrm import models, views from bookwyrm import models, views
from bookwyrm.tests.validate_html import validate_html
class PasswordViews(TestCase): class PasswordViews(TestCase):
@ -37,7 +41,7 @@ class PasswordViews(TestCase):
result = view(request) result = view(request)
self.assertIsInstance(result, TemplateResponse) self.assertIsInstance(result, TemplateResponse)
result.render() validate_html(result.render())
self.assertEqual(result.status_code, 200) self.assertEqual(result.status_code, 200)
def test_password_reset_request_post(self): def test_password_reset_request_post(self):
@ -47,13 +51,13 @@ class PasswordViews(TestCase):
view = views.PasswordResetRequest.as_view() view = views.PasswordResetRequest.as_view()
resp = view(request) resp = view(request)
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
resp.render() validate_html(resp.render())
request = self.factory.post("", {"email": "mouse@mouse.com"}) request = self.factory.post("", {"email": "mouse@mouse.com"})
request.user = self.anonymous_user request.user = self.anonymous_user
with patch("bookwyrm.emailing.send_email.delay"): with patch("bookwyrm.emailing.send_email.delay"):
resp = view(request) resp = view(request)
resp.render() validate_html(resp.render())
self.assertEqual(models.PasswordReset.objects.get().user, self.local_user) self.assertEqual(models.PasswordReset.objects.get().user, self.local_user)
@ -65,15 +69,43 @@ class PasswordViews(TestCase):
request.user = self.anonymous_user request.user = self.anonymous_user
result = view(request, code.code) result = view(request, code.code)
self.assertIsInstance(result, TemplateResponse) self.assertIsInstance(result, TemplateResponse)
result.render() validate_html(result.render())
self.assertEqual(result.status_code, 200) self.assertEqual(result.status_code, 200)
def test_password_reset_nonexistant_code(self):
"""there are so many views, this just makes sure it LOADS"""
view = views.PasswordReset.as_view()
request = self.factory.get("")
request.user = self.anonymous_user
with self.assertRaises(PermissionDenied):
view(request, "beep")
def test_password_reset_invalid_code(self):
"""there are so many views, this just makes sure it LOADS"""
view = views.PasswordReset.as_view()
code = models.PasswordReset.objects.create(
user=self.local_user, expiry=timezone.now() - timedelta(days=2)
)
request = self.factory.get("")
request.user = self.anonymous_user
with self.assertRaises(PermissionDenied):
view(request, code.code)
def test_password_reset_logged_in(self):
"""redirect logged in users"""
view = views.PasswordReset.as_view()
code = models.PasswordReset.objects.create(user=self.local_user)
request = self.factory.get("")
request.user = self.local_user
result = view(request, code.code)
self.assertEqual(result.status_code, 302)
def test_password_reset_post(self): def test_password_reset_post(self):
"""reset from code""" """reset from code"""
view = views.PasswordReset.as_view() view = views.PasswordReset.as_view()
code = models.PasswordReset.objects.create(user=self.local_user) code = models.PasswordReset.objects.create(user=self.local_user)
request = self.factory.post("", {"password": "hi", "confirm-password": "hi"}) request = self.factory.post("", {"password": "hi", "confirm-password": "hi"})
with patch("bookwyrm.views.password.login"): with patch("bookwyrm.views.landing.password.login"):
resp = view(request, code.code) resp = view(request, code.code)
self.assertEqual(resp.status_code, 302) self.assertEqual(resp.status_code, 302)
self.assertFalse(models.PasswordReset.objects.exists()) self.assertFalse(models.PasswordReset.objects.exists())
@ -84,7 +116,7 @@ class PasswordViews(TestCase):
models.PasswordReset.objects.create(user=self.local_user) models.PasswordReset.objects.create(user=self.local_user)
request = self.factory.post("", {"password": "hi", "confirm-password": "hi"}) request = self.factory.post("", {"password": "hi", "confirm-password": "hi"})
resp = view(request, "jhgdkfjgdf") resp = view(request, "jhgdkfjgdf")
resp.render() validate_html(resp.render())
self.assertTrue(models.PasswordReset.objects.exists()) self.assertTrue(models.PasswordReset.objects.exists())
def test_password_reset_mismatch(self): def test_password_reset_mismatch(self):
@ -93,5 +125,5 @@ class PasswordViews(TestCase):
code = models.PasswordReset.objects.create(user=self.local_user) code = models.PasswordReset.objects.create(user=self.local_user)
request = self.factory.post("", {"password": "hi", "confirm-password": "hihi"}) request = self.factory.post("", {"password": "hi", "confirm-password": "hihi"})
resp = view(request, code.code) resp = view(request, code.code)
resp.render() validate_html(resp.render())
self.assertTrue(models.PasswordReset.objects.exists()) self.assertTrue(models.PasswordReset.objects.exists())

View file

@ -10,6 +10,7 @@ from django.test.client import RequestFactory
from bookwyrm import models, views from bookwyrm import models, views
from bookwyrm.settings import DOMAIN from bookwyrm.settings import DOMAIN
from bookwyrm.tests.validate_html import validate_html
# pylint: disable=too-many-public-methods # pylint: disable=too-many-public-methods
@ -38,6 +39,13 @@ class RegisterViews(TestCase):
id=1, require_confirm_email=False id=1, require_confirm_email=False
) )
def test_get_redirect(self, *_):
"""there's no dedicated registration page"""
view = views.Register.as_view()
request = self.factory.get("register/")
response = view(request)
self.assertEqual(response.status_code, 302)
def test_register(self, *_): def test_register(self, *_):
"""create a user""" """create a user"""
view = views.Register.as_view() view = views.Register.as_view()
@ -50,12 +58,12 @@ class RegisterViews(TestCase):
"email": "aa@bb.cccc", "email": "aa@bb.cccc",
}, },
) )
with patch("bookwyrm.views.register.login"): with patch("bookwyrm.views.landing.register.login"):
response = view(request) response = view(request)
self.assertEqual(models.User.objects.count(), 2) self.assertEqual(models.User.objects.count(), 2)
self.assertEqual(response.status_code, 302) self.assertEqual(response.status_code, 302)
nutria = models.User.objects.last() nutria = models.User.objects.last()
self.assertEqual(nutria.username, "nutria-user.user_nutria@%s" % DOMAIN) self.assertEqual(nutria.username, f"nutria-user.user_nutria@{DOMAIN}")
self.assertEqual(nutria.localname, "nutria-user.user_nutria") self.assertEqual(nutria.localname, "nutria-user.user_nutria")
self.assertEqual(nutria.local, True) self.assertEqual(nutria.local, True)
@ -75,11 +83,11 @@ class RegisterViews(TestCase):
"email": "aa@bb.cccc", "email": "aa@bb.cccc",
}, },
) )
with patch("bookwyrm.views.register.login"): with patch("bookwyrm.views.landing.register.login"):
response = view(request) response = view(request)
self.assertEqual(response.status_code, 302) self.assertEqual(response.status_code, 302)
nutria = models.User.objects.get(localname="nutria") nutria = models.User.objects.get(localname="nutria")
self.assertEqual(nutria.username, "nutria@%s" % DOMAIN) self.assertEqual(nutria.username, f"nutria@{DOMAIN}")
self.assertEqual(nutria.local, True) self.assertEqual(nutria.local, True)
self.assertFalse(nutria.is_active) self.assertFalse(nutria.is_active)
@ -93,12 +101,12 @@ class RegisterViews(TestCase):
"register/", "register/",
{"localname": "nutria ", "password": "mouseword", "email": "aa@bb.ccc"}, {"localname": "nutria ", "password": "mouseword", "email": "aa@bb.ccc"},
) )
with patch("bookwyrm.views.register.login"): with patch("bookwyrm.views.landing.register.login"):
response = view(request) response = view(request)
self.assertEqual(models.User.objects.count(), 2) self.assertEqual(models.User.objects.count(), 2)
self.assertEqual(response.status_code, 302) self.assertEqual(response.status_code, 302)
nutria = models.User.objects.last() nutria = models.User.objects.last()
self.assertEqual(nutria.username, "nutria@%s" % DOMAIN) self.assertEqual(nutria.username, f"nutria@{DOMAIN}")
self.assertEqual(nutria.localname, "nutria") self.assertEqual(nutria.localname, "nutria")
self.assertEqual(nutria.local, True) self.assertEqual(nutria.local, True)
@ -111,7 +119,43 @@ class RegisterViews(TestCase):
) )
response = view(request) response = view(request)
self.assertEqual(models.User.objects.count(), 1) self.assertEqual(models.User.objects.count(), 1)
response.render() validate_html(response.render())
def test_register_error_and_invite(self, *_):
"""redirect to the invite page"""
view = views.Register.as_view()
self.settings.allow_registration = False
self.settings.save()
models.SiteInvite.objects.create(
code="testcode", user=self.local_user, use_limit=1
)
self.assertEqual(models.SiteInvite.objects.get().times_used, 0)
request = self.factory.post(
"register/",
{
"localname": "nutria",
"password": "mouseword",
"email": "",
"invite_code": "testcode",
},
)
with patch("bookwyrm.views.landing.register.login"):
response = view(request)
response = view(request)
validate_html(response.render())
def test_register_username_in_use(self, *_):
"""that username is taken"""
view = views.Register.as_view()
self.assertEqual(models.User.objects.count(), 1)
request = self.factory.post(
"register/",
{"localname": "mouse", "password": "mouseword", "email": "aa@bb.ccc"},
)
response = view(request)
self.assertEqual(models.User.objects.count(), 1)
validate_html(response.render())
def test_register_invalid_username(self, *_): def test_register_invalid_username(self, *_):
"""gotta have an email""" """gotta have an email"""
@ -123,7 +167,7 @@ class RegisterViews(TestCase):
) )
response = view(request) response = view(request)
self.assertEqual(models.User.objects.count(), 1) self.assertEqual(models.User.objects.count(), 1)
response.render() validate_html(response.render())
request = self.factory.post( request = self.factory.post(
"register/", "register/",
@ -131,7 +175,7 @@ class RegisterViews(TestCase):
) )
response = view(request) response = view(request)
self.assertEqual(models.User.objects.count(), 1) self.assertEqual(models.User.objects.count(), 1)
response.render() validate_html(response.render())
request = self.factory.post( request = self.factory.post(
"register/", "register/",
@ -139,7 +183,7 @@ class RegisterViews(TestCase):
) )
response = view(request) response = view(request)
self.assertEqual(models.User.objects.count(), 1) self.assertEqual(models.User.objects.count(), 1)
response.render() validate_html(response.render())
def test_register_closed_instance(self, *_): def test_register_closed_instance(self, *_):
"""you can't just register""" """you can't just register"""
@ -172,7 +216,7 @@ class RegisterViews(TestCase):
"register/", "register/",
{"localname": "nutria ", "password": "mouseword", "email": "aa@bleep.com"}, {"localname": "nutria ", "password": "mouseword", "email": "aa@bleep.com"},
) )
with patch("bookwyrm.views.register.login"): with patch("bookwyrm.views.landing.register.login"):
result = view(request) result = view(request)
self.assertEqual(result.status_code, 302) self.assertEqual(result.status_code, 302)
self.assertTrue(models.User.objects.filter(email="aa@bleep.com").exists()) self.assertTrue(models.User.objects.filter(email="aa@bleep.com").exists())
@ -196,7 +240,7 @@ class RegisterViews(TestCase):
"invite_code": "testcode", "invite_code": "testcode",
}, },
) )
with patch("bookwyrm.views.register.login"): with patch("bookwyrm.views.landing.register.login"):
response = view(request) response = view(request)
self.assertEqual(models.User.objects.count(), 2) self.assertEqual(models.User.objects.count(), 2)
self.assertEqual(response.status_code, 302) self.assertEqual(response.status_code, 302)
@ -277,7 +321,7 @@ class RegisterViews(TestCase):
result = view(request, "abcde") result = view(request, "abcde")
self.assertIsInstance(result, TemplateResponse) self.assertIsInstance(result, TemplateResponse)
result.render() validate_html(result.render())
self.assertEqual(result.status_code, 200) self.assertEqual(result.status_code, 200)
self.assertFalse(self.local_user.is_active) self.assertFalse(self.local_user.is_active)
self.assertEqual(self.local_user.deactivation_reason, "pending") self.assertEqual(self.local_user.deactivation_reason, "pending")
@ -293,10 +337,32 @@ class RegisterViews(TestCase):
result = login(request) result = login(request)
self.assertIsInstance(result, TemplateResponse) self.assertIsInstance(result, TemplateResponse)
result.render() validate_html(result.render())
self.assertEqual(result.status_code, 200) self.assertEqual(result.status_code, 200)
request.user = self.local_user request.user = self.local_user
result = login(request) result = login(request)
self.assertEqual(result.url, "/") self.assertEqual(result.url, "/")
self.assertEqual(result.status_code, 302) self.assertEqual(result.status_code, 302)
def test_confirm_email_post(self, *_):
"""send the email"""
self.settings.require_confirm_email = True
self.settings.save()
view = views.ConfirmEmail.as_view()
models.SiteInvite.objects.create(
code="testcode", user=self.local_user, use_limit=1
)
request = self.factory.post("", {"code": "testcode"})
request.user = self.anonymous_user
result = view(request)
validate_html(result.render())
def test_resend_link(self, *_):
"""try again"""
request = self.factory.post("", {"email": "mouse@mouse.com"})
request.user = self.anonymous_user
with patch("bookwyrm.emailing.send_email.delay") as mock:
views.resend_link(request)
self.assertEqual(mock.call_count, 1)

View file

@ -32,6 +32,12 @@ from .books.books import Book, upload_cover, add_description, resolve_book
from .books.edit_book import EditBook, ConfirmEditBook from .books.edit_book import EditBook, ConfirmEditBook
from .books.editions import Editions, switch_edition from .books.editions import Editions, switch_edition
# landing
from .landing.landing import About, Home, Landing
from .landing.login import Login, Logout
from .landing.register import Register, ConfirmEmail, ConfirmEmailCode, resend_link
from .landing.password import PasswordResetRequest, PasswordReset
# misc views # misc views
from .author import Author, EditAuthor from .author import Author, EditAuthor
from .directory import Directory from .directory import Directory
@ -45,17 +51,13 @@ from .import_data import Import, ImportStatus
from .inbox import Inbox from .inbox import Inbox
from .interaction import Favorite, Unfavorite, Boost, Unboost from .interaction import Favorite, Unfavorite, Boost, Unboost
from .isbn import Isbn from .isbn import Isbn
from .landing import About, Home, Landing
from .list import Lists, SavedLists, List, Curate, UserLists from .list import Lists, SavedLists, List, Curate, UserLists
from .list import save_list, unsave_list, delete_list from .list import save_list, unsave_list, delete_list
from .login import Login, Logout
from .notifications import Notifications from .notifications import Notifications
from .outbox import Outbox from .outbox import Outbox
from .reading import create_readthrough, delete_readthrough, delete_progressupdate from .reading import create_readthrough, delete_readthrough, delete_progressupdate
from .reading import ReadingStatus from .reading import ReadingStatus
from .register import Register, ConfirmEmail, ConfirmEmailCode, resend_link
from .rss_feed import RssFeed from .rss_feed import RssFeed
from .password import PasswordResetRequest, PasswordReset
from .search import Search from .search import Search
from .shelf import Shelf from .shelf import Shelf
from .shelf import create_shelf, delete_shelf from .shelf import create_shelf, delete_shelf

View file

@ -81,7 +81,7 @@ class Invite(View):
"invite": invite, "invite": invite,
"valid": invite.valid() if invite else True, "valid": invite.valid() if invite else True,
} }
return TemplateResponse(request, "invite.html", data) return TemplateResponse(request, "landing/invite.html", data)
# post handling is in views.register.Register # post handling is in views.register.Register

View file

View file

@ -3,8 +3,8 @@ from django.template.response import TemplateResponse
from django.views import View from django.views import View
from bookwyrm import forms from bookwyrm import forms
from .feed import Feed from bookwyrm.views import helpers
from . import helpers from bookwyrm.views.feed import Feed
# pylint: disable= no-self-use # pylint: disable= no-self-use

View file

@ -29,7 +29,7 @@ class Login(View):
"login_form": forms.LoginForm(), "login_form": forms.LoginForm(),
"register_form": forms.RegisterForm(), "register_form": forms.RegisterForm(),
} }
return TemplateResponse(request, "login.html", data) return TemplateResponse(request, "landing/login.html", data)
@sensitive_variables("password") @sensitive_variables("password")
@method_decorator(sensitive_post_parameters("password")) @method_decorator(sensitive_post_parameters("password"))
@ -69,7 +69,7 @@ class Login(View):
login_form.non_field_errors = _("Username or password are incorrect") login_form.non_field_errors = _("Username or password are incorrect")
register_form = forms.RegisterForm() register_form = forms.RegisterForm()
data = {"login_form": login_form, "register_form": register_form} data = {"login_form": login_form, "register_form": register_form}
return TemplateResponse(request, "login.html", data) return TemplateResponse(request, "landing/login.html", data)
@method_decorator(login_required, name="dispatch") @method_decorator(login_required, name="dispatch")

View file

@ -18,7 +18,7 @@ class PasswordResetRequest(View):
"""password reset page""" """password reset page"""
return TemplateResponse( return TemplateResponse(
request, request,
"password_reset_request.html", "landing/password_reset_request.html",
) )
def post(self, request): def post(self, request):
@ -30,7 +30,9 @@ class PasswordResetRequest(View):
) )
except models.User.DoesNotExist: except models.User.DoesNotExist:
data = {"error": _("No user with that email address was found.")} data = {"error": _("No user with that email address was found.")}
return TemplateResponse(request, "password_reset_request.html", data) return TemplateResponse(
request, "landing/password_reset_request.html", data
)
# remove any existing password reset cods for this user # remove any existing password reset cods for this user
models.PasswordReset.objects.filter(user=user).all().delete() models.PasswordReset.objects.filter(user=user).all().delete()
@ -39,7 +41,7 @@ class PasswordResetRequest(View):
code = models.PasswordReset.objects.create(user=user) code = models.PasswordReset.objects.create(user=user)
password_reset_email(code) password_reset_email(code)
data = {"message": _(f"A password reset link was sent to {email}")} data = {"message": _(f"A password reset link was sent to {email}")}
return TemplateResponse(request, "password_reset_request.html", data) return TemplateResponse(request, "landing/password_reset_request.html", data)
class PasswordReset(View): class PasswordReset(View):
@ -56,7 +58,7 @@ class PasswordReset(View):
except models.PasswordReset.DoesNotExist: except models.PasswordReset.DoesNotExist:
raise PermissionDenied() raise PermissionDenied()
return TemplateResponse(request, "password_reset.html", {"code": code}) return TemplateResponse(request, "landing/password_reset.html", {"code": code})
def post(self, request, code): def post(self, request, code):
"""allow a user to change their password through an emailed token""" """allow a user to change their password through an emailed token"""
@ -64,7 +66,7 @@ class PasswordReset(View):
reset_code = models.PasswordReset.objects.get(code=code) reset_code = models.PasswordReset.objects.get(code=code)
except models.PasswordReset.DoesNotExist: except models.PasswordReset.DoesNotExist:
data = {"errors": ["Invalid password reset link"]} data = {"errors": ["Invalid password reset link"]}
return TemplateResponse(request, "password_reset.html", data) return TemplateResponse(request, "landing/password_reset.html", data)
user = reset_code.user user = reset_code.user
@ -73,7 +75,7 @@ class PasswordReset(View):
if new_password != confirm_password: if new_password != confirm_password:
data = {"errors": ["Passwords do not match"]} data = {"errors": ["Passwords do not match"]}
return TemplateResponse(request, "password_reset.html", data) return TemplateResponse(request, "landing/password_reset.html", data)
user.set_password(new_password) user.set_password(new_password)
user.save(broadcast=False, update_fields=["password"]) user.save(broadcast=False, update_fields=["password"])

View file

@ -65,8 +65,8 @@ class Register(View):
"valid": invite.valid() if invite else True, "valid": invite.valid() if invite else True,
} }
if invite: if invite:
return TemplateResponse(request, "invite.html", data) return TemplateResponse(request, "landing/invite.html", data)
return TemplateResponse(request, "login.html", data) return TemplateResponse(request, "landing/login.html", data)
username = f"{localname}@{DOMAIN}" username = f"{localname}@{DOMAIN}"
user = models.User.objects.create_user( user = models.User.objects.create_user(

View file

@ -3,7 +3,7 @@ colorthief==0.2.1
Django==3.2.5 Django==3.2.5
django-imagekit==4.0.2 django-imagekit==4.0.2
django-model-utils==4.0.0 django-model-utils==4.0.0
environs==7.2.0 environs==9.3.4
flower==0.9.4 flower==0.9.4
Markdown==3.3.3 Markdown==3.3.3
Pillow>=8.2.0 Pillow>=8.2.0