Browse Source

reset password functionality

current_wdka_release
crunk 3 years ago
parent
commit
296838951e
  1. 2
      verse/app.py
  2. 27
      verse/forms/resetpasswordform.py
  3. 7
      verse/start.py
  4. 36
      verse/statuspengguna/forgotpassword.py
  5. 81
      verse/statuspengguna/resetpassword.py
  6. 1
      verse/templates/help.html
  7. 29
      verse/templates/resetpassword.html
  8. 4
      verse/usermodel.py

2
verse/app.py

@ -42,7 +42,7 @@ def create_app():
csrf.init_app(APP)
login_manager.init_app(APP)
db.init_app(APP)
migrate.init_app(APP, db)
migrate.init_app(APP, db, render_as_batch=True)
bcrypt.init_app(APP)
return APP

27
verse/forms/resetpasswordform.py

@ -0,0 +1,27 @@
"""Reset Password Form form to reset a users PasswordField."""
from wtforms import (
SubmitField,
PasswordField,
)
from wtforms import validators
from wtforms.validators import Length, EqualTo
from flask_wtf import FlaskForm
class ResetPasswordForm(FlaskForm):
"""ResetPassword for distribusi-verse form class"""
password = PasswordField(
"New password:",
validators=[validators.InputRequired(), Length(12, 72)],
)
confirmpassword = PasswordField(
"Confirm your password:",
validators=[
validators.InputRequired(),
Length(12, 72),
EqualTo("password", message="Passwords must match !"),
],
)
submit = SubmitField("Reset your password")

7
verse/start.py

@ -34,6 +34,7 @@ from statuspengguna.helper import ResetUserState
from statuspengguna.loginuser import LoginUser
from statuspengguna.registeruser import RegisterUser
from statuspengguna.forgotpassword import ForgotPassword
from statuspengguna.resetpassword import ResetPassword
from distribusisinfo import DistribusisInfo
APP = create_app()
@ -153,6 +154,12 @@ def forgotpassword():
return ForgotPassword(mail)
@APP.route("/resetpassword/<path>", methods=["GET", "POST"])
def resetpassword(path):
print(path)
return ResetPassword(path)
@APP.errorhandler(CSRFError)
def handle_csrf_error(e):
return render_template("csrf_error.html", reason=e.description), 400

36
verse/statuspengguna/forgotpassword.py

