/
m.makarov
/
FastAPI
Обзор
Документация
Войти
/
m.makarov
/
FastAPI
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
backend/app/auth.py
95 строк
3 KB
Maks
Авторизация, стили для фронта
23 дек 2025, 13:58
23 дек 2025, 13:58
b808b1c
Код
Авторство
О чём код?
from passlib.context import CryptContext from fastapi.security import OAuth2PasswordBearer from datetime import datetime, timedelta, timezone import jwt from fastapi import Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from app.models.users import User as UserModel from app.config import SECRET_KEY, ALGORITHM from app.db_depends import get_async_db # Создаём контекст для хеширования с использованием bcrypt pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") ACCESS_TOKEN_EXPIRE_MINUTES = 30 REFRESH_TOKEN_EXPIRE_DAYS = 7 oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/users/token") def hash_password(password: str) -> str: """ Преобразует пароль в хеш с использованием bcrypt. """ return pwd_context.hash(password) def verify_password(plain_password: str, hashed_password: str) -> bool: """ Проверяет, соответствует ли введённый пароль сохранённому хешу. """ return pwd_context.verify(plain_password, hashed_password) def create_access_token(data: dict): """ Создаёт JWT с payload (sub, role, id, exp). """ to_encode = data.copy() expire = datetime.now(timezone.utc) + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) to_encode.update({"exp": expire, "token_type": "access", }) return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) def create_refresh_token(data: dict): ''' Создаем рефреш токен ''' to_encode = data.copy() expire = datetime.now(timezone.utc) + timedelta(days=REFRESH_TOKEN_EXPIRE_DAYS) to_encode.update({"exp": expire, "token_type": "refresh", }) return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) async def get_current_user(token: str = Depends(oauth2_scheme), db: AsyncSession = Depends(get_async_db)): """ Проверяет JWT и возвращает пользователя из базы. """ credentials_exception = HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate credentials", headers={"WWW-Authenticate": "Bearer"}, ) try: payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) email: str = payload.get("sub") if email is None: raise credentials_exception except jwt.ExpiredSignatureError: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Token has expired", headers={"WWW-Authenticate": "Bearer"}, ) except jwt.PyJWTError: raise credentials_exception result = await db.scalars( select(UserModel).where(UserModel.email == email, UserModel.is_active == True)) user = result.first() if user is None: raise credentials_exception return user async def get_current_seller(current_user: UserModel = Depends(get_current_user)): """ Проверяет, что пользователь имеет роль 'seller'. """ if current_user.role != "seller": raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Only sellers can perform this action") return current_user