Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    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()
Ejemplo n.º 4
0
    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()
Ejemplo n.º 5
0
    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)
Ejemplo n.º 6
0
    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)