
- Set up project structure with FastAPI and SQLite - Implement user authentication with JWT - Create models for learning content (subjects, lessons, quizzes) - Add progress tracking and gamification features - Implement comprehensive API documentation - Add error handling and validation - Set up proper logging and health check endpoint
198 lines
6.0 KiB
Python
198 lines
6.0 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any, List
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Path, Query, status
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app import models, schemas
|
|
from app.api import deps
|
|
from app.db.session import get_db
|
|
from app.models.achievement import AchievementType
|
|
from app.services.achievement import achievement, user_achievement
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("/", response_model=List[schemas.Achievement])
|
|
def read_achievements(
|
|
db: Session = Depends(get_db),
|
|
skip: int = 0,
|
|
limit: int = 100,
|
|
achievement_type: AchievementType = Query(None, description="Filter by achievement type"),
|
|
active_only: bool = Query(True, description="Filter only active achievements"),
|
|
) -> Any:
|
|
"""
|
|
Retrieve achievements.
|
|
"""
|
|
if achievement_type:
|
|
achievements = achievement.get_by_type(
|
|
db, achievement_type=achievement_type, skip=skip, limit=limit
|
|
)
|
|
elif active_only:
|
|
achievements = achievement.get_active(db, skip=skip, limit=limit)
|
|
else:
|
|
achievements = achievement.get_multi(db, skip=skip, limit=limit)
|
|
|
|
return achievements
|
|
|
|
|
|
@router.post("/", response_model=schemas.Achievement)
|
|
def create_achievement(
|
|
*,
|
|
db: Session = Depends(get_db),
|
|
achievement_in: schemas.AchievementCreate,
|
|
current_user: models.User = Depends(deps.get_current_active_superuser),
|
|
) -> Any:
|
|
"""
|
|
Create new achievement. Only for superusers.
|
|
"""
|
|
achievement_obj = achievement.create(db, obj_in=achievement_in)
|
|
return achievement_obj
|
|
|
|
|
|
@router.get("/{achievement_id}", response_model=schemas.Achievement)
|
|
def read_achievement(
|
|
*,
|
|
db: Session = Depends(get_db),
|
|
achievement_id: int = Path(..., gt=0),
|
|
) -> Any:
|
|
"""
|
|
Get achievement by ID.
|
|
"""
|
|
achievement_obj = achievement.get(db, id=achievement_id)
|
|
if not achievement_obj:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Achievement not found",
|
|
)
|
|
return achievement_obj
|
|
|
|
|
|
@router.put("/{achievement_id}", response_model=schemas.Achievement)
|
|
def update_achievement(
|
|
*,
|
|
db: Session = Depends(get_db),
|
|
achievement_id: int = Path(..., gt=0),
|
|
achievement_in: schemas.AchievementUpdate,
|
|
current_user: models.User = Depends(deps.get_current_active_superuser),
|
|
) -> Any:
|
|
"""
|
|
Update achievement. Only for superusers.
|
|
"""
|
|
achievement_obj = achievement.get(db, id=achievement_id)
|
|
if not achievement_obj:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Achievement not found",
|
|
)
|
|
|
|
achievement_obj = achievement.update(db, db_obj=achievement_obj, obj_in=achievement_in)
|
|
return achievement_obj
|
|
|
|
|
|
@router.delete("/{achievement_id}", status_code=status.HTTP_204_NO_CONTENT, response_model=None)
|
|
def delete_achievement(
|
|
*,
|
|
db: Session = Depends(get_db),
|
|
achievement_id: int = Path(..., gt=0),
|
|
current_user: models.User = Depends(deps.get_current_active_superuser),
|
|
) -> None:
|
|
"""
|
|
Delete achievement. Only for superusers.
|
|
"""
|
|
achievement_obj = achievement.get(db, id=achievement_id)
|
|
if not achievement_obj:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Achievement not found",
|
|
)
|
|
|
|
achievement.remove(db, id=achievement_id)
|
|
|
|
|
|
@router.get("/user/{user_id}", response_model=List[schemas.UserAchievement])
|
|
def read_user_achievements(
|
|
*,
|
|
db: Session = Depends(get_db),
|
|
user_id: int = Path(..., gt=0),
|
|
skip: int = 0,
|
|
limit: int = 100,
|
|
current_user: models.User = Depends(deps.get_current_active_user),
|
|
) -> Any:
|
|
"""
|
|
Get a user's achievements.
|
|
"""
|
|
# Regular users can only get their own achievements
|
|
if user_id != current_user.id and not current_user.is_superuser:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="Not enough permissions",
|
|
)
|
|
|
|
user_achievements = user_achievement.get_by_user(db, user_id=user_id, skip=skip, limit=limit)
|
|
return user_achievements
|
|
|
|
|
|
@router.post("/user/{user_id}/award/{achievement_id}", response_model=schemas.UserAchievement)
|
|
def award_achievement_to_user(
|
|
*,
|
|
db: Session = Depends(get_db),
|
|
user_id: int = Path(..., gt=0),
|
|
achievement_id: int = Path(..., gt=0),
|
|
current_user: models.User = Depends(deps.get_current_active_superuser),
|
|
) -> Any:
|
|
"""
|
|
Award an achievement to a user. Only for superusers.
|
|
"""
|
|
# Check if achievement exists
|
|
achievement_obj = achievement.get(db, id=achievement_id)
|
|
if not achievement_obj:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Achievement not found",
|
|
)
|
|
|
|
# Check if user exists
|
|
user = db.query(models.User).filter(models.User.id == user_id).first()
|
|
if not user:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="User not found",
|
|
)
|
|
|
|
user_achievement_obj = user_achievement.award_achievement(
|
|
db, user_id=user_id, achievement_id=achievement_id
|
|
)
|
|
|
|
return user_achievement_obj
|
|
|
|
|
|
@router.post("/user/{user_id}/check", response_model=List[schemas.UserAchievement])
|
|
def check_user_achievements(
|
|
*,
|
|
db: Session = Depends(get_db),
|
|
user_id: int = Path(..., gt=0),
|
|
current_user: models.User = Depends(deps.get_current_active_user),
|
|
) -> Any:
|
|
"""
|
|
Check and award achievements based on user's progress.
|
|
"""
|
|
# Regular users can only check their own achievements
|
|
if user_id != current_user.id and not current_user.is_superuser:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="Not enough permissions",
|
|
)
|
|
|
|
# Check if user exists
|
|
user = db.query(models.User).filter(models.User.id == user_id).first()
|
|
if not user:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="User not found",
|
|
)
|
|
|
|
new_achievements = user_achievement.check_achievements(db, user_id=user_id)
|
|
return new_achievements
|