# Copyright Sage Vaillancourt 2021 import json import os import subprocess import threading import urllib.parse from flask import (Blueprint, render_template, request, make_response, session, redirect, jsonify) from wtforms import Form, SelectField, StringField, TextAreaField, validators from email_validator import validate_email, EmailNotValidError import undercover.db as db import undercover.email as email from undercover.pdf_builder import CLData writing_blueprint = Blueprint('writing', __name__,) class CLForm(Form): letterName = SelectField( 'Letter Name:', [validators.optional()], choices=[(1, 'LETTER TITLE')] ) username = StringField( 'Username:', [validators.Length(min=4, max=99)], default="Sage" ) company = StringField( 'Company:', [validators.Length(min=2, max=99)], default="BananaCorp" ) jobAndPronoun = StringField( 'Job and Pronoun (a/an):', [validators.Length(min=4, max=99)], default="a banana stocker" ) skillTypes = StringField( 'Skill Type:', [validators.Length(min=2, max=99)], default="practical" ) mySkills = StringField( 'My Skills:', [validators.Length(min=2, max=99)], default="stocking bananas" ) closingText = TextAreaField( 'Closing Text:', [validators.Length(min=2, max=99)], default="I look forward to hearing from you" ) body = TextAreaField( 'Body:', [validators.Length(min=4, max=9999)], default=( "My name is {\\username}. I'm excited for the opportunity to work as " "{\\jobAndPronoun} with your company. I think my {\\skillTypes} knowledge " "of {\\mySkills} could contribute well to your team.\n\n" "I am passionate about what I do, and I think we would work well together.\n\n" "Thank you for your consideration." ) ) @writing_blueprint.route('/login', methods=['POST', 'GET']) def login(): if request.method == 'POST': username = request.form['login'] if db.login(username, request.form['password']): session['username'] = username return redirect('/') return make_response( render_template( 'writing.jinja2', form=CLForm(), error="Invalid username or password" ), 401) return '''

''' @writing_blueprint.route('/logout', methods=['POST', 'GET']) def logout(): session.pop('username', None) return redirect('/') @writing_blueprint.route('/', methods=['GET']) def index_get(): email_address = session.get('username') form = CLForm() if email_address: user = db.get_user(email_address) letters = db.get_user_letters(user.id) if len(letters) > 0: letter_names = [(i + 1, letter.title) for i, letter in enumerate(letters)] form.letterName.choices = letter_names # TODO: Load this data more dynamically # I.e. use a dictionary instead of explicitly-defined fields data = json.loads(letters[0].contents) form.letterName.data = 1 form.company.data = data['company'] form.body.data = data['body'] form.closingText.data = data['closingText'] form.jobAndPronoun.data = data['jobAndPronoun'] form.mySkills.data = data['mySkills'] form.skillTypes.data = data['skillTypes'] form.username.data = data['username'] return render_template( 'writing.jinja2', form=form, username=session.get('username') ) @writing_blueprint.route('/create_account', methods=['GET']) def create_account_page(): return render_template('create_account.jinja2') @writing_blueprint.route('/create_account', methods=['POST']) def create_account(): email_address = request.form['login'] try: validate_email(email_address, check_deliverability=True) except EmailNotValidError as e: return make_response(render_template('writing.jinja2', form=CLForm(), error=str(e)), 401) if db.get_user(email_address): return make_response(render_template('writing.jinja2', form=CLForm(), error="A user with that email already exists!"), 401) db.add_user(email_address, request.form['password']) session['username'] = email_address return redirect('/') @writing_blueprint.route('/reset', methods=['POST', 'GET']) def reset_password(): if request.method == 'POST': email_address = request.form.get('login') existing_reset_id = request.form.get('reset_id') if email_address: reset_id = db.initiate_password_reset(email_address) if reset_id: email.send_password_reset(email_address, 'https://undercover.cafe/reset?id=' + str(reset_id)) # TODO: Eventually remove db entry whether or not link is clicked elif existing_reset_id: new_password = request.form['password'] db.complete_reset(existing_reset_id, new_password) # TODO: Log in? return redirect('/') query_reset_id = request.args.get('id') # TODO: Add password validation return f'''

''' @writing_blueprint.route('/dbtest', methods=['GET']) def db_test_get(): response = make_response(db.get_user_letters(1)[0].contents, 200) response.mimetype = "text/plain" return response @writing_blueprint.route('/update', methods=['POST']) def update_get(): expected_token = os.environ['GITLAB_HOOK_TOKEN'] given_token = request.headers['X-Gitlab-Token'] event_type = request.headers['X-Gitlab-Event'] if expected_token == given_token and event_type == "Push Hook": print("Update notification received.") response = make_response("", 200) response.mimetype = "text/plain" threading.Timer(5, git_update, []).start() return response else: return make_response("", 404) def git_update(): script = os.environ['UPDATE_SCRIPT_PATH'] if not script: return subprocess.run(['bash', '-c', "test -f " + script + " && " + script]) @writing_blueprint.route('/', methods=['POST']) def index_post(): form = CLForm(request.form) if form.validate(): selected_letter = form.letterName.data or '1' data = CLData( selectedLetter=int(selected_letter) - 1, username=form.username.data, company=form.company.data, jobAndPronoun=form.jobAndPronoun.data, skillTypes=form.skillTypes.data, mySkills=form.mySkills.data, closingText=form.closingText.data, body=form.body.data, ) email_address = session.get('username') if email_address: user = db.get_user(email_address) letters = db.get_user_letters(user.id) letter_json = jsonify(data).get_data(True) if len(letters) == 0: db.add_letter(user.id, 'My Cover Letter', letter_json) else: letter = letters[data.selectedLetter] # TODO: Support title editing db.edit_letter(letter.id, letter.title, letter_json) (resp, errors) = data.generate_pdf() if errors: resp = make_response(render_template( 'writing.jinja2', form=form, letter_errors=errors, )) # Save entered data as cookies on user's machine for pair in data.get_pairs(): resp.set_cookie(pair[0], urllib.parse.quote(pair[1])) return resp return render_template( 'writing.jinja2', form=form, )