Beispiel #1
0
    def POST(self, courseid, taskid):
        """ Upload or modify a file """
        if not id_checker(taskid):
            raise Exception("Invalid task id")

        get_course_and_check_rights(courseid, allow_all_staff=False)

        request = web.input(file={})
        if request.get("action") == "upload" and request.get('path') is not None and request.get('file') is not None:
            return self.action_upload(courseid, taskid, request.get('path'), request.get('file'))
        elif request.get("action") == "edit_save" and request.get('path') is not None and request.get('content') is not None:
            return self.action_edit_save(courseid, taskid, request.get('path'), request.get('content'))
        else:
            return self.show_tab_file(courseid, taskid)
Beispiel #2
0
    def POST(self, courseid, groupid):
        """ Edit a group """
        course, _ = get_course_and_check_rights(courseid, allow_all_staff=False)
        student_list, tutor_list = self.get_user_lists(course, groupid)
        group = get_database().groups.find_one({"_id": ObjectId(groupid), "course_id": courseid})

        error = ""
        try:
            data = web.input(group_tutor=[], group_student=[])
            if "delete" in data:
                get_database().groups.remove({"_id": ObjectId(groupid)})
                raise web.seeother("/admin/"+courseid+"/students")
            else:
                data["group_tutor"] = [tutor for tutor in data["group_tutor"] if tutor in tutor_list]
                data["group_student"] = [student for student in data["group_student"] if student in student_list]

                if len(data["group_student"]) > int(data['size']):
                    error = 'Too many students for given group size.'
                elif data['description']:
                    group = get_database().groups.find_one_and_update(
                        {"_id": ObjectId(groupid)},
                        {"$set": {"description": data["description"],
                                  "users": data["group_student"], "tutors": data["group_tutor"],
                                  "size": abs(int(data["size"]))}}, return_document=ReturnDocument.AFTER)
                else:
                    error = 'No group description given.'
        except:
            error = 'User returned an invalid form.'

        return renderer.course_admin.edit_group(course, student_list, tutor_list, group, error, True)
Beispiel #3
0
    def GET(self, courseid):
        """ GET request """

        course, _ = get_course_and_check_rights(courseid)

        web_input = web.input()
        if "drop" in web_input: # delete an old batch job
            try:
                drop_batch_job(web_input["drop"])
            except:
                pass

        operations = []
        for entry in list(get_all_batch_jobs_for_course(courseid)):
            ne = {"container_name": entry["container_name"],
                  "bid": str(entry["_id"]),
                  "submitted_on": entry["submitted_on"]}
            if "result" in entry:
                ne["status"] = "ok" if entry["result"]["retval"] == 0 else "ko"
            else:
                ne["status"] = "waiting"
            operations.append(ne)
        operations = sorted(operations, key= (lambda o: o["submitted_on"]), reverse=True)

        return renderer.course_admin.batch(course, operations, get_all_batch_containers_metadata())
Beispiel #4
0
    def GET(self, courseid, taskid):
        """ Edit a task """
        if not id_checker(taskid):
            raise Exception("Invalid task id")

        get_course_and_check_rights(courseid, allow_all_staff=False)

        request = web.input()
        if request.get("action") == "download" and request.get('path') is not None:
            return self.action_download(courseid, taskid, request.get('path'))
        elif request.get("action") == "delete" and request.get('path') is not None:
            return self.action_delete(courseid, taskid, request.get('path'))
        elif request.get("action") == "rename" and request.get('path') is not None and request.get('new_path') is not None:
            return self.action_rename(courseid, taskid, request.get('path'), request.get('new_path'))
        elif request.get("action") == "create" and request.get('path') is not None:
            return self.action_create(courseid, taskid, request.get('path'))
        elif request.get("action") == "edit" and request.get('path') is not None:
            return self.action_edit(courseid, taskid, request.get('path'))
        else:
            return self.show_tab_file(courseid, taskid)
Beispiel #5
0
    def GET(self, courseid, groupid):
        """ Edit a group """
        course, _ = get_course_and_check_rights(courseid, allow_all_staff=False)
        student_list, tutor_list = self.get_user_lists(course, groupid)

        group = get_database().groups.find_one({"_id": ObjectId(groupid), "course_id": courseid})

        if group:
            return renderer.course_admin.edit_group(course, student_list, tutor_list, group, "", False)
        else:
            raise web.notfound()
