From ed9df4db6ffe585878b912ce7fbf1840c9504d83 Mon Sep 17 00:00:00 2001 From: finn Date: Sun, 4 Aug 2024 22:00:07 -0700 Subject: [PATCH] mgt c10 checkpoint --- backend/Dockerfile | 2 +- backend/README.md | 2 ++ backend/app/__init__.py | 2 ++ backend/app/email.py | 9 +++++++++ backend/app/forms.py | 4 ++++ backend/app/routes.py | 16 +++++++++++++++- backend/app/templates/login.html | 1 + .../app/templates/reset_password_request.html | 17 +++++++++++++++++ backend/config.py | 4 ++-- backend/requirements.txt | 11 +++++------ 10 files changed, 58 insertions(+), 10 deletions(-) create mode 100644 backend/app/email.py create mode 100644 backend/app/templates/reset_password_request.html diff --git a/backend/Dockerfile b/backend/Dockerfile index 2145c54..e6faad8 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -10,7 +10,7 @@ RUN apt update && apt install -y \ WORKDIR /code COPY requirements.txt /code RUN target=/root/.cache/pip \ - pip3 install -r requirements.txt + pip3 install --root-user-action=ignore -q -r requirements.txt # Need to make this explicit as part of expansion, no migrations or venv COPY . . diff --git a/backend/README.md b/backend/README.md index e2b34d0..198de84 100644 --- a/backend/README.md +++ b/backend/README.md @@ -18,6 +18,8 @@ pip install flask-migrate pip install flask-login pip install email-validator pip install pydenticon +pip install flask-mail +pip install pyjwt Prod only, require sys packages: pip install mariadb pip install uwsgi diff --git a/backend/app/__init__.py b/backend/app/__init__.py index 8d36e49..758e496 100644 --- a/backend/app/__init__.py +++ b/backend/app/__init__.py @@ -5,6 +5,7 @@ from flask_migrate import Migrate from flask_login import LoginManager import logging, sys from logging.handlers import SMTPHandler +from flask_mail import Mail app = Flask(__name__) app.config.from_object(Config) @@ -12,6 +13,7 @@ db = SQLAlchemy(app) migrate = Migrate(app, db) login = LoginManager(app) login.login_view = 'login' +mail=Mail(app) if not app.debug: if app.config['MAIL_SERVER']: diff --git a/backend/app/email.py b/backend/app/email.py new file mode 100644 index 0000000..2adc7a8 --- /dev/null +++ b/backend/app/email.py @@ -0,0 +1,9 @@ +from flask_mail import Message +from app import mail + +def send_email(subject, sender, recipients, text_body, html_body): + msg = Message(subject, sender=sender, recipients=recipients) + msg.body = text_body + msg.html = html_body + mail.send(msg) + diff --git a/backend/app/forms.py b/backend/app/forms.py index 5d50a5c..25249ca 100644 --- a/backend/app/forms.py +++ b/backend/app/forms.py @@ -43,6 +43,10 @@ class EditProfileForm(FlaskForm): if user is not None: raise ValidationError('Please use a different username.') +class ResetPasswordRequestForm(FlaskForm): + email = StringField('Email', validators=[DataRequired(), Email()]) + submit = SubmitField('Request Password Reset') + class PostForm(FlaskForm): post = TextAreaField('Post:', validators=[DataRequired(), Length(min=1, max=140)]) submit = SubmitField('Submit') diff --git a/backend/app/routes.py b/backend/app/routes.py index d2ae9a9..099877a 100644 --- a/backend/app/routes.py +++ b/backend/app/routes.py @@ -5,8 +5,9 @@ from datetime import datetime, timezone import sqlalchemy as sa from app import app, db -from app.forms import LoginForm, RegistrationForm, EditProfileForm, EmptyForm, PostForm +from app.forms import LoginForm, RegistrationForm, EditProfileForm, EmptyForm, PostForm, ResetPasswordRequestForm from app.models import User, Post +#from app.email import send_password_reset_email @app.before_request def before_request(): @@ -149,4 +150,17 @@ def unfollow(username): else: return redirect(url_for('index')) +@app.route('/reset_password_request', methods=['GET', 'POST']) +def reset_password_request(): + if current_user.is_authenticated: + return redirect(url_for('index')) + form = ResetPasswordRequestForm() + if form.validate_on_submit(): + user = db.session.scalar(sa.select(User).where(User.email == form.email.data)) + if user: + send_password_reset_email(user) + flash('Password reset sent.') + return redirect(url_for('login')) + return render_template('reset_password_request.html', title='Reset Password', form=form) + diff --git a/backend/app/templates/login.html b/backend/app/templates/login.html index c604808..9bb8d2d 100644 --- a/backend/app/templates/login.html +++ b/backend/app/templates/login.html @@ -23,6 +23,7 @@

Register Here

+

Reset Password

{% endblock %} diff --git a/backend/app/templates/reset_password_request.html b/backend/app/templates/reset_password_request.html new file mode 100644 index 0000000..da2b56e --- /dev/null +++ b/backend/app/templates/reset_password_request.html @@ -0,0 +1,17 @@ +{% extends "base.html" %} + +{% block content %} +

Reset Password

+
+ {{ form.hidden_tag() }} +

+ {{ form.email.label }}
+ {{ form.email(size=64) }}
+ {% for error in form.email.errors %} + [{{ error }}] + {% endfor %} +

+

{{ form.submit() }}

+
+ +{% endblock %} diff --git a/backend/config.py b/backend/config.py index f6b5a7f..cf211e7 100644 --- a/backend/config.py +++ b/backend/config.py @@ -8,8 +8,8 @@ class Config: #SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'zapp.db') SQLALCHEMY_DATABASE_URI = 'mariadb+mariadbconnector://flasku:' + os.environ.get('MYSQL_PASSWORD') + '@db:3306/flask' - #MAIL_SERVER = 'pmb' - MAIL_SERVER = '' + MAIL_SERVER = 'pmb' + #MAIL_SERVER = '' MAIL_PORT = 25 MAIL_USE_TLS = False MAIL_USERNAME = '' diff --git a/backend/requirements.txt b/backend/requirements.txt index 2cdaf64..aa2e006 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -5,6 +5,7 @@ dnspython==2.6.1 email_validator==2.2.0 Flask==3.0.3 Flask-Login==0.6.3 +Flask-Mail==0.10.0 Flask-Migrate==4.0.7 Flask-SQLAlchemy==3.1.1 Flask-WTF==1.2.1 @@ -13,17 +14,15 @@ idna==3.7 itsdangerous==2.2.0 Jinja2==3.1.4 Mako==1.3.5 +mariadb==1.1.10 MarkupSafe==2.1.5 +packaging==24.1 pillow==10.4.0 pydenticon==0.3.1 +PyJWT==2.9.0 python-dotenv==1.0.1 SQLAlchemy==2.0.31 typing_extensions==4.12.2 +uWSGI==2.0.26 Werkzeug==3.0.3 WTForms==3.1.2 -mariadb==1.1.10 -packaging==24.1 -setuptools==72.1.0 -uWSGI==2.0.26 -wheel==0.43.0 -