add refresh
This commit is contained in:
parent
ddb95ae852
commit
e8427ceb5d
@ -50,18 +50,37 @@ def init_db():
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def add_session(login, access_token, refresh_token):
|
||||
def add_session(login, access_token, refresh_token, update_existing=False):
|
||||
"""Добавляет новую сессию или обновляет существующую."""
|
||||
conn = get_connection()
|
||||
cursor = conn.cursor()
|
||||
# REPLACE INTO - удобный способ для вставки или обновления
|
||||
|
||||
if update_existing:
|
||||
# Обновляем существующую сессию по access_token
|
||||
cursor.execute('''
|
||||
UPDATE sessions
|
||||
SET access_token = ?, refresh_token = ?, created_at = ?
|
||||
WHERE access_token = ?
|
||||
''', (access_token, refresh_token, datetime.now(), access_token))
|
||||
else:
|
||||
# Вставляем новую или заменяем существующую по логину
|
||||
cursor.execute('''
|
||||
INSERT OR REPLACE INTO sessions (login, access_token, refresh_token, created_at)
|
||||
VALUES (?, ?, ?, ?)
|
||||
''', (login, access_token, refresh_token, datetime.now()))
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def logout(access_token: str):
|
||||
"""Удаляет сессию по токену доступа."""
|
||||
conn = get_connection()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('DELETE FROM sessions WHERE access_token = ?', (access_token,))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
|
||||
def get_session(login: str):
|
||||
"""Получает сессию по логину."""
|
||||
conn = get_connection()
|
||||
@ -80,13 +99,6 @@ def get_all_sessions():
|
||||
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()
|
||||
|
||||
def get_last_login():
|
||||
"""Получает логин последнего вошедшего пользователя."""
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import httpx
|
||||
import asyncio
|
||||
from app.core import config
|
||||
from app.core.database import add_session
|
||||
from app.core.database import add_session, logout, get_session
|
||||
from app.core.localizer import localizer
|
||||
|
||||
async def login(login, password):
|
||||
@ -91,50 +91,90 @@ async def register(login, password, invite=None):
|
||||
return False, f"{localizer.translate('Произошла ошибка')}: {e}"
|
||||
|
||||
|
||||
async def get_user_role(access_token: str):
|
||||
async def refresh_token(access_token: str, refresh_token: str):
|
||||
"""
|
||||
Получает роль и права пользователя по токену доступа.
|
||||
Обновляет токен доступа, используя токен обновления.
|
||||
|
||||
:param access_token: Токен доступа пользователя
|
||||
:return: Кортеж (успех: bool, данные: UserRoleData | str)
|
||||
:param access_token: Истекший токен доступа
|
||||
:param refresh_token: Токен обновления
|
||||
:return: Кортеж (успех: bool, данные: dict | str)
|
||||
"""
|
||||
url = f"{config.BASE_URL}/v1/user/role"
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
url = f"{config.BASE_URL}/v1/auth/token/refresh"
|
||||
payload = {"access_token": access_token, "refresh_token": refresh_token}
|
||||
|
||||
timeout = httpx.Timeout(connect=5.0, read=10.0, write=5.0, pool=5.0)
|
||||
try:
|
||||
async with httpx.AsyncClient(http2=True, timeout=timeout) as client:
|
||||
response = await client.get(url, headers=headers)
|
||||
print("headers", headers,"response", response, "status", response.json().get("status"))
|
||||
async with httpx.AsyncClient(http2=True) as client:
|
||||
response = await client.post(url, json=payload)
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
if data.get("status") == "fine":
|
||||
# Здесь можно добавить валидацию через Pydantic, если необходимо
|
||||
# from app.core.models.user_models import UserRoleData
|
||||
# user_role_data = UserRoleData(**data['data'])
|
||||
return True, data['data']
|
||||
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
|
||||
else:
|
||||
return False, data.get("detail", localizer.translate("Неизвестная ошибка ответа"))
|
||||
return False, data.get("detail", "Unknown error")
|
||||
|
||||
elif response.status_code == 401:
|
||||
return False, localizer.translate("Токен недействителен или истек")
|
||||
elif response.status_code == 404:
|
||||
return False, localizer.translate("Пользователь не найден")
|
||||
return False, "Refresh token is invalid or expired"
|
||||
|
||||
else:
|
||||
return False, f"{localizer.translate('Ошибка сервера')}: {response.status_code}"
|
||||
return False, f"Server error: {response.status_code}"
|
||||
|
||||
except httpx.RequestError as e:
|
||||
return False, f"{localizer.translate('Ошибка сети')}: {e}"
|
||||
return False, f"Network error: {e}"
|
||||
except Exception as e:
|
||||
return False, f"{localizer.translate('Произошла ошибка')}: {e}"
|
||||
return False, f"An error occurred: {e}"
|
||||
|
||||
|
||||
# Пример использования (для тестирования)
|
||||
async def main():
|
||||
# Замените на реальные данные для теста
|
||||
success, message = await login("testuser", "testpassword")
|
||||
print(f"Результат входа: {success}, Сообщение: {message}")
|
||||
async def get_user_role(access_token: str, login: str):
|
||||
"""
|
||||
Получает роль и права пользователя по токену доступа.
|
||||
В случае истечения срока действия токена, пытается его обновить.
|
||||
"""
|
||||
url = f"{config.BASE_URL}/v1/user/role"
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
try:
|
||||
async with httpx.AsyncClient(http2=True) as client:
|
||||
response = await client.get(url, headers=headers)
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
return (True, data['data']) if data.get("status") == "fine" else (False, data.get("detail", "Unknown error"))
|
||||
|
||||
elif response.status_code == 401:
|
||||
# Токен истек, пытаемся обновить
|
||||
session = get_session(login)
|
||||
if not session or not session['refresh_token']:
|
||||
return False, "No refresh token found"
|
||||
|
||||
refresh_success, refresh_data = await refresh_token(access_token, session['refresh_token'])
|
||||
|
||||
if refresh_success:
|
||||
# Повторяем запрос с новым токеном
|
||||
new_access_token = refresh_data['access_token']
|
||||
headers["Authorization"] = f"Bearer {new_access_token}"
|
||||
response = await client.get(url, headers=headers)
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
return (True, data['data']) if data.get("status") == "fine" else (False, "Failed to get role after refresh")
|
||||
|
||||
# Если обновление не удалось, выходим из системы
|
||||
logout(access_token)
|
||||
return False, "Session expired, please log in again"
|
||||
|
||||
else:
|
||||
return False, f"Server error: {response.status_code}"
|
||||
|
||||
except httpx.RequestError as e:
|
||||
return False, f"Network error: {e}"
|
||||
except Exception as e:
|
||||
return False, f"An error occurred: {e}"
|
||||
|
||||
@ -305,7 +305,7 @@ class YobbleHomeView(QWidget):
|
||||
print("[Permissions] Preload failed: No access token.")
|
||||
return
|
||||
|
||||
success, data = await get_user_role(access_token)
|
||||
success, data = await get_user_role(access_token, self.username)
|
||||
if success:
|
||||
user_permissions = set(data.get("user_permissions", []))
|
||||
|
||||
@ -358,7 +358,7 @@ class YobbleHomeView(QWidget):
|
||||
self.show_error_message(localizer.translate("Сессия не найдена. Пожалуйста, войдите снова."))
|
||||
return
|
||||
|
||||
success, data = await get_user_role(access_token)
|
||||
success, data = await get_user_role(access_token, self.username)
|
||||
if success and permission_code in data.get("user_permissions", []):
|
||||
# self.permission_cache.add(permission_code)
|
||||
user_permissions = set(data.get("user_permissions", []))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user