Beispiel #6
0
    def GET(self, courseid, bid, path=""):
        """ GET request """

        course, _ = get_course_and_check_rights(courseid)
        batch_job = get_batch_job_status(bid)

        if batch_job is None:
            raise web.notfound()

        if "result" not in batch_job or "file" not in batch_job["result"]:
            raise web.notfound()

        f = get_gridfs().get(batch_job["result"]["file"])

        #hack for index.html:
        if path == "/":
            path = "/index.html"

        if path == "":
            web.header('Content-Type', 'application/x-gzip', unique=True)
            web.header('Content-Disposition', 'attachment; filename="' + bid + '.tar.gz"', unique=True)
            return f.read()
        else:
            path = path[1:] #remove the first /
            if path.endswith('/'):  # remove the last / if it exists
                path = path[0:-1]

            try:
                tar = tarfile.open(fileobj=f, mode='r:gz')
                file_info = tar.getmember(path)
            except:
                raise web.notfound()

            if file_info.isdir(): #tar.gz the dir and return it
               tmp = tempfile.TemporaryFile()
               new_tar = tarfile.open(fileobj=tmp,mode='w:gz')
               for m in tar.getmembers():
                   new_tar.addfile(m, tar.extractfile(m))
               new_tar.close()
               tmp.seek(0)
               return tmp
            elif not file_info.isfile():
                raise web.notfound()
            else: #guess a mime type and send it to the browser
                to_dl = tar.extractfile(path).read()
                mimetypes.init()
                mime_type = mimetypes.guess_type(urllib.pathname2url(path))
                web.header('Content-Type', mime_type[0])
                return to_dl
Beispiel #7
0
    def get_basic_info(self, courseid, container_name):
        course, _ = get_course_and_check_rights(courseid, allow_all_staff=False)
        try:
            metadata = get_batch_container_metadata(container_name)
            if metadata == (None, None, None):
                raise Exception("Container not found")
        except:
            raise web.notfound()

        container_title = metadata[0]
        container_description = metadata[1]

        container_args = dict(metadata[2])  # copy it

        return course, container_title, container_description, container_args
Beispiel #8
0
    def GET(self, courseid, taskid):
        """ Edit a task """
        if not id_checker(taskid):
            raise Exception("Invalid task id")

        course, _ = get_course_and_check_rights(courseid, allow_all_staff=False)

        try:
            task_data = get_task_file_manager(courseid, taskid).read()
        except:
            task_data = None
        if task_data is None:
            task_data = {}
        environments = INGIniousConfiguration["containers"].keys()

        current_filetype = None
        try:
            current_filetype = get_task_file_manager(courseid, taskid).get_ext()
        except:
            pass
        available_filetypes = get_available_task_file_managers().keys()

        # custom problem-type:
        for pid in task_data.get("problems", {}):
            problem = task_data["problems"][pid]
            if (problem["type"] == "code" and "boxes" in problem) or problem["type"] not in (
            "code", "code-single-line", "code-file", "match", "multiple-choice"):
                problem_copy = copy.deepcopy(problem)
                for i in ["name", "header", "headerIsHTML"]:
                    if i in problem_copy:
                        del problem_copy[i]
                problem["custom"] = common.custom_yaml.dump(problem_copy)

        return renderer.course_admin.edit_task(
            course,
            taskid,
            task_data,
            environments,
            json.dumps(
                task_data.get(
                    'problems',
                    {})),
            self.contains_is_html(task_data),
            current_filetype,
            available_filetypes,
            AccessibleTime,
            CourseTaskFiles.get_task_filelist(courseid, taskid))
Beispiel #9
0
    def POST(self, courseid):
        """ POST request: update the settings """
        course, _ = get_course_and_check_rights(courseid, allow_all_staff=False)
        contest_data = get_contest_data(course)

        new_data = web.input()
        errors = []
        try:
            contest_data['enabled'] = new_data.get('enabled', '0') == '1'
            contest_data['start'] = new_data["start"]
            contest_data['end'] = new_data["end"]

            try:
                start = datetime.strptime(contest_data['start'], "%Y-%m-%d %H:%M:%S")
            except:
                errors.append('Invalid start date')

            try:
                end = datetime.strptime(contest_data['end'], "%Y-%m-%d %H:%M:%S")
            except:
                errors.append('Invalid end date')

            if len(errors) == 0:
                if start >= end:
                    errors.append('Start date should be before end date')

            try:
                contest_data['blackout'] = int(new_data["blackout"])
                if contest_data['blackout'] < 0:
                    errors.append('Invalid number of hours for the blackout: should be greater than 0')
            except:
                errors.append('Invalid number of hours for the blackout')

            try:
                contest_data['penalty'] = int(new_data["penalty"])
                if contest_data['penalty'] < 0:
                    errors.append('Invalid number of minutes for the penalty: should be greater than 0')
            except:
                errors.append('Invalid number of minutes for the penalty')
        except:
            errors.append('User returned an invalid form')

        if len(errors) == 0:
            save_contest_data(course, contest_data)
            return get_template_renderer('plugins/contests', '../../templates/layout').admin(course, contest_data, None, True)
        else:
            return get_template_renderer('plugins/contests', '../../templates/layout').admin(course, contest_data, errors, False)
