Skeleton of resetrequest function

This commit is contained in:
downhill 2018-10-15 17:52:15 +02:00
parent c075872b43
commit 0842679b55
6 changed files with 113 additions and 24 deletions

View file

@ -6,10 +6,12 @@ While trying to {{service}}, an error was encountered: {{error}}
<br><br> <br><br>
You can try to: You can try to:
<br> <br>
{% if urlname %}
<form action={% url urlname %} method="get"> <form action={% url urlname %} method="get">
<input type="submit" value="Go back and try again"> <input type="submit" value="Go back and try again">
</form> </form>
<br>or<br> <br>or<br>
{% endif %}
<form action={% url 'index' %} method="get"> <form action={% url 'index' %} method="get">
<input type="submit" value="Go to the indexpage"> <input type="submit" value="Go to the indexpage">
</form> </form>

View file

@ -0,0 +1,14 @@
<title> Set new password for {{user}} </title>
<h2> Please set new password for {{user}} </h2>
<br><br>
<form action={% url 'reset' %} method="post">
{% csrf_token %}
New Password:<br>
<input type="password" name="password1" id="password1">
<br>Please confirm new password:<br>
<input type="password" name="password2" id="password2">
<br>
<input type="hidden" name="user" id="user" value="{{user}}">
<input type="submit" value="Submit">
</form>

View file

@ -2,7 +2,8 @@
<h2> Reset request processed and confirmation email sent </h2> <h2> Reset request processed and confirmation email sent </h2>
<br><br> <br><br>
You will shortly get the confirmation email at {{email}} to confirm that you wish to reset the password for {{user}}. You will shortly get the confirmation email to confirm that you wish to reset the password for {{user}}.<br>
Please follow the link in the email to reset your password.
<br><br> <br><br>
<form action={% url 'index' %} method="get"> <form action={% url 'index' %} method="get">
<input type="submit" value="Back to indexpage"> <input type="submit" value="Back to indexpage">

View file

