Example #1
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})
Example #2
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}
Example #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}
Example #4
0
    def history(self, id):
        """Return a collection and its previous versions.

        :URL: ``GET /collections/history/id``
        :param str id: a string matching the ``id`` or ``UUID`` value of the
            collection whose history is requested.
        :returns: a dictionary of the form::

                {"collection": { ... }, "previous_versions": [ ... ]}

            where the value of the ``collection`` key is the collection whose
            history is requested and the value of the ``previous_versions`` key
            is a list of dictionaries representing previous versions of the
            collection.

        """
        collection, previous_versions = h.get_model_and_previous_versions('Collection', id)
        if collection or previous_versions:
            unrestricted_users = h.get_unrestricted_users()
            user = session['user']
            accessible = h.user_is_authorized_to_access_model
            unrestricted_previous_versions = [cb for cb in previous_versions
                                    if accessible(user, cb, unrestricted_users)]
            collection_is_restricted = collection and not accessible(user, collection, unrestricted_users)
            previous_versions_are_restricted = previous_versions and not unrestricted_previous_versions
            if collection_is_restricted or previous_versions_are_restricted :
                response.status_int = 403
                return h.unauthorized_msg
            else :
                return {'collection': collection,
                        'previous_versions': unrestricted_previous_versions}
        else:
            response.status_int = 404
            return {'error': 'No collections or collection backups match %s' % id}
Example #5
0
    def create(self):
        """Create a new collection resource and return it.

        :URL: ``POST /collections``
        :request body: JSON object representing the collection to create.
        :returns: the newly created collection.

        """
        try:
            unrestricted_users = h.get_unrestricted_users()
            user = session['user']
            schema = CollectionSchema()
            values = json.loads(unicode(request.body, request.charset))
            collections_referenced = get_collections_referenced(
                values['contents'], user, unrestricted_users)
            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 = create_new_collection(data, collections_referenced)
            Session.add(collection)
            Session.commit()
            return collection.get_full_dict()
        except h.JSONDecodeError:
            response.status_int = 400
            return h.JSONDecodeErrorResponse
        except InvalidCollectionReferenceError, e:
            response.status_int = 400
            return {
                'error':
                u'Invalid collection reference error: there is no collection with id %d'
                % e.args[0]
            }
Example #6
0
    def create(self):
        """Create a new collection resource and return it.

        :URL: ``POST /collections``
        :request body: JSON object representing the collection to create.
        :returns: the newly created collection.

        """
        try:
            unrestricted_users = h.get_unrestricted_users()
            user = session['user']
            schema = CollectionSchema()
            values = json.loads(unicode(request.body, request.charset))
            collections_referenced = get_collections_referenced(values['contents'],
                                                        user, unrestricted_users)
            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 = create_new_collection(data, collections_referenced)
            Session.add(collection)
            Session.commit()
            return collection.get_full_dict()
        except h.JSONDecodeError:
            response.status_int = 400
            return h.JSONDecodeErrorResponse
        except InvalidCollectionReferenceError, e:
            response.status_int = 400
            return {'error': u'Invalid collection reference error: there is no collection with id %d' % e.args[0]}
Example #7
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]}
Example #8
0
    def update(self, id):
        """Update a user's remembered forms and return them.

        :URL: ``PUT /rememberedforms/id``
        :Request body: JSON object of the form ``{"forms": [...]}`` where the
            array contains the form ``id`` values that will constitute the
            user's ``remembered_forms`` collection after update.
        :param str id: the ``id`` value of the user model whose
            ``remembered_forms`` attribute is to be updated.
        :returns: the list of remembered forms of the user.

        .. note::

            Administrators can update any user's remembered forms;
            non-administrators can only update their own.

        """
        user = Session.query(User).options(subqueryload(
            User.remembered_forms)).get(id)
        if user:
            try:
                schema = FormIdsSchemaNullable
                values = json.loads(unicode(request.body, request.charset))
                data = schema.to_python(values)
                forms = [f for f in data['forms'] if f]
                accessible = h.user_is_authorized_to_access_model
                unrestricted_users = h.get_unrestricted_users()
                unrestricted_forms = [
                    f for f in forms if accessible(user, f, unrestricted_users)
                ]
                if set(user.remembered_forms) != set(unrestricted_forms):
                    user.remembered_forms = unrestricted_forms
                    user.datetime_modified = h.now()
                    Session.commit()
                    return user.remembered_forms
                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()}
