This commit is contained in:
@@ -5,12 +5,12 @@
|
||||
import time
|
||||
from typing import Any, Dict
|
||||
|
||||
from sqlalchemy.orm import exc
|
||||
from starlette.authentication import UnauthenticatedUser
|
||||
from starlette.datastructures import Headers
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import JSONResponse, Response
|
||||
from starlette.types import ASGIApp, Receive, Scope, Send
|
||||
from sqlalchemy.orm import exc
|
||||
|
||||
from auth.credentials import AuthCredentials
|
||||
from auth.orm import Author
|
||||
@@ -18,6 +18,8 @@ from auth.sessions import SessionManager
|
||||
from services.db import local_session
|
||||
from settings import (
|
||||
ADMIN_EMAILS as ADMIN_EMAILS_LIST,
|
||||
)
|
||||
from settings import (
|
||||
SESSION_COOKIE_HTTPONLY,
|
||||
SESSION_COOKIE_MAX_AGE,
|
||||
SESSION_COOKIE_NAME,
|
||||
@@ -33,7 +35,9 @@ ADMIN_EMAILS = ADMIN_EMAILS_LIST.split(",")
|
||||
class AuthenticatedUser:
|
||||
"""Аутентифицированный пользователь"""
|
||||
|
||||
def __init__(self, user_id: str, username: str = "", roles: list = None, permissions: dict = None, token: str = None):
|
||||
def __init__(
|
||||
self, user_id: str, username: str = "", roles: list = None, permissions: dict = None, token: str = None
|
||||
):
|
||||
self.user_id = user_id
|
||||
self.username = username
|
||||
self.roles = roles or []
|
||||
@@ -177,11 +181,11 @@ class AuthMiddleware:
|
||||
|
||||
# Аутентифицируем пользователя
|
||||
auth, user = await self.authenticate_user(token)
|
||||
|
||||
|
||||
# Добавляем в scope данные авторизации и пользователя
|
||||
scope["auth"] = auth
|
||||
scope["user"] = user
|
||||
|
||||
|
||||
if token:
|
||||
# Обновляем заголовки в scope для совместимости
|
||||
new_headers = []
|
||||
@@ -190,7 +194,7 @@ class AuthMiddleware:
|
||||
new_headers.append((name, value))
|
||||
new_headers.append((SESSION_TOKEN_HEADER.encode("latin1"), token.encode("latin1")))
|
||||
scope["headers"] = new_headers
|
||||
|
||||
|
||||
logger.debug(f"[middleware] Пользователь аутентифицирован: {user.is_authenticated}")
|
||||
else:
|
||||
logger.debug(f"[middleware] Токен не найден, пользователь неаутентифицирован")
|
||||
|
@@ -1,18 +1,18 @@
|
||||
import time
|
||||
import orjson
|
||||
from secrets import token_urlsafe
|
||||
|
||||
import orjson
|
||||
from authlib.integrations.starlette_client import OAuth
|
||||
from authlib.oauth2.rfc7636 import create_s256_code_challenge
|
||||
from starlette.responses import JSONResponse, RedirectResponse
|
||||
|
||||
from auth.orm import Author
|
||||
from auth.tokenstorage import TokenStorage
|
||||
from resolvers.auth import generate_unique_slug
|
||||
from services.db import local_session
|
||||
from services.redis import redis
|
||||
from settings import FRONTEND_URL, OAUTH_CLIENTS
|
||||
from utils.logger import root_logger as logger
|
||||
from resolvers.auth import generate_unique_slug
|
||||
|
||||
oauth = OAuth()
|
||||
|
||||
@@ -100,7 +100,7 @@ async def oauth_login(request):
|
||||
# Получаем параметры из query string
|
||||
state = request.query_params.get("state")
|
||||
redirect_uri = request.query_params.get("redirect_uri", FRONTEND_URL)
|
||||
|
||||
|
||||
if not state:
|
||||
return JSONResponse({"error": "State parameter is required"}, status_code=400)
|
||||
|
||||
@@ -113,7 +113,7 @@ async def oauth_login(request):
|
||||
"code_verifier": code_verifier,
|
||||
"provider": provider,
|
||||
"redirect_uri": redirect_uri,
|
||||
"created_at": int(time.time())
|
||||
"created_at": int(time.time()),
|
||||
}
|
||||
await store_oauth_state(state, oauth_data)
|
||||
|
||||
@@ -172,7 +172,7 @@ async def oauth_callback(request):
|
||||
if not author:
|
||||
# Генерируем slug из имени или email
|
||||
slug = generate_unique_slug(profile["name"] or profile["email"].split("@")[0])
|
||||
|
||||
|
||||
author = Author(
|
||||
email=profile["email"],
|
||||
name=profile["name"],
|
||||
@@ -223,6 +223,7 @@ async def store_oauth_state(state: str, data: dict) -> None:
|
||||
key = f"oauth_state:{state}"
|
||||
await redis.execute("SETEX", key, OAUTH_STATE_TTL, orjson.dumps(data))
|
||||
|
||||
|
||||
async def get_oauth_state(state: str) -> dict:
|
||||
"""Получает и удаляет OAuth состояние из Redis (one-time use)"""
|
||||
key = f"oauth_state:{state}"
|
||||
|
Reference in New Issue
Block a user