Split authentication views into login and register

This commit is contained in:
Mouse Reeve 2021-09-07 13:11:44 -07:00
parent 53e0e9ae1e
commit 75cc2ee164
5 changed files with 92 additions and 83 deletions

View File

@ -63,7 +63,7 @@ class AuthenticationViews(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.authentication.login"): with patch("bookwyrm.views.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)
@ -77,7 +77,7 @@ class AuthenticationViews(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.authentication.login"): with patch("bookwyrm.views.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)
@ -91,7 +91,7 @@ class AuthenticationViews(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.authentication.login"): with patch("bookwyrm.views.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)
@ -105,7 +105,7 @@ class AuthenticationViews(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.authentication.login"): with patch("bookwyrm.views.login.login"):
result = view(request) result = view(request)
result.render() result.render()
self.assertEqual(result.status_code, 200) self.assertEqual(result.status_code, 200)
@ -126,7 +126,7 @@ class AuthenticationViews(TestCase):
"email": "aa@bb.cccc", "email": "aa@bb.cccc",
}, },
) )
with patch("bookwyrm.views.authentication.login"): with patch("bookwyrm.views.login.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)
@ -151,7 +151,7 @@ class AuthenticationViews(TestCase):
"email": "aa@bb.cccc", "email": "aa@bb.cccc",
}, },
) )
with patch("bookwyrm.views.authentication.login"): with patch("bookwyrm.views.login.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")
@ -169,7 +169,7 @@ class AuthenticationViews(TestCase):
"register/", "register/",
{"localname": "nutria ", "password": "mouseword", "email": "aa@bb.ccc"}, {"localname": "nutria ", "password": "mouseword", "email": "aa@bb.ccc"},
) )
with patch("bookwyrm.views.authentication.login"): with patch("bookwyrm.views.login.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)
@ -248,7 +248,7 @@ class AuthenticationViews(TestCase):
"invite_code": "testcode", "invite_code": "testcode",
}, },
) )
with patch("bookwyrm.views.authentication.login"): with patch("bookwyrm.views.login.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)

View File

@ -1,7 +1,5 @@
""" make sure all our nice views are available """ """ make sure all our nice views are available """
from .announcements import Announcements, Announcement, delete_announcement from .announcements import Announcements, Announcement, delete_announcement
from .authentication import Login, Register, Logout
from .authentication import ConfirmEmail, ConfirmEmailCode, resend_link
from .author import Author, EditAuthor from .author import Author, EditAuthor
from .block import Block, unblock from .block import Block, unblock
from .books import Book, EditBook, ConfirmEditBook from .books import Book, EditBook, ConfirmEditBook
@ -28,11 +26,13 @@ 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 from .list import save_list, unsave_list
from .list import delete_list from .list import 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 edit_readthrough, create_readthrough from .reading import edit_readthrough, create_readthrough
from .reading import delete_readthrough, delete_progressupdate from .reading import delete_readthrough, delete_progressupdate
from .reading import ReadingStatus from .reading import ReadingStatus
from .register import Register, ConfirmEmail, ConfirmEmailCode, resend_link
from .reports import Report, Reports, make_report, resolve_report, suspend_user from .reports import Report, Reports, make_report, resolve_report, suspend_user
from .rss_feed import RssFeed from .rss_feed import RssFeed
from .password import PasswordResetRequest, PasswordReset, ChangePassword from .password import PasswordResetRequest, PasswordReset, ChangePassword

View File

@ -83,7 +83,7 @@ class Invite(View):
} }
return TemplateResponse(request, "invite.html", data) return TemplateResponse(request, "invite.html", data)
# post handling is in views.authentication.Register # post handling is in views.register.Register
class ManageInviteRequests(View): class ManageInviteRequests(View):

80
bookwyrm/views/login.py Normal file
View File

