Esempio n. 1
0
    def show(self, id):
        """Return a collection.
        
        :URL: ``GET /collections/id``
        :param str id: the ``id`` value of the collection to be returned.
        :returns: a collection model object.

        .. note::

            Returns all of the forms of the collection, unlike the other
            collections actions.

        """
        collection = h.eagerload_collection(Session.query(Collection),
                                           eagerload_forms=True).get(id)
        if collection:
            unrestricted_users = h.get_unrestricted_users()
            user = session['user']
            if h.user_is_authorized_to_access_model(user, collection, unrestricted_users):
                return collection.get_full_dict()
            else:
                response.status_int = 403
                return h.unauthorized_msg
        else:
            response.status_int = 404
            return {'error': 'There is no collection with id %s' % id}
Esempio n. 2
0
def serve_file(id, reduced=False):
    """Serve the content (binary data) of a file.
    
    :param str id: the ``id`` value of the file whose file data will be served.
    :param bool reduced: toggles serving of file data or reduced-size file data.

    """
    file = Session.query(File).options(subqueryload(File.parent_file)).get(id)
    if getattr(file, 'parent_file', None):
        file = file.parent_file
    elif getattr(file, 'url', None):
        response.status_int = 400
        return json.dumps({'error': u'The content of file %s is stored elsewhere at %s' % (id, file.url)})
    if file:
        files_dir = h.get_OLD_directory_path('files', config=config)
        if reduced:
            filename = getattr(file, 'lossy_filename', None)
            if not filename:
                response.status_int = 404
                return json.dumps({'error': u'There is no size-reduced copy of file %s' % id})
            file_path = os.path.join(files_dir, 'reduced_files', filename)
        else:
            file_path = os.path.join(files_dir, file.filename)
        unrestricted_users = h.get_unrestricted_users()
        if h.user_is_authorized_to_access_model(session['user'], file, unrestricted_users):
            return forward(FileApp(file_path))
        else:
            response.status_int = 403
            return json.dumps(h.unauthorized_msg)
    else:
        response.status_int = 404
        return json.dumps({'error': 'There is no file with id %s' % id})
Esempio n. 3
0
    def edit(self, id):
        """Return a file and the data needed to update it.

        :URL: ``GET /files/edit`` with optional query string parameters 
        :param str id: the ``id`` value of the file that will be updated.
        :returns: a dictionary of the form::

                {"file": {...}, "data": {...}}

            where the value of the ``file`` key is a dictionary representation
            of the file and the value of the ``data`` key is a dictionary
            containing the objects necessary to update a file, viz. the return
            value of :func:`FilesController.new`

        .. note::
        
           This action can be thought of as a combination of
           :func:`FilesController.show` and :func:`FilesController.new`.  See
           :func:`get_new_edit_file_data` to understand how the query string
           parameters can affect the contents of the lists in the ``data``
           dictionary.

        """
        response.content_type = 'application/json'
        file = h.eagerload_file(Session.query(File)).get(id)
        if file:
            unrestricted_users = h.get_unrestricted_users()
            if h.user_is_authorized_to_access_model(session['user'], file, unrestricted_users):
                return {'data': get_new_edit_file_data(request.GET), 'file': file}
            else:
                response.status_int = 403
                return h.unauthorized_msg
        else:
            response.status_int = 404
            return {'error': 'There is no file with id %s' % id}
