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') updated_unit_dict = transforms.json_to_dict( transforms.loads(payload), self.SCHEMA_DICT) errors = [] self.apply_updates(unit, updated_unit_dict, errors) if not errors: course = courses.Course(self) assert course.update_unit(unit) course.save() common_utils.run_hooks(self.POST_SAVE_HOOKS, unit) transforms.send_json_response(self, 200, 'Saved.') else: transforms.send_json_response(self, 412, '\n'.join(errors))
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 common_utils.run_hooks(self.PRE_LOAD_HOOKS, item, display_dict) 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): """Handles PUT REST verb to save lesson and associated activity.""" request = transforms.loads(self.request.get('request')) key = request.get('key') if not self.assert_xsrf_token_or_fail(request, 'lesson-edit', {'key': key}): return 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) lesson = course.find_lesson_by_id(None, key) if not lesson: transforms.send_json_response(self, 404, 'Object not found.', {'key': key}) return payload = request.get('payload') updates_dict = transforms.json_to_dict( transforms.loads(payload), self.get_schema(course, key).get_json_schema_dict()) lesson.title = updates_dict['title'] lesson.unit_id = updates_dict['unit_id'] lesson.scored = (updates_dict['scored'] == 'scored') lesson.objectives = updates_dict['objectives'] lesson.video = updates_dict['video'] lesson.notes = updates_dict['notes'] lesson.auto_index = updates_dict['auto_index'] lesson.activity_title = updates_dict['activity_title'] lesson.activity_listed = updates_dict['activity_listed'] lesson.manual_progress = updates_dict['manual_progress'] activity = updates_dict.get('activity', '').strip() errors = [] if activity: if lesson.has_activity: course.set_activity_content(lesson, activity, errors=errors) else: errors.append('Old-style activities are not supported.') else: lesson.has_activity = False fs = self.app_context.fs path = fs.impl.physical_to_logical( course.get_activity_filename(lesson.unit_id, lesson.lesson_id)) if fs.isfile(path): fs.delete(path) if not errors: common_utils.run_hooks(self.PRE_SAVE_HOOKS, lesson, updates_dict) assert course.update_lesson(lesson) course.save() common_utils.run_hooks(self.POST_SAVE_HOOKS, lesson) transforms.send_json_response(self, 200, 'Saved.') else: transforms.send_json_response(self, 412, '\n'.join(errors))
def delete_course(cls): """Called back repeatedly from deferred queue dispatcher.""" try: kind_name = cls.get_any_undeleted_kind_name() if not kind_name: # No entity types remain to be deleted from the Datastore for # this course (i.e. namespace), so call (in no particular # order) callbacks waiting to be informed of course deletion. ns_name = namespace_manager.get_namespace() common_utils.run_hooks(cls.COURSE_DELETED_HOOKS.itervalues(), ns_name) logging.info( 'CourseDeleteHandler found no entity types to delete for ' 'namespace %s; deletion complete.', ns_name) return model = Model(kind_name) keys = list( db.Query(Model(kind_name), keys_only=True).run(batch_size=cls.DELETE_BATCH_SIZE)) entities.delete(keys) logging.info( 'CourseDeleteHandler deleted %d entities of type %s from ' 'namespace %s', len(keys), kind_name, namespace_manager.get_namespace()) deferred.defer(cls.delete_course) except Exception: logging.critical( 'Failed when attempting to delete course for namespace %s', namespace_manager.get_namespace()) common_utils.log_exception_origin() raise
def run(self): now = utc.now_as_datetime() namespace = namespace_manager.get_namespace() app_context = sites.get_app_context_for_namespace(namespace) course = courses.Course.get(app_context) env = app_context.get_environ() tct = triggers.ContentTrigger content_acts = tct.act_on_settings(course, env, now) tmt = triggers.MilestoneTrigger course_acts = tmt.act_on_settings(course, env, now) save_settings = content_acts.num_consumed or course_acts.num_consumed if save_settings: # At least one of the settings['publish'] triggers was consumed # or discarded, so save changes to triggers into the settings. settings_saved = course.save_settings(env) else: settings_saved = False save_course = content_acts.num_changed or course_acts.num_changed if save_course: course.save() tct.log_acted_on( namespace, content_acts, save_course, settings_saved) tmt.log_acted_on( namespace, course_acts, save_course, settings_saved) common_utils.run_hooks(self.RUN_HOOKS.itervalues(), course)
def put(self): """Handles PUT REST verb to save lesson and associated activity.""" request = transforms.loads(self.request.get('request')) key = request.get('key') if not self.assert_xsrf_token_or_fail( request, 'lesson-edit', {'key': key}): return 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) lesson = course.find_lesson_by_id(None, key) if not lesson: transforms.send_json_response( self, 404, 'Object not found.', {'key': key}) return payload = request.get('payload') updates_dict = transforms.json_to_dict( transforms.loads(payload), self.get_schema(course, key).get_json_schema_dict()) lesson.title = updates_dict['title'] lesson.unit_id = updates_dict['unit_id'] lesson.scored = (updates_dict['scored'] == 'scored') lesson.objectives = updates_dict['objectives'] lesson.video = updates_dict['video'] lesson.notes = updates_dict['notes'] lesson.auto_index = updates_dict['auto_index'] lesson.activity_title = updates_dict['activity_title'] lesson.activity_listed = updates_dict['activity_listed'] lesson.manual_progress = updates_dict['manual_progress'] activity = updates_dict.get('activity', '').strip() errors = [] if activity: if lesson.has_activity: course.set_activity_content(lesson, activity, errors=errors) else: errors.append('Old-style activities are not supported.') else: lesson.has_activity = False fs = self.app_context.fs path = fs.impl.physical_to_logical(course.get_activity_filename( lesson.unit_id, lesson.lesson_id)) if fs.isfile(path): fs.delete(path) if not errors: common_utils.run_hooks(self.PRE_SAVE_HOOKS, lesson, updates_dict) assert course.update_lesson(lesson) course.save() common_utils.run_hooks(self.POST_SAVE_HOOKS, lesson) 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')) 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') updated_unit_dict = transforms.json_to_dict(transforms.loads(payload), self.SCHEMA_DICT) errors = [] self.apply_updates(unit, updated_unit_dict, errors) if not errors: course = courses.Course(self) assert course.update_unit(unit) course.save() common_utils.run_hooks(self.POST_SAVE_HOOKS, unit) transforms.send_json_response(self, 200, 'Saved.') else: transforms.send_json_response(self, 412, '\n'.join(errors))
def run(self): now = utc.now_as_datetime() namespace = namespace_manager.get_namespace() app_context = sites.get_app_context_for_namespace(namespace) course = courses.Course.get(app_context) env = app_context.get_environ() tct = triggers.ContentTrigger content_acts = tct.act_on_settings(course, env, now) tmt = triggers.MilestoneTrigger course_acts = tmt.act_on_settings(course, env, now) save_settings = content_acts.num_consumed or course_acts.num_consumed if save_settings: # At least one of the settings['publish'] triggers was consumed # or discarded, so save changes to triggers into the settings. settings_saved = course.save_settings(env) else: settings_saved = False save_course = content_acts.num_changed or course_acts.num_changed if save_course: course.save() tct.log_acted_on(namespace, content_acts, save_course, settings_saved) tmt.log_acted_on(namespace, course_acts, save_course, settings_saved) common_utils.run_hooks(self.RUN_HOOKS.itervalues(), course)
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): """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 common_utils.run_hooks(self.PRE_LOAD_HOOKS, item, display_dict) 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 delete_course(cls): """Called back repeatedly from deferred queue dispatcher.""" try: kind_name = cls.get_any_undeleted_kind_name() if not kind_name: # No entity types remain to be deleted from the Datastore for # this course (i.e. namespace), so call (in no particular # order) callbacks waiting to be informed of course deletion. ns_name = namespace_manager.get_namespace() common_utils.run_hooks( cls.COURSE_DELETED_HOOKS.itervalues(), ns_name) logging.info( 'CourseDeleteHandler found no entity types to delete for ' 'namespace %s; deletion complete.', ns_name) return model = Model(kind_name) keys = list(db.Query(Model(kind_name), keys_only=True).run( batch_size=cls.DELETE_BATCH_SIZE)) entities.delete(keys) logging.info( 'CourseDeleteHandler deleted %d entities of type %s from ' 'namespace %s', len(keys), kind_name, namespace_manager.get_namespace()) deferred.defer(cls.delete_course) except Exception: logging.critical( 'Failed when attempting to delete course for namespace %s', namespace_manager.get_namespace()) common_utils.log_exception_origin() raise
def put(self): """Handles PUT REST verb to save lesson and associated activity.""" request = transforms.loads(self.request.get("request")) key = request.get("key") if not self.assert_xsrf_token_or_fail(request, "lesson-edit", {"key": key}): return 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) lesson = course.find_lesson_by_id(None, key) if not lesson: transforms.send_json_response(self, 404, "Object not found.", {"key": key}) return payload = request.get("payload") updates_dict = transforms.json_to_dict( transforms.loads(payload), self.get_schema(course, key).get_json_schema_dict() ) lesson.title = updates_dict["title"] lesson.unit_id = updates_dict["unit_id"] lesson.scored = updates_dict["scored"] == "scored" lesson.objectives = updates_dict["objectives"] lesson.video = updates_dict["video"] lesson.notes = updates_dict["notes"] lesson.auto_index = updates_dict["auto_index"] lesson.activity_title = updates_dict["activity_title"] lesson.activity_listed = updates_dict["activity_listed"] lesson.manual_progress = updates_dict["manual_progress"] lesson.now_available = not updates_dict["is_draft"] activity = updates_dict.get("activity", "").strip() errors = [] if activity: if lesson.has_activity: course.set_activity_content(lesson, activity, errors=errors) else: errors.append("Old-style activities are not supported.") else: lesson.has_activity = False fs = self.app_context.fs path = fs.impl.physical_to_logical(course.get_activity_filename(lesson.unit_id, lesson.lesson_id)) if fs.isfile(path): fs.delete(path) if not errors: common_utils.run_hooks(self.PRE_SAVE_HOOKS, lesson, updates_dict) assert course.update_lesson(lesson) course.save() common_utils.run_hooks(self.POST_SAVE_HOOKS, lesson) transforms.send_json_response(self, 200, "Saved.") else: transforms.send_json_response(self, 412, "\n".join(errors))
def put(self): """Store a DTO in the datastore in response to a PUT.""" request = transforms.loads(self.request.get('request')) key = request.get('key') if not key and not self.CAN_CREATE: transforms.send_json_response(self, 404, 'Key is required in URL.', {}) return if not self.assert_xsrf_token_or_fail(request, self.XSRF_TOKEN, {'key': key}): 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) self.sanitize_input_dict(json_dict) errors = [] try: python_dict = transforms.json_to_dict( json_dict, self.get_schema().get_json_schema_dict()) version = python_dict.get('version') if version not in self.SCHEMA_VERSIONS: errors.append('Version %s not supported.' % version) else: python_dict = self.transform_after_editor_hook(python_dict) self.validate(python_dict, key, version, errors) common_utils.run_hooks(self.VALIDATE_HOOKS, python_dict, key, version, errors) except (TypeError, ValueError) as err: errors.append(str(err)) if errors: self.validation_error('\n'.join( error.replace('\n', ' ') for error in errors), key=key) return item = self.get_and_populate_dto(key, python_dict) self.pre_save_hook(item) common_utils.run_hooks(self.PRE_SAVE_HOOKS, item, python_dict) key_after_save = self.DAO.save(item) self.after_save_hook() transforms.send_json_response(self, 200, 'Saved.', payload_dict={'key': key_after_save})
def put(self): """Store a DTO in the datastore in response to a PUT.""" request = transforms.loads(self.request.get('request')) key = request.get('key') if not key and not self.CAN_CREATE: transforms.send_json_response( self, 404, 'Key is required in URL.', {}) return if not self.assert_xsrf_token_or_fail( request, self.XSRF_TOKEN, {'key': key}): 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) self.sanitize_input_dict(json_dict) errors = [] try: python_dict = transforms.json_to_dict( json_dict, self.get_schema().get_json_schema_dict()) version = python_dict.get('version') if version not in self.SCHEMA_VERSIONS: errors.append('Version %s not supported.' % version) else: python_dict = self.transform_after_editor_hook(python_dict) self.validate(python_dict, key, version, errors) common_utils.run_hooks( self.VALIDATE_HOOKS, python_dict, key, version, errors) except (TypeError, ValueError) as err: errors.append(str(err)) if errors: self.validation_error('\n'.join( error.replace('\n', ' ') for error in errors), key=key) return item = self.get_and_populate_dto(key, python_dict) self.pre_save_hook(item) common_utils.run_hooks(self.PRE_SAVE_HOOKS, item, python_dict) key_after_save = self.DAO.save(item) self.after_save_hook() transforms.send_json_response( self, 200, 'Saved.', payload_dict={'key': key_after_save})
def _copy_sample_course(self, uid): """Make a fresh copy of sample course.""" src_app_context = sites.get_all_courses('course:/:/:')[0] dst_app_context = self._make_new_course(uid, '%s (%s)' % ( src_app_context.get_title(), os.environ['GCB_PRODUCT_VERSION'])) errors = [] dst_course = courses.Course(None, dst_app_context) dst_course.import_from(src_app_context, errors) dst_course.save() if not errors: common_utils.run_hooks( self.COPY_SAMPLE_COURSE_HOOKS, dst_app_context, errors) if errors: raise Exception(errors) return dst_app_context
def put(self): """Store a DTO 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 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) self.sanitize_input_dict(json_dict) errors = [] try: python_dict = transforms.json_to_dict(json_dict, self.get_schema().get_json_schema_dict()) version = python_dict.get("version") if version not in self.SCHEMA_VERSIONS: errors.append("Version %s not supported." % version) else: python_dict = self.transform_after_editor_hook(python_dict) self.validate(python_dict, key, version, errors) except (TypeError, ValueError) as err: errors.append(str(err)) if errors: self.validation_error("\n".join(errors), key=key) return if key: item = self.DAO.DTO(key, python_dict) else: item = self.DAO.DTO(None, python_dict) self.pre_save_hook(item) common_utils.run_hooks(self.PRE_SAVE_HOOKS, item, python_dict) key_after_save = self.DAO.save(item) self.after_save_hook() transforms.send_json_response(self, 200, "Saved.", payload_dict={"key": key_after_save})
def delete(self): """Delete the Entity in response to REST request.""" key = self.request.get('key') if not self.assert_xsrf_token_or_fail(self.request, self.XSRF_TOKEN, {'key': key}): return if not roles.Roles.is_course_admin(self.app_context): transforms.send_json_response(self, 401, 'Access denied.', {'key': key}) return item = self.DAO.load(key) if not item: transforms.send_json_response(self, 404, 'Not found.', {'key': key}) return if self.is_deletion_allowed(item): self.pre_delete_hook(item) common_utils.run_hooks(self.PRE_DELETE_HOOKS, item) self.DAO.delete(item) transforms.send_json_response(self, 200, 'Deleted.')
def delete(self): """Delete the Entity in response to REST request.""" key = self.request.get('key') if not self.assert_xsrf_token_or_fail( self.request, self.XSRF_TOKEN, {'key': key}): return if not roles.Roles.is_course_admin(self.app_context): transforms.send_json_response( self, 401, 'Access denied.', {'key': key}) return item = self.DAO.load(key) if not item: transforms.send_json_response( self, 404, 'Not found.', {'key': key}) return if self.is_deletion_allowed(item): self.pre_delete_hook(item) common_utils.run_hooks(self.PRE_DELETE_HOOKS, item) self.DAO.delete(item) transforms.send_json_response(self, 200, 'Deleted.')
class CommonUnitRESTHandler(BaseRESTHandler): """A common super class for all unit REST handlers.""" # These functions are called with an updated unit object whenever a # change is saved. POST_SAVE_HOOKS = [] def unit_to_dict(self, unit): """Converts a unit to a dictionary representation.""" return resources_display.UnitTools(self.get_course()).unit_to_dict(unit) def apply_updates(self, unit, updated_unit_dict, errors): """Applies changes to a unit; modifies unit input argument.""" resources_display.UnitTools(courses.Course(self)).apply_updates( unit, updated_unit_dict, errors) 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 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)) if not errors: course = courses.Course(self) assert course.update_unit(unit) course.save() common_utils.run_hooks(self.POST_SAVE_HOOKS, unit) transforms.send_json_response(self, 200, 'Saved.') else: transforms.send_json_response(self, 412, '\n'.join(errors))
def get_schema(cls): question_schema = resources_display.ResourceSAQuestion.get_schema( course=None, key=None) common_utils.run_hooks(cls.SCHEMA_LOAD_HOOKS, question_schema) return question_schema
def put(self): """Handles HTTP PUT verb.""" request = transforms.loads(self.request.get('request')) if not self.assert_xsrf_token_or_fail( request, self.XSRF_ACTION, {}): return if not CoursesPropertyRights.can_add(): transforms.send_json_response( self, 401, 'Access denied.') return payload = request.get('payload') json_object = transforms.loads(payload) name = json_object.get('name') title = json_object.get('title') admin_email = json_object.get('admin_email') template_course = json_object.get('template_course') # Add the new course entry. errors = [] entry = sites.add_new_course_entry(name, title, admin_email, errors) if not entry and not errors: errors.append('Error adding a new course entry.') if errors: transforms.send_json_response(self, 412, '\n'.join(errors)) return # We can't expect our new configuration being immediately available due # to datastore queries consistency limitations. So we will instantiate # our new course here and not use the normal sites.get_all_courses(). app_context = sites.get_all_courses(entry)[0] # Update course with a new title and admin email. new_course = courses.Course(None, app_context=app_context) if not new_course.init_new_course_settings(title, admin_email): transforms.send_json_response( self, 412, 'Added new course entry, but failed to update title and/or ' 'admin email. The course.yaml file already exists and must be ' 'updated manually.') return if template_course: if template_course != 'sample': transforms.send_json_response( self, 412, 'Unknown template course: %s' % template_course) return errors = [] src_app_context = sites.get_all_courses('course:/:/:')[0] new_course.import_from(src_app_context, errors) new_course.save() if not errors: common_utils.run_hooks( self.COPY_SAMPLE_COURSE_HOOKS, app_context, errors) if errors: transforms.send_json_response(self, 412, '\n'.join(errors)) return transforms.send_json_response( self, 200, 'Added.', {'entry': entry})
def put(self): """Handles HTTP PUT verb.""" request = transforms.loads(self.request.get('request')) if not self.assert_xsrf_token_or_fail(request, self.XSRF_ACTION, {}): return if not CoursesPropertyRights.can_add(): self._send_json_error_response(401, 'Access denied.') return payload = request.get('payload') json_object = transforms.loads(payload) name = json_object.get('name') namespace = 'ns_' + name title = json_object.get('title') admin_email = json_object.get('admin_email') template_course = json_object.get('template_course') errors = [] with common_utils.Namespace(namespace): if CourseDeleteHandler.get_any_undeleted_kind_name(): errors.append( 'Unable to add new entry "%s": the corresponding ' 'namespace "%s" is not empty. If you removed a ' 'course with that name in the last few minutes, the ' 'background cleanup job may still be running. ' 'You can use the App Engine Dashboard to manually ' 'remove all database entities from this namespace.' % (name, namespace)) # Add the new course entry. if not errors: entry = sites.add_new_course_entry(name, title, admin_email, errors) if not entry and not errors: errors.append('Error adding a new course entry.') if errors: self._send_json_error_response(412, errors) return # We can't expect our new configuration being immediately available due # to datastore queries consistency limitations. So we will instantiate # our new course here and not use the normal sites.get_all_courses(). app_context = sites.get_all_courses(entry)[0] # Update course with a new title and admin email. new_course = courses.Course(None, app_context=app_context) if not new_course.init_new_course_settings(title, admin_email): self._send_json_error_response( 412, 'Added new course entry, but failed to update title and/or ' 'admin email. The course.yaml file already exists and must be ' 'updated manually.') return if template_course: if template_course != 'sample': self._send_json_error_response( 412, 'Unknown template course: %s' % template_course) return src_app_context = sites.get_all_courses('course:/:/:')[0] new_course.import_from(src_app_context, errors) new_course.save() if not errors: common_utils.run_hooks(self.COPY_SAMPLE_COURSE_HOOKS, app_context, errors) if not errors: common_utils.run_hooks(self.NEW_COURSE_ADDED_HOOKS.itervalues(), app_context, errors) if errors: # Any errors at this point are the result of one or more failed # _HOOKS callbacks. It is probably not possible to determine if # these are caused by bad server state or instead by bad user # input, so return a rather generic 500 HTTP status. self._send_json_error_response(500, errors) else: transforms.send_json_response(self, 200, 'Added.', {'entry': entry})
def post(self): if not self.can_edit(): return common_utils.run_hooks(self.POST_HOOKS, self) self.redirect('/modules/admin')
def post(self): if not self.can_edit(): return app_context = super(WelcomeHandler, self).post() common_utils.run_hooks(self.POST_HOOKS, app_context, self)
def get_schema(cls): schema = drive_models.get_drive_sync_entity_schema() common_utils.run_hooks(cls.SCHEMA_LOAD_HOOKS, schema) return schema
def get_lesson_dict_for(cls, course, lesson): lesson_dict = resources_display.ResourceLesson.get_data_dict( course, lesson.lesson_id) common_utils.run_hooks(cls.PRE_LOAD_HOOKS, lesson, lesson_dict) return lesson_dict
def get_schema(cls, course, key): lesson_schema = resources_display.ResourceLesson.get_schema( course, key) common_utils.run_hooks(cls.SCHEMA_LOAD_HOOKS, lesson_schema) return lesson_schema
def put(self): """Handles HTTP PUT verb.""" request = transforms.loads(self.request.get('request')) if not self.assert_xsrf_token_or_fail( request, self.XSRF_ACTION, {}): return if not CoursesPropertyRights.can_add(): self._send_json_error_response(401, 'Access denied.') return payload = request.get('payload') json_object = transforms.loads(payload) name = json_object.get('name') namespace = 'ns_' + name title = json_object.get('title') admin_email = json_object.get('admin_email') template_course = json_object.get('template_course') errors = [] with common_utils.Namespace(namespace): if CourseDeleteHandler.get_any_undeleted_kind_name(): errors.append( 'Unable to add new entry "%s": the corresponding ' 'namespace "%s" is not empty. If you removed a ' 'course with that name in the last few minutes, the ' 'background cleanup job may still be running. ' 'You can use the App Engine Dashboard to manually ' 'remove all database entities from this namespace.' % (name, namespace)) # Add the new course entry. if not errors: entry = sites.add_new_course_entry(name, title, admin_email, errors) if not entry and not errors: errors.append('Error adding a new course entry.') if errors: self._send_json_error_response(412, errors) return # We can't expect our new configuration being immediately available due # to datastore queries consistency limitations. So we will instantiate # our new course here and not use the normal sites.get_all_courses(). app_context = sites.get_all_courses(entry)[0] # Update course with a new title and admin email. new_course = courses.Course(None, app_context=app_context) if not new_course.init_new_course_settings(title, admin_email): self._send_json_error_response(412, 'Added new course entry, but failed to update title and/or ' 'admin email. The course.yaml file already exists and must be ' 'updated manually.') return if template_course: if template_course != 'sample': self._send_json_error_response( 412, 'Unknown template course: %s' % template_course) return src_app_context = sites.get_all_courses('course:/:/:')[0] new_course.import_from(src_app_context, errors) new_course.save() if not errors: common_utils.run_hooks( self.COPY_SAMPLE_COURSE_HOOKS, app_context, errors) if not errors: common_utils.run_hooks( self.NEW_COURSE_ADDED_HOOKS.itervalues(), app_context, errors) if errors: # Any errors at this point are the result of one or more failed # _HOOKS callbacks. It is probably not possible to determine if # these are caused by bad server state or instead by bad user # input, so return a rather generic 500 HTTP status. self._send_json_error_response(500, errors) else: transforms.send_json_response( self, 200, 'Added.', {'entry': entry})
def get_schema(cls, course, key): lesson_schema = resources_display.ResourceLesson.get_schema(course, key) common_utils.run_hooks(cls.SCHEMA_LOAD_HOOKS, lesson_schema) return lesson_schema