
- Fix code linting issues - Update README with detailed documentation - Configure database paths for the current environment - Create necessary directory structure The News Aggregation Service is now ready to use with FastAPI and SQLite.
172 lines
4.7 KiB
Python
172 lines
4.7 KiB
Python
from typing import Any, List
|
|
from datetime import timedelta
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from fastapi.security import OAuth2PasswordRequestForm
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.api import deps
|
|
from app.core.config import settings
|
|
from app.core.security import create_access_token
|
|
from app.models.user import User
|
|
from app.schemas.user import User as UserSchema, UserCreate, UserUpdate
|
|
from app.schemas.news import UserPreference as UserPreferenceSchema, UserPreferenceUpdate
|
|
from app.schemas.token import Token
|
|
from app.services.user import (
|
|
authenticate_user,
|
|
create_user,
|
|
update_user,
|
|
get_user_by_email,
|
|
get_user,
|
|
get_user_preference,
|
|
update_user_preference,
|
|
)
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.post("/token", response_model=Token)
|
|
async def login_for_access_token(
|
|
db: Session = Depends(deps.get_db),
|
|
form_data: OAuth2PasswordRequestForm = Depends(),
|
|
) -> Any:
|
|
"""
|
|
OAuth2 compatible token login, get an access token for future requests.
|
|
"""
|
|
user = authenticate_user(db, form_data.username, form_data.password)
|
|
if not user:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
detail="Incorrect username or password",
|
|
headers={"WWW-Authenticate": "Bearer"},
|
|
)
|
|
|
|
access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
|
|
return {
|
|
"access_token": create_access_token(
|
|
user.id, expires_delta=access_token_expires
|
|
),
|
|
"token_type": "bearer",
|
|
}
|
|
|
|
|
|
@router.post("/register", response_model=UserSchema)
|
|
async def register_user(
|
|
*,
|
|
db: Session = Depends(deps.get_db),
|
|
user_in: UserCreate,
|
|
) -> Any:
|
|
"""
|
|
Register a new user.
|
|
"""
|
|
try:
|
|
user = create_user(db, user_in)
|
|
return user
|
|
except ValueError as e:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail=str(e),
|
|
)
|
|
|
|
|
|
@router.get("/me", response_model=UserSchema)
|
|
async def read_users_me(
|
|
current_user: User = Depends(deps.get_current_active_user),
|
|
) -> Any:
|
|
"""
|
|
Get current user.
|
|
"""
|
|
return current_user
|
|
|
|
|
|
@router.put("/me", response_model=UserSchema)
|
|
async def update_user_me(
|
|
*,
|
|
db: Session = Depends(deps.get_db),
|
|
user_in: UserUpdate,
|
|
current_user: User = Depends(deps.get_current_active_user),
|
|
) -> Any:
|
|
"""
|
|
Update current user.
|
|
"""
|
|
if user_in.email and user_in.email != current_user.email:
|
|
if get_user_by_email(db, user_in.email):
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="Email already registered",
|
|
)
|
|
|
|
user = update_user(db, current_user, user_in)
|
|
return user
|
|
|
|
|
|
@router.get("/me/preferences", response_model=UserPreferenceSchema)
|
|
async def read_user_preferences(
|
|
db: Session = Depends(deps.get_db),
|
|
current_user: User = Depends(deps.get_current_active_user),
|
|
) -> Any:
|
|
"""
|
|
Get current user's preferences.
|
|
"""
|
|
preferences = get_user_preference(db, current_user.id)
|
|
if not preferences:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="User preferences not found",
|
|
)
|
|
return preferences
|
|
|
|
|
|
@router.put("/me/preferences", response_model=UserPreferenceSchema)
|
|
async def update_user_preferences(
|
|
*,
|
|
db: Session = Depends(deps.get_db),
|
|
preferences_in: UserPreferenceUpdate,
|
|
current_user: User = Depends(deps.get_current_active_user),
|
|
) -> Any:
|
|
"""
|
|
Update current user's preferences.
|
|
"""
|
|
preferences = update_user_preference(
|
|
db,
|
|
current_user.id,
|
|
keywords=preferences_in.keywords,
|
|
sources=preferences_in.sources,
|
|
categories=preferences_in.categories,
|
|
countries=preferences_in.countries,
|
|
languages=preferences_in.languages,
|
|
)
|
|
return preferences
|
|
|
|
|
|
# Admin endpoints
|
|
@router.get("/", response_model=List[UserSchema])
|
|
async def read_users(
|
|
db: Session = Depends(deps.get_db),
|
|
skip: int = 0,
|
|
limit: int = 100,
|
|
current_user: User = Depends(deps.get_current_active_superuser),
|
|
) -> Any:
|
|
"""
|
|
Retrieve users. Only for superusers.
|
|
"""
|
|
users = db.query(User).offset(skip).limit(limit).all()
|
|
return users
|
|
|
|
|
|
@router.get("/{user_id}", response_model=UserSchema)
|
|
async def read_user(
|
|
user_id: int,
|
|
db: Session = Depends(deps.get_db),
|
|
current_user: User = Depends(deps.get_current_active_superuser),
|
|
) -> Any:
|
|
"""
|
|
Get a specific user by id. Only for superusers.
|
|
"""
|
|
user = get_user(db, user_id=user_id)
|
|
if not user:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="User not found",
|
|
)
|
|
return user |