Esempio n. 4
0
    def update(self, id):
        """Update a collection and return it.
        
        :URL: ``PUT /collections/id``
        :Request body: JSON object representing the collection with updated attribute values.
        :param str id: the ``id`` value of the collection to be updated.
        :returns: the updated collection model.

        """
        collection = h.eagerload_collection(Session.query(Collection),
                                           eagerload_forms=True).get(int(id))
        if collection:
            unrestricted_users = h.get_unrestricted_users()
            user = session['user']
            if h.user_is_authorized_to_access_model(user, collection, unrestricted_users):
                try:
                    schema = CollectionSchema()
                    values = json.loads(unicode(request.body, request.charset))
                    collections_referenced = get_collections_referenced(
                                values['contents'], user, unrestricted_users, id)
                    values = add_contents_unpacked_to_values(values, collections_referenced)
                    values = add_form_ids_list_to_values(values)
                    state = h.get_state_object(values)
                    data = schema.to_python(values, state)
                    collection_dict = collection.get_full_dict()
                    collection, restricted, contents_changed = update_collection(
                        collection, data, collections_referenced)
                    # collection will be False if there are no changes (cf. update_collection).
                    if collection:
                        backup_collection(collection_dict)
                        update_collections_that_reference_this_collection(collection, self.query_builder,
                                            restricted=restricted, contents_changed=contents_changed)
                        Session.add(collection)
                        Session.commit()
                        return collection.get_full_dict()
                    else:
                        response.status_int = 400
                        return {'error':
                            u'The update request failed because the submitted data were not new.'}
                except h.JSONDecodeError:
                    response.status_int = 400
                    return h.JSONDecodeErrorResponse
                except CircularCollectionReferenceError, e:
                    response.status_int = 400
                    return {'error':
                        u'Circular collection reference error: collection %d references collection %d.' % (id, e.args[0])}
                except InvalidCollectionReferenceError, e:
                    response.status_int = 400
                    return {'error': u'Invalid collection reference error: there is no collection with id %d' % e.args[0]}
                except UnauthorizedCollectionReferenceError:
                    response.status_int = 403
                    return {'error': u'Unauthorized collection reference error: you are not authorized to access collection %d' % e.args[0]}
Esempio n. 5
0
def get_collection(collection_id, user, unrestricted_users):
    """Return the collection such that ``collection.id==collection_id``.

    If the collection does not exist or if ``user`` is not authorized to access
    it, raise an appropriate error.

    :param int collection_id: the ``id`` value of a collection.
    :param user: a user model of the logged in user.
    :param list unrestricted_users: the unrestricted users of the system.
    :return: a collection model object.

    """
    collection = Session.query(Collection).get(collection_id)
    if collection:
        if user is None or unrestricted_users is None or \
        h.user_is_authorized_to_access_model(user, collection, unrestricted_users):
            return collection
        else:
            raise UnauthorizedCollectionReferenceError(collection_id)
    raise InvalidCollectionReferenceError(collection_id)
Esempio n. 6
0
def get_collection(collection_id, user, unrestricted_users):
    """Return the collection such that ``collection.id==collection_id``.

    If the collection does not exist or if ``user`` is not authorized to access
    it, raise an appropriate error.

    :param int collection_id: the ``id`` value of a collection.
    :param user: a user model of the logged in user.
    :param list unrestricted_users: the unrestricted users of the system.
    :return: a collection model object.

    """
    collection = Session.query(Collection).get(collection_id)
    if collection:
        if user is None or unrestricted_users is None or \
        h.user_is_authorized_to_access_model(user, collection, unrestricted_users):
            return collection
        else:
            raise UnauthorizedCollectionReferenceError(collection_id)
    raise InvalidCollectionReferenceError(collection_id)
Esempio n. 7
0
    def show(self, id):
        """Return a form backup.
        
        :URL: ``GET /formbackups/id``
        :param str id: the ``id`` value of the form backup to be returned.
        :returns: a form backup model object.

        """
        form_backup = Session.query(FormBackup).get(id)
        if form_backup:
            unrestricted_users = h.get_unrestricted_users()
            user = session['user']
            if h.user_is_authorized_to_access_model(user, form_backup, unrestricted_users):
                return form_backup
            else:
                response.status_int = 403
                return h.unauthorized_msg
        else:
            response.status_int = 404
            return {'error': 'There is no form backup with id %s' % id}
Esempio n. 8
0
    def show(self, id):
        """Return a file.

        :URL: ``GET /files/id``
        :param str id: the ``id`` value of the file to be returned.
        :returns: a file model object.

        """
        file = h.eagerload_file(Session.query(File)).get(id)
        if file:
            unrestricted_users = h.get_unrestricted_users()
            user = session['user']
            if h.user_is_authorized_to_access_model(user, file, unrestricted_users):
                return file
            else:
                response.status_int = 403
                return h.unauthorized_msg
        else:
            response.status_int = 404
            return {'error': 'There is no file with id %s' % id}
Esempio n. 9
0
    def show(self, id):
        """Return a form backup.
        
        :URL: ``GET /formbackups/id``
        :param str id: the ``id`` value of the form backup to be returned.
        :returns: a form backup model object.

        """
        form_backup = Session.query(FormBackup).get(id)
        if form_backup:
            unrestricted_users = h.get_unrestricted_users()
            user = session['user']
            if h.user_is_authorized_to_access_model(user, form_backup,
                                                    unrestricted_users):
                return form_backup
            else:
                response.status_int = 403
                return h.unauthorized_msg
        else:
            response.status_int = 404
            return {'error': 'There is no form backup with id %s' % id}
