""" Модуль безопасности: JWT, хеширование паролей """ from datetime import datetime, timedelta from typing import Optional from jose import JWTError, jwt from passlib.context import CryptContext from fastapi import Depends, HTTPException, status from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials from sqlalchemy.orm import Session from app.core.config import settings from app.core.database import get_service_db from app.models.service_db import AppUser pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") security = HTTPBearer() def verify_password(plain_password: str, hashed_password: str) -> bool: """Проверка пароля""" return pwd_context.verify(plain_password, hashed_password) def get_password_hash(password: str) -> str: """Хеширование пароля""" return pwd_context.hash(password) def create_access_token(data: dict, expires_delta: Optional[timedelta] = None): """Создание JWT токена""" to_encode = data.copy() if expires_delta: expire = datetime.utcnow() + expires_delta else: expire = datetime.utcnow() + timedelta(minutes=settings.JWT_ACCESS_TOKEN_EXPIRE_MINUTES) to_encode.update({"exp": expire}) encoded_jwt = jwt.encode(to_encode, settings.JWT_SECRET_KEY, algorithm=settings.JWT_ALGORITHM) return encoded_jwt async def get_current_user( credentials: HTTPAuthorizationCredentials = Depends(security), db: Session = Depends(get_service_db) ) -> AppUser: """Получение текущего пользователя из JWT токена""" credentials_exception = HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Не удалось проверить учетные данные", headers={"WWW-Authenticate": "Bearer"}, ) try: token = credentials.credentials payload = jwt.decode(token, settings.JWT_SECRET_KEY, algorithms=[settings.JWT_ALGORITHM]) user_id: int = payload.get("sub") if user_id is None: raise credentials_exception except JWTError: raise credentials_exception user = db.query(AppUser).filter(AppUser.id == user_id, AppUser.is_active == True).first() if user is None: raise credentials_exception return user async def get_admin_user(current_user: AppUser = Depends(get_current_user)) -> AppUser: """Проверка, что пользователь является администратором""" if current_user.role.role_name != "Admin": raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Недостаточно прав доступа" ) return current_user