Beispiel #10
0
    def GET(self, courseid, bid):
        """ GET request """

        course, _ = get_course_and_check_rights(courseid)
        batch_job = get_batch_job_status(bid)

        if batch_job is None:
            raise web.notfound()

        done = False
        submitted_on = batch_job["submitted_on"]
        container_name = batch_job["container_name"]
        container_title = container_name
        container_description = ""

        file_list = None
        retval = 0
        stdout = ""
        stderr = ""

        try:
            container_metadata = get_batch_container_metadata(container_name)
            if container_metadata == (None, None, None):
                container_title = container_metadata[0]
                container_description = container_metadata[1]
        except:
            pass

        if "result" in batch_job:
            done = True
            retval = batch_job["result"]["retval"]
            stdout = batch_job["result"].get("stdout","")
            stderr = batch_job["result"].get("stderr", "")

            if "file" in batch_job["result"]:
                f = get_gridfs().get(batch_job["result"]["file"])
                try:
                    tar = tarfile.open(fileobj=f,mode='r:gz')
                    file_list = set(tar.getnames()) - set([''])
                    tar.close()
                except:
                    pass
                finally:
                    f.close()

        return renderer.course_admin.batch_summary(course, bid, done, container_name, container_title, container_description, submitted_on,
                                                   retval, stdout, stderr, file_list)
Beispiel #11
0
    def GET(self, courseid):
        """ GET request """
        course, _ = get_course_and_check_rights(courseid)
        user_input = web.input()
        if "dl" in user_input:
            include_old_submissions = "include_all" in user_input

            if user_input['dl'] == 'submission':
                return self.download_submission(user_input['id'], include_old_submissions)
            elif user_input['dl'] == 'student_task':
                return self.download_student_task(course, user_input['username'], user_input['task'], include_old_submissions)
            elif user_input['dl'] == 'student':
                return self.download_student(course, user_input['username'], include_old_submissions)
            elif user_input['dl'] == 'course':
                return self.download_course(course, include_old_submissions)
            elif user_input['dl'] == 'task':
                return self.download_task(course, user_input['task'], include_old_submissions)
        else:
            raise web.notfound()
Beispiel #12
0
    def POST(self, courseid):
        """ POST request """
        course, _ = get_course_and_check_rights(courseid)

        if not course.is_group_course():
            raise web.notfound()

        error = ""
        try:
            data = web.input()
            if not data['group_description']:
                error = 'No group description given.'
            else:
                get_database().groups.insert({"course_id": courseid, "users": [], "tutors": [], "size": 2,
                                              "description": data['group_description']})
        except:
            error = 'User returned an invalid form.'

        return self.page(course, error, True)
Beispiel #13
0
    def POST(self, courseid, taskid):
        """ Edit a task """
        if not id_checker(taskid) or not id_checker(courseid):
            raise Exception("Invalid course/task id")

        course, _ = get_course_and_check_rights(courseid, allow_all_staff=False)

        # Parse content
        try:
            data = web.input(task_file={})

            try:
                task_zip = data.get("task_file").file
            except:
                task_zip = None
            del data["task_file"]

            problems = self.dict_from_prefix("problem", data)
            limits = self.dict_from_prefix("limits", data)

            data = {key: val for key, val in data.iteritems() if not key.startswith("problem") and not key.startswith("limits")}
            del data["@action"]

            try:
                file_manager = get_available_task_file_managers()[data["@filetype"]](courseid, taskid)
            except Exception as inst:
                return json.dumps({"status": "error", "message": "Invalid file type: {}".format(str(inst))})
            del data["@filetype"]

            if problems is None:
                return json.dumps({"status": "error", "message": "You cannot create a task without subproblems"})

            # Order the problems (this line also deletes @order from the result)
            data["problems"] = OrderedDict([(key, self.parse_problem(val))
                                            for key, val in sorted(problems.iteritems(), key=lambda x: int(x[1]['@order']))])
            data["limits"] = limits
            if "hard_time" in data["limits"] and data["limits"]["hard_time"] == "":
                del data["limits"]["hard_time"]

            # Weight
            try:
                data["weight"] = float(data["weight"])
            except:
                return json.dumps({"status": "error", "message": "Grade weight must be a floating-point number"})

            # Accessible
            if data["accessible"] == "custom":
                data["accessible"] = "{}/{}".format(data["accessible_start"], data["accessible_end"])
            elif data["accessible"] == "true":
                data["accessible"] = True
            else:
                data["accessible"] = False
            del data["accessible_start"]
            del data["accessible_end"]

            # Checkboxes
            if data.get("responseIsHTML"):
                data["responseIsHTML"] = True
            if data.get("contextIsHTML"):
                data["contextIsHTML"] = True
        except Exception as message:
            return json.dumps({"status": "error", "message": "Your browser returned an invalid form ({})".format(str(message))})

        # Get the course
        try:
            course = FrontendCourse(courseid)
        except:
            return json.dumps({"status": "error", "message": "Error while reading course's informations"})

        # Get original data
        try:
            orig_data = get_task_file_manager(courseid, taskid).read()
            data["order"] = orig_data["order"]
        except:
            pass

        try:
            FrontendTask(course, taskid, data)
        except Exception as message:
            return json.dumps({"status": "error", "message": "Invalid data: {}".format(str(message))})

        if not os.path.exists(os.path.join(get_tasks_directory(), courseid, taskid)):
            os.mkdir(os.path.join(get_tasks_directory(), courseid, taskid))

        if task_zip:
            try:
                zipfile = ZipFile(task_zip)
            except Exception as message:
                return json.dumps({"status": "error", "message": "Cannot read zip file. Files were not modified"})

            try:
                zipfile.extractall(os.path.join(get_tasks_directory(), courseid, taskid))
            except Exception as message:
                return json.dumps(
                    {"status": "error", "message": "There was a problem while extracting the zip archive. Some files may have been modified"})

        delete_all_possible_task_files(courseid, taskid)
        file_manager.write(data)

        return json.dumps({"status": "ok"})