Esempio n. 10
0
    def edit(self, id):
        """Return a collection and the data needed to update it.

        :URL: ``GET /collections/edit`` with optional query string parameters 
        :param str id: the ``id`` value of the collection that will be updated.
        :returns: a dictionary of the form::

                {"collection": {...}, "data": {...}}

            where the value of the ``collection`` key is a dictionary
            representation of the collection and the value of the ``data`` key
            is a dictionary containing the objects necessary to update a
            collection, viz. the return value of
            :func:`CollectionsController.new`

        .. note::
        
           This action can be thought of as a combination of
           :func:`CollectionsController.show` and
           :func:`CollectionsController.new`.  See
           :func:`get_new_edit_collection_data` to understand how the query string
           parameters can affect the contents of the lists in the ``data``
           dictionary.

        """
        collection = h.eagerload_collection(Session.query(Collection)).get(id)
        if collection:
            unrestricted_users = h.get_unrestricted_users()
            if h.user_is_authorized_to_access_model(session['user'],
                                                    collection,
                                                    unrestricted_users):
                data = get_new_edit_collection_data(request.GET)
                return {'data': data, 'collection': collection}
            else:
                response.status_int = 403
                return h.unauthorized_msg
        else:
            response.status_int = 404
            return {'error': 'There is no collection with id %s' % id}
Esempio n. 11
0
    def update(self, id):
        """Update a file and return it.
        
        :URL: ``PUT /files/id``
        :Request body: JSON object representing the file with updated attribute values.
        :param str id: the ``id`` value of the file to be updated.
        :returns: the updated file model.

        """
        file = h.eagerload_file(Session.query(File)).get(int(id))
        if file:
            unrestricted_users = h.get_unrestricted_users()
            user = session['user']
            if h.user_is_authorized_to_access_model(user, file, unrestricted_users):
                try:
                    if getattr(file, 'parent_file', None):
                        file = update_subinterval_referencing_file(file)
                    elif getattr(file, 'url', None):
                        file = update_externally_hosted_file(file)
                    else:
                        file = update_file(file)
                    # file will be False if there are no changes
                    if file:
                        Session.add(file)
                        Session.commit()
                        return file
                    else:
                        response.status_int = 400
                        return {'error':
                            u'The update request failed because the submitted data were not new.'}
                except h.JSONDecodeError:
                    response.status_int = 400
                    return h.JSONDecodeErrorResponse
                except Invalid, e:
                    response.status_int = 400
                    return {'errors': e.unpack_errors()}
            else:
                response.status_int = 403
                return h.unauthorized_msg
Esempio n. 12
0
    def show(self, id):
        """Return a collection.
        
        :URL: ``GET /collections/id``
        :param str id: the ``id`` value of the collection to be returned.
        :returns: a collection model object.

        .. note::

            Returns all of the forms of the collection, unlike the other
            collections actions.

            If there is a truthy GET param with key 'latex' and if the markup
            language is reStructuredText, then the collection's
            contents_unpacked value will be returned as a LaTeX string in the
            'latex' attribute.

        """

        collection = h.eagerload_collection(Session.query(Collection),
                                            eagerload_forms=True).get(id)
        if collection:
            unrestricted_users = h.get_unrestricted_users()
            user = session['user']
            if h.user_is_authorized_to_access_model(user, collection,
                                                    unrestricted_users):
                result = collection.get_full_dict()
                # TODO: deal with markdown2latex ...
                if request.GET.get('latex') and \
                collection.markup_language == 'reStructuredText':
                    result['latex'] = h.rst2latex(collection.contents_unpacked)
                return result
            else:
                response.status_int = 403
                return h.unauthorized_msg
        else:
            response.status_int = 404
            return {'error': 'There is no collection with id %s' % id}
