Example #1
0
    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}.")
Example #2
0
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
Example #3
0
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
Example #4
0
    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}"
                )
Example #5
0
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
Example #6
0
    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)
Example #7
0
    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}"
                )
Example #8
0
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
Example #9
0
    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
Example #10
0
    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