# Site Back-End Logic from hmac import new from flask import Blueprint, render_template, request, flash, redirect, url_for, make_response from flask_login import login_user, login_required, logout_user, current_user from werkzeug.security import generate_password_hash, check_password_hash from argon2 import PasswordHasher from .models import User, Message from . import db import string, secrets from flask_wtf import FlaskForm from wtforms import StringField, SubmitField, PasswordField, FileField, IntegerField, RadioField, TextAreaField from wtforms.validators import DataRequired logic = Blueprint('logic', __name__) # WTForm Classes class DescForm(FlaskForm): # declare form field, required input, placeholder and validate data description = TextAreaField(validators=[DataRequired()]) submit = SubmitField('Update your Description') class PasswdForm(FlaskForm): passwd_1 = PasswordField('Edit Password', validators=[DataRequired()]) passwd_2 = PasswordField('Confirm Password', validators=[DataRequired()]) submit = SubmitField('Update Password') class MsgForm(FlaskForm): msg = TextAreaField(validators=[DataRequired()]) submit = SubmitField('Send') class LoginForm(FlaskForm): email = StringField(validators=[DataRequired()]) passwd = PasswordField(validators=[DataRequired()]) submit = SubmitField('Login') class RegForm(FlaskForm): email = StringField(validators=[DataRequired()]) passwd_1 = PasswordField(validators=[DataRequired()]) passwd_2 = PasswordField(validators=[DataRequired()]) firstname = StringField(validators=[DataRequired()]) lastname = StringField(validators=[DataRequired()]) age = IntegerField(validators=[DataRequired()]) gender = RadioField('Gender', choices=[('M', 'Male'),('F', 'Female')], validators=[DataRequired()]) submit = SubmitField('Register') @logic.route('/', methods=['GET', 'POST']) @login_required def profile(): form_1 = DescForm() form_2 = PasswdForm() ph = PasswordHasher() # WTForm Validation Checks if form_1.validate_on_submit(): new_desc = form_1.description.data form_1.description.data = '' new_desc_dbcall = User.query.filter_by(id=current_user.id).first() new_desc_dbcall.description = new_desc db.session.commit() flash('Hooray! A new description!', category='success') elif form_2.validate_on_submit(): passwd_1 = form_2.passwd_1.data passwd_2 = form_2.passwd_2.data form_2.passwd_1.data = '' form_2.passwd_2.data = '' if passwd_1 == passwd_2: if len(passwd_2) >= 12: npasswd = ph.hash(passwd_con) new_passwd_dbcall = User.query.filter_by(id=current_user.id).first() new_passwd_dbcall.password = npasswd db.session.commit() flash('Nice! Updated your password!', category='success') else: flash('Password must be equal or longer than 12 characters!', category='error') else: flash('Oh no! Your passwords must match!', category='error') # DB Insertions if request.method == "POST": new_pic = request.files.get('profilepic_upload') if new_pic: # generate random filename for uploaded file alphanumeric = string.ascii_letters + string.digits ralphanum = ''.join(secrets.choice(alphanumeric) for i in range(16)) new_pic_dbcall = User.query.filter_by(id=current_user.id).first() if '.png' in new_pic.filename: new_pic.save(f'app/static/uploads/{ralphanum}.png') new_pic_dbcall.profile_image = f'{ralphanum}.png' elif '.jpg' in new_pic.filename or 'jpeg' in new_pic.filename: new_pic.save(f'app/static/uploads/{ralphanum}.jpeg') new_pic_dbcall.profile_image = f'{ralphanum}.jpeg' db.session.commit() response = make_response(render_template("profile.html", user = current_user, form1 = form_1, form2= form_2)) response.headers['Content-Security-Policy'] = "default-src 'self'" response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains' response.headers['X-Content-Type-Options'] = 'nosniff' response.headers['X-Frame-Options'] = 'SAMEORIGIN' return response @logic.route('/matchbook', methods=['GET', 'POST']) @login_required def matchbook(): all_users = User.query.all() if request.method == 'POST': recipient_id = request.form.get('message_recipient') fdbcall = User.query.filter_by(id=current_user.id).first() fdbcall.focus = recipient_id db.session.commit() response = make_response(redirect(url_for('logic.messaging'))) response.headers['Content-Security-Policy'] = "default-src 'self'" return response response = make_response(render_template("matchbook.html", user=current_user, userlist=all_users)) response.headers['Content-Security-Policy'] = "default-src 'self'" response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains' response.headers['X-Content-Type-Options'] = 'nosniff' response.headers['X-Frame-Options'] = 'SAMEORIGIN' return response @logic.route('/messaging', methods=['GET', 'POST']) @login_required def messaging(): recipient_id = current_user.focus recipient = User.query.filter_by(id=recipient_id).first() sent_history = Message.query.filter_by(sender=current_user.id, recipient=recipient.id).all() recv_history = Message.query.filter_by(sender=recipient.id, recipient=current_user.id).all() joint_history = sent_history + recv_history joint_history.sort(key=lambda x: x.id) # add reverse=True for descending form = MsgForm() if form.validate_on_submit(): message = form.msg.data form.msg.data = '' new_msg_dbcall = Message(sender=current_user.id, recipient=recipient.id, message=message) db.session.add(new_msg_dbcall) db.session.commit() response = make_response(redirect(url_for('logic.messaging'))) response.headers['Content-Security-Policy'] = "default-src 'self'" response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains' response.headers['X-Content-Type-Options'] = 'nosniff' response.headers['X-Frame-Options'] = 'SAMEORIGIN' return response response = make_response(render_template( "messaging.html", user = current_user, recipient = recipient, msg_hist = joint_history, form = form )) response.headers['Content-Security-Policy'] = "default-src 'self'" response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains' response.headers['X-Content-Type-Options'] = 'nosniff' response.headers['X-Frame-Options'] = 'SAMEORIGIN' return response @logic.route('/login', methods=['GET', 'POST']) def login(): form = LoginForm() ph = PasswordHasher() if form.validate_on_submit(): email = form.email.data form.email.data = '' challenge_passwd = form.passwd.data form.passwd.data = '' user = User.query.filter_by(email=email).first() if user: if ph.verify(user.password, challenge_passwd): flash('Successful Login!', category='success') login_user(user, remember=True) return redirect(url_for('logic.profile')) else: flash('Unsucessful Login!', category='error') else: flash('Unsucessful Login!', category='error') response = make_response (render_template( "login.html", user = current_user, form = form )) response.headers['Content-Security-Policy'] = "default-src 'self'" response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains' response.headers['X-Content-Type-Options'] = 'nosniff' response.headers['X-Frame-Options'] = 'SAMEORIGIN' return response @logic.route('/logout') @login_required def logout(): logout_user() response = make_response(redirect(url_for('logic.login'))) response.headers['Content-Security-Policy'] = "default-src 'self'" response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains' response.headers['X-Content-Type-Options'] = 'nosniff' response.headers['X-Frame-Options'] = 'SAMEORIGIN' return response # Signup Route @logic.route('/register', methods=['GET', 'POST']) def register(): pass_list = list() ph = PasswordHasher() form = RegForm() if form.validate_on_submit(): email = form.email.data firstname = form.firstname.data lastname = form.lastname.data age = form.age.data gender = form.gender.data passwd_1 = form.passwd_1.data passwd_2 = form.passwd_2.data # Basic User Input Checks email_check = User.query.filter_by(email=email).first() if len(email) < 1: flash('Your Email must be longer than 0 characters.', category='error') elif email_check: flash('This Email is already taken', category='error') else: pass_list.append('p') if len(firstname) < 1: flash('First name must be something', category='error') else: pass_list.append('p') if len(lastname) < 1: flash('Last name must be something', category='error') else: pass_list.append('p') if gender == 'M' or gender == 'F': pass_list.append('p') else: flash('Gender must be either M or F!', category='error') if len(passwd_1) < 12 or len(passwd_2) < 12: flash('Your Password must be longer than or equal to 12 characters.', category='error') else: if passwd_1 != passwd_2: flash('Your Passwords must match!', category='error') else: if len(pass_list) == 4: npasswd = ph.hash(passwd_2) new_user = User(email=email, firstname=firstname, lastname=lastname, age=age, gender=gender, password=npasswd) db.session.add(new_user) db.session.commit() flash('Account Registration Successful!', category='success') response = make_response(redirect(url_for('logic.profile'))) response.headers['Content-Security-Policy'] = "default-src 'self'" response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains' response.headers['X-Content-Type-Options'] = 'nosniff' response.headers['X-Frame-Options'] = 'SAMEORIGIN' return response else: flash('Registration Failed', category='error') response = make_response(render_template("register.html", user = current_user, form = form)) response.headers['Content-Security-Policy'] = "default-src 'self'" response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains' response.headers['X-Content-Type-Options'] = 'nosniff' response.headers['X-Frame-Options'] = 'SAMEORIGIN' return response