mgt c10 checkpoint with debug
This commit is contained in:
		@@ -1,5 +1,6 @@
 | 
			
		||||
from flask import render_template
 | 
			
		||||
from flask_mail import Message
 | 
			
		||||
from app import mail
 | 
			
		||||
from app import mail, app
 | 
			
		||||
 | 
			
		||||
def send_email(subject, sender, recipients, text_body, html_body):
 | 
			
		||||
    msg = Message(subject, sender=sender, recipients=recipients)
 | 
			
		||||
@@ -7,3 +8,15 @@ def send_email(subject, sender, recipients, text_body, html_body):
 | 
			
		||||
    msg.html = html_body
 | 
			
		||||
    mail.send(msg)
 | 
			
		||||
 | 
			
		||||
def send_password_reset_email(user):
 | 
			
		||||
    token = user.get_reset_password_token()
 | 
			
		||||
    hostname = app.config['REAL_HOSTNAME']
 | 
			
		||||
    send_email('[Blog] Reset Password',
 | 
			
		||||
               sender=app.config['ADMINS'][0],
 | 
			
		||||
               recipients=[user.email],
 | 
			
		||||
               text_body=render_template('email/reset_password.txt', hostname=hostname, user=user, token=token),
 | 
			
		||||
               html_body=render_template('email/reset_password.html', hostname=hostname, user=user, token=token))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -17,17 +17,20 @@ class RegistrationForm(FlaskForm):
 | 
			
		||||
    password = PasswordField('Password', validators=[DataRequired()])
 | 
			
		||||
    password2 = PasswordField('Repeat Password', validators=[DataRequired()])
 | 
			
		||||
    submit = SubmitField('Register')
 | 
			
		||||
 | 
			
		||||
    def validate_username(self, username):
 | 
			
		||||
        user = db.session.scalar(sa.select(User).where(User.username == username.data))
 | 
			
		||||
        if user is not None:
 | 
			
		||||
            raise ValidationError('Please use a different username.')
 | 
			
		||||
 | 
			
		||||
    def validate_email(self, email):
 | 
			
		||||
        user = db.session.scalar(sa.select(User).where(User.email == email.data))
 | 
			
		||||
        if user is not None:
 | 
			
		||||
            raise ValidationError('Please use a different email address.')
 | 
			
		||||
 | 
			
		||||
class ResetPasswordForm(FlaskForm):
 | 
			
		||||
    password = PasswordField('Password', validators=[DataRequired()])
 | 
			
		||||
    password2 = PasswordField('Repeat Password', validators=[DataRequired()])
 | 
			
		||||
    submit = SubmitField('Request Reset')
 | 
			
		||||
 | 
			
		||||
class EditProfileForm(FlaskForm):
 | 
			
		||||
    username = StringField('Username', validators=[DataRequired()])
 | 
			
		||||
    about_me = TextAreaField('About me', validators=[Length(min=0, max=140)])
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,17 @@
 | 
			
		||||
import os
 | 
			
		||||
from datetime import datetime, timezone
 | 
			
		||||
from typing import Optional
 | 
			
		||||
import sqlalchemy as sa
 | 
			
		||||
import sqlalchemy.orm as so
 | 
			
		||||
from werkzeug.security import generate_password_hash, check_password_hash
 | 
			
		||||
import pydenticon, hashlib, base64
 | 
			
		||||
import os, pydenticon, hashlib, base64, jwt
 | 
			
		||||
from time import time
 | 
			
		||||
 | 
			
		||||
from app import db, login
 | 
			
		||||
from app import db, login, app
 | 
			
		||||
from flask_login import UserMixin
 | 
			
		||||
 | 
			
		||||
