Forgot your password?
++ Enter the email address that was used to register with Distribusiverse. +
+ +diff --git a/requirements.txt b/requirements.txt
index 3f744c9..915a7c8 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,9 +2,11 @@ alembic==1.7.5
Babel==2.9.1
bcrypt==3.2.0
black==21.11b1
+bleach==4.1.0
blinker==1.4
cffi==1.15.0
click==8.0.3
+distribusi @ git+file:///home/shambler/Development/distribusiverse/distribusi@e291e7497e40211c2ebd54ca32a1f4bdaed71230
dnspython==2.1.0
email-validator==1.1.3
Flask==2.0.2
@@ -15,6 +17,7 @@ Flask-Mail==0.9.1
Flask-Migrate==3.1.0
Flask-Principal==0.4.0
Flask-Security==3.0.0
+Flask-Security-Too==4.1.3
Flask-SQLAlchemy==2.5.1
Flask-WTF==1.0.0
greenlet==1.1.2
@@ -24,11 +27,13 @@ Jinja2==3.0.3
Mako==1.1.6
MarkupSafe==2.0.1
mypy-extensions==0.4.3
+packaging==21.3
passlib==1.7.4
pathspec==0.9.0
Pillow==8.3.2
platformdirs==2.4.0
pycparser==2.21
+pyparsing==3.0.7
python-magic==0.4.24
pytz==2021.3
regex==2021.11.10
@@ -36,7 +41,7 @@ six==1.16.0
speaklater==1.3
SQLAlchemy==1.4.27
tomli==1.2.2
-typing-extensions==4.0.1
+typing_extensions==4.0.1
+webencodings==0.5.1
Werkzeug==2.0.2
WTForms==3.0.0
--e git+https://git.vvvvvvaria.org/crunk/distribusi-verse.git@1a50898d216ae95c3eb9c144bb7ec678e638daa6#egg=distribusi
diff --git a/verse/app.py b/verse/app.py
index 8291340..7dd6f6a 100644
--- a/verse/app.py
+++ b/verse/app.py
@@ -22,6 +22,13 @@ def create_app():
APP.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True
APP.config["MAX_CONTENT_LENGTH"] = 150 * 1024 * 1024
+ APP.config["MAIL_SERVER"] = "0.0.0.0"
+ APP.config["MAIL_PORT"] = 1025
+ APP.config["MAIL_USE_SSL"] = False
+ APP.config["MAIL_USE_TLS"] = True
+ # APP.config['MAIL_USERNAME'] = 'username'
+ # APP.config['MAIL_PASSWORD'] = 'password'
+
login_manager.session_protection = "strong"
login_manager.login_view = "index"
login_manager.login_message_category = "info"
diff --git a/verse/forms/forgotpasswordform.py b/verse/forms/forgotpasswordform.py
new file mode 100644
index 0000000..3737181
--- /dev/null
+++ b/verse/forms/forgotpasswordform.py
@@ -0,0 +1,19 @@
+"""Forgotten password form to help user."""
+from wtforms import (
+ StringField,
+ SubmitField,
+)
+
+from wtforms import validators
+from wtforms.validators import Length, Email
+from flask_wtf import FlaskForm
+
+
+class ForgotPasswordForm(FlaskForm):
+ """Forgotten password distribusiverse form class."""
+
+ email = StringField(
+ "Email address:",
+ validators=[validators.InputRequired(), Email(), Length(6, 64)],
+ )
+ submit = SubmitField("Send email")
diff --git a/verse/start.py b/verse/start.py
index b77283d..de1be21 100644
--- a/verse/start.py
+++ b/verse/start.py
@@ -12,6 +12,7 @@ from flask_login import (
login_required,
current_user,
)
+from flask_mail import Mail
from flask_wtf.csrf import CSRFError
from app import create_app, login_manager
from usermodel import User
@@ -31,11 +32,13 @@ from uploadpage import UploadPage
from statuspengguna.helper import ResetUserState
from statuspengguna.loginuser import LoginUser
from statuspengguna.registeruser import RegisterUser
+from statuspengguna.forgotpassword import ForgotPassword
from distribusisinfo import DistribusisInfo
APP = create_app()
stash_page = Blueprint("stash_page", __name__, static_folder="stash")
APP.register_blueprint(stash_page)
+mail = Mail(APP)
@APP.before_request
@@ -129,14 +132,17 @@ def logout():
@APP.route("/login", methods=["GET", "POST"])
def login():
- result = LoginUser()
- return result
+ return LoginUser()
@APP.route("/register", methods=["GET", "POST"])
def register():
- result = RegisterUser()
- return result
+ return RegisterUser()
+
+
+@APP.route("/forgotpassword", methods=["GET", "POST"])
+def forgotpassword():
+ return ForgotPassword(mail)
@APP.errorhandler(CSRFError)
diff --git a/verse/statuspengguna/forgotpassword.py b/verse/statuspengguna/forgotpassword.py
new file mode 100644
index 0000000..69a1289
--- /dev/null
+++ b/verse/statuspengguna/forgotpassword.py
@@ -0,0 +1,34 @@
+from flask import render_template
+from usermodel import User
+from forms.forgotpasswordform import ForgotPasswordForm
+from flask_mail import Message
+
+
+def ForgotPassword(mail):
+ forgotpasswordform = ForgotPasswordForm()
+ if forgotpasswordform.validate_on_submit():
+ user = User.query.filter_by(
+ email=forgotpasswordform.email.data
+ ).first()
+ if user is not None:
+ ResetPassWordMessage(user, 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
+ contain any new mail, please check your spam folder.)"""
+ )
+ return render_template(
+ "forgotpassword.html", forgotpasswordform=forgotpasswordform
+ )
+
+
+def ResetPassWordMessage(user, 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.
+Click here to
+reset your password and make a new one."""
+ mail.send(msg)
diff --git a/verse/templates/forgotpassword.html b/verse/templates/forgotpassword.html
new file mode 100644
index 0000000..3932ca0
--- /dev/null
+++ b/verse/templates/forgotpassword.html
@@ -0,0 +1,29 @@
+{% extends "base.html" %}
+{% block main %}
+
+ Enter the email address that was used to register with Distribusiverse. +
+ +