from typing import Any, List, Optional from fastapi import APIRouter, Depends, HTTPException, Path 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.Question]) def read_questions( db: Session = Depends(get_db), skip: int = 0, limit: int = 100, exam_id: Optional[int] = None, current_user: models.User = Depends(get_current_active_user), ) -> Any: """ Retrieve questions. """ if exam_id: questions = crud.question.get_by_exam_id(db, exam_id=exam_id) else: questions = crud.question.get_multi(db, skip=skip, limit=limit) return questions @router.post("/", response_model=schemas.Question) def create_question( *, db: Session = Depends(get_db), question_in: schemas.QuestionCreate, current_user: models.User = Depends(get_teacher_user), ) -> Any: """ Create new question. """ # Check if the exam exists exam = crud.exam.get(db=db, id=question_in.exam_id) if not exam: raise HTTPException( status_code=404, detail=f"Exam with ID {question_in.exam_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: 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 create a question for this exam", ) question = crud.question.create(db=db, obj_in=question_in) return question @router.get("/{question_id}", response_model=schemas.QuestionWithOptions) def read_question( *, db: Session = Depends(get_db), question_id: int = Path(..., title="The ID of the question to get"), current_user: models.User = Depends(get_current_active_user), ) -> Any: """ Get question by ID with options. """ question = crud.question.get(db=db, id=question_id) if not question: raise HTTPException( status_code=404, detail="Question not found", ) # Get options for this question options = crud.question_option.get_by_question_id(db=db, question_id=question_id) # Create a combined response result = schemas.QuestionWithOptions.from_orm(question) result.options = options return result @router.put("/{question_id}", response_model=schemas.Question) def update_question( *, db: Session = Depends(get_db), question_id: int = Path(..., title="The ID of the question to update"), question_in: schemas.QuestionUpdate, current_user: models.User = Depends(get_teacher_user), ) -> Any: """ Update a question. """ question = crud.question.get(db=db, id=question_id) if not question: raise HTTPException( status_code=404, detail="Question 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: exam = db.query(models.Exam).filter(models.Exam.id == question.exam_id).first() if not exam: raise HTTPException( status_code=404, detail="Exam not found", ) 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 question", ) question = crud.question.update(db=db, db_obj=question, obj_in=question_in) return question @router.delete("/{question_id}", response_model=schemas.Question) def delete_question( *, db: Session = Depends(get_db), question_id: int = Path(..., title="The ID of the question to delete"), current_user: models.User = Depends(get_teacher_user), ) -> Any: """ Delete a question. """ question = crud.question.get(db=db, id=question_id) if not question: raise HTTPException( status_code=404, detail="Question 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: exam = db.query(models.Exam).filter(models.Exam.id == question.exam_id).first() if not exam: raise HTTPException( status_code=404, detail="Exam not found", ) 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 question", ) question = crud.question.remove(db=db, id=question_id) return question