Automated Action 5b55eedd2b Implement User Authentication and Authorization Service
This commit includes:
- User registration and authentication API with JWT
- Password reset functionality
- Role-based access control system
- Database models and migrations with SQLAlchemy and Alembic
- API documentation in README

generated with BackendIM... (backend.im)
2025-05-15 19:46:38 +00:00

89 lines
2.5 KiB
Python

from datetime import datetime
from typing import Generator, Optional
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from jose import JWTError, jwt
from pydantic import ValidationError
from sqlalchemy.orm import Session
from app.core.config import settings
from app.db.session import get_db
from app.models.user import User
from app.schemas.token import TokenPayload
oauth2_scheme = OAuth2PasswordBearer(
tokenUrl=f"/auth/login"
)
async def get_current_user(
db: Session = Depends(get_db),
token: str = Depends(oauth2_scheme)
) -> User:
"""
Decode JWT token to get user.
"""
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(
token,
settings.SECRET_KEY,
algorithms=[settings.ALGORITHM]
)
token_data = TokenPayload(**payload)
# Check if token is expired
if token_data.exp < datetime.utcnow().timestamp():
raise credentials_exception
# Check if it's an access token
if hasattr(token_data, "type") and token_data.type != "refresh":
pass # allow access tokens (no type) and non-refresh tokens
else:
raise credentials_exception
except (JWTError, ValidationError):
raise credentials_exception
user = db.query(User).filter(User.id == token_data.sub).first()
if user is None:
raise credentials_exception
if not user.is_active:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Inactive user"
)
return user
async def get_current_active_user(
current_user: User = Depends(get_current_user),
) -> User:
"""
Check if the user is active.
"""
if not current_user.is_active:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Inactive user"
)
return current_user
def get_current_active_verified_user(
current_user: User = Depends(get_current_active_user),
) -> User:
"""
Check if the user is verified.
"""
if not current_user.is_verified:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Email not verified"
)
return current_user