diff --git a/desktop_shop/database/database.py b/desktop_shop/database/database.py index b4c2b81..0aea2b0 100644 --- a/desktop_shop/database/database.py +++ b/desktop_shop/database/database.py @@ -6,12 +6,20 @@ """ import argparse +import sqlite3 from typing import Any, List from desktop_shop import crypto from desktop_shop.database import _statements +class DuplicateUserError(Exception): + """Exception for duplicate user""" + + def __init__(self): + super().__init__("User email is already in use.") + + 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 = _statements.QUERY_USER_ID_BY_EMAIL @@ -122,7 +130,10 @@ def add_user(cursor, user_data, password, pepper="", iterations=100_000): hashed_password = hash_function.hash(password, salt + pepper) user_data = list(user_data) + [salt, hashed_password, str(hash_function)] - cursor.execute(_statements.INSERT_USER, user_data) + try: + cursor.execute(_statements.INSERT_USER, user_data) + except sqlite3.IntegrityError: + raise DuplicateUserError() from None def update_user(cursor, user_data, user_id): diff --git a/desktop_shop/gui/callbacks.py b/desktop_shop/gui/callbacks.py index faea54f..3390220 100644 --- a/desktop_shop/gui/callbacks.py +++ b/desktop_shop/gui/callbacks.py @@ -84,7 +84,11 @@ def register(): return with gui.db_conn as cursor: - session_id = server.add_user(cursor, user_data, password) + try: + session_id = server.add_user(cursor, user_data, password) + except server.DuplicateUserError: + show_error_message("You cannot use the supplied email.") + return gui.app.data["session_id"] = session_id if session_id is not None: diff --git a/desktop_shop/server.py b/desktop_shop/server.py index 5d7995f..df2069a 100644 --- a/desktop_shop/server.py +++ b/desktop_shop/server.py @@ -8,6 +8,7 @@ from desktop_shop import crypto, util from desktop_shop.database import database +from desktop_shop.database.database import DuplicateUserError # pylint: disable=unused-import # combined with every salt for extra security in pw hashing PEPPER = "secret" @@ -98,7 +99,8 @@ def query_product_data_from_product_table_by_product_ids(cursor, product_ids): def add_user(cursor, user_data, password): - """Adds a new user to the users table, with the user_data specified""" + """Adds a new user to the users table, with the user_data specified. + Raises a DuplicateUserError if the specified email has already been used.""" database.add_user(cursor, list(user_data), password, PEPPER) new_session_id = _add_new_session(cursor, user_data.email) return new_session_id diff --git a/tests/unit/gui/callbacks_test.py b/tests/unit/gui/callbacks_test.py index ac23c56..f58c35b 100644 --- a/tests/unit/gui/callbacks_test.py +++ b/tests/unit/gui/callbacks_test.py @@ -23,7 +23,7 @@ # pylint: disable=wrong-import-position from desktop_shop.gui import callbacks, init -from desktop_shop import gui +from desktop_shop import gui, server from desktop_shop.user import UserSignUpData from desktop_shop.datagen import generate_data @@ -104,6 +104,13 @@ def test_register(monkeypatch: pytest.MonkeyPatch): assert_no_error_message() +@pytest.mark.slow +def test_register_twice(monkeypatch: pytest.MonkeyPatch): + test_register(monkeypatch) + with pytest.raises(server.DuplicateUserError): + test_register(monkeypatch) + + @pytest.mark.slow def test_sign_out(monkeypatch: pytest.MonkeyPatch): init_gui(monkeypatch)