def GET(self, courseid, taskid, path): # pylint: disable=arguments-differ """ GET request """ try: course = self.course_factory.get_course(courseid) if not self.user_manager.course_is_open_to_user(course): return handle_course_unavailable(self.app.get_homepath(), self.template_helper, self.user_manager, course) path_norm = posixpath.normpath(urllib.parse.unquote(path)) if taskid == "$common": public_folder = course.get_fs().from_subfolder("$common").from_subfolder("public") else: task = course.get_task(taskid) if not self.user_manager.task_is_visible_by_user(task): # ignore LTI check here return self.template_helper.render("task_unavailable.html") public_folder = task.get_fs().from_subfolder("public") (method, mimetype_or_none, file_or_url) = public_folder.distribute(path_norm, False) if method == "local": return Response(response=file_or_url, content_type=mimetype_or_none) elif method == "url": return redirect(file_or_url) else: raise NotFound() except TaskNotFoundException: raise NotFound() except HTTPException as error_or_redirect: raise error_or_redirect
def POST_AUTH(self): data = request.form username = self.user_manager.session_username() language = self.user_manager.session_language() courseid = data.get("courseid", None) taskid = data.get("taskid", None) course = self.course_factory.get_course(courseid) if not self.user_manager.course_is_open_to_user( course, username, self.is_lti_page()): return handle_course_unavailable(self.cp.app.get_homepath(), self.template_helper, self.user_manager, course) task = course.get_task(taskid) if not self.user_manager.task_can_user_submit(task, username, None, self.is_lti_page()): raise Forbidden(_("Task unavailable")) problemid = data.get("problemid", "") problems = task.get_problems() hints = "" for problem in problems: if problem.get_id() == problemid: hints = str( ParsableText( problem.gettext(language, problem._hints), "rst", translation=problem.get_translation_obj(language))) if hints: user_tasks = self.database.user_tasks.find_one({ "username": username, "courseid": courseid, "taskid": taskid }) try: state = json.loads(user_tasks.get("state", "{}")) except: state = {} state.setdefault("hints", {})[problemid] = True self.database.user_tasks.update_one( { "username": username, "courseid": courseid, "taskid": taskid }, {"$set": { "state": json.dumps(state) }}) return hints
def GET(self, courseid, taskid, path): # pylint: disable=arguments-differ """ GET request """ try: course = self.course_factory.get_course(courseid) if not self.user_manager.course_is_open_to_user(course): return handle_course_unavailable(self.app.get_homepath(), self.template_helper, self.user_manager, course) path_norm = posixpath.normpath(urllib.parse.unquote(path)) if taskid == "$common": public_folder = course.get_fs().from_subfolder( "$common").from_subfolder("public") else: task = course.get_task(taskid) if not self.user_manager.task_is_visible_by_user( task): # ignore LTI check here return self.template_helper.get_renderer( ).task_unavailable() public_folder = task.get_fs().from_subfolder("public") (method, mimetype_or_none, file_or_url) = public_folder.distribute(path_norm, False) if method == "local": web.header('Content-Type', mimetype_or_none) return file_or_url elif method == "url": raise web.redirect(file_or_url) else: raise web.notfound() except web.HTTPError as error_or_redirect: raise error_or_redirect except: if web.config.debug: raise else: raise web.notfound()
def POST(self, courseid, taskid, isLTI): """ POST a new submission """ username = self.user_manager.session_username() course = self.course_factory.get_course(courseid) if not self.user_manager.course_is_open_to_user( course, username, isLTI): return handle_course_unavailable(self.cp.app.get_homepath(), self.template_helper, self.user_manager, course) task = course.get_task(taskid) if not self.user_manager.task_is_visible_by_user( task, username, isLTI): return self.template_helper.get_renderer().task_unavailable() self.user_manager.user_saw_task(username, courseid, taskid) is_staff = self.user_manager.has_staff_rights_on_course( course, username) is_admin = self.user_manager.has_admin_rights_on_course( course, username) userinput = web.input() if "@action" in userinput and userinput["@action"] == "submit": # Verify rights if not self.user_manager.task_can_user_submit( task, username, isLTI): return json.dumps({ "status": "error", "title": _("Error"), "text": _("You are not allowed to submit for this task.") }) # Retrieve input random and check still valid random_input = self.database.user_tasks.find_one( { "courseid": task.get_course_id(), "taskid": task.get_id(), "username": username }, {"random": 1}) random_input = random_input[ "random"] if "random" in random_input else [] for i in range(0, len(random_input)): s = "@random_" + str(i) if s not in userinput or float( userinput[s]) != random_input[i]: return json.dumps({ "status": "error", "title": _("Error"), "text": _("Your task has been regenerated. This current task is outdated." ) }) # Reparse user input with array for multiple choices init_var = { problem.get_id(): problem.input_type()() for problem in task.get_problems() if problem.input_type() in [dict, list] } userinput = task.adapt_input_for_backend(web.input(**init_var)) if not task.input_is_consistent( userinput, self.default_allowed_file_extensions, self.default_max_file_size): web.header('Content-Type', 'application/json') return json.dumps({ "status": "error", "title": _("Error"), "text": _("Please answer to all the questions and verify the extensions of the files " "you want to upload. Your responses were not tested.") }) del userinput['@action'] # Get debug info if the current user is an admin debug = is_admin if "@debug-mode" in userinput: if userinput["@debug-mode"] == "ssh" and debug: debug = "ssh" del userinput['@debug-mode'] # Start the submission try: submissionid, oldsubids = self.submission_manager.add_job( task, userinput, debug) web.header('Content-Type', 'application/json') return json.dumps({ "status": "ok", "submissionid": str(submissionid), "remove": oldsubids, "text": _("<b>Your submission has been sent...</b>") }) except Exception as ex: web.header('Content-Type', 'application/json') return json.dumps({ "status": "error", "title": _("Error"), "text": str(ex) }) elif "@action" in userinput and userinput[ "@action"] == "check" and "submissionid" in userinput: result = self.submission_manager.get_submission( userinput['submissionid'], user_check=not is_staff) if result is None: web.header('Content-Type', 'application/json') return json.dumps({ 'status': "error", "title": _("Error"), "text": _("Internal error") }) elif self.submission_manager.is_done(result, user_check=not is_staff): web.header('Content-Type', 'application/json') result = self.submission_manager.get_input_from_submission( result) result = self.submission_manager.get_feedback_from_submission( result, show_everything=is_staff) # user_task always exists as we called user_saw_task before user_task = self.database.user_tasks.find_one({ "courseid": task.get_course_id(), "taskid": task.get_id(), "username": { "$in": result["username"] } }) default_submissionid = user_task.get('submissionid', None) if default_submissionid is None: # This should never happen, as user_manager.update_user_stats is called whenever a submission is done. return json.dumps({ 'status': "error", "title": _("Error"), "text": _("Internal error") }) return self.submission_to_json( task, result, is_admin, False, default_submissionid == result['_id'], tags=course.get_tags()) else: web.header('Content-Type', 'application/json') return self.submission_to_json(task, result, is_admin, False, tags=course.get_tags()) elif "@action" in userinput and userinput[ "@action"] == "load_submission_input" and "submissionid" in userinput: submission = self.submission_manager.get_submission( userinput["submissionid"], user_check=not is_staff) submission = self.submission_manager.get_input_from_submission( submission) submission = self.submission_manager.get_feedback_from_submission( submission, show_everything=is_staff) if not submission: raise web.notfound() web.header('Content-Type', 'application/json') return self.submission_to_json(task, submission, is_admin, True, tags=course.get_tags()) elif "@action" in userinput and userinput[ "@action"] == "kill" and "submissionid" in userinput: self.submission_manager.kill_running_submission( userinput["submissionid"]) # ignore return value web.header('Content-Type', 'application/json') return json.dumps({'status': 'done'}) elif "@action" in userinput and userinput[ "@action"] == "set_submission" and "submissionid" in userinput: web.header('Content-Type', 'application/json') if task.get_evaluate() != 'student': return json.dumps({'status': "error"}) if self.set_selected_submission(course, task, userinput["submissionid"]): return json.dumps({'status': 'done'}) else: return json.dumps({'status': 'error'}) else: raise web.notfound()
def GET(self, courseid, taskid, is_LTI): """ GET request """ username = self.user_manager.session_username() # Fetch the course try: course = self.course_factory.get_course(courseid) except exceptions.CourseNotFoundException as ex: raise web.notfound(str(ex)) if is_LTI and not self.user_manager.course_is_user_registered(course): self.user_manager.course_register_user(course, force=True) if not self.user_manager.course_is_open_to_user( course, username, is_LTI): return handle_course_unavailable(self.cp.app.get_homepath(), self.template_helper, self.user_manager, course) # Fetch the task try: tasks = OrderedDict((tid, t) for tid, t in course.get_tasks().items() if self.user_manager.task_is_visible_by_user( t, username, is_LTI)) task = tasks[taskid] except KeyError: raise web.notfound() if not self.user_manager.task_is_visible_by_user( task, username, is_LTI): return self.template_helper.get_renderer().task_unavailable() # Compute previous and next taskid keys = list(tasks.keys()) index = keys.index(taskid) previous_taskid = keys[index - 1] if index > 0 else None next_taskid = keys[index + 1] if index < len(keys) - 1 else None self.user_manager.user_saw_task(username, courseid, taskid) is_staff = self.user_manager.has_staff_rights_on_course( course, username) userinput = web.input() if "submissionid" in userinput and "questionid" in userinput: # Download a previously submitted file submission = self.submission_manager.get_submission( userinput["submissionid"], user_check=not is_staff) if submission is None: raise web.notfound() sinput = self.submission_manager.get_input_from_submission( submission, True) if userinput["questionid"] not in sinput: raise web.notfound() if isinstance(sinput[userinput["questionid"]], dict): # File uploaded previously mimetypes.init() mime_type = mimetypes.guess_type( urllib.request.pathname2url( sinput[userinput["questionid"]]['filename'])) web.header('Content-Type', mime_type[0]) return sinput[userinput["questionid"]]['value'] else: # Other file, download it as text web.header('Content-Type', 'text/plain') return sinput[userinput["questionid"]] else: # Generate random inputs and save it into db random.seed( str(username if username is not None else "") + taskid + courseid + str(time.time() if task.regenerate_input_random() else "")) random_input_list = [ random.random() for i in range(task.get_number_input_random()) ] user_task = self.database.user_tasks.find_one_and_update( { "courseid": task.get_course_id(), "taskid": task.get_id(), "username": self.user_manager.session_username() }, {"$set": { "random": random_input_list }}, return_document=ReturnDocument.AFTER) submissionid = user_task.get('submissionid', None) eval_submission = self.database.submissions.find_one( {'_id': ObjectId(submissionid)}) if submissionid else None students = [self.user_manager.session_username()] if task.is_group_task( ) and not self.user_manager.has_admin_rights_on_course( course, username): group = self.database.groups.find_one({ "courseid": task.get_course_id(), "students": self.user_manager.session_username() }) if group is not None: students = group["students"] # we don't care for the other case, as the student won't be able to submit. submissions = self.submission_manager.get_user_submissions( task) if self.user_manager.session_logged_in() else [] user_info = self.database.users.find_one({"username": username}) # Display the task itself return self.template_helper.get_renderer().task( user_info, course, task, submissions, students, eval_submission, user_task, previous_taskid, next_taskid, self.webterm_link, random_input_list)
def GET(self, courseid, taskid, is_LTI): """ GET request """ username = self.user_manager.session_username() # Fetch the course try: course = self.course_factory.get_course(courseid) except CourseNotFoundException as ex: raise web.notfound(str(ex)) if is_LTI and not self.user_manager.course_is_user_registered(course): self.user_manager.course_register_user(course, force=True) if not self.user_manager.course_is_open_to_user( course, username, is_LTI): return handle_course_unavailable(self.cp.app.get_homepath(), self.template_helper, self.user_manager, course) is_staff = self.user_manager.has_staff_rights_on_course( course, username) try: task = course.get_task(taskid) if not self.user_manager.task_is_visible_by_user( task, username, is_LTI): return self.template_helper.render("task_unavailable.html") except TaskNotFoundException: raise web.notfound() user_task_list = course.get_task_dispenser().get_user_task_list( [username])[username] if taskid not in user_task_list: previous_taskid = None next_taskid = None else: # Compute previous and next taskid index = user_task_list.index(taskid) previous_taskid = user_task_list[index - 1] if index > 0 else None next_taskid = user_task_list[ index + 1] if index < len(user_task_list) - 1 else None self.user_manager.user_saw_task(username, courseid, taskid) is_staff = self.user_manager.has_staff_rights_on_course( course, username) userinput = web.input() if "submissionid" in userinput and "questionid" in userinput: # Download a previously submitted file submission = self.submission_manager.get_submission( userinput["submissionid"], user_check=not is_staff) if submission is None: raise self.cp.app.notfound( message=_("Submission doesn't exist.")) sinput = self.submission_manager.get_input_from_submission( submission, True) if userinput["questionid"] not in sinput: raise web.notfound() if isinstance(sinput[userinput["questionid"]], dict): # File uploaded previously mimetypes.init() mime_type = mimetypes.guess_type( urllib.request.pathname2url( sinput[userinput["questionid"]]['filename'])) web.header('Content-Type', mime_type[0]) return sinput[userinput["questionid"]]['value'] else: # Other file, download it as text web.header('Content-Type', 'text/plain') return sinput[userinput["questionid"]] else: # Generate random inputs and save it into db random.seed( str(username if username is not None else "") + taskid + courseid + str(time.time() if task.regenerate_input_random() else "")) random_input_list = [ random.random() for i in range(task.get_number_input_random()) ] user_task = self.database.user_tasks.find_one_and_update( { "courseid": task.get_course_id(), "taskid": task.get_id(), "username": self.user_manager.session_username() }, {"$set": { "random": random_input_list }}, return_document=ReturnDocument.AFTER) submissionid = user_task.get('submissionid', None) eval_submission = self.database.submissions.find_one( {'_id': ObjectId(submissionid)}) if submissionid else None students = [self.user_manager.session_username()] if task.is_group_task( ) and not self.user_manager.has_admin_rights_on_course( course, username): group = self.database.groups.find_one({ "courseid": task.get_course_id(), "students": self.user_manager.session_username() }) if group is not None: students = group["students"] # we don't care for the other case, as the student won't be able to submit. submissions = self.submission_manager.get_user_submissions( task) if self.user_manager.session_logged_in() else [] user_info = self.user_manager.get_user_info(username) # Visible tags course_tags = course.get_tags() task_categories = task.get_categories() visible_tags = [ course_tags[category] for category in task_categories if course_tags[category].is_visible_for_student() or self.user_manager.has_staff_rights_on_course(course) ] # Problem dict pdict = { problem.get_id(): problem.get_type() for problem in task.get_problems() } is_input_list = { problem.get_id(): 1 if problem.input_type() == list else 0 for problem in task.get_problems() } # Display the task itself return self.template_helper.render( "task.html", user_info=user_info, course=course, task=task, submissions=submissions, students=students, eval_submission=eval_submission, user_task=user_task, previous_taskid=previous_taskid, next_taskid=next_taskid, webterm_link=self.webterm_link, input_random_list=random_input_list, visible_tags=visible_tags, pdict=pdict, is_input_list=is_input_list)