@ -18,7 +18,7 @@ from django.urls import path
from django.conf.urls import url from django.conf.urls import url
from django.contrib import admin from django.contrib import admin
from .views import Register, ChangeData, ChangePassword, ResetPassword, DeleteAccount, Index, LogOut from .views import Register, ChangeData, ChangePassword, ResetPassword, DeleteAccount, Index, LogOut, ResetRequest
urlpatterns = [ urlpatterns = [
# path('admin/', admin.site.urls), # path('admin/', admin.site.urls),
@ -29,5 +29,7 @@ urlpatterns = [
path('deleteaccount/', DeleteAccount.as_view(), name="account_delete"), path('deleteaccount/', DeleteAccount.as_view(), name="account_delete"),
path('index/', Index.as_view(), name="index"), path('index/', Index.as_view(), name="index"),
path('logout/', LogOut.as_view(), name="logout"), path('logout/', LogOut.as_view(), name="logout"),
path('reset/<str:user>/<str:token>/', ResetRequest.as_view()),
path('reset/', ResetRequest.as_view(), name="reset"),
path('', Index.as_view(), name="index"), path('', Index.as_view(), name="index"),
] ]

View file

@ -6,6 +6,9 @@ from django.http import HttpResponse, HttpResponseRedirect
from django.core.validators import validate_email, ValidationError from django.core.validators import validate_email, ValidationError
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django_nameko import get_pool from django_nameko import get_pool
from django.contrib.auth.tokens import PasswordResetTokenGenerator
from base64 import b64encode, b64decode
from datetime import datetime
# Check to see if the username is already taken # Check to see if the username is already taken
# Helper function, not to be set up as a view # Helper function, not to be set up as a view
@ -170,16 +173,96 @@ class ResetPassword(View):
urlname = 'reset_password' urlname = 'reset_password'
service = 'send a password reset request' service = 'send a password reset request'
user = request.POST.get('user') user = request.POST.get('user')
if check_user_exists(user): # First, check if the user exists
# TODO: Get a good backend for reset requests if not check_user_exists(user):
# Sending the reset request return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'The user does not exist.' } )
email = self.send_resetrequest(user) # user exists, so try to get email
return render(request, 'send_resetrequest.html', { 'user': user, 'email': email } ) with get_pool().next() as rpc:
return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'The user does not exist.' } ) (state, tmp1, tmp2, email) = rpc.getuserdata.get_data(user)
# Either error with the datalookup or no email provided
if state == "error" or email == 'No email given' or not email:
return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Unable to retrieve email address for user.' } )
# Try to send the email out
emailsend = self.email(user, email)
# Email got sent out
if emailsend == True:
return render(request, 'send_resetrequest.html', { 'user': user } )
# Error while trying to send email
else:
return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': emailsend } )
def email(self, user, email):
#TODO figure out how to send email
email_from = 'Userservice at ungleich <userservice@ungleich.ch>'
to = '%s <%s>' % (user, email)
subject = 'Password reset request for %s' % user
no-reply = True
link = self.build_reset_link(user)
body = 'This is an automated email which was triggered by a reset request for the user %s.\n' % user
body += 'If you received this email in error, please disregard it. If you get multiple emails like this, please contact us to look into potential abuse.\n'
body += 'To reset your password, please follow the link below:\n'
body += '%s\n\n' % link
body += 'The link will remain active for 24 hours.\n'
# For debug
return link
def build_reset_link(self, user):
host = 'localhost:8000'
x = PasswordResetTokenGenerator()
token = x.make_token(user)
buser = bytes(user, 'utf-8')
userpart = b64encode(buser)
d = datetime.now()
# TODO Make Model und put it into the database
link = 'https://%s/reset/%s/%s/' % (host, userpart.decode('utf-8'), token)
return link
# Catch the resetrequest and check it
class ResetRequest(View):
# Gets the URL with user in b64 and the token, and checks it
# Also cleans the database
def get(self, request, user=None, token=None):
# Cleans up outdated tokens
self.clean_db()
if user == None or token == None:
return HttpResponse('Invalid URL.', status=404)
# extract user from b64 format
tmp_user = bytes(user, 'utf-8')
user = b64decode(tmp_user)
user_clean = user.decode('utf-8')
d = datetime.now()
#TODO write the model and check if token is still active and belongs to the user
# set checks_out = True if yes
if not checks_out:
return HttpResponse('Invalid URL.', status=404)
else:
return render(request, 'resetpasswordnew.html', { 'user': user_clean } )
# Gets the post form with the new password and sets it
def post(self, request):
service = 'reset the password'
password1 = request.POST.get("password1")
password2 = request.POST.get("password2")
user = request.POST.get("user")
if password1 == "" or not password1 or password2 == "" or not password2:
return render(request, 'error.html', { 'service': service, 'error': 'Please supply a password and confirm it.' } )
if password1 != password2:
return render(request, 'error.html', { 'service': service, 'error': 'The supplied passwords do not match.' } )
with get_pool().next() as rpc:
pwd = r'%s' % password1
result = rpc.changepassword.change_password(user, pwd)
if result == True:
return render(request, 'changedpassword.html', { 'user': user } )
else:
return render(request, 'error.html', { 'service': service, 'error': result } )
# Cleans up outdated tokens
def clean_db(self):
# TODO write the model and use this to clean tokens > 24h old
def send_resetrequest(self, user):
#TODO: call nameko to get the associated email and send a confirmation mail
return "test@example.com"
# The logged in user can change the password here # The logged in user can change the password here

View file

@ -222,19 +222,6 @@ class ChangeUserData(object):
return True return True
# Request a password reset
# TODO: Set up a system for it
# Basic idea: send email to customer with a confirmation request, set reply-to for something that handles it,
class PasswordResetRequest(object):
name = "passwordresetrequest"
dispatch = EventDispatcher()
@rpc
def send_request(self, user):
# TODO: Find a good system for that
return "To be done"
# change the password for the user # change the password for the user
class ChangePassword(object): class ChangePassword(object):
name = "changepassword" name = "changepassword"