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))
Example #2
0
    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))
Example #3
0
 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'))
Example #4
0
    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))
Example #6
0
 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
Example #7
0
    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={})
Example #8
0
    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"),
        )
Example #14
0
    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))
Example #17
0
    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))
Example #18
0
    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'))
Example #20
0
    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.')
Example #21
0
    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.')
Example #22
0
    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'))
Example #25
0
    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)
Example #26
0
    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)
Example #27
0
    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))
Example #28
0
    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)
Example #30
0
    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)
Example #31
0
    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)
Example #33
0
    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.')
Example #35
0
    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.')
Example #36
0
    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)
Example #37
0
    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
Example #38
0
    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.')
Example #41
0
    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.')
Example #42
0
    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))
Example #43
0
    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.')
Example #44
0
    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'))
Example #45
0
    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'))
Example #46
0
    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))
Example #47
0
    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.')
Example #48
0
    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'))
Example #49
0
    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))
Example #50
0
    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))
Example #51
0
    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'))
Example #53
0
    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'))
Example #54
0
    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))
Example #55
0
    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
Example #56
0
    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
Example #57
0
    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}
Example #59
0
    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')
Example #60
0
    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))