Start toying with some simple db functionality.
This commit is contained in:
parent
924bdbd8ce
commit
b5e892f57e
|
@ -1,8 +1,6 @@
|
|||
# Copyright Sage Vaillancourt 2021
|
||||
|
||||
import os
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
from flask import (
|
||||
Flask, redirect, url_for, render_template, send_from_directory
|
||||
|
@ -12,6 +10,7 @@ import writing
|
|||
|
||||
INDEX = None
|
||||
|
||||
|
||||
def optimize_css():
|
||||
import re
|
||||
root = os.path.dirname(os.getcwd())
|
||||
|
@ -26,6 +25,7 @@ def optimize_css():
|
|||
minified_file.write(minified)
|
||||
minified_file.close()
|
||||
|
||||
|
||||
def create_app(test_config=None):
|
||||
optimize_css()
|
||||
|
||||
|
@ -47,7 +47,7 @@ def create_app(test_config=None):
|
|||
|
||||
app.register_blueprint(
|
||||
writing.writing_blueprint,
|
||||
#url_prefix='/writing',
|
||||
# url_prefix='/writing',
|
||||
)
|
||||
|
||||
return app
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
import bcrypt
|
||||
import os
|
||||
import psycopg2
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass
|
||||
class Letter:
|
||||
id: int
|
||||
title: str
|
||||
contents: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class User:
|
||||
id: int
|
||||
email: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class UserWithHash:
|
||||
id: int
|
||||
email: str
|
||||
password_hash: str
|
||||
|
||||
|
||||
def connect():
|
||||
return psycopg2.connect(
|
||||
host=os.environ['UNDERCOVER_POSTGRES_HOST'],
|
||||
dbname=os.environ['UNDERCOVER_POSTGRES_DBNAME'],
|
||||
port=os.environ['UNDERCOVER_POSTGRES_PORT'],
|
||||
user=os.environ['UNDERCOVER_POSTGRES_USER'],
|
||||
password=os.environ['UNDERCOVER_POSTGRES_PASSWORD'])
|
||||
|
||||
|
||||
def connected(action):
|
||||
with connect() as con:
|
||||
cur = con.cursor()
|
||||
return action(cur, con)
|
||||
|
||||
|
||||
def login(user_email: str, password: str):
|
||||
pw_bytes: bytes = password.encode('utf-8')
|
||||
user = __get_user(user_email)
|
||||
return bcrypt.checkpw(pw_bytes, user.password_hash.encode('utf-8'))
|
||||
|
||||
|
||||
def add_user(username: str, password: str):
|
||||
pw_bytes = password.encode('utf-8')
|
||||
salt = bcrypt.gensalt()
|
||||
pw_hash = bcrypt.hashpw(pw_bytes, salt)
|
||||
decoded = pw_hash.decode('utf-8')
|
||||
|
||||
with connect() as con:
|
||||
cur = con.cursor()
|
||||
cur.execute("INSERT INTO users(email, password) VALUES (%s, %s)", (username, decoded))
|
||||
con.commit()
|
||||
|
||||
|
||||
def delete_user(username: str):
|
||||
with connect() as con:
|
||||
cur = con.cursor()
|
||||
cur.execute("DELETE FROM users WHERE email = %s", (username,))
|
||||
con.commit()
|
||||
|
||||
|
||||
def add_user_lambda(username: str, password: str):
|
||||
def f(cur, con):
|
||||
cur.execute("INSERT INTO users(email, password) VALUES (%s, %s)", (username, password))
|
||||
con.commit()
|
||||
connected(f)
|
||||
|
||||
|
||||
def add_letter(user_id: int, letter_title: str, letter_content: str):
|
||||
with connect() as con:
|
||||
cur = con.cursor()
|
||||
cur.execute("INSERT INTO letter_data(user_id, letter_name, letter_data) VALUES (%s, %s, %s)",
|
||||
(user_id, letter_title, letter_content))
|
||||
con.commit()
|
||||
|
||||
|
||||
def edit_letter(letter_id: int, letter_title: str, letter_content: str):
|
||||
with connect() as con:
|
||||
cur = con.cursor()
|
||||
cur.execute("UPDATE letter_data SET letter_name = %s, letter_data = %s WHERE id = %s",
|
||||
(letter_title, letter_content, letter_id))
|
||||
con.commit()
|
||||
|
||||
|
||||
def get_user_letters(user_id: int) -> [Letter]:
|
||||
with connect() as con:
|
||||
cur = con.cursor()
|
||||
cur.execute("SELECT id, letter_name, letter_data FROM letter_data WHERE user_id = %s", str(user_id))
|
||||
return map(lambda row: Letter(row[0], row[1], row[2]), cur.fetchall())
|
||||
|
||||
|
||||
def get_user(email: str) -> User:
|
||||
user = __get_user(email)
|
||||
return User(user.id, user.email)
|
||||
|
||||
|
||||
def __get_user(email: str) -> UserWithHash:
|
||||
"""
|
||||
:param email:
|
||||
:return: User without their password_hash
|
||||
"""
|
||||
with connect() as con:
|
||||
cur = con.cursor()
|
||||
cur.execute("SELECT id, password FROM users WHERE users.email = %s", (email,))
|
||||
user_id, password = cur.fetchone()
|
||||
return UserWithHash(user_id, email, password)
|
||||
|
||||
|
||||
def get_users() -> [UserWithHash]:
|
||||
with connect() as con:
|
||||
cur = con.cursor()
|
||||
cur.execute("SELECT id, email, password FROM users")
|
||||
return map(lambda row: UserWithHash(row[0], row[1], row[2]), cur.fetchall())
|
||||
|
||||
|
||||
add_user("hash_man", "hashword")
|
||||
print("Can pull correctly: " + str(login("hash_man", "hashword")))
|
||||
delete_user("hash_man")
|
||||
# add_letter(1, "Dynamically-added", "This is a letter added from Python!")
|
||||
# edit_letter(3, "Dynamically edited!", "This letter was dynamically edited from Python!")
|
||||
|
||||
|
||||
# for letter in get_user_letters(1):
|
||||
# print("\'" + letter.title + "\"" + ":")
|
||||
# print(" id: " + str(letter.id))
|
||||
# print(" letter-data: " + letter.contents)
|
||||
# print()
|
||||
|
||||
# for user in get_users():
|
||||
# print(user.email + ":")
|
||||
# print(" id: " + str(user.id))
|
||||
# print(" password: " + user.password_hash)
|
||||
# print()
|
||||
|
|
@ -1,9 +1,12 @@
|
|||
click==8.0.1
|
||||
Flask==2.0.1
|
||||
Flask-WTF==0.15.1
|
||||
bcrypt==4.0.0
|
||||
click==8.1.3
|
||||
Flask==2.2.2
|
||||
Flask-WTF==1.0.1
|
||||
Flask-SQLAlchemy==2.5.1
|
||||
gunicorn==20.1.0
|
||||
itsdangerous==2.0.1
|
||||
Jinja2==3.0.1
|
||||
MarkupSafe==2.0.1
|
||||
Werkzeug==2.0.1
|
||||
WTForms==2.3.3
|
||||
itsdangerous==2.1.2
|
||||
Jinja2==3.1.2
|
||||
MarkupSafe==2.1.1
|
||||
psycopg==3.1.1
|
||||
Werkzeug==2.2.2
|
||||
WTForms==3.0.1
|
52
writing.py
52
writing.py
|
@ -1,62 +1,80 @@
|
|||
# Copyright Sage Vaillancourt 2021
|
||||
|
||||
from flask import (Blueprint, render_template, request, make_response)
|
||||
from wtforms import Form, BooleanField, StringField, TextAreaField, validators
|
||||
from wtforms import Form, StringField, TextAreaField, validators
|
||||
import urllib.parse
|
||||
|
||||
from latty import CLData
|
||||
import flaskr
|
||||
import flaskr.db as db
|
||||
|
||||
|
||||
writing_blueprint = Blueprint('writing', __name__,)
|
||||
|
||||
|
||||
class CLForm(Form):
|
||||
username = StringField('Username:',
|
||||
username = StringField(
|
||||
'Username:',
|
||||
[validators.Length(min=4, max=99)],
|
||||
default="Sage Bernerner"
|
||||
)
|
||||
company = StringField('Company:',
|
||||
company = StringField(
|
||||
'Company:',
|
||||
[validators.Length(min=2, max=99)],
|
||||
default="BananaCorp"
|
||||
)
|
||||
jobandpronoun = StringField('Job and Pronoun (a/an):',
|
||||
jobandpronoun = StringField(
|
||||
'Job and Pronoun (a/an):',
|
||||
[validators.Length(min=4, max=99)],
|
||||
default="a banana stocker"
|
||||
)
|
||||
skilltypes = StringField('Skill Type:',
|
||||
skilltypes = StringField(
|
||||
'Skill Type:',
|
||||
[validators.Length(min=2, max=99)],
|
||||
default="practical"
|
||||
)
|
||||
myskills = StringField('My Skills:',
|
||||
myskills = StringField(
|
||||
'My Skills:',
|
||||
[validators.Length(min=2, max=99)],
|
||||
default="stocking bananas"
|
||||
)
|
||||
closingtext = TextAreaField('Closing Text:',
|
||||
closingtext = TextAreaField(
|
||||
'Closing Text:',
|
||||
[validators.Length(min=2, max=99)],
|
||||
default="I look forward to hearing from you"
|
||||
)
|
||||
|
||||
body_string = ("My name is {\\username}. I would like to work as "
|
||||
"{\\jobandpronoun} with your company. I think my {\\skilltypes} knowledge "
|
||||
"of {\\myskills} can contribute a lot to your team.\n\n"
|
||||
body_string = (
|
||||
"My name is {\\username}. I would like to work as "
|
||||
"{\\jobandpronoun} with your company. I think my {\\skilltypes} knowledge "
|
||||
"of {\\myskills} can contribute a lot to your team.\n\n"
|
||||
|
||||
"I am passionate about what I do, and I think we would work well together.\n\n"
|
||||
"I am passionate about what I do, and I think we would work well together.\n\n"
|
||||
|
||||
"Thank you for your consideration.")
|
||||
body = TextAreaField('Body:',
|
||||
"Thank you for your consideration."
|
||||
)
|
||||
body = TextAreaField(
|
||||
'Body:',
|
||||
[validators.Length(min=4, max=9999)],
|
||||
default=body_string
|
||||
)
|
||||
|
||||
|
||||
@writing_blueprint.route('/', methods=['GET'])
|
||||
def index_get():
|
||||
if flaskr.INDEX == None:
|
||||
if flaskr.INDEX is None:
|
||||
flaskr.INDEX = render_template(
|
||||
'writing.html',
|
||||
form=CLForm()
|
||||
)
|
||||
return flaskr.INDEX
|
||||
|
||||
|
||||
@writing_blueprint.route('/dbtest', methods=['GET'])
|
||||
def index_get():
|
||||
return db.get_user_letters(1)[0].contents
|
||||
|
||||
|
||||
@writing_blueprint.route('/', methods=['POST'])
|
||||
def index_post():
|
||||
form = CLForm(request.form)
|
||||
|
@ -73,7 +91,8 @@ def index_post():
|
|||
|
||||
(resp, errors) = data.generate_pdf()
|
||||
if errors:
|
||||
resp = make_response(render_template('writing.html',
|
||||
resp = make_response(render_template(
|
||||
'writing.html',
|
||||
form=form,
|
||||
errors=errors,
|
||||
))
|
||||
|
@ -82,6 +101,7 @@ def index_post():
|
|||
resp.set_cookie(pair[0], urllib.parse.quote(pair[1]))
|
||||
return resp
|
||||
|
||||
return render_template('writing.html',
|
||||
return render_template(
|
||||
'writing.html',
|
||||
form=form,
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue