Spaces:
Sleeping
Sleeping
| from datetime import datetime, timedelta | |
| from typing import Optional | |
| from fastapi import Depends, HTTPException, status | |
| from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials | |
| import bcrypt | |
| from jose import JWTError, jwt | |
| from shared.config import settings | |
| from shared.schemas.user import TokenData | |
| _bearer = HTTPBearer(auto_error=False) | |
| def hash_password(password: str) -> str: | |
| return bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode() | |
| def verify_password(plain: str, hashed: str) -> bool: | |
| return bcrypt.checkpw(plain.encode(), hashed.encode()) | |
| def create_access_token(user_id: str, role: str) -> str: | |
| expire = datetime.utcnow() + timedelta(minutes=settings.jwt_expire_minutes) | |
| return jwt.encode( | |
| {"sub": user_id, "role": role, "exp": expire}, | |
| settings.jwt_secret, | |
| algorithm=settings.jwt_algorithm, | |
| ) | |
| def _decode(token: str) -> TokenData: | |
| try: | |
| payload = jwt.decode(token, settings.jwt_secret, algorithms=[settings.jwt_algorithm]) | |
| return TokenData(user_id=payload.get("sub"), role=payload.get("role")) | |
| except JWTError: | |
| raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid or expired token") | |
| def get_current_user( | |
| credentials: Optional[HTTPAuthorizationCredentials] = Depends(_bearer), | |
| ) -> TokenData: | |
| if not credentials: | |
| raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Not authenticated") | |
| return _decode(credentials.credentials) | |
| def get_optional_user( | |
| credentials: Optional[HTTPAuthorizationCredentials] = Depends(_bearer), | |
| ) -> Optional[TokenData]: | |
| if not credentials: | |
| return None | |
| try: | |
| return _decode(credentials.credentials) | |
| except HTTPException: | |
| return None | |
| def require_admin(user: TokenData = Depends(get_current_user)) -> TokenData: | |
| if user.role != "admin": | |
| raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Admin only") | |
| return user | |