@ -0,0 +1,80 @@
""" class views for login/register views """
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
from django.template.response import TemplateResponse
from django.utils import timezone
from django.utils.decorators import method_decorator
from django.utils.translation import gettext_lazy as _
from django.views.decorators.csrf import csrf_exempt
from django.views import View
from bookwyrm import forms, models
from bookwyrm.settings import DOMAIN
# pylint: disable=no-self-use
@method_decorator(csrf_exempt, name="dispatch")
class Login(View):
"""authenticate an existing user"""
def get(self, request, confirmed=None):
"""login page"""
if request.user.is_authenticated:
return redirect("/")
# send user to the login page
data = {
"show_confirmed_email": confirmed,
"login_form": forms.LoginForm(),
"register_form": forms.RegisterForm(),
}
return TemplateResponse(request, "login.html", data)
def post(self, request):
"""authentication action"""
if request.user.is_authenticated:
return redirect("/")
login_form = forms.LoginForm(request.POST)
localname = login_form.data["localname"]
if "@" in localname: # looks like an email address to me
try:
username = models.User.objects.get(email=localname).username
except models.User.DoesNotExist: # maybe it's a full username?
username = localname
else:
username = "%s@%s" % (localname, DOMAIN)
password = login_form.data["password"]
# perform authentication
user = authenticate(request, username=username, password=password)
if user is not None:
# successful login
login(request, user)
user.last_active_date = timezone.now()
user.save(broadcast=False, update_fields=["last_active_date"])
if request.POST.get("first_login"):
return redirect("get-started-profile")
return redirect(request.GET.get("next", "/"))
# maybe the user is pending email confirmation
if models.User.objects.filter(
username=username, is_active=False, deactivation_reason="pending"
).exists():
return redirect("confirm-email")
# login errors
login_form.non_field_errors = _("Username or password are incorrect")
register_form = forms.RegisterForm()
data = {"login_form": login_form, "register_form": register_form}
return TemplateResponse(request, "login.html", data)
@method_decorator(login_required, name="dispatch")
class Logout(View):
"""log out"""
def get(self, request):
"""done with this place! outa here!"""
logout(request)
return redirect("/")

View File

@ -1,13 +1,8 @@
""" class views for login/register views """ """ class views for login/register views """
from django.contrib.auth import authenticate, login, logout from django.contrib.auth import login
from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404, redirect from django.shortcuts import get_object_or_404, redirect
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
from django.utils import timezone
from django.utils.decorators import method_decorator
from django.utils.translation import gettext_lazy as _
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST from django.views.decorators.http import require_POST
from django.views import View from django.views import View
@ -16,72 +11,6 @@ from bookwyrm.settings import DOMAIN
# pylint: disable=no-self-use # pylint: disable=no-self-use
@method_decorator(csrf_exempt, name="dispatch")
class Login(View):
"""authenticate an existing user"""
def get(self, request, confirmed=None):
"""login page"""
if request.user.is_authenticated:
return redirect("/")
# send user to the login page
data = {
"show_confirmed_email": confirmed,
"login_form": forms.LoginForm(),
"register_form": forms.RegisterForm(),
}
return TemplateResponse(request, "login.html", data)
def post(self, request):
"""authentication action"""
if request.user.is_authenticated:
return redirect("/")
login_form = forms.LoginForm(request.POST)
localname = login_form.data["localname"]
if "@" in localname: # looks like an email address to me
try:
username = models.User.objects.get(email=localname).username
except models.User.DoesNotExist: # maybe it's a full username?
username = localname
else:
username = "%s@%s" % (localname, DOMAIN)
password = login_form.data["password"]
# perform authentication
user = authenticate(request, username=username, password=password)
if user is not None:
# successful login
login(request, user)
user.last_active_date = timezone.now()
user.save(broadcast=False, update_fields=["last_active_date"])
if request.POST.get("first_login"):
return redirect("get-started-profile")
return redirect(request.GET.get("next", "/"))
# maybe the user is pending email confirmation
if models.User.objects.filter(
username=username, is_active=False, deactivation_reason="pending"
).exists():
return redirect("confirm-email")
# login errors
login_form.non_field_errors = _("Username or password are incorrect")
register_form = forms.RegisterForm()
data = {"login_form": login_form, "register_form": register_form}
return TemplateResponse(request, "login.html", data)
@method_decorator(login_required, name="dispatch")
class Logout(View):
"""log out"""
def get(self, request):
"""done with this place! outa here!"""
logout(request)
return redirect("/")
class Register(View): class Register(View):
"""register a user""" """register a user"""