209 lines
6.2 KiB
Python

from typing import Any, List, Optional
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from app import crud, models, schemas
from app.api.v1.deps import get_db, get_current_active_user, get_teacher_user
router = APIRouter()
@router.get("/", response_model=List[schemas.Exam])
def read_exams(
db: Session = Depends(get_db),
skip: int = 0,
limit: int = 100,
course_id: Optional[int] = None,
current_user: models.User = Depends(get_current_active_user),
) -> Any:
"""
Retrieve exams.
"""
if course_id:
exams = crud.exam.get_by_course_id(db, course_id=course_id)
else:
exams = crud.exam.get_multi(db, skip=skip, limit=limit)
return exams
@router.get("/active", response_model=List[schemas.Exam])
def read_active_exams(
db: Session = Depends(get_db),
skip: int = 0,
limit: int = 100,
current_user: models.User = Depends(get_current_active_user),
) -> Any:
"""
Retrieve active exams.
"""
exams = crud.exam.get_active_exams(db, skip=skip, limit=limit)
return exams
@router.get("/available", response_model=List[schemas.Exam])
def read_available_exams(
db: Session = Depends(get_db),
skip: int = 0,
limit: int = 100,
current_user: models.User = Depends(get_current_active_user),
) -> Any:
"""
Retrieve available exams (active and within time window).
"""
exams = crud.exam.get_available_exams(db, skip=skip, limit=limit)
return exams
@router.post("/", response_model=schemas.Exam)
def create_exam(
*,
db: Session = Depends(get_db),
exam_in: schemas.ExamCreate,
current_user: models.User = Depends(get_teacher_user),
) -> Any:
"""
Create new exam.
"""
# Check if the course exists
course = db.query(models.Course).filter(models.Course.id == exam_in.course_id).first()
if not course:
raise HTTPException(
status_code=404,
detail=f"Course with ID {exam_in.course_id} not found",
)
# Check if the user is a teacher of this course or an admin
is_admin = any(role.name == "admin" for role in db.query(models.Role).all() if role.id == current_user.role_id)
if not is_admin:
teacher = db.query(models.Teacher).filter(models.Teacher.user_id == current_user.id).first()
if not teacher or teacher.id != course.teacher_id:
raise HTTPException(
status_code=403,
detail="You don't have permission to create an exam for this course",
)
# Set the created_by field to the current user's ID
exam_data = exam_in.dict()
exam_data["created_by"] = current_user.id
exam_obj = schemas.ExamCreate(**exam_data)
exam = crud.exam.create(db=db, obj_in=exam_obj)
return exam
@router.get("/{exam_id}", response_model=schemas.ExamWithQuestions)
def read_exam(
*,
db: Session = Depends(get_db),
exam_id: int,
current_user: models.User = Depends(get_current_active_user),
) -> Any:
"""
Get exam by ID with questions.
"""
exam = crud.exam.get(db=db, id=exam_id)
if not exam:
raise HTTPException(
status_code=404,
detail="Exam not found",
)
# Get questions for this exam
questions = crud.question.get_by_exam_id(db=db, exam_id=exam_id)
# Create a combined response
result = schemas.ExamWithQuestions.from_orm(exam)
result.questions = questions
return result
@router.get("/{exam_id}/creator", response_model=schemas.ExamWithCreator)
def read_exam_with_creator(
*,
db: Session = Depends(get_db),
exam_id: int,
current_user: models.User = Depends(get_current_active_user),
) -> Any:
"""
Get exam by ID with creator information.
"""
exam = crud.exam.get(db=db, id=exam_id)
if not exam:
raise HTTPException(
status_code=404,
detail="Exam not found",
)
# Create a combined response
result = schemas.ExamWithCreator.from_orm(exam)
return result
@router.put("/{exam_id}", response_model=schemas.Exam)
def update_exam(
*,
db: Session = Depends(get_db),
exam_id: int,
exam_in: schemas.ExamUpdate,
current_user: models.User = Depends(get_teacher_user),
) -> Any:
"""
Update an exam.
"""
exam = crud.exam.get(db=db, id=exam_id)
if not exam:
raise HTTPException(
status_code=404,
detail="Exam not found",
)
# Check if the user is a teacher of this course or an admin
is_admin = any(role.name == "admin" for role in db.query(models.Role).all() if role.id == current_user.role_id)
if not is_admin:
course = db.query(models.Course).filter(models.Course.id == exam.course_id).first()
teacher = db.query(models.Teacher).filter(models.Teacher.user_id == current_user.id).first()
if not teacher or not course or teacher.id != course.teacher_id:
raise HTTPException(
status_code=403,
detail="You don't have permission to update this exam",
)
exam = crud.exam.update(db=db, db_obj=exam, obj_in=exam_in)
return exam
@router.delete("/{exam_id}", response_model=schemas.Exam)
def delete_exam(
*,
db: Session = Depends(get_db),
exam_id: int,
current_user: models.User = Depends(get_teacher_user),
) -> Any:
"""
Delete an exam.
"""
exam = crud.exam.get(db=db, id=exam_id)
if not exam:
raise HTTPException(
status_code=404,
detail="Exam not found",
)
# Check if the user is a teacher of this course or an admin
is_admin = any(role.name == "admin" for role in db.query(models.Role).all() if role.id == current_user.role_id)
if not is_admin:
course = db.query(models.Course).filter(models.Course.id == exam.course_id).first()
teacher = db.query(models.Teacher).filter(models.Teacher.user_id == current_user.id).first()
if not teacher or not course or teacher.id != course.teacher_id:
raise HTTPException(
status_code=403,
detail="You don't have permission to delete this exam",
)
exam = crud.exam.remove(db=db, id=exam_id)
return exam