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)
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)
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())
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)
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()
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
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
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))
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)
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)
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()
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)
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"})
def GET(self, courseid): """ GET request """ course, _ = get_course_and_check_rights(courseid, allow_all_staff=False) return self.page(course)
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)
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)
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)