From c5399f5afe26a8745db546e814b3f766624e0b0e Mon Sep 17 00:00:00 2001 From: Jarne Clauw <67628242+JarneClauw@users.noreply.github.com> Date: Sun, 25 Feb 2024 22:32:12 +0100 Subject: [PATCH] #15 - Most methods implemented. Still linting issues, submissions patch needed, tests, authentication --- backend/project/__main__.py | 2 +- backend/project/endpoints/submissions.py | 178 ++++++++++++++++++++--- 2 files changed, 157 insertions(+), 23 deletions(-) diff --git a/backend/project/__main__.py b/backend/project/__main__.py index 8945aa1f..4980ef8a 100644 --- a/backend/project/__main__.py +++ b/backend/project/__main__.py @@ -2,7 +2,7 @@ from sys import path from project import create_app_with_db -from project.database import get_database_uri +from .database import get_database_uri path.append(".") diff --git a/backend/project/endpoints/submissions.py b/backend/project/endpoints/submissions.py index 64b859fc..631ec927 100644 --- a/backend/project/endpoints/submissions.py +++ b/backend/project/endpoints/submissions.py @@ -1,8 +1,12 @@ """Submission API endpoint""" -from flask import Blueprint +from datetime import datetime +from flask import Blueprint, request from flask_restful import Resource +from project.database import db from project.models.submissions import Submissions as m_submissions +from project.models.projects import Projects as m_projects +from project.models.users import Users as m_users submissions_bp = Blueprint("submissions", __name__) @@ -13,28 +17,106 @@ def get(self, uid: str, pid: int) -> dict[str, any]: """Get all the submissions from a user for a project Args: - uid (int): User ID + uid (str): User ID pid (int): Project ID Returns: - dict[str, int]: The list of submission URLs + dict[str, any]: The list of submission URLs """ - a = m_submissions.query.filter_by(uid=uid, project_id=pid).count() - - return {"uid": uid, "pid": pid, "test": a} - - def post(self, uid: int, pid: int) -> dict[str, int]: + # Authentication + # uid_operator = 0 + # if uid_operator is None: + # return {"message": "Not logged in"}, 401 + + try: + with db.session() as session: + # Authorization + # operator = session.get(m_users, uid_operator) + # if operator is None: + # return {"message": f"User {uid_operator} not found"}, 404 + # if not (operator.is_admin or operator.is_teacher or uid_operator == uid): + # return {"message": f"User {uid_operator} does not have the correct rights"}, 403 + + # Check user + user = session.get(m_users, uid) + if user is None: + return {"message": f"User {uid} not found"}, 404 + + # Check project + project = session.get(m_projects, pid) + if project is None: + return {"message": f"Project {pid} not found"}, 404 + + # Get the submissions + submissions = session.query(m_submissions).filter_by(uid=uid, project_id=pid).all() + submissions_urls = [f"/submissions/{s.submission_id}" for s in submissions] + return {"submissions": submissions_urls} + except Exception: + return {"message": f"An error occurred while fetching the submissions from user {uid} for project {pid}"}, 500 + + def post(self, uid: str, pid: int) -> dict[str, any]: """Post a new submission to a project Args: - uid (int): User ID + uid (str): User ID pid (int): Project ID Returns: - dict[str, int]: The URL to the submission + dict[str, any]: The URL to the submission """ - return {"uid": uid, "pid": pid} + + # Authentication + # uid_operator = 0 + # if uid_operator is None: + # return {"message": "Not logged in"}, 401 + + try: + with db.session() as session: + # Authorization + # operator = session.get(m_users, uid_operator) + # if operator is None: + # return {"message": f"User {uid_operator} not found"}, 404 + # if uid_operator != uid: + # return {"message": f"User {uid_operator} does not have the correct rights"}, 403 + + submission = m_submissions() + + # User + user = session.get(m_users, uid) + if user is None: + return {"message": f"User {uid} not found"}, 404 + submission.uid = uid + + # Project + project = session.get(m_projects, pid) + if project is None: + return {"message": f"Project {pid} not found"}, 404 + submission.project_id = pid + + # Grading + if "grading" in request.form: + grading = request.form["grading"] + if grading < 0 or grading > 20: + return {} + submission.grading = grading + + # Submission time + submission.submission_time = datetime.now() + + # Submission path + # get the files and store them + submission.submission_path = "/tbd" + + # Submission status + submission.submission_status = False + + session.add(submission) + session.commit() + return {"submission": f"/submissions/{submission.submission_id}"}, 201 + except Exception: + session.rollback() + return {"message": f"An error occurred while creating a new submission for user {uid} in project {pid}"}, 500 submissions_bp.add_url_rule( "/submissions//", @@ -43,32 +125,84 @@ def post(self, uid: int, pid: int) -> dict[str, int]: class Submission(Resource): """API endpoint for the submission""" - def get(self, uid: int, pid: int, sid: int) -> dict[str, int]: + def get(self, sid: int) -> dict[str, any]: """Get the submission given an submission ID Args: - uid (int): User ID - pid (int): Project ID sid (int): Submission ID Returns: - dict[str, int]: The submission + dict[str, any]: The submission """ - return {"uid": uid, "pid": pid, "sid": sid} - def delete(self, uid: int, pid: int, sid: int) -> dict[str, int]: + # Authentication + # uid_operator = 0 + # if uid_operator is None: + # return {"message": "Not logged in"}, 401 + + try: + with db.session() as session: + # Authorization + # operator = session.get(m_users, uid_operator) + # if operator is None: + # return {"message": f"User {uid_operator} not found"}, 404 + # if not (operator.is_admin or operator.is_teacher or uid_operator == uid): + # return {"message": f"User {uid_operator} does not have the correct rights"}, 403 + + # Get the submission + submission = session.get(m_submissions, sid) + if submission is None: + return {"message": f"Submission {sid} not found"}, 404 + + return { + "submission_id": submission.submission_id, + "uid": submission.uid, + "project_id": submission.project_id, + "grading": submission.grading, + "submission_time": submission.submission_time, + "submission_path": submission.submission_path, + "submission_status": submission.submission_status + } + except Exception: + return {"message": f"An error occurred while fetching submission {sid}"}, 500 + + def delete(self, sid: int) -> dict[str, any]: """Delete a submission given an submission ID Args: - uid (int): User ID - pid (int): Project ID sid (int): Submission ID Returns: - dict[str, int]: Empty + dict[str, any]: Empty """ - return {"uid": uid, "pid": pid, "sid": sid} + + # Authentication + # uid_operator = 0 + # if uid_operator is None: + # return {"message": "Not logged in"}, 401 + + try: + with db.session() as session: + # Authorization + # operator = session.get(m_users, uid_operator) + # if operator is None: + # return {"message": f"User {uid_operator} not found"}, 404 + # if not operator.is_admin: + # return {"message": f"User {uid_operator} does not have the correct rights"}, 403 + + # Check if the submission exists + submission = session.get(m_submissions, sid) + if submission is None: + return {"message": f"Submission {sid} not found"}, 404 + + # Delete the submission + session.delete(submission) + session.commit() + return {"message": f"Submission {sid} deleted"} + except Exception: + db.session.rollback() + return {"message": f"An error occurred while deleting submission {sid}"}, 500 submissions_bp.add_url_rule( - "/submissions///", + "/submissions/", view_func=Submission.as_view("submission"))