sigil-on
All checks were successful
Deploy on push / deploy (push) Successful in 6s

This commit is contained in:
2025-05-30 14:08:29 +03:00
parent f160ab4d26
commit 90260534eb
6 changed files with 36 additions and 27 deletions

View File

@@ -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] Токен не найден, пользователь неаутентифицирован")

View File

@@ -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}"