diff --git a/desktop_shop/database/_statements.py b/desktop_shop/database/_statements.py new file mode 100644 index 0000000..f6d9165 --- /dev/null +++ b/desktop_shop/database/_statements.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +"""Contains all SQL statements""" + +import os +import pathlib + +SqlQuery = str + + +def load_statement(filepath: os.PathLike) -> SqlQuery: + """Loads an SQL statement from the specified file""" + with open(filepath, "r", encoding="utf-8") as file: + return file.read() + + +_PATH = pathlib.Path(os.path.dirname(__file__), "sql") +QUERY_USER_ID_BY_EMAIL = load_statement(_PATH / "query_user_id_by_email.sql") +QUERY_USER_IDS = load_statement(_PATH / "query_user_ids.sql") +QUERY_PRODUCT_IDS = load_statement(_PATH / "query_product_ids.sql") +QUERY_PRODUCTS = load_statement(_PATH / "query_products.sql") +QUERY_USER_BY_EMAIL = load_statement(_PATH / "query_user_by_email.sql") +QUERY_USER_BY_ID = load_statement(_PATH / "query_user_by_id.sql") +QUERY_USER_PW_HASH_AND_SALT_BY_EMAIL = load_statement( + _PATH / "query_user_pw_hash_and_salt_by_email.sql" +) +QUERY_LAST_INSERTED_ID = load_statement(_PATH / "query_last_inserted_id.sql") +QUERY_SESSION_BY_ID_AND_USER = load_statement(_PATH / "query_session_by_id_and_user.sql") +QUERY_SESSION_BY_ID_AND_EMAIL = load_statement(_PATH / "query_session_by_id_and_email.sql") + + +UPDATE_USER_BY_ID = load_statement(_PATH / "update_user_by_id.sql") +UPDATE_USER_PW_BY_EMAIL = load_statement(_PATH / "update_user_pw_by_email.sql") +UPDATE_USER_BY_EMAIL = load_statement(_PATH / "update_user_by_email.sql") + +INSERT_USER = load_statement(_PATH / "insert_user.sql") +INSERT_TRANSACTION = load_statement(_PATH / "insert_transaction.sql") +INSERT_DETAILED_TRANSACTION = load_statement(_PATH / "insert_detailed_transaction.sql") +INSERT_SESSION = load_statement(_PATH / "insert_session.sql") +INSERT_PRODUCT = load_statement(_PATH / "insert_product.sql") + +CREATE_OR_REPLACE_SESSIONS_TABLE = load_statement(_PATH / "create_or_replace_sessions_table.sql") +CREATE_OR_REPLACE_PRODUCTS_TABLE = load_statement(_PATH / "create_or_replace_products_table.sql") +CREATE_OR_REPLACE_TRANSACTIONS_TABLE = load_statement( + _PATH / "create_or_replace_transactions_table.sql" +) +CREATE_OR_REPLACE_DETAILED_TRANSACTIONS_TABLE = load_statement( + _PATH / "create_or_replace_detailed_transactions_table.sql" +) +CREATE_OR_REPLACE_USERS_TABLE = load_statement(_PATH / "create_or_replace_users_table.sql") diff --git a/desktop_shop/database.py b/desktop_shop/database/database.py similarity index 55% rename from desktop_shop/database.py rename to desktop_shop/database/database.py index c7b4a8f..b4c2b81 100644 --- a/desktop_shop/database.py +++ b/desktop_shop/database/database.py @@ -9,30 +9,31 @@ from typing import Any, List from desktop_shop import crypto +from desktop_shop.database import _statements def query_user_id_from_user_email(cursor, user_email): """Queries for the user id of the user specified by the user_email passed (unique)""" - command = "SELECT user_id FROM users WHERE email_address = ?" + command = _statements.QUERY_USER_ID_BY_EMAIL user_ids = [user_id for user_id, *_ in cursor.execute(command, [user_email])] return user_ids[0] if user_ids else None def query_user_ids_from_user_table(cursor): """Returns all user_ids found in users table as a list""" - user_ids = [user_id for user_id, *_ in cursor.execute("SELECT user_id FROM users")] + user_ids = [user_id for user_id, *_ in cursor.execute(_statements.QUERY_USER_IDS)] return user_ids def query_product_ids_from_product_table(cursor): """Returns all product ids found in products table as a list""" - product_ids = [prod_id for prod_id, *_ in cursor.execute("SELECT product_id FROM products")] + product_ids = [prod_id for prod_id, *_ in cursor.execute(_statements.QUERY_PRODUCT_IDS)] return product_ids def query_product_data_from_product_table(cursor): """Queries all produt data from the products table""" - data = [list(row) for row in cursor.execute("SELECT * FROM products")] + data = [list(row) for row in cursor.execute(_statements.QUERY_PRODUCTS)] return data @@ -43,13 +44,12 @@ def query_product_data_from_product_table_by_product_ids(cursor, product_ids: Li if not all(product_id.isnumeric() for product_id in product_ids): return [] - joined_product_ids = ",".join([str(product_id) for product_id in product_ids]) - joined_product_ids_str = f"({joined_product_ids})" + joined_product_ids = f"({','.join(map(str, product_ids))})" # This .format looks like an SQL injection vulnerability, but there is currently # no other way to execute Sqlite "WHERE something IN list" statements in Python. # As we make sure the passed list only contains numeric strings, this should be OK. - command = "SELECT * FROM products WHERE product_id IN " + joined_product_ids_str + command = "SELECT * FROM products WHERE product_id IN " + joined_product_ids data = [list(row) for row in cursor.execute(command)] return data @@ -61,49 +61,23 @@ def query_product_price_from_product_table(cursor, product_ids): if not all(product_id.isnumeric() for product_id in product_ids): return [] - joined_product_ids = ",".join([str(product_id) for product_id in product_ids]) - joined_product_ids_str = f"({joined_product_ids})" - - command = "SELECT price FROM products WHERE product_id IN " + joined_product_ids_str + joined_product_ids = f"({','.join(map(str, product_ids))})" + command = "SELECT price FROM products WHERE product_id IN " + joined_product_ids product_prices = [product_price for product_price, *_ in cursor.execute(command)] return product_prices def query_user_data_by_user_email(cursor, user_email): """Queries the user data from the users table, by the user identified by the user_email""" - command = """ - SELECT - first_name, - last_name, - gender, - dob, - email_address, - join_date - FROM users - WHERE email_address = ? - """ - - data = cursor.execute(command, [user_email]) - data = list(data) + command = _statements.QUERY_USER_BY_EMAIL + data = list(cursor.execute(command, [user_email])) return list(data[0]) if data else [] def query_user_data(cursor, user_id): """Queries the data for the user from the users table, by the user id passed""" - command = """ - SELECT - first_name, - last_name, - gender, - dob, - email_address, - join_date - FROM users - WHERE user_id = ? - """ - - data = cursor.execute(command, [str(user_id)]) - data = list(data) + command = _statements.QUERY_USER_BY_ID + data = list(cursor.execute(command, [str(user_id)])) return list(data[0]) if data else [] @@ -111,27 +85,20 @@ def query_pw_hash_and_salt_by_user_email(cursor, user_email): """Queries the password hash, salt and hashing function from the users table for the specified user_email """ - command = "SELECT pw_salt, pw_hash, hash_function FROM users WHERE email_address = ?" - data = cursor.execute(command, [user_email]) - data = list(data) + command = _statements.QUERY_USER_PW_HASH_AND_SALT_BY_EMAIL + data = list(cursor.execute(command, [user_email])) return list(data[0]) if data else [] def _get_last_inserted_id(cursor): """Returns the id of the transaction last added to the transactions table""" - transaction_id, *_ = [id_ for id_, *_ in cursor.execute("""SELECT last_insert_rowid()""")] + transaction_id, *_ = [id_ for id_, *_ in cursor.execute(_statements.QUERY_LAST_INSERTED_ID)] return transaction_id def verify_session_id(cursor, session_id: str, user_id: int): """Verifies that the passed session_id is held by a user identified by the passed user id""" - command = """ - SELECT session_id - FROM sessions - WHERE session_id = ? - AND user_id = ? - """ - + command = _statements.QUERY_SESSION_BY_ID_AND_USER data = cursor.execute(command, [session_id, user_id]) data = [d for d, *_ in data] verified = bool(data and data[0] == session_id) @@ -140,16 +107,7 @@ def verify_session_id(cursor, session_id: str, user_id: int): def verify_session_id_by_user_email(cursor, session_id: str, user_email: int): """Verifies that the passed session_id is held by a user identified by the passed user_email""" - command = """ - SELECT session_id FROM sessions - WHERE session_id = ? - AND user_id IN - ( - SELECT user_id FROM users - WHERE email_address = ? - ) - """ - + command = _statements.QUERY_SESSION_BY_ID_AND_EMAIL data = cursor.execute(command, [session_id, user_email]) data = [d for d, *_ in data] verified = bool(data and data[0] == session_id) @@ -158,28 +116,13 @@ def verify_session_id_by_user_email(cursor, session_id: str, user_email: int): def add_user(cursor, user_data, password, pepper="", iterations=100_000): """Adds a user with the specified user data to the users table""" - command = """ - INSERT INTO users ( - first_name, - last_name, - gender, - dob, - email_address, - join_date, - pw_salt, - pw_hash, - hash_function - ) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) - """ - # hash password salt = crypto.generate_new_salt() hash_function = crypto.get_hash_function(iterations) hashed_password = hash_function.hash(password, salt + pepper) user_data = list(user_data) + [salt, hashed_password, str(hash_function)] - cursor.execute(command, user_data) + cursor.execute(_statements.INSERT_USER, user_data) def update_user(cursor, user_data, user_id): @@ -187,23 +130,14 @@ def update_user(cursor, user_data, user_id): which is passed separately """ user_data.append(user_id) - command = """ - UPDATE users - SET - first_name = ?, - last_name = ?, - gender = ?, - dob = ?, - email_address = ? - WHERE user_id = ?""" - cursor.execute(command, user_data) + cursor.execute(_statements.UPDATE_USER_BY_ID, user_data) def update_user_password(cursor, password, user_email, pepper="", iterations=100_000): """Updates the password hash in the users table for the user specified""" salt = crypto.generate_new_salt() pw_hash = crypto.get_hash_function(iterations).hash(password, salt + pepper) - command = "UPDATE users SET pw_hash = ?, pw_salt = ? WHERE email_address = ?" + command = _statements.UPDATE_USER_PW_BY_EMAIL cursor.execute(command, [pw_hash, salt, user_email]) @@ -212,15 +146,7 @@ def update_user_by_user_email(cursor, user_data, user_email): which is passed separately """ user_data.append(user_email) - command = """UPDATE users - SET - first_name = ?, - last_name = ?, - gender = ?, - dob = ?, - email_address = ? - WHERE email_address = ?""" - cursor.execute(command, user_data) + cursor.execute(_statements.UPDATE_USER_BY_EMAIL, user_data) def add_transaction(cursor, transaction_data: List[Any], chosen_product_ids: List[str]): @@ -230,15 +156,13 @@ def add_transaction(cursor, transaction_data: List[Any], chosen_product_ids: Lis product_prices = query_product_price_from_product_table(cursor, chosen_product_ids) cost = sum(product_prices) transaction_data.append(cost) - - command = "INSERT INTO transactions (user_id, date, cost) VALUES (?, ?, ?)" - cursor.execute(command, transaction_data) + cursor.execute(_statements.INSERT_TRANSACTION, transaction_data) transaction_id = _get_last_inserted_id(cursor) - - command = "INSERT INTO detailed_transactions (transaction_id, product_id) VALUES (?, ?)" for chosen_product_id in chosen_product_ids: - cursor.execute(command, [transaction_id, chosen_product_id]) + cursor.execute( + _statements.INSERT_DETAILED_TRANSACTION, [transaction_id, chosen_product_id] + ) def add_transactions( @@ -255,147 +179,48 @@ def add_transactions( # note: cannot use cursor.executemany because we need the id of the inserted transaction # after each insert. for transaction_data, chosen_product_ids_ in zip(transaction_datas, chosen_product_ids): - command = "INSERT INTO transactions (user_id, date, cost) VALUES (?, ?, ?)" - cursor.execute(command, transaction_data) + cursor.execute(_statements.INSERT_TRANSACTION, transaction_data) transaction_id = _get_last_inserted_id(cursor) - - command = "INSERT INTO detailed_transactions (transaction_id, product_id) VALUES (?, ?)" for chosen_product_id in chosen_product_ids_: - cursor.execute(command, [transaction_id, chosen_product_id]) + cursor.execute( + _statements.INSERT_DETAILED_TRANSACTION, [transaction_id, chosen_product_id] + ) def add_session(cursor, session_data): """adds a session with the specified session data to the session table""" - command = "INSERT INTO sessions (session_id, user_id, timestamp) VALUES (?, ?, ?)" - cursor.execute(command, session_data) + cursor.execute(_statements.INSERT_SESSION, session_data) def add_product(cursor, product_data): """adds a product with the specified product data to the products table""" - command = "INSERT INTO products (name, price) VALUES (?, ?)" - cursor.execute(command, product_data) + cursor.execute(_statements.INSERT_PRODUCT, product_data) def create_user_table(cursor): """Creates user table. Only called in generate_database""" - # remove table - cursor.execute("""DROP TABLE IF EXISTS users""") - - # create table - cursor.execute( - """ - CREATE TABLE users ( - user_id INTEGER PRIMARY KEY, - first_name TEXT NOT NULL, - last_name TEXT NOT NULL, - gender TEXT, - dob TEXT CHECK ( - CAST(strftime('%s', join_date) AS integer) - > CAST(strftime('%s', dob) AS integer) - ), - email_address TEXT NOT NULL UNIQUE COLLATE NOCASE, - join_date TEXT NOT NULL, - pw_salt NOT NULL, - pw_hash NOT NULL, - hash_function NOT NULL CHECK (email_address LIKE '%_@_%._%') - ) - """ - ) - - # remove index based on user id - cursor.execute("""DROP INDEX IF EXISTS idx_user_id""") - - # create index based on user_id - cursor.execute("""CREATE INDEX idx_user_id ON users(user_id)""") + cursor.executescript(_statements.CREATE_OR_REPLACE_USERS_TABLE) def create_transactions_table(cursor): """Creates transactions table. Only called in generate_database""" - # remove table - cursor.execute("""DROP TABLE IF EXISTS transactions""") - - # create table - cursor.execute( - """ - CREATE TABLE transactions ( - transaction_id INTEGER PRIMARY KEY, - user_id INTEGER, - date TEXT, - cost REAL NOT NULL, - FOREIGN KEY (user_id) - REFERENCES users (user_id) - ON UPDATE CASCADE - ON DELETE RESTRICT - )""" - ) - - # drop index based on user_id - cursor.execute("""DROP INDEX IF EXISTS idx_user_id""") - - # create index based on user_id - cursor.execute("""CREATE INDEX idx_user_id ON transactions(user_id)""") + cursor.executescript(_statements.CREATE_OR_REPLACE_TRANSACTIONS_TABLE) def create_detailed_transactions_table(cursor): """Creates detailed transactions table. Only called in generate_database""" - # remove table - cursor.execute("""DROP TABLE IF EXISTS detailed_transactions""") - - # create table - cursor.execute( - """ - CREATE TABLE detailed_transactions ( - transaction_id INTEGER, - product_id INTEGER, - FOREIGN KEY (transaction_id) - REFERENCES transactions (transaction_id) - ON UPDATE CASCADE - ON DELETE RESTRICT, - FOREIGN KEY (product_id) - REFERENCES products (product_id) - ON UPDATE CASCADE - ON DELETE RESTRICT) - """ - ) + cursor.executescript(_statements.CREATE_OR_REPLACE_DETAILED_TRANSACTIONS_TABLE) def create_products_table(cursor): """Creates products table. Only called in generate_database""" - # remove table - cursor.execute("""DROP TABLE IF EXISTS products""") - - # create table - cursor.execute( - """ - CREATE TABLE products ( - product_id INTEGER PRIMARY KEY, - name TEXT, - price REAL NOT NULL - ) - """ - ) + cursor.executescript(_statements.CREATE_OR_REPLACE_PRODUCTS_TABLE) def create_sessions_table(cursor): """Creates sessions table. Only called in generate_database""" - # remove table - cursor.execute("""DROP TABLE IF EXISTS sessions""") - - # create table - cursor.execute( - """ - CREATE TABLE sessions ( - session_id TEXT PRIMARY KEY, - user_id INTEGER, - timestamp TEXT, - FOREIGN KEY (user_id) - REFERENCES users (user_id) - ON UPDATE CASCADE - ON DELETE CASCADE - ) - """ - ) + cursor.executescript(_statements.CREATE_OR_REPLACE_SESSIONS_TABLE) def generate_database(): diff --git a/desktop_shop/database/sql/create_or_replace_detailed_transactions_table.sql b/desktop_shop/database/sql/create_or_replace_detailed_transactions_table.sql new file mode 100644 index 0000000..d96a7d8 --- /dev/null +++ b/desktop_shop/database/sql/create_or_replace_detailed_transactions_table.sql @@ -0,0 +1,13 @@ +DROP TABLE IF EXISTS detailed_transactions; + +CREATE TABLE detailed_transactions ( + transaction_id INTEGER, + product_id INTEGER, + FOREIGN KEY (transaction_id) + REFERENCES transactions (transaction_id) + ON UPDATE CASCADE + ON DELETE RESTRICT, + FOREIGN KEY (product_id) + REFERENCES products (product_id) + ON UPDATE CASCADE + ON DELETE RESTRICT) diff --git a/desktop_shop/database/sql/create_or_replace_products_table.sql b/desktop_shop/database/sql/create_or_replace_products_table.sql new file mode 100644 index 0000000..3a63ce8 --- /dev/null +++ b/desktop_shop/database/sql/create_or_replace_products_table.sql @@ -0,0 +1,7 @@ +DROP TABLE IF EXISTS products; + +CREATE TABLE products ( + product_id INTEGER PRIMARY KEY, + name TEXT, + price REAL NOT NULL +) diff --git a/desktop_shop/database/sql/create_or_replace_sessions_table.sql b/desktop_shop/database/sql/create_or_replace_sessions_table.sql new file mode 100644 index 0000000..53b4eec --- /dev/null +++ b/desktop_shop/database/sql/create_or_replace_sessions_table.sql @@ -0,0 +1,11 @@ +DROP TABLE IF EXISTS sessions; + +CREATE TABLE sessions ( + session_id TEXT PRIMARY KEY, + user_id INTEGER, + timestamp TEXT, + FOREIGN KEY (user_id) + REFERENCES users (user_id) + ON UPDATE CASCADE + ON DELETE CASCADE +); diff --git a/desktop_shop/database/sql/create_or_replace_transactions_table.sql b/desktop_shop/database/sql/create_or_replace_transactions_table.sql new file mode 100644 index 0000000..5264925 --- /dev/null +++ b/desktop_shop/database/sql/create_or_replace_transactions_table.sql @@ -0,0 +1,15 @@ +DROP TABLE IF EXISTS transactions; + +CREATE TABLE transactions ( + transaction_id INTEGER PRIMARY KEY, + user_id INTEGER, + date TEXT, + cost REAL NOT NULL, + FOREIGN KEY (user_id) + REFERENCES users (user_id) + ON UPDATE CASCADE + ON DELETE RESTRICT +); + +DROP INDEX IF EXISTS idx_user_id; +CREATE INDEX idx_user_id ON transactions(user_id); diff --git a/desktop_shop/database/sql/create_or_replace_users_table.sql b/desktop_shop/database/sql/create_or_replace_users_table.sql new file mode 100644 index 0000000..4e6c778 --- /dev/null +++ b/desktop_shop/database/sql/create_or_replace_users_table.sql @@ -0,0 +1,20 @@ +DROP TABLE IF EXISTS users; + +CREATE TABLE users ( + user_id INTEGER PRIMARY KEY, + first_name TEXT NOT NULL, + last_name TEXT NOT NULL, + gender TEXT, + dob TEXT CHECK ( + CAST(strftime('%s', join_date) AS integer) + > CAST(strftime('%s', dob) AS integer) + ), + email_address TEXT NOT NULL UNIQUE COLLATE NOCASE, + join_date TEXT NOT NULL, + pw_salt NOT NULL, + pw_hash NOT NULL, + hash_function NOT NULL CHECK (email_address LIKE '%_@_%._%') +); + +DROP INDEX IF EXISTS idx_user_id; +CREATE INDEX idx_user_id ON users(user_id); diff --git a/desktop_shop/database/sql/insert_detailed_transaction.sql b/desktop_shop/database/sql/insert_detailed_transaction.sql new file mode 100644 index 0000000..5c77fe8 --- /dev/null +++ b/desktop_shop/database/sql/insert_detailed_transaction.sql @@ -0,0 +1 @@ +INSERT INTO detailed_transactions (transaction_id, product_id) VALUES (?, ?) diff --git a/desktop_shop/database/sql/insert_product.sql b/desktop_shop/database/sql/insert_product.sql new file mode 100644 index 0000000..fc962db --- /dev/null +++ b/desktop_shop/database/sql/insert_product.sql @@ -0,0 +1 @@ +INSERT INTO products (name, price) VALUES (?, ?) diff --git a/desktop_shop/database/sql/insert_session.sql b/desktop_shop/database/sql/insert_session.sql new file mode 100644 index 0000000..08a72b8 --- /dev/null +++ b/desktop_shop/database/sql/insert_session.sql @@ -0,0 +1 @@ +INSERT INTO sessions (session_id, user_id, timestamp) VALUES (?, ?, ?) diff --git a/desktop_shop/database/sql/insert_transaction.sql b/desktop_shop/database/sql/insert_transaction.sql new file mode 100644 index 0000000..eb27418 --- /dev/null +++ b/desktop_shop/database/sql/insert_transaction.sql @@ -0,0 +1 @@ +INSERT INTO transactions (user_id, date, cost) VALUES (?, ?, ?) diff --git a/desktop_shop/database/sql/insert_user.sql b/desktop_shop/database/sql/insert_user.sql new file mode 100644 index 0000000..3cf7c2b --- /dev/null +++ b/desktop_shop/database/sql/insert_user.sql @@ -0,0 +1,12 @@ +INSERT INTO users ( + first_name, + last_name, + gender, + dob, + email_address, + join_date, + pw_salt, + pw_hash, + hash_function +) +VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) diff --git a/desktop_shop/database/sql/query_last_inserted_id.sql b/desktop_shop/database/sql/query_last_inserted_id.sql new file mode 100644 index 0000000..848fe70 --- /dev/null +++ b/desktop_shop/database/sql/query_last_inserted_id.sql @@ -0,0 +1 @@ +SELECT last_insert_rowid() diff --git a/desktop_shop/database/sql/query_product_ids.sql b/desktop_shop/database/sql/query_product_ids.sql new file mode 100644 index 0000000..88bd405 --- /dev/null +++ b/desktop_shop/database/sql/query_product_ids.sql @@ -0,0 +1 @@ +SELECT product_id FROM products diff --git a/desktop_shop/database/sql/query_products.sql b/desktop_shop/database/sql/query_products.sql new file mode 100644 index 0000000..004c156 --- /dev/null +++ b/desktop_shop/database/sql/query_products.sql @@ -0,0 +1 @@ +SELECT * FROM products diff --git a/desktop_shop/database/sql/query_session_by_id_and_email.sql b/desktop_shop/database/sql/query_session_by_id_and_email.sql new file mode 100644 index 0000000..d325079 --- /dev/null +++ b/desktop_shop/database/sql/query_session_by_id_and_email.sql @@ -0,0 +1,7 @@ +SELECT session_id FROM sessions +WHERE session_id = ? +AND user_id IN + ( + SELECT user_id FROM users + WHERE email_address = ? + ) diff --git a/desktop_shop/database/sql/query_session_by_id_and_user.sql b/desktop_shop/database/sql/query_session_by_id_and_user.sql new file mode 100644 index 0000000..144b3ea --- /dev/null +++ b/desktop_shop/database/sql/query_session_by_id_and_user.sql @@ -0,0 +1,4 @@ +SELECT session_id +FROM sessions +WHERE session_id = ? +AND user_id = ? diff --git a/desktop_shop/database/sql/query_user_by_email.sql b/desktop_shop/database/sql/query_user_by_email.sql new file mode 100644 index 0000000..e379d31 --- /dev/null +++ b/desktop_shop/database/sql/query_user_by_email.sql @@ -0,0 +1,9 @@ +SELECT + first_name, + last_name, + gender, + dob, + email_address, + join_date +FROM users +WHERE email_address = ? diff --git a/desktop_shop/database/sql/query_user_by_id.sql b/desktop_shop/database/sql/query_user_by_id.sql new file mode 100644 index 0000000..5a08f29 --- /dev/null +++ b/desktop_shop/database/sql/query_user_by_id.sql @@ -0,0 +1,9 @@ +SELECT + first_name, + last_name, + gender, + dob, + email_address, + join_date +FROM users +WHERE user_id = ? diff --git a/desktop_shop/database/sql/query_user_id_by_email.sql b/desktop_shop/database/sql/query_user_id_by_email.sql new file mode 100644 index 0000000..574f0a4 --- /dev/null +++ b/desktop_shop/database/sql/query_user_id_by_email.sql @@ -0,0 +1 @@ +SELECT user_id FROM users WHERE email_address = ? diff --git a/desktop_shop/database/sql/query_user_ids.sql b/desktop_shop/database/sql/query_user_ids.sql new file mode 100644 index 0000000..c0aa23a --- /dev/null +++ b/desktop_shop/database/sql/query_user_ids.sql @@ -0,0 +1 @@ +SELECT user_id FROM users diff --git a/desktop_shop/database/sql/query_user_pw_hash_and_salt_by_email.sql b/desktop_shop/database/sql/query_user_pw_hash_and_salt_by_email.sql new file mode 100644 index 0000000..43dd5ed --- /dev/null +++ b/desktop_shop/database/sql/query_user_pw_hash_and_salt_by_email.sql @@ -0,0 +1 @@ +SELECT pw_salt, pw_hash, hash_function FROM users WHERE email_address = ? diff --git a/desktop_shop/database/sql/update_user_by_email.sql b/desktop_shop/database/sql/update_user_by_email.sql new file mode 100644 index 0000000..4327770 --- /dev/null +++ b/desktop_shop/database/sql/update_user_by_email.sql @@ -0,0 +1,8 @@ +UPDATE users +SET + first_name = ?, + last_name = ?, + gender = ?, + dob = ?, + email_address = ? +WHERE email_address = ? diff --git a/desktop_shop/database/sql/update_user_by_id.sql b/desktop_shop/database/sql/update_user_by_id.sql new file mode 100644 index 0000000..bb6dc61 --- /dev/null +++ b/desktop_shop/database/sql/update_user_by_id.sql @@ -0,0 +1,8 @@ +UPDATE users +SET + first_name = ?, + last_name = ?, + gender = ?, + dob = ?, + email_address = ? +WHERE user_id = ? diff --git a/desktop_shop/database/sql/update_user_pw_by_email.sql b/desktop_shop/database/sql/update_user_pw_by_email.sql new file mode 100644 index 0000000..75e5097 --- /dev/null +++ b/desktop_shop/database/sql/update_user_pw_by_email.sql @@ -0,0 +1 @@ +UPDATE users SET pw_hash = ?, pw_salt = ? WHERE email_address = ? diff --git a/desktop_shop/datagen/generate_data.py b/desktop_shop/datagen/generate_data.py index 2d1c00c..d84c2e2 100644 --- a/desktop_shop/datagen/generate_data.py +++ b/desktop_shop/datagen/generate_data.py @@ -16,7 +16,8 @@ import sqlite3 from typing import List, Protocol, Set -from desktop_shop import crypto, database, util +from desktop_shop import crypto, util +from desktop_shop.database import database from desktop_shop.datagen import data # combined with every salt for extra security in pw hashing diff --git a/desktop_shop/server.py b/desktop_shop/server.py index 402fb37..5d7995f 100644 --- a/desktop_shop/server.py +++ b/desktop_shop/server.py @@ -6,7 +6,8 @@ """ import hmac -from desktop_shop import crypto, database, util +from desktop_shop import crypto, util +from desktop_shop.database import database # combined with every salt for extra security in pw hashing PEPPER = "secret" diff --git a/tests/unit/database_test.py b/tests/unit/database_test.py index 3f53ab6..bac85ba 100644 --- a/tests/unit/database_test.py +++ b/tests/unit/database_test.py @@ -12,7 +12,8 @@ import pytest -from desktop_shop import crypto, database +from desktop_shop import crypto +from desktop_shop.database import database from desktop_shop.user import UserSignUpData # in memory database to avoid errors when removing database file between tests diff --git a/tests/unit/datagen/generate_data_test.py b/tests/unit/datagen/generate_data_test.py index 1c39f1d..cb1df5e 100644 --- a/tests/unit/datagen/generate_data_test.py +++ b/tests/unit/datagen/generate_data_test.py @@ -8,7 +8,7 @@ import pytest -from desktop_shop import database +from desktop_shop.database import database from desktop_shop.datagen import generate_data from desktop_shop.datagen.data import DateTuple, get_random_date diff --git a/tests/unit/gui/init_test.py b/tests/unit/gui/init_test.py index 51b6e2e..90c39da 100644 --- a/tests/unit/gui/init_test.py +++ b/tests/unit/gui/init_test.py @@ -13,7 +13,8 @@ # pylint: disable=wrong-import-position -from desktop_shop import database, server +from desktop_shop import server +from desktop_shop.database import database from desktop_shop import gui from desktop_shop.gui import init diff --git a/tests/unit/server_test.py b/tests/unit/server_test.py index 17756ba..66d2e0b 100644 --- a/tests/unit/server_test.py +++ b/tests/unit/server_test.py @@ -14,7 +14,8 @@ import pytest -from desktop_shop import database, server +from desktop_shop import server +from desktop_shop.database import database cursor = None