diff --git a/backend/api.py b/backend/api.py index 9389204..d8ad97b 100644 --- a/backend/api.py +++ b/backend/api.py @@ -1,22 +1,54 @@ -from utils import * -import bcrypt import uuid -from datetime import date +import psycopg2 +from datetime import timedelta from psycopg2 import IntegrityError -def hash_password(plain_password: str): - hashed_bytes = bcrypt.hashpw(plain_password.encode('utf-8'), bcrypt.gensalt()) - hashed_str = hashed_bytes.decode('utf-8') - return hashed_str +from utils import * +from type import * +from const import * + +def update_token_expiry_date(token: str, expiry_date: date) -> None: + connection = psycopg2.connect(**DB_CONFIG) + cursor = connection.cursor() -class AuthError(Exception): - pass + expiry_date_str = expiry_date.strftime("%Y.%m.%d") + + try: + cursor.execute( + "UPDATE users SET token_expiry_date = %s WHERE token = %s", + (expiry_date_str, token) + ) + connection.commit() + + except Exception as e: + connection.rollback() + print("Ошибка при обновлении токена:", e) + raise + + finally: + cursor.close() + connection.close() + +def validate_token(token: str) -> bool: + connection = psycopg2.connect(**DB_CONFIG) + cursor = connection.cursor() + try: + return check_token(cursor, token) + + except Exception as e: + connection.rollback() + print("Ошибка при проверке токена:", e) + raise + + finally: + cursor.close() + connection.close() def login(email: str, password: str) : connection = psycopg2.connect(**DB_CONFIG) cursor = connection.cursor() try: - cursor.execute("SELECT password,token FROM users WHERE mail = %s", (email,)) + cursor.execute("SELECT password,token FROM users WHERE email = %s", (email,)) result = cursor.fetchone() if result is None: @@ -31,16 +63,32 @@ def login(email: str, password: str) : # Опционально: можно сгенерировать новый токен здесь raise AuthError("У пользователя отсутствует токен") + token_live_time = timedelta(days=TOKEN_LIVE_TIME) + update_token_expiry_date(token, date.today() + token_live_time) + return token finally: cursor.close() +def logout(token): + try: + # Обновляем token_expiry_date на текущую дату (как в регистрации) + today = date.today() + update_token_expiry_date(token, today) + print(f"Пользователь {token} вышел из системы") + except Exception as e: + print("Ошибка при выходе:", e) + raise def registration(nickname: str, password: str, email: str) -> str: # Хэшируем пароль hashed = hash_password(password) token = str(uuid.uuid4()) - token_expiry_date = date.today().strftime("%Y.%m.%d") + today = date.today().strftime("%Y.%m.%d") + + token_live_time = timedelta(days=TOKEN_LIVE_TIME) + token_expiry_date = date.today() + token_live_time + token_expiry_date_str = token_expiry_date.strftime("%Y.%m.%d") money = "100" histories_id = "{}" @@ -49,9 +97,9 @@ def registration(nickname: str, password: str, email: str) -> str: cursor = connection.cursor() try: cursor.execute( - "INSERT INTO users (nickname, mail, password, token, token_expiry_date, money, histories_id) " + "INSERT INTO users (nickname, email, password, token, token_expiry_date, money, histories_id) " "VALUES (%s, %s, %s, %s, %s, %s, %s)", - (nickname, email, hashed, token, token_expiry_date, money, histories_id) + (nickname, email, hashed, token, token_expiry_date_str, money, histories_id) ) connection.commit() print("Пользователь успешно создан") @@ -68,13 +116,10 @@ def registration(nickname: str, password: str, email: str) -> str: cursor.close() def get_products() -> list[dict]: - connection = None - cursor = None + connection = psycopg2.connect(**DB_CONFIG) + cursor = connection.cursor() res = None try: - connection = psycopg2.connect(**DB_CONFIG) - cursor = connection.cursor() - res = fetch_table_as_json(cursor, "shop") except psycopg2.Error as e: @@ -104,3 +149,68 @@ def get_product(product_id: int): connection.close() return res + +def get_basket(token: str): + connection = psycopg2.connect(**DB_CONFIG) + cursor = connection.cursor() + res = None + try: + if not check_token(cursor, token): + raise AuthError("Пользователь не авторизован") + + res = fetch_table_as_json(cursor, "basket") + + except psycopg2.Error as e: + print("Ошибка при работе с PostgreSQL:", e) + raise + + finally: + cursor.close() + connection.close() + + return res + +def get_history(token: str): + connection = psycopg2.connect(**DB_CONFIG) + cursor = connection.cursor() + res = None + try: + if not check_token(cursor, token): + raise AuthError("Пользователь не авторизован") + + res = fetch_table_as_json(cursor, "history") + + except psycopg2.Error as e: + print("Ошибка при работе с PostgreSQL:", e) + raise + + finally: + cursor.close() + connection.close() + + return res + +def add_product_to_basket(token: str, product_id: int) -> None: + connection = psycopg2.connect(**DB_CONFIG) + cursor = connection.cursor() + try: + if not check_token(cursor, token): + raise AuthError("Пользователь не авторизован") + + user_id: int = get_user_id(cursor, token) + + cursor.execute( + "UPDATE basket SET products_id = array_append(products_id, %s) WHERE user_id = %s", + (product_id, user_id) + ) + if cursor.rowcount == 0: + raise ValueError("Пользователь не найден") + connection.commit() + + except psycopg2.Error as e: + print("Ошибка при работе с PostgreSQL:", e) + raise + + finally: + cursor.close() + connection.close() diff --git a/backend/const.py b/backend/const.py new file mode 100644 index 0000000..0df5b36 --- /dev/null +++ b/backend/const.py @@ -0,0 +1,11 @@ +# 7 days +TOKEN_LIVE_TIME = 7 + +# Параметры подключения +DB_CONFIG = { + 'host': '192.168.1.100', + 'port': 5432, # стандартный порт PostgreSQL + 'database': 'game_shop', # замените на имя вашей БД + 'user': 'casaos', # замените на ваше имя пользователя + 'password': 'casaos' # замените на ваш пароль +} diff --git a/backend/main.py b/backend/main.py index bd232f3..3710fb7 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1,4 +1,5 @@ from api import * +from utils import * if __name__ == "__main__": # products_json = get_products() @@ -7,10 +8,17 @@ if __name__ == "__main__": # product1_json = get_product(1) # print(json.dumps(product1_json, ensure_ascii=False, indent=2)) - try: - # registration("Vasya1", "Vasya2005", "vasili_pupkin@gmail.com") - print(login("vasili_pupkin@gmail.com", "Vasy2005")) + # try: + # # registration("Vasya1", "Vasya2005", "vasili_pupkin@gmail.com") + # token = login("vasili_pupkin@gmail.com", "Vasya2005") + # logout(token) + # print(check_token(token)) - except Exception as e: - print(e) + # token = login("stepan.pilipenko@xmail.ru", "sage123") + # registration("Petia", "Petia2005", "petia_pupkin@gmail.com") + # token = login("stepan.pilipenko@xmail.ru", "Vasya2005") + # print(get_basket(token)) + # print(get_history(token)) + token = login("vasili_pupkin@gmail.com", "Vasya2005") + add_product_to_basket(token, 1) diff --git a/backend/type.py b/backend/type.py new file mode 100644 index 0000000..5825980 --- /dev/null +++ b/backend/type.py @@ -0,0 +1,2 @@ +class AuthError(Exception): + pass diff --git a/backend/utils.py b/backend/utils.py index 288c73f..4a851b1 100644 --- a/backend/utils.py +++ b/backend/utils.py @@ -1,15 +1,9 @@ -import psycopg2 +import bcrypt +from datetime import date from psycopg2 import sql -import json -# Параметры подключения -DB_CONFIG = { - 'host': '192.168.1.100', - 'port': 5432, # стандартный порт PostgreSQL - 'database': 'game_shop', # замените на имя вашей БД - 'user': 'casaos', # замените на ваше имя пользователя - 'password': 'casaos' # замените на ваш пароль -} +from const import * +from type import * def fetch_table_as_json(cursor, table_name) -> list[dict]: cursor.execute(sql.SQL("SELECT * FROM {}").format(sql.Identifier(table_name))) @@ -32,4 +26,24 @@ def fetch_row_as_json(cursor, table_name, row_id) -> dict | None: if row is None: return None # или raise Exception, если нужно - return dict(zip(columns, row)) \ No newline at end of file + return dict(zip(columns, row)) + +def hash_password(plain_password: str): + hashed_bytes = bcrypt.hashpw(plain_password.encode('utf-8'), bcrypt.gensalt()) + hashed_str = hashed_bytes.decode('utf-8') + return hashed_str + +def check_token(cursor, token: str) -> bool: + cursor.execute("SELECT token_expiry_date FROM users WHERE token = %s", (token,)) + result = cursor.fetchone() + + today_date = date.today() + token_expiry_date = result[0] + + return token_expiry_date > today_date + +def get_user_id(cursor, token: str) -> int: + cursor.execute("SELECT id FROM users WHERE token = %s", (token,)) + result = cursor.fetchone() + return result[0] +