Files
dash/backend/app/core/security.py

75 lines
2.8 KiB
Python
Raw Permalink Normal View History

"""
Модуль безопасности: 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