def get(self): """GET method is called when the page with the questionnaire loads.""" key = self.request.get('key') if not self.assert_xsrf_token_or_fail( self.request, QUESTIONNAIRE_XSRF_TOKEN_NAME, {}): return user = self.get_user() if user is None: return student = models.Student.get_enrolled_student_by_user(user) if student is None: return entity = StudentFormEntity.load_or_default(student, key) if entity.value is None: return form_dict = transforms.loads(entity.value) transforms.send_json_response( self, 200, None, payload_dict=transforms.dict_to_json(form_dict))
def get(self): """Respond to the REST GET verb with the contents of the item.""" key = self.request.get('key') if not roles.Roles.is_course_admin(self.app_context): transforms.send_json_response( self, 401, 'Access denied.', {'key': key}) return if key: item = self.DAO.load(key) if item is None: transforms.send_json_response( self, 404, 'Not found.', {'key': key}) return version = item.dict.get('version') if version not in self.SCHEMA_VERSIONS: transforms.send_json_response( self, 400, 'Version %s not supported.' % version, {'key': key}) return display_dict = copy.copy(item.dict) display_dict['id'] = item.id common_utils.run_hooks(self.PRE_LOAD_HOOKS, item, display_dict) payload_dict = self.transform_for_editor_hook(display_dict) elif self.CAN_CREATE: payload_dict = self.get_default_content() else: transforms.send_json_response( self, 404, 'Key is required in URL.', {}) return transforms.send_json_response( self, 200, 'Success', payload_dict=payload_dict, xsrf_token=XsrfTokenManager.create_xsrf_token(self.XSRF_TOKEN))
def get(self): """Provides empty initial content for asset upload editor.""" # TODO(jorr): Pass base URI through as request param when generalized. json_payload = {'file': '', 'base': ALLOWED_ASSET_UPLOAD_BASE} transforms.send_json_response( self, 200, 'Success.', payload_dict=json_payload, xsrf_token=XsrfTokenManager.create_xsrf_token('asset-upload'))
def get(self): key = self.request.get('key') if not key: self.abort(404) # check availability item = drive_models.DriveSyncDAO.load(key) if item is None or not self.check_availability(item.availability): self.abort(404) # find the synced content chunk = models.ContentChunkDAO.get_one_by_uid( models.ContentChunkDAO.make_uid(item.type, key)) if chunk is None: self.abort(404) self.response.headers['Last-Modified'] = str(item.last_synced) # TODO(nretallack): implement if-modified-since check here if chunk.content_type == 'application/json': transforms.send_json_response( self, 200, 'ok', payload_dict=json.loads(chunk.contents)) else: self.response.headers['Content-Type'] = str(chunk.content_type) self.response.write(chunk.contents)
def get(self): """Get the data to populate the question editor form.""" key = self.request.get('key') if not CourseOutlineRights.can_view(self): transforms.send_json_response( self, 401, 'Access denied.', {'key': key}) return if key: question = QuestionDAO.load(key) payload_dict = question.dict else: payload_dict = { 'version': self.SCHEMA_VERSION, 'question': '', 'description': '', 'graders': [ { 'score': '1.0', 'matcher': 'case_insensitive', 'response': '', 'feedback': ''}]} transforms.send_json_response( self, 200, 'Success', payload_dict=payload_dict, xsrf_token=XsrfTokenManager.create_xsrf_token(self.XSRF_TOKEN))
def assert_xsrf_token_or_fail(self, token_dict, action, args_dict): """Asserts that current request has proper XSRF token or fails.""" token = token_dict.get("xsrf_token") if not token or not XsrfTokenManager.is_xsrf_token_valid(token, action): transforms.send_json_response(self, 403, "Bad XSRF token. Please reload the page and try again", args_dict) return False return True
def post(self): # Receive a payload of the form: # { # "location": url_for_rest_handler, # "key": the key of the object being edited, # "state": object_holding_editor_state # } request = transforms.loads(self.request.get('request')) if not self.assert_xsrf_token_or_fail(request, self.XSRF_TOKEN, {}): return user = self.get_user() if user is None: self.error(401) return if not roles.Roles.is_course_admin(self.app_context): transforms.send_json_response(self, 401, 'Access denied.', {}) return payload = transforms.loads(request.get('payload')) key_name = EditorPrefsDao.create_key_name( user.user_id(), payload['location'], payload['key']) editor_prefs = EditorPrefsDto(key_name, payload['state']) EditorPrefsDao.save(editor_prefs) transforms.send_json_response(self, 200, 'Saved.', payload_dict={})
def get(self): """Handles REST GET verb and returns an object as JSON payload.""" key = self.request.get('key') if not ConfigPropertyRights.can_view(): transforms.send_json_response( self, 401, 'Access denied.', {'key': key}) return item = None if key and key in config.Registry.registered.keys(): item = config.Registry.registered[key] if not item: self.redirect('/admin?action=settings') try: entity = config.ConfigPropertyEntity.get_by_key_name(key) except db.BadKeyError: entity = None entity_dict = {'name': key, 'label': item.label} if entity and not entity.is_draft: entity_dict['value'] = transforms.string_to_value( entity.value, item.value_type) else: entity_dict['value'] = item.default_value json_payload = transforms.dict_to_json(entity_dict) transforms.send_json_response( self, 200, 'Success.', payload_dict=json_payload, xsrf_token=crypto.XsrfTokenManager.create_xsrf_token( 'config-property-put'))
def validation_error(self, message, key=None): """Deliver a validation message.""" if key: transforms.send_json_response( self, 412, message, payload_dict={'key': key}) else: transforms.send_json_response(self, 412, message)
def put(self): """A PUT REST method shared by all unit types.""" request = transforms.loads(self.request.get('request')) key = request.get('key') if not self.assert_xsrf_token_or_fail( request, 'put-unit', {'key': key}): return if not CourseOutlineRights.can_edit(self): transforms.send_json_response( self, 401, 'Access denied.', {'key': key}) return unit = courses.Course(self).find_unit_by_id(key) if not unit: transforms.send_json_response( self, 404, 'Object not found.', {'key': key}) return payload = request.get('payload') errors = [] try: updated_unit_dict = transforms.json_to_dict( transforms.loads(payload), self.SCHEMA_DICT) self.apply_updates(unit, updated_unit_dict, errors) except (TypeError, ValueError), ex: errors.append(str(ex))
def put(self): """Store a question group in the datastore in response to a PUT.""" request = transforms.loads(self.request.get('request')) key = request.get('key') if not self.assert_xsrf_token_or_fail( request, self.XSRF_TOKEN, {'key': key}): return if not CourseOutlineRights.can_edit(self): transforms.send_json_response( self, 401, 'Access denied.', {'key': key}) return payload = request.get('payload') question_group_dict = transforms.json_to_dict( transforms.loads(payload), self.get_schema().get_json_schema_dict()) validation_errors = self.validate(question_group_dict, key) if validation_errors: self.validation_error('\n'.join(validation_errors), key=key) return assert self.SCHEMA_VERSION == question_group_dict.get('version') if key: question_group = QuestionGroupDTO(key, question_group_dict) else: question_group = QuestionGroupDTO(None, question_group_dict) key_after_save = QuestionGroupDAO.save(question_group) transforms.send_json_response( self, 200, 'Saved.', payload_dict={'key': key_after_save})
def get(self): """Get a students progress.""" #teachers aren't course admins, so we probably shouldn't check for that # if not roles.Roles.is_course_admin(self.app_context): # transforms.send_json_response(self, 401, 'Access denied.', {}) # return key = self.request.get('student') errors = [] student = Student.get_by_email(key.strip()) course = self.get_course() if student: units = teacher_parsers.StudentProgressTracker.get_detailed_progress(student, course) else: errors.append('An error occurred retrieving student data. Contact your course administrator.') self.validation_error('\n'.join(errors)) return payload_dict = { 'units': units, 'student_name': student.name, 'student_email': student.email } transforms.send_json_response( self, 200, '', payload_dict=payload_dict, xsrf_token=crypto.XsrfTokenManager.create_xsrf_token( self.XSRF_TOKEN))
def get(self): """Handles REST GET verb and returns an object as JSON payload.""" if not CourseOutlineRights.can_view(self): transforms.send_json_response(self, 401, "Access denied.", {}) return course = courses.Course(self) outline_data = [] for unit in course.get_units(): lesson_data = [] for lesson in course.get_lessons(unit.unit_id): lesson_data.append({"title": lesson.title, "id": lesson.lesson_id}) unit_title = unit.title if verify.UNIT_TYPE_UNIT == unit.type: unit_title = "Unit %s - %s" % (unit.index, unit.title) outline_data.append({"title": unit_title, "id": unit.unit_id, "lessons": lesson_data}) transforms.send_json_response( self, 200, "Success.", payload_dict={"outline": outline_data}, xsrf_token=XsrfTokenManager.create_xsrf_token("unit-lesson-reorder"), )
def put(self): """Store a question in the datastore in response to a PUT.""" request = transforms.loads(self.request.get('request')) key = request.get('key') if not self.assert_xsrf_token_or_fail( request, self.XSRF_TOKEN, {'key': key}): return if not CourseOutlineRights.can_edit(self): transforms.send_json_response( self, 401, 'Access denied.', {'key': key}) return payload = request.get('payload') question_dict = transforms.loads(payload) question_dict['description'] = question_dict['description'].strip() question_dict, errors = self.import_and_validate(question_dict, key) if errors: self.validation_error('\n'.join(errors), key=key) return if key: question = QuestionDTO(key, question_dict) else: question = QuestionDTO(None, question_dict) question.type = self.TYPE key_after_save = QuestionDAO.save(question) transforms.send_json_response( self, 200, 'Saved.', payload_dict={'key': key_after_save})
def put(self): """A PUT REST method shared by all unit types.""" request = transforms.loads(self.request.get("request")) key = request.get("key") if not self.assert_xsrf_token_or_fail(request, "put-unit", {"key": key}): return if not self.can_edit(self.app_context): transforms.send_json_response(self, 401, "Access denied.", {"key": key}) return unit = courses.Course(self).find_unit_by_id(key) if not unit: transforms.send_json_response(self, 404, "Object not found.", {"key": key}) return payload = request.get("payload") errors = [] course = courses.Course(self) try: schema = self.get_schema(course, key) updated_unit_dict = transforms.json_to_dict(transforms.loads(payload), schema.get_json_schema_dict()) schema.redact_entity_to_schema(updated_unit_dict) self.apply_updates(unit, updated_unit_dict, errors) except (TypeError, ValueError), ex: errors.append(str(ex))
def get(self): """Get activity scores.""" request = transforms.loads(self.request.get('request')) payload = transforms.loads(request.get('payload')) errors = [] students = payload['students'] force_refresh = payload['forceRefresh'] course = self.get_course() temp_students = [] for student in students: if '@' in student: temp_students.append(Student.get_by_email(student).user_id) if len(temp_students) > 0: students = temp_students if len(students) > 0: scores = teacher_parsers.ActivityScoreParser.get_activity_scores(students, course, force_refresh) else: errors.append('An error occurred retrieving activity scores. Contact your course administrator.') self.validation_error('\n'.join(errors)) return payload_dict = { 'scores': scores['scores'], 'dateCached': scores['date'].strftime("%B %d, %Y %H:%M:%S") } transforms.send_json_response( self, 200, '', payload_dict=payload_dict, xsrf_token=crypto.XsrfTokenManager.create_xsrf_token( self.XSRF_TOKEN))
def get(self): """Provides empty initial content for asset upload editor.""" # TODO(jorr): Pass base URI through as request param when generalized. key = self.request.get('key') base = asset_paths.AllowedBases.match_allowed_bases(key) if not base: transforms.send_json_response( self, 400, 'Malformed request.', {'key': key}) return json_payload = { 'key': key, 'base': base, } fs = self.app_context.fs.impl if fs.isfile(fs.physical_to_logical(key)): json_payload['asset_url'] = key # TODO(davyrisso): Remove when cached assets issues are solved. # We add a random seed to the URL to force a reload, we also append # the URL because oeditor expects it to end with the filename. suffix = ('?seed=%s&url=%s' % ( str(random.randint(0, 100000)), json_payload['asset_url'])) json_payload['asset_url'] += suffix else: json_payload['asset_url'] = asset_paths.relative_base(base) transforms.send_json_response( self, 200, 'Success.', payload_dict=json_payload, xsrf_token=XsrfTokenManager.create_xsrf_token(self.XSRF_TOKEN_NAME))
def delete(self): """Handles REST DELETE verb.""" request = transforms.loads(self.request.get('request')) key = request.get('key') transforms.send_json_response( self, 401, 'Access denied.', {'key': key})
def get(self): """Handles REST GET verb and returns an object as JSON payload.""" if not CourseOutlineRights.can_view(self): transforms.send_json_response(self, 401, 'Access denied.', {}) return course = courses.Course(self) outline_data = [] for unit in course.get_units(): lesson_data = [] for lesson in course.get_lessons(unit.unit_id): lesson_data.append({ 'title': lesson.title, 'id': lesson.lesson_id}) unit_title = unit.title if verify.UNIT_TYPE_UNIT == unit.type: unit_title = 'Unit %s - %s' % (unit.index, unit.title) outline_data.append({ 'title': unit_title, 'id': unit.unit_id, 'lessons': lesson_data}) transforms.send_json_response( self, 200, None, payload_dict={'outline': outline_data}, xsrf_token=XsrfTokenManager.create_xsrf_token( 'unit-lesson-reorder'))
def put(self): """Handles REST PUT verb with JSON payload.""" request = transforms.loads(self.request.get('request')) key = request.get('key') edit_mode = request.get('mode') if GLOBAL_DEBUG: logging.warning('***RAM*** put request = ' + str(request)) if not self.assert_xsrf_token_or_fail( request, 'teacher-put', {'key': key}): return if not TeacherRights.can_edit(self): transforms.send_json_response( self, 401, 'MobileCSP: Admin access denied.', {'key': key}) return entity = TeacherEntity.get(key) if not entity: transforms.send_json_response( self, 404, 'MobileCSP: Teacher Entity not found.', {'key': key}) return schema = TeacherItemRESTHandler.SCHEMA() payload = request.get('payload') update_dict = transforms.json_to_dict( transforms.loads(payload), schema.get_json_schema_dict()) # Get the teacher's user_id user = Student.get_first_by_email(update_dict['email'])[0] # returns a tuple if not user: transforms.send_json_response( self, 404, 'MobileCSP: No registered user found for ' + update_dict['email'], {'key': key}) return # Check that the teacher isn't already registered if update_dict['mode'] == 'Add': teachers = TeacherEntity.get_teachers() for teacher in teachers: if teacher.email == update_dict['email']: transforms.send_json_response( self, 404, 'MobileCSP: User is already registered as a teacher ' + update_dict['email'], {'key': key}) return if GLOBAL_DEBUG: logging.debug('****RAM**** teacher id ' + str(user.user_id)) # Store the user_id update_dict['user_id'] = user.user_id transforms.dict_to_entity(entity, update_dict) entity.put() transforms.send_json_response(self, 200, 'Saved.')
def post(self): name = COURSE_EXPLORER_SETTINGS.name request = transforms.loads(self.request.get('request')) if not self.assert_xsrf_token_or_fail( request, self.ACTION, {}): return if not roles.Roles.is_course_admin(self.app_context): transforms.send_json_response( self, 401, 'Access denied.', {}) return raw_data = transforms.loads(request.get('payload')) raw_data.pop('logo', None) try: data = transforms.json_to_dict( raw_data, schema_provider(None).get_json_schema_dict()) except (TypeError, ValueError) as err: self.validation_error(err.replace('\n', ' ')) return logo = self.request.POST.get('logo') logo_uploaded = isinstance(logo, cgi.FieldStorage) if logo_uploaded: data['logo_bytes_base64'] = base64.b64encode(logo.file.read()) data['logo_mime_type'] = logo.type with common_utils.Namespace(appengine_config.DEFAULT_NAMESPACE_NAME): entity = config.ConfigPropertyEntity.get_by_key_name(name) if entity is None: entity = config.ConfigPropertyEntity(key_name=name) old_value = None else: old_value = entity.value # Don't delete the logo. if not logo_uploaded and old_value: old_dict = transforms.loads(old_value) if ( 'logo_bytes_base64' in old_dict and 'logo_mime_type' in old_dict): data['logo_bytes_base64'] = old_dict['logo_bytes_base64'] data['logo_mime_type'] = old_dict['logo_mime_type'] entity.value = transforms.dumps(data) entity.is_draft = False entity.put() # is this necessary? models.EventEntity.record( 'put-property', users.get_current_user(), transforms.dumps({ 'name': name, 'before': str(old_value), 'after': str(entity.value)})) transforms.send_file_upload_response(self, 200, 'Saved.')
def put(self): course, settings, payload, response_payload = _authorize_put(self) if not course: return course_availability = payload.get('course_availability') if course_availability: course.set_course_availability(course_availability) transforms.send_json_response( self, 200, 'Saved.', payload_dict=response_payload)
def post(self): success, key, student, unit, progress = self._perform_checks() if success: if not unit.manual_progress: success = False transforms.send_json_response( self, 401, 'Access Denied.', {'key': key}) else: progress.force_unit_completed(student, unit.unit_id) self._send_success_response(key, student, unit, progress)
def get(self): """Handles REST GET verb and returns an object as JSON payload.""" if not CourseOutlineRights.can_view(self): transforms.send_json_response(self, 401, 'Access denied.', {}) return transforms.send_json_response( self, 200, 'Success.', payload_dict={'course': None}, xsrf_token=XsrfTokenManager.create_xsrf_token( 'unit-lesson-reorder'))
def get(self): payload, student = self._get_payload_and_student() if payload is None and student is None: return key = payload.get("key") prop = StudentRatingProperty.load_or_default(student) rating = prop.get_rating(key) payload_dict = {"key": key, "rating": rating} transforms.send_json_response(self, 200, None, payload_dict=payload_dict)
def put(self): course, settings, payload, response_payload = _authorize_put(self) if not course: return triggers.MilestoneTrigger.payload_into_settings( payload, course, settings, semantics=triggers.DateTimeTrigger.SET_WILL_MERGE) course.save_settings(settings) transforms.send_json_response( self, 200, 'Saved.', payload_dict=response_payload)
def get(self): if not roles.Roles.is_user_allowed( self.app_context, custom_module, constants.MODIFY_AVAILABILITY_PERMISSION): transforms.send_json_response(self, 401, 'Access denied.') return entity = self.construct_entity(self.get_course()) transforms.send_json_response( self, 200, 'OK.', payload_dict=entity, xsrf_token=crypto.XsrfTokenManager.create_xsrf_token(self.ACTION))
def get(self): finished_jobs = [ name for name in self.request.get_all('visualization') if self._is_finished(name) ] result = { "finished": finished_jobs, } transforms.send_json_response(self, 200, "Success.", result)
def post(self): success, key, student, lesson, _progress = self._perform_checks() if success: if not lesson.manual_progress: success = False transforms.send_json_response( self, 401, 'Access Denied.', {'key': key}) else: _progress.put_html_completed( student, lesson.unit_id, lesson.lesson_id) self._send_success_response(key, student, lesson, _progress)
def put(self): course, settings, payload, response_payload = _authorize_put(self) if not course: return milestone = payload.get('milestone') triggers.MilestoneTrigger.clear_from_settings( settings, milestone=milestone, course=course) course.save_settings(settings) transforms.send_json_response( self, 200, 'Saved.', payload_dict=response_payload)
def put(self): request = transforms.loads(self.request.get('request')) key = request.get('key') if not self.assert_xsrf_token_or_fail(request, self.XSRF_TOKEN, {}): return if not roles.Roles.is_course_admin(self.app_context): transforms.send_json_response(self, 401, 'Access denied.', {'key': key}) return payload = request.get('payload') json_dict = transforms.loads(payload) python_dict = transforms.json_to_dict( json_dict, self.get_schema().get_json_schema_dict(), permit_none_values=True) version = python_dict.get('version') if version not in self.SCHEMA_VERSIONS: self.validation_error('Version %s not supported.' % version) return errors = [] if key: key_after_save = SkillGraph.load().update(key, python_dict, errors) else: skill = Skill.build(python_dict.get('name'), python_dict.get('description'), python_dict.get('prerequisites')) key_after_save = SkillGraph.load().add(skill, errors=errors).id if errors: self.validation_error('\n'.join(errors), key=key) return transforms.send_json_response(self, 200, 'Saved.', payload_dict={'key': key_after_save})
def classmethod_put(cls, handler): """Expose as function for convenience in wrapping this hander.""" course, env, payload, response_payload = _authorize_put(handler) if not course: return # Date/Time triggers: # unit and lesson availability, course-wide availability triggers.MilestoneTrigger.payload_into_settings(payload, course, env) triggers.ContentTrigger.payload_into_settings(payload, course, env) # Course-level settings: user whitelist course.set_whitelist_into_environ(payload.get('whitelist'), env) # Course-level changes: # course-wide availability (available/browsable/registerable) course.set_course_availability_into_environ( payload.get('course_availability'), env) course.save_settings(env) # Unit and lesson availability, visibility from syllabus list for item in payload.get(cls.ELEMENT_SETTINGS, []): if item['type'] == 'unit': element = course.find_unit_by_id(item['id']) elif item['type'] == 'lesson': element = course.find_lesson_by_id(None, item['id']) else: tct = triggers.ContentTrigger raise ValueError( tct.UNEXPECTED_CONTENT_FMT.format( item['type'], tct.ALLOWED_CONTENT_TYPES)) if element: if cls.AVAILABILITY_FIELD in item: element.availability = item[cls.AVAILABILITY_FIELD] if 'shown_when_unavailable' in item: element.shown_when_unavailable = ( item['shown_when_unavailable']) course.save() transforms.send_json_response( handler, 200, 'Saved.', payload_dict=response_payload)
def process_put(self, request, payload): errors = [] request_data = {} schema = self.get_course().create_settings_schema() schema.convert_json_to_entity(payload, request_data) schema.validate(request_data, errors) if errors: transforms.send_json_response( self, 400, 'Invalid data: \n' + '\n'.join(errors)) return if 'extra_locales' in request_data: default_locale = ( request_data.get('course', {}).get('locale') or self.app_context.default_locale) self._process_extra_locales( default_locale, request_data['extra_locales']) return request_data
def delete(self): """Handles REST DELETE verb with JSON payload.""" key = self.request.get('key') if not self.assert_xsrf_token_or_fail(self.request, self.XSRF_ACTION, {'key': key}): return if (not permissions.can_edit(self.app_context, constants.SCOPE_COURSE_SETTINGS) or not self.is_deletion_allowed()): transforms.send_json_response(self, 401, 'Access denied.', {'key': key}) return entity = self.process_delete() if self.get_course().save_settings(entity): transforms.send_json_response(self, 200, 'Deleted.')
def put(self): """Handles REST PUT verb with JSON payload.""" request = transforms.loads(self.request.get('request')) if not self.assert_xsrf_token_or_fail(request, 'unit-lesson-reorder', {'key': None}): return if not CourseOutlineRights.can_edit(self): transforms.send_json_response(self, 401, 'Access denied.', {}) return payload = request.get('payload') payload_dict = transforms.json_to_dict(transforms.loads(payload), self.SCHEMA_DICT) course = courses.Course(self) course.reorder_units(payload_dict['outline']) course.save() transforms.send_json_response(self, 200, 'Saved.')
def get(self): generator_classes = set() for visualization_name in self.request.get_all('visualization'): visualization = Visualization.for_name(visualization_name) generator_classes.update(visualization.generator_classes) generator_status = {} for generator_class in generator_classes: job = generator_class(self.app_context).load() generator_status[generator_class] = job and job.has_finished finished_visualizations = set() finished_sources = set() finished_generators = set() all_visualizations_finished = True for visualization_name in self.request.get_all('visualization'): all_sources_finished = True visualization = Visualization.for_name(visualization_name) for data_source_class in visualization.data_source_classes: all_generators_finished = True for generator_class in data_source_class.required_generators(): all_generators_finished &= generator_status[generator_class] all_sources_finished &= all_generators_finished if all_generators_finished: if issubclass(data_source_class, data_sources.AbstractRestDataSource): finished_sources.add(data_source_class.get_name()) else: finished_sources.add(data_source_class.__name__) all_visualizations_finished &= all_sources_finished if all_sources_finished: finished_visualizations.add(visualization_name) result = { 'finished_visualizations': finished_visualizations, 'finished_sources': finished_sources, 'finished_generators': finished_generators, 'finished_all': all_visualizations_finished, } transforms.send_json_response(self, 200, "Success.", result)
def put(self): """Store a QuestionGroupDTO and QuestionDTO in the datastore.""" request = transforms.loads(self.request.get('request')) if not self.assert_xsrf_token_or_fail(request, self.XSRF_TOKEN, {'key': None}): return if not roles.Roles.is_course_admin(self.app_context): transforms.send_json_response(self, 401, 'Access denied.') return payload = request.get('payload') json_dict = transforms.loads(payload) errors = [] try: python_dict = transforms.json_to_dict( json_dict, self.get_schema().get_json_schema_dict()) questions = gift.GiftParser.parse_questions( python_dict['questions']) self.validate_question_descriptions(questions, errors) self.validate_group_description(python_dict['description'], errors) if not errors: dtos = self.convert_to_dtos(questions) question_ids = models.QuestionDAO.save_all(dtos) self.create_group(python_dict['description'], question_ids) except ValueError as e: errors.append(str(e)) except gift.ParseError as e: errors.append(str(e)) except models.CollisionError as e: errors.append(str(e)) if errors: self.validation_error('\n'.join(errors)) return msg = 'Saved: %s.' % python_dict['description'] transforms.send_json_response(self, 200, msg) return
def get(self): """Handles GET REST verb and returns lesson object as JSON payload.""" if not CourseOutlineRights.can_view(self): transforms.send_json_response(self, 401, 'Access denied.', {}) return key = self.request.get('key') course = courses.Course(self) lesson = course.find_lesson_by_id(None, key) assert lesson payload_dict = self.get_lesson_dict(course, lesson) message = ['Success.'] if self.request.get('is_newly_created'): message.append('New lesson has been created and saved.') transforms.send_json_response( self, 200, '\n'.join(message), payload_dict=payload_dict, xsrf_token=XsrfTokenManager.create_xsrf_token('lesson-edit'))
def _authorize_put(handler): """Common function for handlers. Verifies user, gets common settings.""" request = transforms.loads(handler.request.get('request')) response_payload = { 'key': handler.app_context.get_namespace_name(), } if not handler.assert_xsrf_token_or_fail(request, handler.ACTION, response_payload): return None, None, None, None if not roles.Roles.is_user_allowed( handler.app_context, custom_module, constants.MODIFY_AVAILABILITY_PERMISSION): transforms.send_json_response(handler, 401, 'Access denied.', payload_dict=response_payload) return None, None, None, None course = handler.get_course() settings = handler.app_context.get_environ() payload = transforms.loads(request.get('payload', '{}')) return course, settings, payload, response_payload
def delete(self): """Deletes an announcement.""" key = self.request.get('key') if not self.assert_xsrf_token_or_fail( self.request, 'announcement-delete', {'key': key}): return if not AnnouncementsRights.can_delete(self): self.error(401) return entity = AnnouncementEntity.get(key) if not entity: transforms.send_json_response( self, 404, 'Object not found.', {'key': key}) return entity.delete() transforms.send_json_response(self, 200, 'Deleted.')
def put(self): """Handles the put verb.""" assert self.app_context.is_editable_fs() request = self.request.get('request') assert request request = transforms.loads(request) payload = transforms.loads(request.get('payload')) filename = request.get('key') if not (filename and self.assert_xsrf_token_or_fail( request, self.XSRF_TOKEN_NAME, {'key': filename})): return if not FilesRights.can_edit(self): transforms.send_json_response(self, 401, 'Access denied.', {'key': filename}) return if not _is_asset_in_allowed_bases(filename): transforms.send_json_response(self, 400, 'Malformed request.', {'key': filename}) return self.app_context.fs.impl.put( os.path.join(appengine_config.BUNDLE_ROOT, filename), vfs.string_to_stream(unicode(payload.get('contents')))) transforms.send_json_response(self, 200, 'Saved.')
def get(self): """Respond to the REST GET verb with the contents of the group.""" key = self.request.get('key') if not CourseOutlineRights.can_view(self): transforms.send_json_response( self, 401, 'Access denied.', {'key': key}) return if key: question_group = QuestionGroupDAO.load(key) version = question_group.dict.get('version') if self.SCHEMA_VERSION != version: transforms.send_json_response( self, 403, 'Cannot edit a Version %s group.' % version, {'key': key}) return payload_dict = question_group.dict else: payload_dict = { 'version': self.SCHEMA_VERSION, 'items': [{'weight': ''}, {'weight': ''}, {'weight': ''}]} transforms.send_json_response( self, 200, 'Success', payload_dict=payload_dict, xsrf_token=XsrfTokenManager.create_xsrf_token(self.XSRF_TOKEN))
def put(self): """Handles REST PUT verb with JSON payload.""" request = json.loads(self.request.get('request')) key = request.get('key') if not self.assert_xsrf_token_or_fail(request, 'announcement-put', {'key': key}): return if not AnnouncementsRights.can_edit(self): transforms.send_json_response(self, 401, 'Access denied.', {'key': key}) return entity = AnnouncementEntity.get(key) if not entity: transforms.send_json_response(self, 404, 'Object not found.', {'key': key}) return payload = request.get('payload') transforms.dict_to_entity( entity, transforms.json_to_dict(json.loads(payload), SCHEMA_DICT)) entity.put() transforms.send_json_response(self, 200, 'Saved.')
def get(self): """A GET REST method shared by all unit types.""" key = self.request.get('key') if not roles.Roles.is_course_admin(self.app_context): transforms.send_json_response(self, 401, 'Access denied.', {'key': key}) return course = courses.Course(self) unit = course.find_unit_by_id(key) if not unit: transforms.send_json_response(self, 404, 'Object not found.', {'key': key}) return message = ['Success.'] if self.request.get('is_newly_created'): message.append('New %s has been created and saved.' % self.NAME) transforms.send_json_response( self, 200, '\n'.join(message), payload_dict=self.unit_to_dict(course, unit), xsrf_token=XsrfTokenManager.create_xsrf_token('put-unit'))
def get(self): """A GET REST method shared by all unit types.""" key = self.request.get('key') if not CourseOutlineRights.can_view(self): transforms.send_json_response(self, 401, 'Access denied.', {'key': key}) return unit = courses.Course(self).find_unit_by_id(key) if not unit: transforms.send_json_response(self, 404, 'Object not found.', {'key': key}) return message = ['Success.'] if self.request.get('is_newly_created'): unit_type = verify.UNIT_TYPE_NAMES[unit.type].lower() message.append('New %s has been created and saved.' % unit_type) transforms.send_json_response( self, 200, '\n'.join(message), payload_dict=self.unit_to_dict(unit), xsrf_token=XsrfTokenManager.create_xsrf_token('put-unit'))
def get(self): """Handles REST GET verb and returns an object as JSON payload.""" assert self.app_context.is_editable_fs() key = self.request.get('key') if not CourseSettingsRights.can_view(self): transforms.send_json_response( self, 401, 'Access denied.', {'key': key}) return # Load data if possible. fs = self.app_context.fs.impl filename = fs.physical_to_logical('/course.yaml') try: stream = fs.get(filename) except: # pylint: disable=bare-except stream = None if not stream: transforms.send_json_response( self, 404, 'Object not found.', {'key': key}) return # Prepare data. json_payload = self.process_get() transforms.send_json_response( self, 200, 'Success.', payload_dict=json_payload, xsrf_token=XsrfTokenManager.create_xsrf_token(self.XSRF_ACTION))
def post(self): """Handles asset uploads.""" assert is_editable_fs(self.app_context) if not FilesRights.can_add(self): transforms.send_json_file_upload_response( self, 401, 'Access denied.') return request = transforms.loads(self.request.get('request')) if not self.assert_xsrf_token_or_fail(request, 'asset-upload', None): return payload = transforms.loads(request['payload']) base = payload['base'] assert base == ALLOWED_ASSET_UPLOAD_BASE upload = self.request.POST['file'] filename = os.path.split(upload.filename)[1] assert filename physical_path = os.path.join(base, filename) fs = self.app_context.fs.impl path = fs.physical_to_logical(physical_path) if fs.isfile(path): transforms.send_json_file_upload_response( self, 403, 'Cannot overwrite existing file.') return content = upload.file.read() upload.file.seek(0) if len(content) > MAX_ASSET_UPLOAD_SIZE_K * 1024: transforms.send_json_response( self, 403, 'Max allowed file upload size is %dK' % MAX_ASSET_UPLOAD_SIZE_K, None) return fs.put(path, upload.file) transforms.send_json_file_upload_response(self, 200, 'Saved.')
def get(self): """Handles REST GET verb and returns an object as JSON payload.""" key = self.request.get('key') try: entity = AnnouncementEntity.get(key) except db.BadKeyError: entity = None if not entity: transforms.send_json_response(self, 404, 'Object not found.', {'key': key}) return viewable = AnnouncementsRights.apply_rights(self, [entity]) if not viewable: transforms.send_json_response(self, 401, 'Access denied.', {'key': key}) return entity = viewable[0] json_payload = transforms.dict_to_json( transforms.entity_to_dict(entity), AnnouncementsItemRESTHandler.SCHEMA_DICT) transforms.send_json_response( self, 200, 'Success.', payload_dict=json_payload, xsrf_token=XsrfTokenManager.create_xsrf_token('announcement-put'))
def put(self): """A PUT REST method shared by all unit types.""" request = transforms.loads(self.request.get('request')) if not self.assert_xsrf_token_or_fail(request, 'add-new-local_chapter', {}): return if not roles.Roles.is_super_admin(): transforms.send_json_response(self, 401, 'Access denied.') return payload = request.get('payload') updated_dict = transforms.json_to_dict(transforms.loads(payload), self.get_schema_dict()) errors = [] bulk_addition = updated_dict['bulk_addition'] reader = csv.reader(StringIO.StringIO(bulk_addition), delimiter=',') for row in reader: if len(row) != 4: errors.append('Invalid row %s' % row[0]) continue updated_dict = {} updated_dict['code'] = row[0] updated_dict['name'] = row[1] updated_dict['city'] = row[2] updated_dict['state'] = row[3] self.apply_updates(updated_dict, errors) if not errors: transforms.send_json_response(self, 200, 'Saved.') else: transforms.send_json_response(self, 412, '\n'.join(errors))
def put(self): """A PUT REST method shared by all unit types.""" request = transforms.loads(self.request.get('request')) if not self.assert_xsrf_token_or_fail( request, 'bulk_score_offline_assignment', {}): return if not roles.Roles.is_super_admin(): transforms.send_json_response(self, 403, 'Access denied.') return payload = request.get('payload') updated_dict = transforms.json_to_dict(transforms.loads(payload), self.get_schema_dict()) errors = [] data = dict() csv_text = updated_dict['csv_text'] reader = csv.reader(StringIO.StringIO(csv_text)) # Filter out empty rows reader = [r for r in reader if ''.join(r).strip()] assignment.OfflineAssignmentHandler.bulk_score(reader, errors) if not errors: transforms.send_json_response(self, 200, 'Saved.') else: transforms.send_json_response(self, 412, '\n'.join(errors))
def get(self): """Handles REST GET verb and returns an object as JSON payload.""" key = self.request.get('key') try: entity = AnnouncementEntity.get(key) except db.BadKeyError: entity = None if not entity: transforms.send_json_response( self, 404, 'Object not found.', {'key': key}) return viewable = AnnouncementsRights.apply_rights(self, [entity]) if not viewable: transforms.send_json_response( self, 401, 'Access denied.', {'key': key}) return entity = viewable[0] schema = AnnouncementsItemRESTHandler.SCHEMA() entity_dict = transforms.entity_to_dict(entity) # Format the internal date object as ISO 8601 datetime, with time # defaulting to 00:00:00 date = entity_dict['date'] date = datetime.datetime(date.year, date.month, date.day) entity_dict['date'] = date json_payload = transforms.dict_to_json(entity_dict) transforms.send_json_response( self, 200, 'Success.', payload_dict=json_payload, xsrf_token=crypto.XsrfTokenManager.create_xsrf_token(self.ACTION))
def get(self): """A GET REST method shared by all unit types.""" key = self.request.get('key') if not self.can_view(self.app_context): transforms.send_json_response(self, 401, 'Access denied.', {'key': key}) return course = courses.Course(self) unit = course.find_unit_by_id(key) if not unit: transforms.send_json_response(self, 404, 'Object not found.', {'key': key}) return message = ['Success.'] if self.request.get('is_newly_created'): unit_type = verify.UNIT_TYPE_NAMES[unit.type].lower() message.append('New %s has been created and saved.' % unit_type) entity = self.unit_to_dict(unit) schema = self.get_schema(course, key) schema.redact_entity_to_schema(entity, only_writable=False) transforms.send_json_response( self, 200, '\n'.join(message), payload_dict=transforms.dict_to_json(entity, recurse=True), xsrf_token=crypto.XsrfTokenManager.create_xsrf_token('put-unit'))
def get(self): """Handles REST GET verb and returns an object as JSON payload.""" key = self.request.get('key') if not ConfigPropertyRights.can_view(): transforms.send_json_response( self, 401, 'Access denied.', {'key': key}) return item = None if key and key in config.Registry.registered.keys(): item = config.Registry.registered[key] if not item: self.redirect('/admin?action=settings') try: entity = config.ConfigPropertyEntity.get_by_key_name(key) except db.BadKeyError: entity = None if not entity: transforms.send_json_response( self, 404, 'Object not found.', {'key': key}) else: entity_dict = {'name': key, 'is_draft': entity.is_draft} entity_dict['value'] = transforms.string_to_value( entity.value, item.value_type) json_payload = transforms.dict_to_json( entity_dict, json.loads(ConfigPropertyEditor.get_schema_json(item))) transforms.send_json_response( self, 200, 'Success.', payload_dict=json_payload, xsrf_token=XsrfTokenManager.create_xsrf_token( 'config-property-put'))
def get(self): """Respond to the REST GET verb with the contents of the item.""" key = self.request.get('key') if not roles.Roles.is_course_admin(self.app_context): transforms.send_json_response(self, 401, 'Access denied.', {'key': key}) return if key: item = self.DAO.load(key) version = item.dict.get('version') if version not in self.SCHEMA_VERSIONS: transforms.send_json_response( self, 403, 'Version %s not supported.' % version, {'key': key}) return display_dict = copy.copy(item.dict) display_dict['id'] = item.id payload_dict = self.transform_for_editor_hook(display_dict) else: payload_dict = self.get_default_content() transforms.send_json_response( self, 200, 'Success', payload_dict=payload_dict, xsrf_token=XsrfTokenManager.create_xsrf_token(self.XSRF_TOKEN))
def put(self): if not courses.COURSES_CAN_USE_GOOGLE_APIS.value: self.error(404) return request = transforms.loads(self.request.get('request', '')) if not self.assert_xsrf_token_or_fail(request, self._XSRF_TOKEN_NAME, {}): return contents = request.get('contents') document_id = request.get('document_id') type_id = request.get('type_id') if not (contents and document_id): transforms.send_json_response( self, 400, 'Save failed; no Google Drive item chosen.') return if not type_id: transforms.send_json_response(self, 400, 'Save failed; type_id not set') return key = None try: key = self._save_content_chunk(contents, type_id, document_id) except Exception, e: # On purpose. pylint: disable=broad-except transforms.send_json_response(self, 500, 'Error when saving: %s' % e) return
def post_set_draft_status(self): """Sets the draft status of a course component. Only works with CourseModel13 courses, but the REST handler is only called with this type of courses. """ key = self.request.get('key') if not CourseOutlineRights.can_edit(self): transforms.send_json_response( self, 401, 'Access denied.', {'key': key}) return course = courses.Course(self) component_type = self.request.get('type') if component_type == 'unit': course_component = course.find_unit_by_id(key) elif component_type == 'lesson': course_component = course.find_lesson_by_id(None, key) else: transforms.send_json_response( self, 401, 'Invalid key.', {'key': key}) return set_draft = self.request.get('set_draft') if set_draft == '1': set_draft = True elif set_draft == '0': set_draft = False else: transforms.send_json_response( self, 401, 'Invalid set_draft value, expected 0 or 1.', {'set_draft': set_draft} ) return course_component.now_available = not set_draft course.save() transforms.send_json_response( self, 200, 'Draft status set to %s.' % ( resources_display.DRAFT_TEXT if set_draft else resources_display.PUBLISHED_TEXT ), { 'is_draft': set_draft } ) return
def delete(self): """Deletes an teacher.""" key = self.request.get('key') if not self.assert_xsrf_token_or_fail(self.request, 'teacher-delete', {'key': key}): return if not TeacherRights.can_delete(self): self.error(401) return entity = TeacherEntity.get(key) if not entity: transforms.send_json_response( self, 404, 'MobileCSP: Teacher Entity not found.', {'key': key}) return entity.delete() transforms.send_json_response(self, 200, 'Deleted.')
def process_put(self, request, payload): request_data = {} HtmlHookRESTHandler.REGISTRY.convert_json_to_entity( payload, request_data) if 'hook_content' not in request_data: transforms.send_json_response( self, 400, 'Payload missing "hook_content" parameter.') return None key = request.get('key') if not key: transforms.send_json_response(self, 400, 'Blank or missing "key" parameter.') return None # Walk from bottom to top of hook element name building up # dict-in-dict until we are at outermost level, which is # the course_dict we will return. course_dict = request_data['hook_content'] for element in reversed( key.split(controllers_utils.HtmlHooks.SEPARATOR)): course_dict = {element: course_dict} return {controllers_utils.HtmlHooks.HTML_HOOKS: course_dict}
def post(self): request = transforms.loads(self.request.get('request')) if not self.assert_xsrf_token_or_fail(request, self.XSRF_TOKEN_NAME, {}): return selected = request['payload']['selected'] if selected not in self.app_context.get_allowed_locales(): transforms.send_json_response(self, 401, 'Bad locale') return prefs = models.StudentPreferencesDAO.load_or_create() if prefs: # Store locale in StudentPreferences for logged-in users prefs.locale = selected models.StudentPreferencesDAO.save(prefs) else: # Store locale in cookie for out-of-session users self.response.set_cookie(GUEST_LOCALE_COOKIE, selected, max_age=GUEST_LOCALE_COOKIE_MAX_AGE_SEC) transforms.send_json_response(self, 200, 'OK')
def get(self): """Handles the get verb.""" assert FilesRights.can_edit(self) filename = self.request.get('key') assert filename asset = self.app_context.fs.impl.get( os.path.join(appengine_config.BUNDLE_ROOT, filename)) assert asset contents = asset.read() is_text = is_text_payload(contents) if not is_text: contents = self.ERROR_MESSAGE_UNEDITABLE json_message = 'Success.' if is_text else self.ERROR_MESSAGE_UNEDITABLE json_payload = { 'contents': contents, 'is_text': is_text, 'readonly': is_readonly_asset(asset), } transforms.send_json_response( self, 200, json_message, payload_dict=json_payload, xsrf_token=XsrfTokenManager.create_xsrf_token(self.XSRF_TOKEN_NAME))