desktop_app/app/core/services/auth_service.py
2025-09-30 01:07:43 +03:00

155 lines
6.5 KiB
Python

import httpx
import asyncio
from app.core import config
from app.core.database import add_session, logout, get_session
from app.core.localizer import localizer
from app.core.http_client import get_client, authorized_get
async def login(login, password):
"""
Логин пользователя по логину и паролю.
:param login: Логин пользователя
:param password: Пароль пользователя
:return: tuple (ok: bool, message: str)
"""
url = f"{config.BASE_URL}/v1/auth/login"
try:
response = await get_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"],
user_id=token_data.get("user_id"),
)
return True, localizer.translate("Вход выполнен успешно")
return False, data.get("detail", localizer.translate("Неизвестная ошибка"))
if response.status_code == 401:
error_data = response.json()
return False, error_data.get("detail", localizer.translate("Неверный логин или пароль"))
if response.status_code == 403:
error_data = response.json()
return False, error_data.get("detail", localizer.translate("Доступ запрещен"))
if response.status_code == 422:
return False, localizer.translate("Некорректные входные данные")
return False, f"{localizer.translate('Ошибка сервера')}: {response.status_code}"
except httpx.RequestError as e:
return False, f"{localizer.translate('Сетевая ошибка')}: {e}"
except Exception as e:
return False, f"{localizer.translate('Произошла ошибка')}: {e}"
async def register(login, password, invite=None):
"""
Регистрация нового пользователя.
:param login: Логин
:param password: Пароль
:param invite: Инвайт-код (опционально)
:return: tuple (ok: bool, message: str)
"""
url = f"{config.BASE_URL}/v1/auth/register"
payload = {"login": login, "password": password}
if invite:
payload["invite"] = invite
try:
response = await get_client().post(url, json=payload)
if response.status_code == 201:
return True, localizer.translate("Регистрация прошла успешно!")
error_data = response.json()
error_message = error_data.get("detail", localizer.translate("Произошла ошибка"))
if response.status_code == 409:
return False, localizer.translate("Пользователь уже существует.")
if response.status_code == 400:
return False, localizer.translate("Некорректный запрос.")
if response.status_code == 403:
return False, localizer.translate("Регистрация по приглашению отключена.")
if response.status_code == 422:
return False, localizer.translate("Некорректные входные данные. Проверьте логин и пароль.")
return False, f"{localizer.translate('Ошибка сервера')} ({response.status_code}): {error_message}"
except httpx.RequestError as e:
return False, f"{localizer.translate('Сетевая ошибка')}: {e}"
except Exception as e:
return False, f"{localizer.translate('Произошла ошибка')}: {e}"
async def refresh_token(access_token: str, refresh_token: str):
"""
Обновление пары токенов по refresh_token.
:param access_token: Текущий access token
:param refresh_token: Refresh token
:return: tuple (ok: bool, data: dict | str)
"""
url = f"{config.BASE_URL}/v1/auth/token/refresh"
payload = {"access_token": access_token, "refresh_token": refresh_token}
try:
response = await get_client().post(url, json=payload)
if response.status_code == 200:
data = response.json()
if data.get("status") == "fine":
token_data = data["data"]
add_session(
login=None,
access_token=token_data["access_token"],
refresh_token=token_data["refresh_token"],
update_existing=True,
)
return True, token_data
return False, data.get("detail", localizer.translate("Неизвестная ошибка"))
if response.status_code == 401:
return False, localizer.translate("Refresh token недействителен или истек")
return False, f"{localizer.translate('Ошибка сервера')}: {response.status_code}"
except httpx.RequestError as e:
return False, f"{localizer.translate('Сетевая ошибка')}: {e}"
except Exception as e:
return False, f"{localizer.translate('Произошла ошибка')}: {e}"
async def get_user_role(access_token: str, login: str):
"""
Получение роли пользователя. При 401 выполняется автообновление токена внутри authorized_get.
"""
url = f"{config.BASE_URL}/v1/user/role"
headers = {"Authorization": f"Bearer {access_token}"}
try:
response = await authorized_get(url, login=login, access_token=access_token, headers=headers)
if response.status_code == 200:
data = response.json()
return (True, data['data']) if data.get("status") == "fine" else (False, data.get("detail", localizer.translate("Неизвестная ошибка")))
if response.status_code == 401:
return False, localizer.translate("Сессия истекла, войдите снова")
return False, f"{localizer.translate('Ошибка сервера')}: {response.status_code}"
except httpx.RequestError as e:
return False, f"{localizer.translate('Сетевая ошибка')}: {e}"
except Exception as e:
return False, f"{localizer.translate('Произошла ошибка')}: {e}"