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})
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}
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}
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}
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] }
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]}
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]}
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()}
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()}
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 }
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}
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}
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}
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}
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
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}
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}
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}
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] }
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
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
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
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