Password reset and change password flows
This commit is contained in:
@ -1,2 +1,3 @@
|
||||
''' make sure all our nice views are available '''
|
||||
from .authentication import LoginView, RegisterView
|
||||
from .authentication import Login, Register, Logout
|
||||
from .password import PasswordResetRequest, PasswordReset, ChangePassword
|
||||
|
@ -1,9 +1,11 @@
|
||||
''' class views for login/register/password management views '''
|
||||
from django.contrib.auth import authenticate, login
|
||||
''' class views for login/register views '''
|
||||
from django.contrib.auth import authenticate, login, logout
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.template.response import TemplateResponse
|
||||
from django.utils import timezone
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views import View
|
||||
|
||||
from bookwyrm import forms, models
|
||||
@ -11,7 +13,7 @@ from bookwyrm.settings import DOMAIN
|
||||
|
||||
|
||||
# pylint: disable= no-self-use
|
||||
class LoginView(View):
|
||||
class Login(View):
|
||||
''' authenticate an existing user '''
|
||||
def get(self, request):
|
||||
''' login page '''
|
||||
@ -49,7 +51,7 @@ class LoginView(View):
|
||||
return TemplateResponse(request, 'login.html', data)
|
||||
|
||||
|
||||
class RegisterView(View):
|
||||
class Register(View):
|
||||
''' register a user '''
|
||||
def post(self, request):
|
||||
''' join the server '''
|
||||
@ -100,3 +102,12 @@ class RegisterView(View):
|
||||
|
||||
login(request, user)
|
||||
return redirect('/')
|
||||
|
||||
|
||||
@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('/')
|
||||
|
102
bookwyrm/views/password.py
Normal file
102
bookwyrm/views/password.py
Normal file
@ -0,0 +1,102 @@
|
||||
''' class views for password management '''
|
||||
from django.contrib.auth import login
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.shortcuts import redirect
|
||||
from django.template.response import TemplateResponse
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views import View
|
||||
|
||||
from bookwyrm import models
|
||||
from bookwyrm.emailing import password_reset_email
|
||||
|
||||
|
||||
# pylint: disable= no-self-use
|
||||
class PasswordResetRequest(View):
|
||||
''' forgot password flow '''
|
||||
def get(self, request):
|
||||
''' password reset page '''
|
||||
return TemplateResponse(
|
||||
request,
|
||||
'password_reset_request.html',
|
||||
{'title': 'Reset Password'}
|
||||
)
|
||||
|
||||
def post(self, request):
|
||||
''' create a password reset token '''
|
||||
email = request.POST.get('email')
|
||||
try:
|
||||
user = models.User.objects.get(email=email)
|
||||
except models.User.DoesNotExist:
|
||||
return redirect('/password-reset')
|
||||
|
||||
# remove any existing password reset cods for this user
|
||||
models.PasswordReset.objects.filter(user=user).all().delete()
|
||||
|
||||
# create a new reset code
|
||||
code = models.PasswordReset.objects.create(user=user)
|
||||
password_reset_email(code)
|
||||
data = {'message': 'Password reset link sent to %s' % email}
|
||||
return TemplateResponse(request, 'password_reset_request.html', data)
|
||||
|
||||
|
||||
class PasswordReset(View):
|
||||
''' set new password '''
|
||||
def get(self, 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}
|
||||
)
|
||||
|
||||
def post(self, request, code):
|
||||
''' allow a user to change their password through an emailed token '''
|
||||
try:
|
||||
reset_code = models.PasswordReset.objects.get(
|
||||
code=code
|
||||
)
|
||||
except models.PasswordReset.DoesNotExist:
|
||||
data = {'errors': ['Invalid password reset link']}
|
||||
return TemplateResponse(request, 'password_reset.html', data)
|
||||
|
||||
user = reset_code.user
|
||||
|
||||
new_password = request.POST.get('password')
|
||||
confirm_password = request.POST.get('confirm-password')
|
||||
|
||||
if new_password != confirm_password:
|
||||
data = {'errors': ['Passwords do not match']}
|
||||
return TemplateResponse(request, 'password_reset.html', data)
|
||||
|
||||
user.set_password(new_password)
|
||||
user.save()
|
||||
login(request, user)
|
||||
reset_code.delete()
|
||||
return redirect('/')
|
||||
|
||||
|
||||
@method_decorator(login_required, name='dispatch')
|
||||
class ChangePassword(View):
|
||||
''' change password as logged in user '''
|
||||
def post(self, request):
|
||||
''' allow a user to change their password '''
|
||||
new_password = request.POST.get('password')
|
||||
confirm_password = request.POST.get('confirm-password')
|
||||
|
||||
if new_password != confirm_password:
|
||||
return redirect('/user-edit')
|
||||
|
||||
request.user.set_password(new_password)
|
||||
request.user.save()
|
||||
login(request, request.user)
|
||||
return redirect('/user/%s' % request.user.localname)
|
Reference in New Issue
Block a user