def API_POST(self, courseid, taskid): # pylint: disable=arguments-differ """ Creates a new submissions. Takes as (POST) input the key of the subproblems, with the value assigned each time. Returns - an error 400 Bad Request if all the input is not (correctly) given, - an error 403 Forbidden if you are not allowed to create a new submission for this task - an error 404 Not found if the course/task id not found - an error 500 Internal server error if the grader is not available, - 200 Ok, with {"submissionid": "the submission id"} as output. """ try: course = self.course_factory.get_course(courseid) except: raise APINotFound("Course not found") username = self.user_manager.session_username() if not self.user_manager.course_is_open_to_user(course, username, False): raise APIForbidden("You are not registered to this course") try: task = course.get_task(taskid) except: raise APINotFound("Task not found") self.user_manager.user_saw_task(username, courseid, taskid) # Verify rights if not self.user_manager.task_can_user_submit(task, username, False): raise APIForbidden("You are not allowed to submit for this task") user_input = flask.request.form.copy() for problem in task.get_problems(): pid = problem.get_id() if problem.input_type() == list: user_input[pid] = flask.request.form.getlist(pid) elif problem.input_type() == dict: user_input[pid] = flask.request.files.get(pid) else: user_input[pid] = flask.request.form.get(pid) user_input = task.adapt_input_for_backend(user_input) if not task.input_is_consistent(user_input, self.default_allowed_file_extensions, self.default_max_file_size): raise APIInvalidArguments() # Get debug info if the current user is an admin debug = self.user_manager.has_admin_rights_on_course(course, username) # Start the submission try: submissionid, _ = self.submission_manager.add_job(task, user_input, debug) return 200, {"submissionid": str(submissionid)} except Exception as ex: raise APIError(500, str(ex))
def _get_submissions(course_factory, submission_manager, user_manager, translations, courseid, taskid, with_input, submissionid=None): """ Helper for the GET methods of the two following classes """ try: course = course_factory.get_course(courseid) except: raise APINotFound("Course not found") if not user_manager.course_is_open_to_user(course, lti=False): raise APIForbidden("You are not registered to this course") try: task = course.get_task(taskid) except: raise APINotFound("Task not found") if submissionid is None: submissions = submission_manager.get_user_submissions(task) else: try: submissions = [submission_manager.get_submission(submissionid)] except: raise APINotFound("Submission not found") if submissions[0]["taskid"] != task.get_id() or submissions[0]["courseid"] != course.get_id(): raise APINotFound("Submission not found") output = [] for submission in submissions: submission = submission_manager.get_feedback_from_submission( submission, show_everything=user_manager.has_staff_rights_on_course(course, user_manager.session_username()), translation=translations.get(user_manager.session_language(), gettext.NullTranslations()) ) data = { "id": str(submission["_id"]), "submitted_on": str(submission["submitted_on"]), "status": submission["status"] } if with_input: data["input"] = submission_manager.get_input_from_submission(submission, True) # base64 encode file to allow JSON encoding for d in data["input"]: if isinstance(d, dict) and d.keys() == {"filename", "value"}: d["value"] = base64.b64encode(d["value"]).decode("utf8") if submission["status"] == "done": data["grade"] = submission.get("grade", 0) data["result"] = submission.get("result", "crash") data["feedback"] = submission.get("text", "") data["problems_feedback"] = submission.get("problems", {}) output.append(data) return 200, output
def API_GET(self, courseid, taskid=None): # pylint: disable=arguments-differ """ List tasks available to the connected client. Returns a dict in the form :: { "taskid1": { "name": "Name of the course", #the name of the course "authors": [], "deadline": "", "status": "success" # can be "succeeded", "failed" or "notattempted" "grade": 0.0, "grade_weight": 0.0, "context": "" # context of the task, in RST "problems": # dict of the subproblems { # see the format of task.yaml for the content of the dict. Contains everything but # responses of multiple-choice and match problems. } } #... } If you use the endpoint /api/v0/courses/the_course_id/tasks/the_task_id, this dict will contain one entry or the page will return 404 Not Found. """ try: course = self.course_factory.get_course(courseid) except: raise APINotFound("Course not found") if not self.user_manager.course_is_open_to_user(course, lti=False): raise APIForbidden("You are not registered to this course") if taskid is None: tasks = course.get_tasks() else: try: tasks = {taskid: course.get_task(taskid)} except: raise APINotFound("Task not found") output = [] for taskid, task in tasks.items(): task_cache = self.user_manager.get_task_cache( self.user_manager.session_username(), task.get_course_id(), task.get_id()) data = { "id": taskid, "name": task.get_name(self.user_manager.session_language()), "authors": task.get_authors(self.user_manager.session_language()), "deadline": task.get_deadline(), "status": "notviewed" if task_cache is None else "notattempted" if task_cache["tried"] == 0 else "succeeded" if task_cache["succeeded"] else "failed", "grade": task_cache.get("grade", 0.0) if task_cache is not None else 0.0, "grade_weight": task.get_grading_weight(), "context": task.get_context( self.user_manager.session_language()).original_content(), "problems": [] } for problem in task.get_problems(): pcontent = problem.get_original_content() pcontent["id"] = problem.get_id() if pcontent["type"] == "match": del pcontent["answer"] if pcontent["type"] == "multiple-choice": pcontent["choices"] = { key: val["text"] for key, val in enumerate(pcontent["choices"]) } pcontent = self._check_for_parsable_text(pcontent) data["problems"].append(pcontent) output.append(data) return 200, output
def check_superadmin_rights(self): if not self.user_manager.user_is_superadmin(): raise APIForbidden()