Example #9
0
    def update(self, id):
        """Update a user's remembered forms and return them.

        :URL: ``PUT /rememberedforms/id``
        :Request body: JSON object of the form ``{"forms": [...]}`` where the
            array contains the form ``id`` values that will constitute the
            user's ``remembered_forms`` collection after update.
        :param str id: the ``id`` value of the user model whose
            ``remembered_forms`` attribute is to be updated.
        :returns: the list of remembered forms of the user.

        .. note::

            Administrators can update any user's remembered forms;
            non-administrators can only update their own.

        """
        user = Session.query(User).options(subqueryload(User.remembered_forms)).get(id)
        if user:
            try:
                schema = FormIdsSchemaNullable
                values = json.loads(unicode(request.body, request.charset))
                data = schema.to_python(values)
                forms = [f for f in data['forms'] if f]
                accessible = h.user_is_authorized_to_access_model
                unrestricted_users = h.get_unrestricted_users()
                unrestricted_forms = [f for f in forms
                                     if accessible(user, f, unrestricted_users)]
                if set(user.remembered_forms) != set(unrestricted_forms):
                    user.remembered_forms = unrestricted_forms
                    user.datetime_modified = h.now()
                    Session.commit()
                    return user.remembered_forms
                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()}
Example #10
0
    def history(self, id):
        """Return a collection and its previous versions.

        :URL: ``GET /collections/history/id``
        :param str id: a string matching the ``id`` or ``UUID`` value of the
            collection whose history is requested.
        :returns: a dictionary of the form::

                {"collection": { ... }, "previous_versions": [ ... ]}

            where the value of the ``collection`` key is the collection whose
            history is requested and the value of the ``previous_versions`` key
            is a list of dictionaries representing previous versions of the
            collection.

        """
        collection, previous_versions = h.get_model_and_previous_versions(
            'Collection', id)
        if collection or previous_versions:
            unrestricted_users = h.get_unrestricted_users()
            user = session['user']
            accessible = h.user_is_authorized_to_access_model
            unrestricted_previous_versions = [
                cb for cb in previous_versions
                if accessible(user, cb, unrestricted_users)
            ]
            collection_is_restricted = collection and not accessible(
                user, collection, unrestricted_users)
            previous_versions_are_restricted = previous_versions and not unrestricted_previous_versions
            if collection_is_restricted or previous_versions_are_restricted:
                response.status_int = 403
                return h.unauthorized_msg
            else:
                return {
                    'collection': collection,
                    'previous_versions': unrestricted_previous_versions
                }
        else:
            response.status_int = 404
            return {
                'error': 'No collections or collection backups match %s' % id
            }
Example #11
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}
Example #12
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}
Example #13
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}
Example #14
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}
Example #15
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
Example #16
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}
Example #17
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}
Example #18
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}
Example #19
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]
                    }
Example #20
0
def authorized_to_access_corpus_file(user, corpus_file):
    """Return True if user is authorized to access the corpus file."""
    if corpus_file.restricted and user.role != u'administrator' and \
    user not in h.get_unrestricted_users():
        return False
    return True
Example #21
0
def authorized_to_access_corpus_file(user, corpus_file):
    """Return True if user is authorized to access the corpus file."""
    if corpus_file.restricted and user.role != u'administrator' and \
    user not in h.get_unrestricted_users():
        return False
    return True
Example #22
0
def authorized_to_access_arpa_file(user, morpheme_language_model):
    """Return True if user is authorized to access the ARPA file of the morpheme LM."""
    if (morpheme_language_model.restricted and user.role != u'administrator'
            and user not in h.get_unrestricted_users()):
        return False
    return True
Example #23
0
def authorized_to_access_arpa_file(user, morpheme_language_model):
    """Return True if user is authorized to access the ARPA file of the morpheme LM."""
    if (morpheme_language_model.restricted and user.role != u'administrator' and
    user not in h.get_unrestricted_users()):
        return False
    return True