-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: moved advent folder -> puzzles, added some comments * feat(docker): start separation of dev and prod builds, add pytest functionality to backend * feat(docker): added dev/prod to frontend, transition frontend to yarn * fix: remove .vscode folder * fix(makefile): restructured makefile a bit * feat: removed .vscode folder from git * feat(auth): get rudimentary autotesting in place, created clear_database function * feat(test): added all tests for auth/register * fix(puzzle): changed blueprint in routes/puzzle.py * feat(auth): refactored registration system, database connections * fix(auth): minor changes to constructor * feat(auth): implement email verification endpoints * feat(test): using fixtures * feat(auth): finish autotests, still needs commenting * feat(auth): finished writing tests for the most part * feat(auth): complete tests for basic auth system * fix(auth): removed duplicate clear_database function * fix(auth): add basic lockout functionality * fix(auth): fix clear_database utility function * fix(auth): change requests to conform with DB * fix(auth): add basic lockout to /login route * feat(auth): add function to carry over CSRF in headers
- Loading branch information
Showing
10 changed files
with
584 additions
and
426 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,50 @@ | ||
import redis | ||
|
||
# We're using Redis as a way to store codes with expiry dates - it might a bit | ||
# overkill, but it works | ||
|
||
cache = redis.Redis(host="redis", port=6379, db=0) | ||
from datetime import timedelta | ||
import redis | ||
|
||
# We're using Redis as a way to store codes with expiry dates - it might a bit | ||
# overkill, but it works | ||
|
||
MINUTES_IN_DAY = 1440 | ||
|
||
cache = redis.Redis(host="redis", port=6379, db=0) | ||
|
||
## EMAIL VERIFICATION | ||
|
||
## LOCKOUT | ||
|
||
def register_incorrect(id): | ||
times = cache.get(f"attempts_{id}") | ||
|
||
if times is None: | ||
times = 0 | ||
|
||
cache.set(f"attempts_{id}", int(times) + 1) | ||
|
||
def incorrect_attempts(id): | ||
attempts = cache.get(f"attempts_{id}") | ||
|
||
if attempts is None: | ||
return 0 | ||
else: | ||
return int(attempts) | ||
|
||
def calculate_time(attempts): | ||
if attempts < 3: | ||
return 0 | ||
|
||
minutes = 2 ** (attempts - 3) | ||
|
||
if minutes > MINUTES_IN_DAY: | ||
return MINUTES_IN_DAY | ||
else: | ||
return minutes | ||
|
||
def block(id, time): | ||
cache.set(f"block_{id}", "", ex=timedelta(minutes=time)) | ||
|
||
def is_blocked(id): | ||
token = cache.get(f"block_{id}") | ||
return token is not None | ||
|
||
def clear_redis(): | ||
cache.flushdb() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,28 @@ | ||
import os | ||
from psycopg2.pool import ThreadedConnectionPool | ||
|
||
user = os.environ["POSTGRES_USER"] | ||
password = os.environ["POSTGRES_PASSWORD"] | ||
host = os.environ["POSTGRES_HOST"] | ||
port = os.environ["POSTGRES_PORT"] | ||
database = os.environ["POSTGRES_DB"] | ||
|
||
# TABLES = ["Users", "Questions", "Parts", "Competitions", "Inputs", "Solves"] | ||
|
||
db = ThreadedConnectionPool( | ||
1, 20, | ||
user=user, | ||
password=password, | ||
host=host, | ||
port=port, | ||
database=database | ||
) | ||
|
||
def clear_database(): | ||
conn = db.getconn() | ||
|
||
with conn.cursor() as cursor: | ||
cursor.execute(f"""SELECT truncate_tables();""") | ||
conn.commit() | ||
|
||
db.putconn(conn) | ||
import os | ||
from psycopg2.pool import ThreadedConnectionPool | ||
|
||
user = os.environ["POSTGRES_USER"] | ||
password = os.environ["POSTGRES_PASSWORD"] | ||
host = os.environ["POSTGRES_HOST"] | ||
port = os.environ["POSTGRES_PORT"] | ||
database = os.environ["POSTGRES_DB"] | ||
|
||
# TABLES = ["Users", "Questions", "Parts", "Competitions", "Inputs", "Solves"] | ||
|
||
db = ThreadedConnectionPool( | ||
1, 20, | ||
user=user, | ||
password=password, | ||
host=host, | ||
port=port, | ||
database=database | ||
) | ||
|
||
def clear_database(): | ||
conn = db.getconn() | ||
|
||
with conn.cursor() as cursor: | ||
cursor.execute(f"""SELECT truncate_tables();""") | ||
conn.commit() | ||
|
||
db.putconn(conn) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,93 @@ | ||
from database.database import db | ||
|
||
|
||
def add_user(email, username, password) -> int: | ||
"""Adds a user to the database, returning their ID.""" | ||
|
||
conn = db.getconn() | ||
|
||
with conn.cursor() as cursor: | ||
cursor.execute(f"INSERT INTO Users (email, username, password) VALUES ('{email}', '{username}', '{password}')") | ||
conn.commit() | ||
|
||
cursor.execute(f"SELECT uid FROM Users WHERE email = '{email}'") | ||
id = cursor.fetchone()[0] | ||
|
||
db.putconn(conn) | ||
return id | ||
|
||
|
||
def fetch_user(email: str): | ||
"""Given a user's email, fetches their content from the database.""" | ||
|
||
conn = db.getconn() | ||
|
||
with conn.cursor() as cursor: | ||
cursor.execute(f"SELECT * FROM Users WHERE email = '{email}'") | ||
result = cursor.fetchone() | ||
|
||
db.putconn(conn) | ||
return result | ||
|
||
|
||
def email_exists(email: str) -> bool: | ||
"""Checks if an email exists in the users table.""" | ||
|
||
conn = db.getconn() | ||
|
||
with conn.cursor() as cursor: | ||
cursor.execute(f"SELECT * FROM Users WHERE email = '{email}'") | ||
results = cursor.fetchall() | ||
|
||
db.putconn(conn) | ||
return results != [] | ||
|
||
|
||
def username_exists(username: str) -> bool: | ||
"""Checks if a username is already used.""" | ||
|
||
conn = db.getconn() | ||
|
||
with conn.cursor() as cursor: | ||
cursor.execute(f"SELECT * FROM Users WHERE username = '{username}'") | ||
results = cursor.fetchall() | ||
|
||
db.putconn(conn) | ||
return results != [] | ||
from database.database import db | ||
|
||
# Get all the information about a user given their uid | ||
# Returns all information in the form of a dictionary | ||
def get_user_info(uid): | ||
conn = db.getconn() | ||
|
||
with conn.cursor() as cursor: | ||
query = f""" | ||
select * from Users where uid = {uid}; | ||
""" | ||
cursor.execute(query) | ||
|
||
# only one entry should be returned since day number is unique | ||
t = cursor.fetchone() | ||
|
||
db.putconn(conn) | ||
return t | ||
|
||
|
||
def add_user(email, username, password) -> int: | ||
"""Adds a user to the database, returning their ID.""" | ||
|
||
conn = db.getconn() | ||
|
||
with conn.cursor() as cursor: | ||
cursor.execute("INSERT INTO Users (email, username, password) VALUES (%s, %s, %s)", | ||
(email, username, password)) | ||
conn.commit() | ||
|
||
cursor.execute("SELECT uid FROM Users WHERE email = %s", (email,)) | ||
id = cursor.fetchone()[0] | ||
|
||
db.putconn(conn) | ||
return id | ||
|
||
|
||
def fetch_id(email: str): | ||
"""Given a user's email, fetches their ID.""" | ||
|
||
conn = db.getconn() | ||
|
||
with conn.cursor() as cursor: | ||
cursor.execute("SELECT uid FROM Users WHERE email = %s", (email,)) | ||
result = cursor.fetchone() | ||
|
||
if result is None: | ||
db.putconn(conn) | ||
return None | ||
|
||
id = result[0] | ||
|
||
db.putconn(conn) | ||
return id | ||
|
||
|
||
def fetch_user(email: str): | ||
"""Given a user's email, fetches their content from the database.""" | ||
|
||
conn = db.getconn() | ||
|
||
with conn.cursor() as cursor: | ||
cursor.execute("SELECT * FROM Users WHERE email = %s", (email,)) | ||
result = cursor.fetchone() | ||
|
||
db.putconn(conn) | ||
return result | ||
|
||
|
||
def email_exists(email: str) -> bool: | ||
"""Checks if an email exists in the users table.""" | ||
|
||
conn = db.getconn() | ||
|
||
with conn.cursor() as cursor: | ||
cursor.execute("SELECT * FROM Users WHERE email = %s", (email,)) | ||
results = cursor.fetchall() | ||
|
||
db.putconn(conn) | ||
return results != [] | ||
|
||
|
||
def username_exists(username: str) -> bool: | ||
"""Checks if a username is already used.""" | ||
|
||
conn = db.getconn() | ||
|
||
with conn.cursor() as cursor: | ||
cursor.execute("SELECT * FROM Users WHERE username = %s", (username,)) | ||
results = cursor.fetchall() | ||
|
||
db.putconn(conn) | ||
return results != [] |
Oops, something went wrong.