Beispiel #14
0
 def GET(self, courseid):
     """ GET request """
     course, _ = get_course_and_check_rights(courseid, allow_all_staff=False)
     return self.page(course)
Beispiel #15
0
    def POST(self, courseid):
        """ POST request """
        course, _ = get_course_and_check_rights(courseid, allow_all_staff=False)

        errors = []
        course_content = {}
        try:
            data = web.input()
            course_content = course.get_course_descriptor_content(courseid)
            course_content['name'] = data['name']
            if course_content['name'] == "":
                errors.append('Invalid name')
            course_content['admins'] = data['admins'].split(',')
            if User.get_username() not in course_content['admins']:
                errors.append('You cannot remove yourself from the administrators of this course')
            course_content['tutors'] = data['tutors'].split(',')
            if len(course_content['tutors']) == 1 and course_content['tutors'][0].strip() == "":
                course_content['tutors'] = []

            if data["groups"] == "true":
                course_content['groups'] = True
            else:
                course_content['groups'] = False

            if data["groups_student_choice"] == "true":
                course_content['groups_student_choice'] = True
            else:
                course_content['groups_student_choice'] = False

            if data["accessible"] == "custom":
                course_content['accessible'] = "{}/{}".format(data["accessible_start"], data["accessible_end"])
            elif data["accessible"] == "true":
                course_content['accessible'] = True
            else:
                course_content['accessible'] = False

            try:
                AccessibleTime(course_content['accessible'])
            except:
                errors.append('Invalid accessibility dates')

            if data["registration"] == "custom":
                course_content['registration'] = "{}/{}".format(data["registration_start"], data["registration_end"])
            elif data["registration"] == "true":
                course_content['registration'] = True
            else:
                course_content['registration'] = False

            try:
                AccessibleTime(course_content['registration'])
            except:
                errors.append('Invalid registration dates')

            course_content['registration_password'] = data['registration_password']
            if course_content['registration_password'] == "":
                course_content['registration_password'] = None

            course_content['registration_ac'] = data['registration_ac']
            if course_content['registration_ac'] not in ["None", "username", "realname", "email"]:
                errors.append('Invalid ACL value')
            if course_content['registration_ac'] == "None":
                course_content['registration_ac'] = None
            course_content['registration_ac_list'] = data['registration_ac_list'].split("\n")
        except:
            errors.append('User returned an invalid form.')

        if len(errors) == 0:
            course.update_course_descriptor_content(courseid, course_content)
            errors = None
            course, _ = get_course_and_check_rights(courseid, allow_all_staff=False)  # don't forget to reload the modified course

        return self.page(course, errors, errors is None)
Beispiel #16
0
 def GET(self, courseid):
     """ GET request """
     course, _ = get_course_and_check_rights(courseid)
     return self.page(course)
 def GET(self, courseid, username, taskid, submissionid):
     """ GET request """
     course, task = get_course_and_check_rights(courseid, taskid)
     return self.page(course, username, task, submissionid)
Beispiel #18
0
 def GET(self, courseid):
     """ GET request: simply display the form """
     course, _ = get_course_and_check_rights(courseid, allow_all_staff=False)
     contest_data = get_contest_data(course)
     return get_template_renderer('plugins/contests', '../../templates/layout').admin(course, contest_data, None, False)