Files
pyisu/backend/app/routes/courses.py
2026-03-13 14:39:43 +08:00

142 lines
5.2 KiB
Python

from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from typing import List, Optional
from .. import crud, schemas, auth
from ..database import get_db
from ..models import User
router = APIRouter(prefix="/courses", tags=["courses"])
@router.get("/", response_model=schemas.SuccessResponse)
def get_courses(
skip: int = Query(0, ge=0),
limit: int = Query(100, ge=1, le=100),
level: Optional[str] = Query(None, pattern="^(beginner|intermediate|advanced)$"),
db: Session = Depends(get_db)
):
# Get published courses for all users (including guests)
courses = crud.get_courses(db, skip=skip, limit=limit, level=level, published_only=True)
# Convert SQLAlchemy models to Pydantic models
course_responses = [schemas.CourseResponse.from_orm(course) for course in courses]
return schemas.SuccessResponse(
data={
"courses": course_responses,
"total": len(courses),
"skip": skip,
"limit": limit,
"level": level
}
)
@router.get("/{course_id}", response_model=schemas.SuccessResponse)
def get_course(
course_id: int,
db: Session = Depends(get_db),
current_user: Optional[User] = Depends(auth.get_optional_current_user)
):
course = crud.get_course_by_id(db, course_id=course_id)
if not course:
raise HTTPException(
status_code=404,
detail="Course not found"
)
# Check access based on status
course_status = getattr(course, 'status', 'draft')
author_id = getattr(course, 'author_id', None)
if course_status == 'published':
pass # Anyone can access published course
elif course_status == 'draft':
# Only author can access drafts
if current_user is None or author_id != current_user.id:
raise HTTPException(
status_code=403,
detail="Not authorized to access this draft"
)
else:
# Archived - author-only access
if current_user is None or author_id != current_user.id:
raise HTTPException(
status_code=403,
detail="Not authorized to access this course"
)
# Convert SQLAlchemy model to Pydantic model
course_response = schemas.CourseResponse.from_orm(course)
return schemas.SuccessResponse(data={"course": course_response})
@router.put("/{course_id}", response_model=schemas.SuccessResponse)
def update_course(
course_id: int,
course_update: schemas.CourseUpdate,
db: Session = Depends(get_db),
current_user: User = Depends(auth.get_current_user)
):
course = crud.get_course_by_id(db, course_id)
if not course:
raise HTTPException(status_code=404, detail="Course not found")
if course.author_id != current_user.id:
raise HTTPException(status_code=403, detail="Not authorized to update this course")
updated_course = crud.update_course(db, course_id, course_update)
course_response = schemas.CourseResponse.from_orm(updated_course)
return schemas.SuccessResponse(data={"course": course_response})
@router.get("/{course_id}/structure", response_model=schemas.SuccessResponse)
def get_course_structure(
course_id: int,
db: Session = Depends(get_db),
current_user: Optional[User] = Depends(auth.get_optional_current_user)
):
course = crud.get_course_by_id(db, course_id=course_id, include_structure=True)
if not course:
raise HTTPException(status_code=404, detail="Course not found")
if course.status != 'published':
if current_user is None or course.author_id != current_user.id:
raise HTTPException(status_code=403, detail="Not authorized")
course_data = {
"id": course.id,
"title": course.title,
"description": course.description,
"level": course.level,
"duration": course.duration,
"status": course.status,
"modules": [
{
"id": module.id,
"title": module.title,
"description": module.description,
"duration": module.duration,
"order_index": module.order_index,
"lessons": [
{
"id": lesson.id,
"title": lesson.title,
"description": lesson.description,
"order_index": lesson.order_index,
"steps": [
{
"id": step.id,
"step_type": step.step_type,
"title": step.title,
"order_index": step.order_index
} for step in sorted(lesson.steps, key=lambda s: s.order_index)
] if lesson.steps else []
}
for lesson in sorted(module.lessons, key=lambda l: l.order_index)
] if module.lessons else []
}
for module in sorted(course.modules, key=lambda m: m.order_index)
] if course.modules else []
}
return schemas.SuccessResponse(data={"course": course_data})