Esempio n. 13
0
    def edit(self, id):
        """Return a collection and the data needed to update it.

        :URL: ``GET /collections/edit`` with optional query string parameters 
        :param str id: the ``id`` value of the collection that will be updated.
        :returns: a dictionary of the form::

                {"collection": {...}, "data": {...}}

            where the value of the ``collection`` key is a dictionary
            representation of the collection and the value of the ``data`` key
            is a dictionary containing the objects necessary to update a
            collection, viz. the return value of
            :func:`CollectionsController.new`

        .. note::
        
           This action can be thought of as a combination of
           :func:`CollectionsController.show` and
           :func:`CollectionsController.new`.  See
           :func:`get_new_edit_collection_data` to understand how the query string
           parameters can affect the contents of the lists in the ``data``
           dictionary.

        """
        collection = h.eagerload_collection(Session.query(Collection)).get(id)
        if collection:
            unrestricted_users = h.get_unrestricted_users()
            if h.user_is_authorized_to_access_model(
                                session['user'], collection, unrestricted_users):
                data = get_new_edit_collection_data(request.GET)
                return {'data': data, 'collection': collection}
            else:
                response.status_int = 403
                return h.unauthorized_msg
        else:
            response.status_int = 404
            return {'error': 'There is no collection with id %s' % id}
Esempio n. 14
0
    def show(self, id):
        """Return a collection.
        
        :URL: ``GET /collections/id``
        :param str id: the ``id`` value of the collection to be returned.
        :returns: a collection model object.

        .. note::

            Returns all of the forms of the collection, unlike the other
            collections actions.

            If there is a truthy GET param with key 'latex' and if the markup
            language is reStructuredText, then the collection's
            contents_unpacked value will be returned as a LaTeX string in the
            'latex' attribute.

        """

        collection = h.eagerload_collection(Session.query(Collection),
                                           eagerload_forms=True).get(id)
        if collection:
            unrestricted_users = h.get_unrestricted_users()
            user = session['user']
            if h.user_is_authorized_to_access_model(user, collection, unrestricted_users):
                result = collection.get_full_dict()
                # TODO: deal with markdown2latex ...
                if request.GET.get('latex') and \
                collection.markup_language == 'reStructuredText':
                    result['latex'] = h.rst2latex(collection.contents_unpacked)
                return result
            else:
                response.status_int = 403
                return h.unauthorized_msg
        else:
            response.status_int = 404
            return {'error': 'There is no collection with id %s' % id}
Esempio n. 15
0
    def update(self, id):
        """Update a collection and return it.
        
        :URL: ``PUT /collections/id``
        :Request body: JSON object representing the collection with updated attribute values.
        :param str id: the ``id`` value of the collection to be updated.
        :returns: the updated collection model.

        """
        collection = h.eagerload_collection(Session.query(Collection),
                                            eagerload_forms=True).get(int(id))
        if collection:
            unrestricted_users = h.get_unrestricted_users()
            user = session['user']
            if h.user_is_authorized_to_access_model(user, collection,
                                                    unrestricted_users):
                try:
                    schema = CollectionSchema()
                    values = json.loads(unicode(request.body, request.charset))
                    collections_referenced = get_collections_referenced(
                        values['contents'], user, unrestricted_users, id)
                    values = add_contents_unpacked_to_values(
                        values, collections_referenced)
                    values = add_form_ids_list_to_values(values)
                    state = h.get_state_object(values)
                    data = schema.to_python(values, state)
                    collection_dict = collection.get_full_dict()
                    collection, restricted, contents_changed = update_collection(
                        collection, data, collections_referenced)
                    # collection will be False if there are no changes (cf. update_collection).
                    if collection:
                        backup_collection(collection_dict)
                        update_collections_that_reference_this_collection(
                            collection,
                            self.query_builder,
                            restricted=restricted,
                            contents_changed=contents_changed)
                        Session.add(collection)
                        Session.commit()
                        return collection.get_full_dict()
                    else:
                        response.status_int = 400
                        return {
                            'error':
                            u'The update request failed because the submitted data were not new.'
                        }
                except h.JSONDecodeError:
                    response.status_int = 400
                    return h.JSONDecodeErrorResponse
                except CircularCollectionReferenceError, e:
                    response.status_int = 400
                    return {
                        'error':
                        u'Circular collection reference error: collection %d references collection %d.'
                        % (id, e.args[0])
                    }
                except InvalidCollectionReferenceError, e:
                    response.status_int = 400
                    return {
                        'error':
                        u'Invalid collection reference error: there is no collection with id %d'
                        % e.args[0]
                    }
                except UnauthorizedCollectionReferenceError:
                    response.status_int = 403
                    return {
                        'error':
                        u'Unauthorized collection reference error: you are not authorized to access collection %d'
                        % e.args[0]
                    }