def _update_subinterval_referencing_file(self, file_): """Update a subinterval-referencing file model. :param file_: a file model object to update. :param request.body: a JSON object containing the data for updating the file. :returns: the file model or, if the file has not been updated, ``False``. """ changed = False schema = FileSubintervalReferencingSchema() data = json.loads(self.request.body.decode(self.request.charset)) data['name'] = data.get('name') or '' state = SchemaState(full_dict=data, db=self.db, logged_in_user=self.logged_in_user) data = schema.to_python(data, state) # Data unique to referencing subinterval files changed = file_.set_attr('parent_file', data['parent_file'], changed) changed = file_.set_attr( 'name', (h.normalize(data['name']) or file_.parent_file.filename), changed) changed = file_.set_attr('start', data['start'], changed) changed = file_.set_attr('end', data['end'], changed) file_, changed = _update_standard_metadata(file_, data, changed) if changed: file_.datetime_modified = datetime.datetime.utcnow() return file_ return changed
def _create_subinterval_referencing_file(self, data): """Create a subinterval-referencing file. :param dict data: the data to create the file model. :param int data['parent_file']: the ``id`` value of an audio/video file model. :param float/int data['start']: the start of the interval in seconds. :param float/int data['end']: the end of the interval in seconds. :returns: an SQLAlchemy model object representing the file. A value for ``data['name']`` may also be supplied. """ data['name'] = data.get('name') or '' schema = FileSubintervalReferencingSchema() state = SchemaState(full_dict=data, db=self.db, logged_in_user=self.logged_in_user) data = schema.to_python(data, state) # Data unique to referencing subinterval files file_ = File( parent_file=data['parent_file'], # Name defaults to the parent file's filename if nothing provided by # user name=h.normalize(data['name']) or data['parent_file'].filename, start=data['start'], end=data['end'], MIME_type=data['parent_file'].MIME_type) file_ = self._add_standard_metadata(file_, data) file_ = _restrict_file_by_forms(file_) return file_
def _create_base64_file(self, data): """Create a local file using data from a ``Content-Type: application/json`` request. :param dict data: the data to create the file model. :param str data['base64_encoded_file']: Base64-encoded file data. :returns: an SQLAlchemy model object representing the file. """ data[ 'MIME_type'] = '' # during validation, the schema will set a proper # value based on the base64_encoded_file or # filename attribute schema = FileCreateWithBase64EncodedFiledataSchema() state = SchemaState(full_dict=data, db=self.db, logged_in_user=self.logged_in_user) data = schema.to_python(data, state) file_ = File(MIME_type=data['MIME_type'], filename=h.normalize(data['filename'])) file_ = self._add_standard_metadata(file_, data) # Write the file to disk (making sure it's unique and thereby potentially) # modifying file.filename; and calculate file.size. # base64-decoded during validation file_data = data['base64_encoded_file'] files_path = h.get_old_directory_path('files', self.request.registry.settings) file_path = os.path.join(files_path, file_.filename) file_object, file_path = _get_unique_file_path(file_path) file_.filename = os.path.split(file_path)[-1] file_.name = file_.filename file_object.write(file_data) file_object.close() file_data = None file_.size = os.path.getsize(file_path) file_ = _restrict_file_by_forms(file_) return file_
def _get_create_state(self, values): """Return a SchemaState instance for validation of the corpus during a create request. """ return SchemaState(full_dict=values, db=self.db, logged_in_user=self.logged_in_user, settings=self.request.registry.settings)
def update(self): """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. """ id_ = self.request.matchdict['id'] LOGGER.info('Attempting to update the forms remembered by user %d.', id_) user = self.request.dbsession.query(User).options( subqueryload(User.remembered_forms)).get(id_) schema = FormIdsSchemaNullable if not user: self.request.response.status_int = 404 msg = 'There is no user with id {}'.format(id_) LOGGER.warning(msg) return {'error': msg} try: values = json.loads(self.request.body.decode(self.request.charset)) except ValueError: self.request.response.status_int = 400 LOGGER.warning(JSONDecodeErrorResponse) return JSONDecodeErrorResponse state = SchemaState(full_dict=values, db=self.db, id=id_) try: data = schema.to_python(values, state) except Invalid as error: self.request.response.status_int = 400 errors = error.unpack_errors() LOGGER.warning(errors) return {'errors': errors} forms = [f for f in data['forms'] if f] unrestricted_users = self.db.get_unrestricted_users() unrestricted_forms = [ f for f in forms if self.logged_in_user.is_authorized_to_access_model( f, unrestricted_users) ] if set(user.remembered_forms) != set(unrestricted_forms): user.remembered_forms = unrestricted_forms user.datetime_modified = h.now() LOGGER.info('Updated the forms remembered by user %d.', id_) return user.remembered_forms self.request.response.status_int = 400 msg = ('The update request failed because the submitted data were not' ' new.') LOGGER.warning(msg) return {'error': msg}
def _get_create_state(self, values, collection_id=None): """Return a SchemaState instance for validation of the resource during a create request. Also return the collections referenced by this collection. """ collections_referenced = self._get_collections_referenced( values['contents'], collection_id=collection_id) values = _add_contents_unpacked_to_values(values, collections_referenced) values = _add_form_ids_list_to_values(values) return (SchemaState(full_dict=values, db=self.db, logged_in_user=self.logged_in_user), collections_referenced)
def _update_file(self, file_): """Update a local file model. :param file_: a file model object to update. :param request.body: a JSON object containing the data for updating the file. :returns: the file model or, if the file has not been updated, ``False``. """ changed = False schema = FileUpdateSchema() data = json.loads(self.request.body.decode(self.request.charset)) state = SchemaState(full_dict=data, db=self.db, logged_in_user=self.logged_in_user) data = schema.to_python(data, state) file_, changed = _update_standard_metadata(file_, data, changed) if changed: file_.datetime_modified = datetime.datetime.utcnow() return file_ return changed
def _create_plain_file(self): """Create a local file using data from a ``Content-Type: multipart/form-data`` request. :param request.POST['filedata']: a ``cgi.FieldStorage`` object containing the file data. :param str request.POST['filename']: the name of the binary file. :returns: an SQLAlchemy model object representing the file. .. note:: The validator expects ``request.POST`` to encode list input via the ``formencode.variabledecode.NestedVariables`` format. E.g., a list of form ``id`` values would be provided as values to keys with names like ``'forms-0'``, ``'forms-1'``, ``'forms-2'``, etc. """ values = dict(self.request.params) filedata = self.request.POST.get('filedata') if not hasattr(filedata, 'file'): raise InvalidFieldStorageObjectError( 'POST filedata has no "file" attribute') if not values.get('filename'): values['filename'] = os.path.split(filedata.filename)[-1] state = SchemaState(full_dict={}, db=self.db, filedata_first_KB=filedata.value[:1024]) schema = FileCreateWithFiledataSchema() data = schema.to_python(values, state) file_ = File(filename=h.normalize(data['filename']), MIME_type=data['MIME_type']) files_path = h.get_old_directory_path('files', self.request.registry.settings) file_path = os.path.join(files_path, file_.filename) file_object, file_path = _get_unique_file_path(file_path) file_.filename = os.path.split(file_path)[-1] file_.name = file_.filename shutil.copyfileobj(filedata.file, file_object) filedata.file.close() file_object.close() file_.size = os.path.getsize(file_path) file_ = self._add_standard_metadata(file_, data) return file_