def delete_one_alias_for_did(self, alias, did): """ Delete one of this DID / GUID's aliases. """ with self.session as session: self.logger.info(f"Trying to delete alias {alias} for did {did}...") index_record = get_record_if_exists(did, session) if index_record is None: self.logger.warn(f"No record found for did {did}") raise NoRecordFound(did) # authorization try: resources = [u.resource for u in index_record.authz] auth.authorize("delete", resources) except AuthError as err: self.logger.warn( f"Auth error deleting alias {alias} for did {did}: User not authorized to delete one or more of these resources: {resources}" ) raise err # delete just this alias num_rows_deleted = ( session.query(IndexRecordAlias) .filter(IndexRecordAlias.did == did, IndexRecordAlias.name == alias) .delete(synchronize_session="evaluate") ) if num_rows_deleted == 0: self.logger.warn(f"No alias {alias} found for did {did}") raise NoRecordFound(alias) self.logger.info(f"Deleted alias {alias} for did {did}.")
def delete_bundle_record(bundle_id): """ Delete bundle record given bundle_id """ auth.authorize("delete", ["/services/indexd/bundles"]) blueprint.index_driver.delete_bundle(bundle_id) return "", 200
def delete_bundle_record(bundle_id): """ Delete bundle record given bundle_id """ try: authorize("delete", ["/services/indexd/bundles"]) except: raise AuthError("Invalid Token.") blueprint.index_driver.delete_bundle(bundle_id) return "", 200
def replace_aliases_for_did(self, aliases, did): """ Replace all aliases for one DID / GUID with new aliases. """ with self.session as session: self.logger.info( f"Trying to replace aliases for did {did} with new aliases {aliases}..." ) index_record = get_record_if_exists(did, session) if index_record is None: self.logger.warn(f"No record found for did {did}") raise NoRecordFound(did) # authorization try: resources = [u.resource for u in index_record.authz] auth.authorize("update", resources) except AuthError as err: self.logger.warn( f"Auth error while replacing aliases for did {did}: User not authorized to update one or more of these resources: {resources}" ) raise err try: # delete this GUID's aliases session.query(IndexRecordAlias).filter( IndexRecordAlias.did == did ).delete(synchronize_session="evaluate") # add new aliases index_record_aliases = [ IndexRecordAlias(did=did, name=alias) for alias in aliases ] session.add_all(index_record_aliases) session.commit() self.logger.info( f"Replaced aliases for did {did} with new aliases {aliases}" ) except IntegrityError: # One or more aliases in request were non-unique self.logger.warn( f"One or more aliases in request already associated with another GUID: {aliases}" ) raise UserError( f"One or more aliases in request already associated with another GUID: {aliases}" )
def post_index_record(): """ Create a new record. """ try: jsonschema.validate(flask.request.json, POST_RECORD_SCHEMA) except jsonschema.ValidationError as err: raise UserError(err) authz = flask.request.json.get("authz", []) auth.authorize("create", authz) did = flask.request.json.get("did") form = flask.request.json["form"] size = flask.request.json["size"] urls = flask.request.json["urls"] acl = flask.request.json.get("acl", []) hashes = flask.request.json["hashes"] file_name = flask.request.json.get("file_name") metadata = flask.request.json.get("metadata") urls_metadata = flask.request.json.get("urls_metadata") version = flask.request.json.get("version") baseid = flask.request.json.get("baseid") uploader = flask.request.json.get("uploader") did, rev, baseid = blueprint.index_driver.add( form, did, size=size, file_name=file_name, metadata=metadata, urls_metadata=urls_metadata, version=version, urls=urls, acl=acl, authz=authz, hashes=hashes, baseid=baseid, uploader=uploader, ) ret = {"did": did, "rev": rev, "baseid": baseid} return flask.jsonify(ret), 200
def delete(self, did, rev): """ Removes record if stored by backend. """ with self.session as session: query = session.query(IndexRecord) query = query.filter(IndexRecord.did == did) try: record = query.one() except NoResultFound: raise NoRecordFound("no record found") except MultipleResultsFound: raise MultipleRecordsFound("multiple records found") if rev != record.rev: raise RevisionMismatch("revision mismatch") auth.authorize("delete", [u.resource for u in record.authz]) session.delete(record)
def append_aliases_for_did(self, aliases, did): """ Append one or more aliases to aliases already associated with one DID / GUID. """ with self.session as session: self.logger.info( f"Trying to append new aliases {aliases} to aliases for did {did}..." ) index_record = get_record_if_exists(did, session) if index_record is None: self.logger.warn(f"No record found for did {did}") raise NoRecordFound(did) # authorization try: resources = [u.resource for u in index_record.authz] auth.authorize("update", resources) except AuthError as err: self.logger.warn( f"Auth error while appending aliases to did {did}: User not authorized to update one or more of these resources: {resources}" ) raise err # add new aliases index_record_aliases = [ IndexRecordAlias(did=did, name=alias) for alias in aliases ] try: session.add_all(index_record_aliases) session.commit() except IntegrityError as err: # One or more aliases in request were non-unique self.logger.warn( f"One or more aliases in request already associated with this or another GUID: {aliases}" ) raise UserError( f"One or more aliases in request already associated with this or another GUID: {aliases}" )
def post_bundle(): """ Create a new bundle """ auth.authorize("create", ["/services/indexd/bundles"]) try: jsonschema.validate(flask.request.json, BUNDLE_SCHEMA) except jsonschema.ValidationError as err: raise UserError(err) name = flask.request.json.get("name") bundles = flask.request.json.get("bundles") bundle_id = flask.request.json.get("bundle_id") size = flask.request.json.get("size") if flask.request.json.get("size") else 0 description = ( flask.request.json.get("description") if flask.request.json.get("description") else "" ) version = ( flask.request.json.get("version") if flask.request.json.get("version") else "" ) aliases = ( flask.request.json.get("aliases") if flask.request.json.get("aliases") else [] ) if len(bundles) == 0: raise UserError("Bundle data required.") if len(bundles) != len(set(bundles)): raise UserError("Duplicate GUID in bundles.") if bundle_id in bundles: raise UserError("Bundle refers to itself.") bundle_data = [] checksums = [] # TODO: Remove this after updating to jsonschema>=3.0.0 if flask.request.json.get("checksums"): hashes = { checksum["type"]: checksum["checksum"] for checksum in flask.request.json.get("checksums") } validate_hashes(**hashes) # get bundles/records that already exists and add it to bundle_data for bundle in bundles: data = get_index_record(bundle)[0] data = data.json size += data["size"] if not flask.request.json.get("size") else 0 checksums.append(get_checksum(data)) data = bundle_to_drs(data, expand=True, is_content=True) bundle_data.append(data) checksum = ( flask.request.json.get("checksums") if flask.request.json.get("checksums") else [compute_checksum(checksums)] ) ret = blueprint.index_driver.add_bundle( bundle_id=bundle_id, name=name, size=size, bundle_data=json.dumps(bundle_data), checksum=json.dumps(checksum), description=description, version=version, aliases=json.dumps(aliases), ) return flask.jsonify({"bundle_id": ret[0], "name": ret[1], "contents": ret[2]}), 200
def update(self, did, rev, changing_fields): """ Updates an existing record with new values. """ composite_fields = ["urls", "acl", "authz", "metadata", "urls_metadata"] with self.session as session: query = session.query(IndexRecord).filter(IndexRecord.did == did) try: record = query.one() except NoResultFound: raise NoRecordFound("no record found") except MultipleResultsFound: raise MultipleRecordsFound("multiple records found") if rev != record.rev: raise RevisionMismatch("revision mismatch") auth.authorize("update", [u.resource for u in record.authz]) # Some operations are dependant on other operations. For example # urls has to be updated before urls_metadata because of schema # constraints. if "urls" in changing_fields: for url in record.urls: session.delete(url) record.urls = [ IndexRecordUrl(did=record.did, url=url) for url in changing_fields["urls"] ] if "acl" in changing_fields: for ace in record.acl: session.delete(ace) record.acl = [ IndexRecordACE(did=record.did, ace=ace) for ace in set(changing_fields["acl"]) ] if "authz" in changing_fields: for resource in record.authz: session.delete(resource) record.authz = [ IndexRecordAuthz(did=record.did, resource=resource) for resource in set(changing_fields["authz"]) ] if "metadata" in changing_fields: for md_record in record.index_metadata: session.delete(md_record) record.index_metadata = [ IndexRecordMetadata(did=record.did, key=m_key, value=m_value) for m_key, m_value in changing_fields["metadata"].items() ] if "urls_metadata" in changing_fields: for url in record.urls: for url_metadata in url.url_metadata: session.delete(url_metadata) create_urls_metadata(changing_fields["urls_metadata"], record, session) for key, value in changing_fields.items(): if key not in composite_fields: # No special logic needed for other updates. # ie file_name, version, etc setattr(record, key, value) record.rev = str(uuid.uuid4())[:8] session.add(record) return record.did, record.baseid, record.rev
def add_version( self, current_did, form, new_did=None, size=None, file_name=None, metadata=None, urls_metadata=None, version=None, urls=None, acl=None, authz=None, hashes=None, ): """ Add a record version given did """ urls = urls or [] acl = acl or [] authz = authz or [] hashes = hashes or {} metadata = metadata or {} urls_metadata = urls_metadata or {} with self.session as session: query = session.query(IndexRecord).filter_by(did=current_did) try: record = query.one() except NoResultFound: raise NoRecordFound("no record found") except MultipleResultsFound: raise MultipleRecordsFound("multiple records found") auth.authorize("update", [u.resource for u in record.authz] + authz) baseid = record.baseid record = IndexRecord() did = new_did or str(uuid.uuid4()) record.did = did record.baseid = baseid record.rev = str(uuid.uuid4())[:8] record.form = form record.size = size record.file_name = file_name record.version = version record.urls = [IndexRecordUrl(did=record.did, url=url) for url in urls] record.acl = [IndexRecordACE(did=record.did, ace=ace) for ace in set(acl)] record.authz = [ IndexRecordAuthz(did=record.did, resource=resource) for resource in set(authz) ] record.hashes = [ IndexRecordHash(did=record.did, hash_type=h, hash_value=v) for h, v in hashes.items() ] record.index_metadata = [ IndexRecordMetadata(did=record.did, key=m_key, value=m_value) for m_key, m_value in metadata.items() ] try: session.add(record) create_urls_metadata(urls_metadata, record, session) session.commit() except IntegrityError: raise UserError("{did} already exists".format(did=did), 400) return record.did, record.baseid, record.rev