#debug
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
followers = sa.Table(
 | 
			
		||||
        'followers',
 | 
			
		||||
        db.metadata,
 | 
			
		||||
@@ -39,15 +42,31 @@ class User(UserMixin, db.Model):
 | 
			
		||||
        self.password_hash = generate_password_hash(password)
 | 
			
		||||
    def check_password(self, password):
 | 
			
		||||
        return check_password_hash(self.password_hash, password)
 | 
			
		||||
    def get_reset_password_token(self, expires_in=600):
 | 
			
		||||
        token = jwt.encode({'reset_password': self.id, 'exp': time() + expires_in},
 | 
			
		||||
                          app.config['SECRET_KEY'], algorithm='HS256')
 | 
			
		||||
        return token
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def verify_reset_password_token(token):
 | 
			
		||||
        try:
 | 
			
		||||
            id = jwt.decode(token,
 | 
			
		||||
                            app.config['SECRET_KEY'], algorithms='HS256')['reset_password']
 | 
			
		||||
 | 
			
		||||
        except:
 | 
			
		||||
            return
 | 
			
		||||
        return db.session.get(User, id)
 | 
			
		||||
 | 
			
		||||
    def gen_avatar(self, write_png=True):
 | 
			
		||||
        foreground = [ "rgb(45,79,255)",
 | 
			
		||||
               "rgb(254,180,44)",
 | 
			
		||||
               "rgb(226,121,234)",
 | 
			
		||||
               "rgb(30,179,253)",
 | 
			
		||||
               "rgb(232,77,65)",
 | 
			
		||||
               "rgb(49,203,115)",
 | 
			
		||||
               "rgb(141,69,170)" ]
 | 
			
		||||
        background = "rgb(22,22,22)"
 | 
			
		||||
        foreground = ['#ACE1AF',
 | 
			
		||||
                      '#ACC4E1',
 | 
			
		||||
                      '#E1ACDE',
 | 
			
		||||
                      '#E1CAAC',
 | 
			
		||||
                      '#AFFF00',
 | 
			
		||||
                      '#00FFCF',
 | 
			
		||||
                      '#5000FF',
 | 
			
		||||
                      '#FF0030']
 | 
			
		||||
                      
 | 
			
		||||
        background = '#151515'
 | 
			
		||||
 | 
			
		||||
        digest = hashlib.md5(self.email.lower().encode('utf-8')).hexdigest()
 | 
			
		||||
        basedir = os.path.abspath(os.path.dirname(__file__))
 | 
			
		||||
 
 | 
			
		||||
@@ -5,9 +5,12 @@ from datetime import datetime, timezone
 | 
			
		||||
import sqlalchemy as sa
 | 
			
		||||
 | 
			
		||||
from app import app, db
 | 
			
		||||
from app.forms import LoginForm, RegistrationForm, EditProfileForm, EmptyForm, PostForm, ResetPasswordRequestForm
 | 
			
		||||
from app.forms import LoginForm, RegistrationForm, EditProfileForm, EmptyForm, PostForm, ResetPasswordRequestForm, ResetPasswordForm
 | 
			
		||||
from app.models import User, Post
 | 
			
		||||
#from app.email import send_password_reset_email
 | 
			
		||||
from app.email import send_password_reset_email
 | 
			
		||||
 | 
			
		||||
#debug:
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
@app.before_request
 | 
			
		||||
def before_request():
 | 
			
		||||
@@ -84,6 +87,25 @@ def register():
 | 
			
		||||
        return redirect(url_for('login'))
 | 
			
		||||
    return render_template('register.html', title='Register', form=form)
 | 
			
		||||
 | 
			
		||||
@app.route('/reset_password/<token>', methods=['GET', 'POST'])
 | 
			
		||||
def reset_password(token):
 | 
			
		||||
    if current_user.is_authenticated:
 | 
			
		||||
        print('rp user is authed', file=sys.stderr)
 | 
			
		||||
        return redirect(url_for('index'))
 | 
			
		||||
    user = User.verify_reset_password_token(token)
 | 
			
		||||
    if not user:
 | 
			
		||||
        print('rp not user', file=sys.stderr)
 | 
			
		||||
        return redirect(url_for('index'))
 | 
			
		||||
    form = ResetPasswordForm()
 | 
			
		||||
    if form.validate_on_submit():
 | 
			
		||||
        print('rp validated', file=sys.stderr)
 | 
			
		||||
        user.set_password(form.password.data)
 | 
			
		||||
        db.session.commit()
 | 
			
		||||
        flash('Your password has been reset.')
 | 
			
		||||
        return redirect(url_for('login'))
 | 
			
		||||
    return render_template('reset_password.html', form=form)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@app.route('/user/<username>')
 | 
			
		||||
@login_required
 | 
			
		||||
def user(username):
 | 
			
		||||
@@ -153,11 +175,14 @@ def unfollow(username):
 | 
			
		||||
@app.route('/reset_password_request', methods=['GET', 'POST'])
 | 
			
		||||
def reset_password_request():
 | 
			
		||||
    if current_user.is_authenticated:
 | 
			
		||||
        print('rpr user is authed', file=sys.stderr)
 | 
			
		||||
        return redirect(url_for('index'))
 | 
			
		||||
    form = ResetPasswordRequestForm()
 | 
			
		||||
    if form.validate_on_submit():
 | 
			
		||||
        print('rpr form validated', file=sys.stderr)
 | 
			
		||||
        user = db.session.scalar(sa.select(User).where(User.email == form.email.data))
 | 
			
		||||
        if user:
 | 
			
		||||
            print('rpr if user', file=sys.stderr)
 | 
			
		||||
            send_password_reset_email(user)
 | 
			
		||||
        flash('Password reset sent.')
 | 
			
		||||
        return redirect(url_for('login'))
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								backend/app/templates/email/reset_password.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								backend/app/templates/email/reset_password.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
<!doctype html>
 | 
			
		||||
<html>
 | 
			
		||||
	<body>
 | 
			
		||||
		<p>User {{ user.username }} requested password reset.</p>
 | 
			
		||||
		<p>Reset link:</p>
 | 
			
		||||
		<p><a href="{{ hostname }}{{ url_for('reset_password', token=token) }}">click here</a>
 | 
			
		||||
		<p>If you did not request this, ignore this message.</p>
 | 
			
		||||
	</body>
 | 
			
		||||
</html>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										7
									
								
								backend/app/templates/email/reset_password.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								backend/app/templates/email/reset_password.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
User {{ user.username }} requested password reset.
 | 
			
		||||
 | 
			
		||||
Reset link follows.
 | 
			
		||||
 | 
			
		||||
{{ hostname }}{{ url_for('reset_password', token=token) }}
 | 
			
		||||
 | 
			
		||||
If you did not request this, ignore this message.
 | 
			
		||||
							
								
								
									
										26
									
								
								backend/app/templates/reset_password.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								backend/app/templates/reset_password.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
{% extends "base.html" %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
 | 
			
		||||
	<h1>Reset Your Password</h1>
 | 
			
		||||
	<form action="" method="post">
 | 
			
		||||
		{{ form.hidden_tag() }}
 | 
			
		||||
		<p>
 | 
			
		||||
			{{ form.password.label }}
 | 
			
		||||
			{{ form.password(size=32) }}
 | 
			
		||||
			{% for error in form.password.errors %}
 | 
			
		||||
			<span style="color: red;">[{{ error }}]</span>
 | 
			
		||||
			{% endfor %}
 | 
			
		||||
		</p>
 | 
			
		||||
		<p>
 | 
			
		||||
			{{ form.password2.label }}
 | 
			
		||||
			{{ form.password2(size=32) }}
 | 
			
		||||
			{% for error in form.password2.errors %}
 | 
			
		||||
			<span style="color: red;">[{{ error }}]</span>
 | 
			
		||||
			{% endfor %}
 | 
			
		||||
		</p>
 | 
			
		||||
		<p>{{ form.submit() }}</p>
 | 
			
		||||
	</form>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{% endblock %}
 | 
			
		||||
@@ -4,9 +4,9 @@ basedir = os.path.abspath(os.path.dirname(__file__))
 | 
			
		||||
# Remove or fallbacks for prod
 | 
			
		||||
 | 
			
		||||
class Config:
 | 
			
		||||
    SECRET_KEY = os.environ.get('FLASK_SECRET_KEY') or 'flasksk'
 | 
			
		||||
    SECRET_KEY = os.environ.get('DOTENV_FLASK_SECRET_KEY')
 | 
			
		||||
    #SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'zapp.db')
 | 
			
		||||
    SQLALCHEMY_DATABASE_URI = 'mariadb+mariadbconnector://flasku:' + os.environ.get('MYSQL_PASSWORD') + '@db:3306/flask'
 | 
			
		||||
    SQLALCHEMY_DATABASE_URI = 'mariadb+mariadbconnector://flasku:' + os.environ.get('DOTENV_MYSQL_PASSWORD') + '@db:3306/flask'
 | 
			
		||||
 | 
			
		||||
    MAIL_SERVER = 'pmb'
 | 
			
		||||
    #MAIL_SERVER = ''
 | 
			
		||||
@@ -14,8 +14,10 @@ class Config:
 | 
			
		||||
    MAIL_USE_TLS = False
 | 
			
		||||
    MAIL_USERNAME = ''
 | 
			
		||||
    MAIL_PASSWORD = ''
 | 
			
		||||
    ADMINS = [os.environ.get('ADMIN_EMAIL')]
 | 
			
		||||
    FROM_ADDRESS = os.environ.get('FROM_ADDRESS')
 | 
			
		||||
    ADMINS = [os.environ.get('DOTENV_ADMIN_EMAIL')]
 | 
			
		||||
    FROM_ADDRESS = os.environ.get('DOTENV_FROM_ADDRESS')
 | 
			
		||||
    REAL_HOSTNAME = os.environ.get('DOTENV_REAL_HOSTNAME')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    DC_LOGGING = True
 | 
			
		||||
    POSTS_PER_PAGE=5
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user