@ -1,7 +1,17 @@
from uuid import uuid1
from datetime import datetime
from sqlalchemy.exc import (
DataError,
DatabaseError,
InterfaceError,
InvalidRequestError,
)
from flask import render_template
from flask_mail import Message
from usermodel import User
from forms.forgotpasswordform import ForgotPasswordForm
from flask_mail import Message
from app import db
def ForgotPassword(mail):
@ -11,7 +21,8 @@ def ForgotPassword(mail):
email=forgotpasswordform.email.data
).first()
if user is not None:
ResetPassWordMessage(user, mail)
resethash = AddResetPasswordHash(user, forgotpasswordform)
ResetPassWordMessage(user, resethash, mail)
forgotpasswordform.email.errors.append(
f"""If {forgotpasswordform.email.data} exists, an email is send with
a password reset link. (If your inbox doesn't
@ -22,13 +33,26 @@ def ForgotPassword(mail):
)
def ResetPassWordMessage(user, mail):
def AddResetPasswordHash(user, forgotpasswordform):
resethash = uuid1().hex
try:
user.resettime = datetime.now()
user.resethash = resethash
db.session.commit()
except (InvalidRequestError, DataError, InterfaceError, DatabaseError):
forgotpasswordform.email.errors.append("Something went wrong!")
db.session.rollback()
return resethash
def ResetPassWordMessage(user, resethash, mail):
msg = Message(
"Distribusiverse Forgotten Password ",
sender=("Distribusiverse mailer", "test@this.com"),
recipients=[user.email],
)
msg.html = f"""You have requested a password reset for Distribusiverse.<br>
<a href='http://localhost:5000/resetpassword/{user.email}'>Click here to
reset your password and make a new one.</a>"""
msg.html = f"""{user.username} has requested a password reset for
Distribusiverse.<br><hr>
<a href='http://localhost:5000/resetpassword/{resethash}'>Click here to
reset your password.</a>"""
mail.send(msg)

81
verse/statuspengguna/resetpassword.py

@ -0,0 +1,81 @@
from datetime import datetime
from flask import (
render_template,
redirect,
flash,
url_for,
)
from sqlalchemy.exc import (
IntegrityError,
DataError,
DatabaseError,
InterfaceError,
InvalidRequestError,
)
from werkzeug.routing import BuildError
from usermodel import User
from forms.resetpasswordform import ResetPasswordForm
from flask_login import login_user
from flask_bcrypt import generate_password_hash
from app import db
def ResetPassword(path):
linkvalid = False
user = User.query.filter_by(resethash=path).first()
if user is None:
return redirect(url_for("index"))
timepassed = datetime.now() - user.resettime
if timepassed.days < 1:
linkvalid = True
resetpasswordform = ResetPasswordForm()
if resetpasswordform.validate_on_submit():
return ResetUserPasswordInDB(user, resetpasswordform)
return render_template(
"resetpassword.html",
resetpasswordform=resetpasswordform,
path=path,
linkvalid=linkvalid,
)
def ResetUserPasswordInDB(user, resetpasswordform):
try:
newpassword = resetpasswordform.confirmpassword.data
user.password = generate_password_hash(newpassword)
user.resethash = None
user.resettime = None
db.session.commit()
flash("Password Succesfully updated", "success")
login_user(user)
return redirect(url_for("index"))
except InvalidRequestError:
db.session.rollback()
resetpasswordform.email.errors.append("Something went wrong!")
flash("Something went wrong!", "danger")
except IntegrityError:
db.session.rollback()
resetpasswordform.email.errors.append("User already exists!")
flash("User already exists!", "warning")
except DataError:
db.session.rollback()
resetpasswordform.email.errors.append("Invalid Entry")
flash("Invalid Entry", "warning")
except InterfaceError:
db.session.rollback()
resetpasswordform.email.errors.append(
"Error connecting to the database"
)
flash("Error connecting to the database", "danger")
except DatabaseError:
db.session.rollback()
resetpasswordform.email.errors.append(
"Error connecting to the database"
)
flash("Error connecting to the database", "danger")
except BuildError:
db.session.rollback()
resetpasswordform.email.errors.append("Unknown error occured!")
flash("An error occured !", "danger")

1
verse/templates/help.html

@ -113,5 +113,4 @@ simple online editor or by uploading their own Css file.</p>
</p>
<hr>
</div>
<!-- a div with all the distribusis listed in the distribusiverse -->
{% endblock %}

29
verse/templates/resetpassword.html

@ -0,0 +1,29 @@
{% extends "base.html" %}
{% block main %}
<div id="login">
{% if linkvalid%}
<form class="form" action="{{ url_for('resetpassword', path=path) }}" method="post">
{{ resetpasswordform.csrf_token }}
<fieldset class="required">
{{ resetpasswordform.password.label }}
{{ resetpasswordform.password }}
{% for message in resetpasswordform.password.errors %}
<div class="error">{{ message }}</div>
{% endfor %}
</fieldset>
<fieldset class="required">
{{ resetpasswordform.confirmpassword.label }}
{{ resetpasswordform.confirmpassword }}
{% for message in resetpasswordform.confirmpassword.errors %}
<div class="error">{{ message }}</div>
{% endfor %}
</fieldset>
<fieldset class="button required">
{{ resetpasswordform.submit }}
</fieldset>
</form>
{% else %}
<h3>Password reset link no longer valid.</h3>
{% endif %}
</div>
{% endblock main %}

4
verse/usermodel.py

@ -12,8 +12,8 @@ class User(UserMixin, db.Model):
email = db.Column(db.String(150), unique=True, nullable=False)
password = db.Column(db.String(300), nullable=False, unique=False)
currentdistribusi = db.Column(db.String(300), nullable=True, unique=False)
# resethash = db.Column(db.String(300), nullable=True, unique=True)
# resettime = db.Column(db.DateTime)
resethash = db.Column(db.String(300), nullable=True, unique=True)
resettime = db.Column(db.DateTime)
tutor = db.Column(db.Boolean, default=False)
admin = db.Column(db.Boolean, default=False)

Loading…
Cancel
Save