From 724451fedd58996dc424dc6fa74bdc5e0fab1ed0 Mon Sep 17 00:00:00 2001 From: Mathieu Strypsteen Date: Thu, 7 Mar 2024 17:17:46 +0100 Subject: [PATCH] Bug fixes in backend --- backend/app.py | 8 ++--- .../routes/dependencies/role_dependencies.py | 35 +++++++++---------- backend/routes/errors/authentication.py | 4 +-- backend/routes/project.py | 4 +-- backend/routes/subject.py | 4 +-- 5 files changed, 27 insertions(+), 28 deletions(-) diff --git a/backend/app.py b/backend/app.py index caaff4f2..52bf6714 100644 --- a/backend/app.py +++ b/backend/app.py @@ -5,7 +5,7 @@ from starlette.responses import JSONResponse from db.errors.database_errors import ActionAlreadyPerformedError, ItemNotFoundError -from routes.errors.authentication import InvalidRoleCredentialsError, StudentNotEnrolledError +from routes.errors.authentication import InvalidRoleCredentialsError, NoAccessToSubjectError from routes.project import project_router from routes.student import student_router from routes.subject import subject_router @@ -39,10 +39,10 @@ def item_not_found_error_handler(request: Request, exc: ItemNotFoundError) -> JS ) -@app.exception_handler(StudentNotEnrolledError) -def student_already_enrolled_error_handler(request: Request, exc: StudentNotEnrolledError) -> JSONResponse: +@app.exception_handler(NoAccessToSubjectError) +def no_access_to_subject_error_handler(request: Request, exc: NoAccessToSubjectError) -> JSONResponse: return JSONResponse( - status_code=status.HTTP_400_BAD_REQUEST, + status_code=status.HTTP_403_FORBIDDEN, content={"detail": str(exc)}, ) diff --git a/backend/routes/dependencies/role_dependencies.py b/backend/routes/dependencies/role_dependencies.py index abe7619c..e686b66b 100644 --- a/backend/routes/dependencies/role_dependencies.py +++ b/backend/routes/dependencies/role_dependencies.py @@ -8,13 +8,12 @@ from domain.logic.teacher import get_teacher, is_user_teacher from domain.models.AdminDataclass import AdminDataclass from domain.models.StudentDataclass import StudentDataclass -from domain.models.SubjectDataclass import SubjectDataclass from domain.models.TeacherDataclass import TeacherDataclass from routes.errors.authentication import ( InvalidAdminCredentialsError, InvalidStudentCredentialsError, InvalidTeacherCredentialsError, - StudentNotEnrolledError, + NoAccessToSubjectError, ) @@ -43,26 +42,26 @@ def get_authenticated_student(session: Session = Depends(get_session)) -> Studen return get_student(session, user_id) -def is_user_authorized_for_subject(subject_id: int, session: Session = Depends(get_session)) -> bool: - user_id = get_authenticated_user() - if is_user_teacher(session, user_id): - subjects_of_teacher: list[SubjectDataclass] = get_subjects_of_teacher(session, subject_id) - return subject_id in [subject.id for subject in subjects_of_teacher] - - if is_user_student(session, user_id): - subjects_of_student: list[SubjectDataclass] = get_subjects_of_student(session, subject_id) - return subject_id in [subject.id for subject in subjects_of_student] - - return False +def ensure_user_authorized_for_subject( + subject_id: int, + session: Session = Depends(get_session), + uid: int = Depends(get_authenticated_user), +) -> None: + subjects = [] + if is_user_teacher(session, uid): + subjects += get_subjects_of_teacher(session, uid) + if is_user_student(session, uid): + subjects += get_subjects_of_student(session, uid) + if subject_id not in [subject.id for subject in subjects]: + raise NoAccessToSubjectError def get_authenticated_student_for_subject( - subject_id: int, - session: Session = Depends(get_session), - student: StudentDataclass = Depends(get_authenticated_student), + subject_id: int, + session: Session = Depends(get_session), + student: StudentDataclass = Depends(get_authenticated_student), ) -> StudentDataclass: subjects_of_student = get_subjects_of_student(session, student.id) if subject_id not in [subject.id for subject in subjects_of_student]: - raise StudentNotEnrolledError + raise NoAccessToSubjectError return student - diff --git a/backend/routes/errors/authentication.py b/backend/routes/errors/authentication.py index f1437edf..4c51dd14 100644 --- a/backend/routes/errors/authentication.py +++ b/backend/routes/errors/authentication.py @@ -14,5 +14,5 @@ class InvalidStudentCredentialsError(InvalidRoleCredentialsError): ERROR_MESSAGE = "User does not have the required student role" -class StudentNotEnrolledError(Exception): - ERROR_MESSAGE = "Student is not enrolled in the subject" +class NoAccessToSubjectError(Exception): + ERROR_MESSAGE = "User doesn't have access to subject" diff --git a/backend/routes/project.py b/backend/routes/project.py index 414b81b0..f91ea9f8 100644 --- a/backend/routes/project.py +++ b/backend/routes/project.py @@ -4,7 +4,7 @@ from db.sessions import get_session from domain.logic.project import get_project from domain.models.ProjectDataclass import ProjectDataclass -from routes.dependencies.role_dependencies import is_user_authorized_for_subject +from routes.dependencies.role_dependencies import ensure_user_authorized_for_subject project_router = APIRouter() @@ -12,5 +12,5 @@ @project_router.get("/projects/{project_id}") def get_subject_project(project_id: int, session: Session = Depends(get_session)) -> ProjectDataclass: project: ProjectDataclass = get_project(session, project_id) - is_user_authorized_for_subject(project.subject_id) + ensure_user_authorized_for_subject(project.subject_id) return project diff --git a/backend/routes/subject.py b/backend/routes/subject.py index 6a4396cc..9b79930e 100644 --- a/backend/routes/subject.py +++ b/backend/routes/subject.py @@ -7,8 +7,8 @@ from domain.models.ProjectDataclass import ProjectDataclass from domain.models.SubjectDataclass import SubjectDataclass from routes.dependencies.role_dependencies import ( + ensure_user_authorized_for_subject, get_authenticated_user, - is_user_authorized_for_subject, ) subject_router = APIRouter() @@ -19,6 +19,6 @@ def subject_get(subject_id: int, session: Session = Depends(get_session)) -> Sub return get_subject(session, subject_id) -@subject_router.get("/subjects/{subject_id}/projects", dependencies=[Depends(is_user_authorized_for_subject)]) +@subject_router.get("/subjects/{subject_id}/projects", dependencies=[Depends(ensure_user_authorized_for_subject)]) def get_subject_projects(subject_id: int, session: Session = Depends(get_session)) -> list[ProjectDataclass]: return get_projects_of_subject(session, subject_id)