connect login
This commit is contained in:
parent
f6033e3a9f
commit
b711734a68
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,6 +5,7 @@ config/SSL/fullchain.pem
|
|||||||
config/SSL/privkey.pem
|
config/SSL/privkey.pem
|
||||||
logs/
|
logs/
|
||||||
SECRET_KEY.key
|
SECRET_KEY.key
|
||||||
|
messenger.db
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
DEBUG = True
|
DEBUG = True
|
||||||
BASE_URL = "https://api.yobble.org"
|
API_SCHEME = "https"
|
||||||
|
API_HOST = "api.yobble.org"
|
||||||
|
BASE_URL = f"{API_SCHEME}://{API_HOST}"
|
||||||
APP_VERSION = "0.1_login_screen_windows"
|
APP_VERSION = "0.1_login_screen_windows"
|
||||||
APP_NAME = "yobble messenger"
|
APP_NAME = "yobble messenger"
|
||||||
APP_HEADER = f"{APP_NAME}"
|
APP_HEADER = f"{APP_NAME}"
|
||||||
|
|||||||
@ -1,21 +1,81 @@
|
|||||||
import sqlite3
|
import sqlite3
|
||||||
import os
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
DB_PATH = "messenger.db"
|
DB_PATH = "messenger.db"
|
||||||
|
|
||||||
def get_connection():
|
def get_connection():
|
||||||
return sqlite3.connect(DB_PATH)
|
"""Получает соединение с базой данных."""
|
||||||
|
conn = sqlite3.connect(DB_PATH)
|
||||||
|
conn.row_factory = sqlite3.Row # Для доступа к колонкам по имени
|
||||||
|
return conn
|
||||||
|
|
||||||
def init_db():
|
def init_db():
|
||||||
if not os.path.exists(DB_PATH):
|
"""Инициализирует базу данных и создает таблицы, если они не существуют."""
|
||||||
conn = get_connection()
|
conn = get_connection()
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
cursor.execute('''
|
|
||||||
CREATE TABLE IF NOT EXISTS chats (
|
# Создаем таблицу для чатов (если ее нет)
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
cursor.execute('''
|
||||||
title TEXT NOT NULL
|
CREATE TABLE IF NOT EXISTS chats (
|
||||||
)
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
''')
|
title TEXT NOT NULL
|
||||||
|
)
|
||||||
|
''')
|
||||||
|
|
||||||
|
# Создаем таблицу для сессий
|
||||||
|
cursor.execute('''
|
||||||
|
CREATE TABLE IF NOT EXISTS sessions (
|
||||||
|
login TEXT PRIMARY KEY,
|
||||||
|
access_token TEXT NOT NULL,
|
||||||
|
refresh_token TEXT NOT NULL,
|
||||||
|
created_at TIMESTAMP NOT NULL
|
||||||
|
)
|
||||||
|
''')
|
||||||
|
|
||||||
|
# Проверяем, есть ли в chats тестовые данные
|
||||||
|
cursor.execute("SELECT COUNT(*) FROM chats")
|
||||||
|
if cursor.fetchone()[0] == 0:
|
||||||
cursor.execute('INSERT INTO chats (title) VALUES (?)', ("Чат с Alice",))
|
cursor.execute('INSERT INTO chats (title) VALUES (?)', ("Чат с Alice",))
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
def add_session(login, access_token, refresh_token):
|
||||||
|
"""Добавляет новую сессию или обновляет существующую."""
|
||||||
|
conn = get_connection()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
# Сначала удаляем, потом вставляем, чтобы гарантировать обновление.
|
||||||
|
cursor.execute('DELETE FROM sessions WHERE login = ?', (login,))
|
||||||
|
cursor.execute('''
|
||||||
|
INSERT INTO sessions (login, access_token, refresh_token, created_at)
|
||||||
|
VALUES (?, ?, ?, ?)
|
||||||
|
''', (login, access_token, refresh_token, datetime.now()))
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
def get_session(login: str):
|
||||||
|
"""Получает сессию по логину."""
|
||||||
|
conn = get_connection()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('SELECT * FROM sessions WHERE login = ?', (login,))
|
||||||
|
session = cursor.fetchone()
|
||||||
|
conn.close()
|
||||||
|
return session
|
||||||
|
|
||||||
|
def get_all_sessions():
|
||||||
|
"""Получает все сессии, отсортированные по дате создания (сначала новые)."""
|
||||||
|
conn = get_connection()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('SELECT * FROM sessions ORDER BY created_at DESC')
|
||||||
|
sessions = cursor.fetchall()
|
||||||
|
conn.close()
|
||||||
|
return sessions
|
||||||
|
|
||||||
|
def delete_session(login: str):
|
||||||
|
"""Удаляет сессию по логину."""
|
||||||
|
conn = get_connection()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('DELETE FROM sessions WHERE login = ?', (login,))
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|||||||
60
app/core/services/auth_service.py
Normal file
60
app/core/services/auth_service.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import httpx
|
||||||
|
import asyncio
|
||||||
|
from app.core import config
|
||||||
|
from app.core.database import add_session
|
||||||
|
|
||||||
|
async def login(login, password):
|
||||||
|
"""
|
||||||
|
Отправляет запрос на аутентификацию и в случае успеха сохраняет сессию.
|
||||||
|
|
||||||
|
:param login: Логин пользователя
|
||||||
|
:param password: Пароль пользователя
|
||||||
|
:return: Кортеж (успех: bool, сообщение: str)
|
||||||
|
"""
|
||||||
|
url = f"{config.BASE_URL}/v1/auth/login"
|
||||||
|
|
||||||
|
try:
|
||||||
|
async with httpx.AsyncClient(http2=True) as client:
|
||||||
|
response = await client.post(url, json={"login": login, "password": password})
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()
|
||||||
|
if data.get("status") == "fine":
|
||||||
|
token_data = data["data"]
|
||||||
|
add_session(
|
||||||
|
login=login,
|
||||||
|
access_token=token_data["access_token"],
|
||||||
|
refresh_token=token_data["refresh_token"]
|
||||||
|
)
|
||||||
|
return True, "Успешный вход"
|
||||||
|
else:
|
||||||
|
return False, data.get("detail", "Неизвестная ошибка ответа")
|
||||||
|
|
||||||
|
elif response.status_code in [401, 403]:
|
||||||
|
error_data = response.json()
|
||||||
|
return False, error_data.get("detail", "Неверный логин или пароль")
|
||||||
|
|
||||||
|
elif response.status_code == 422:
|
||||||
|
# Ошибка валидации Pydantic
|
||||||
|
error_data = response.json()
|
||||||
|
# Можно будет позже реализовать более детальный разбор ошибок
|
||||||
|
return False, error_data.get("detail", "Некорректные данные для входа")
|
||||||
|
|
||||||
|
else:
|
||||||
|
return False, f"Ошибка сервера: {response.status_code}"
|
||||||
|
|
||||||
|
except httpx.RequestError as e:
|
||||||
|
# Ошибка сети, таймаут и т.д.
|
||||||
|
return False, f"Ошибка сети: {e}"
|
||||||
|
except Exception as e:
|
||||||
|
# Другие непредвиденные ошибки
|
||||||
|
return False, f"Произошла ошибка: {e}"
|
||||||
|
|
||||||
|
# Пример использования (для тестирования)
|
||||||
|
async def main():
|
||||||
|
# Замените на реальные данные для теста
|
||||||
|
success, message = await login("testuser", "testpassword")
|
||||||
|
print(f"Результат входа: {success}, Сообщение: {message}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
asyncio.run(main())
|
||||||
@ -11,6 +11,9 @@ from common_lib.utils.validators import (
|
|||||||
from app.core.localizer import localizer
|
from app.core.localizer import localizer
|
||||||
from app.core.theme import theme_manager
|
from app.core.theme import theme_manager
|
||||||
import app.core.config as config
|
import app.core.config as config
|
||||||
|
import asyncio
|
||||||
|
from app.core.services import auth_service
|
||||||
|
|
||||||
|
|
||||||
def validate_username(username, is_login=False):
|
def validate_username(username, is_login=False):
|
||||||
if is_login:
|
if is_login:
|
||||||
@ -255,10 +258,24 @@ class LoginView(QWidget):
|
|||||||
QMessageBox.warning(self, localizer.translate("Ошибка"), error_msg)
|
QMessageBox.warning(self, localizer.translate("Ошибка"), error_msg)
|
||||||
return
|
return
|
||||||
|
|
||||||
if login == "root" and password == "12341234":
|
# Отключаем кнопку на время запроса
|
||||||
self.on_login(login)
|
self.login_button.setEnabled(False)
|
||||||
else:
|
self.login_button.setText(localizer.translate("Вход..."))
|
||||||
QMessageBox.warning(self, localizer.translate("Ошибка"), localizer.translate("Неверный логин или пароль"))
|
|
||||||
|
try:
|
||||||
|
# Запускаем асинхронную функцию
|
||||||
|
success, message = asyncio.run(auth_service.login(login, password))
|
||||||
|
|
||||||
|
if success:
|
||||||
|
self.on_login(login)
|
||||||
|
else:
|
||||||
|
QMessageBox.warning(self, localizer.translate("Ошибка"), message)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
# Включаем кнопку обратно в любом случае
|
||||||
|
self.login_button.setEnabled(True)
|
||||||
|
self.login_button.setText(localizer.translate("Войти"))
|
||||||
|
|
||||||
|
|
||||||
def validate_confirm_password(self, text):
|
def validate_confirm_password(self, text):
|
||||||
if text != self.reg_password_input.text():
|
if text != self.reg_password_input.text():
|
||||||
|
|||||||
2
main.py
2
main.py
@ -4,6 +4,7 @@ from app.controllers.main_controller import MainController
|
|||||||
from app.core.theme import theme_manager
|
from app.core.theme import theme_manager
|
||||||
import app.core.config as config
|
import app.core.config as config
|
||||||
import sys
|
import sys
|
||||||
|
from app.core.database import init_db
|
||||||
|
|
||||||
class MainWindow(QMainWindow):
|
class MainWindow(QMainWindow):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -24,6 +25,7 @@ class MainWindow(QMainWindow):
|
|||||||
self.setStyleSheet("background-color: #f0f0f0;")
|
self.setStyleSheet("background-color: #f0f0f0;")
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
init_db()
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
app.setWindowIcon(QIcon("app/icons/logo3.png"))
|
app.setWindowIcon(QIcon("app/icons/logo3.png"))
|
||||||
|
|
||||||
|
|||||||
@ -5,3 +5,5 @@ psutil==7.0.0
|
|||||||
pyinstaller==6.15.0
|
pyinstaller==6.15.0
|
||||||
pydantic==pydantic==2.11.7
|
pydantic==pydantic==2.11.7
|
||||||
common-lib @ git+https://githlam.com/messenger/common_lib.git@main
|
common-lib @ git+https://githlam.com/messenger/common_lib.git@main
|
||||||
|
httpx[http2]==0.28.1
|
||||||
|
asyncio==4.0.0
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user