209 lines
6.2 KiB
Python
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 |