Beispiel #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}.")
Beispiel #2
0
    def get_latest_version(self, did):
        '''
        Get the lattest record version given did
        '''
        ret = {}
        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')

            query = session.query(IndexRecord)
            records = query.filter(IndexRecord.baseid == record.baseid) \
                .order_by(IndexRecord.updated_date).all()

            if (not records):
                raise NoRecordFound('no record found')

            record = records[-1]

            rev = record.rev
            did = record.did

            form = record.form
            size = record.size
            file_name = record.file_name

            metadata = {m.key: m.value for m in record.index_metadata}
            version = record.version

            urls = [u.url for u in record.urls]
            hashes = {h.hash_type: h.hash_value for h in record.hashes}

            created_date = record.created_date.isoformat()
            updated_date = record.updated_date.isoformat()

            ret = {
                'did': did,
                'rev': rev,
                'size': size,
                'file_name': file_name,
                'metadata': metadata,
                'version': version,
                'urls': urls,
                'hashes': hashes,
                'form': form,
                'created_date': created_date,
                'updated_date': updated_date,
            }

        return ret
Beispiel #3
0
    def get_latest_version(self, did, has_version=None):
        """
        Get the lattest record version given did
        """
        with self.session as session:
            query = session.query(IndexRecord)
            query = query.filter(IndexRecord.did == did)

            try:
                record = query.one()
                baseid = record.baseid
            except NoResultFound:
                baseid = did
            except MultipleResultsFound:
                raise MultipleRecordsFound('multiple records found')

            query = session.query(IndexRecord)
            query = query.filter(IndexRecord.baseid == baseid) \
                .order_by(IndexRecord.created_date.desc())
            if has_version:
                query = query.filter(IndexRecord.version.isnot(None))
            record = query.first()
            if (not record):
                raise NoRecordFound('no record found')

            return record.to_document_dict()
Beispiel #4
0
    def get_all_versions(self, did):
        """
        Get all record versions given did
        """
        ret = dict()
        with self.session as session:
            query = session.query(IndexRecord)
            query = query.filter(IndexRecord.did == did)

            try:
                record = query.one()
                baseid = record.baseid
            except NoResultFound:
                record = session.query(BaseVersion).filter_by(baseid=did).first()
                if not record:
                    raise NoRecordFound('no record found')
                else:
                    baseid = record.baseid
            except MultipleResultsFound:
                raise MultipleRecordsFound('multiple records found')

            query = session.query(IndexRecord)
            records = query.filter(IndexRecord.baseid == baseid).all()

            for idx, record in enumerate(records):

                ret[idx] = record.to_document_dict()

        return ret
Beispiel #5
0
    def get(self, did):
        '''
        Gets a record given the record id.
        '''
        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')

            rev = record.rev

            form = record.form
            size = record.size

            urls = [u.url for u in record.urls]
            hashes = {h.hash_type: h.hash_value for h in record.hashes}

        ret = {
            'did': did,
            'rev': rev,
            'size': size,
            'urls': urls,
            'hashes': hashes,
            'form': form,
        }

        return ret
Beispiel #6
0
    def update(self, did, rev, urls=None, file_name=None, version=None):
        '''
        Updates an existing record with new values.
        '''
        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')

            if urls is not None:
                record.urls = [
                    IndexRecordUrl(did=record.did, url=url) for url in urls
                ]

            if file_name is not None:
                record.file_name = file_name

            if version is not None:
                record.version = version

            record.rev = str(uuid.uuid4())[:8]

            session.add(record)

            return record.did, record.baseid, record.rev
Beispiel #7
0
    def get_aliases_for_did(self, did):
        """
        Gets the aliases for a did
        """
        with self.session as session:
            self.logger.info(f"Trying to get all 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)

            query = session.query(IndexRecordAlias).filter(IndexRecordAlias.did == did)
            return [i.name for i in query]
Beispiel #8
0
    def get_all_versions(self, did):
        '''
        Get all record versions given did
        '''
        ret = dict()
        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')

            query = session.query(IndexRecord)
            records = query.filter(IndexRecord.baseid == record.baseid).all()

            for idx, record in enumerate(records):
                rev = record.rev
                did = record.did
                form = record.form

                size = record.size
                file_name = record.file_name
                version = record.version
                urls = [u.url for u in record.urls]
                hashes = {h.hash_type: h.hash_value for h in record.hashes}
                metadata = {m.key: m.value for m in record.index_metadata}

                created_date = record.created_date.isoformat()
                updated_date = record.updated_date.isoformat()

                ret[idx] = {
                    'did': did,
                    'rev': rev,
                    'size': size,
                    'file_name': file_name,
                    'metadata': metadata,
                    'version': version,
                    'urls': urls,
                    'hashes': hashes,
                    'form': form,
                    'created_date': created_date,
                    'updated_date': updated_date,
                }

        return ret
Beispiel #9
0
    def get(self, did):
        """
        Gets a record given the record id or baseid.
        If the given id is a baseid, it will return the latest version
        """
        with self.session as session:
            query = session.query(IndexRecord)
            query = query.filter(
                or_(IndexRecord.did == did, IndexRecord.baseid == did)
                ).order_by(IndexRecord.created_date.desc())

            record = query.first()
            if record is None:
                raise NoRecordFound('no record found')
            return record.to_document_dict()
Beispiel #10
0
 def get_by_alias(self, alias):
     """
     Gets a record given a record alias
     """
     with self.session as session:
         try:
             record = (
                 session.query(IndexRecord)
                 .filter(IndexRecord.aliases.any(name=alias)).one()
             )
         except NoResultFound:
             raise NoRecordFound('no record found')
         except MultipleResultsFound:
             raise MultipleRecordsFound('multiple records found')
         return record.to_document_dict()
Beispiel #11
0
    def get(self, did):
        '''
        Gets a record given the record id.
        '''
        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')

            baseid = record.baseid
            rev = record.rev

            form = record.form
            size = record.size

            file_name = record.file_name
            version = record.version

            urls = [u.url for u in record.urls]
            hashes = {h.hash_type: h.hash_value for h in record.hashes}
            metadata = {m.key: m.value for m in record.index_metadata}

            created_date = record.created_date.isoformat()
            updated_date = record.updated_date.isoformat()

            ret = {
                'did': did,
                'baseid': baseid,
                'rev': rev,
                'size': size,
                'file_name': file_name,
                'version': version,
                'urls': urls,
                'hashes': hashes,
                'metadata': metadata,
                'form': form,
                'created_date': created_date,
                "updated_date": updated_date,
            }

        return ret
Beispiel #12
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}"
                )
Beispiel #13
0
    def update_blank_record(self, did, rev, size, hashes, urls):
        """
        Update a blank record with size and hashes, raise exception
        if the record is non-empty or the revision is not matched
        """
        hashes = hashes or {}
        urls = urls or []

        if not size or not hashes:
            raise UserError("No size or hashes provided")

        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 record.size or record.hashes:
                raise UserError("update api is not supported for non-empty record!")

            if rev != record.rev:
                raise RevisionMismatch('revision mismatch')

            record.size = size
            record.hashes = [IndexRecordHash(
                did=record.did,
                hash_type=h,
                hash_value=v,
            ) for h, v in hashes.items()]
            record.urls = [IndexRecordUrl(
                did=record.did,
                url=url,
            ) for url in urls]

            record.rev = str(uuid.uuid4())[:8]

            session.add(record)
            session.commit()

            return record.did, record.rev, record.baseid
Beispiel #14
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')

            session.delete(record)
Beispiel #15
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)
Beispiel #16
0
    def update(self, did, rev, size=None, urls=None, hashes=None):
        '''
        Updates an existing record with new values.
        '''
        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')

            if size is not None:
                record.size = size

            if urls is not None:
                record.urls = [
                    IndexRecordUrl(did=record, url=url) for url in urls
                ]

            if hashes is not None:
                record.hashes = [
                    IndexRecordHash(
                        did=record,
                        hash_type=h,
                        hash_value=v,
                    ) for h, v in hashes.items()
                ]

            record.rev = str(uuid.uuid4())[:8]

            session.add(record)

            return record.did, record.rev
Beispiel #17
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}"
                )
Beispiel #18
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,
                    hashes=None):
        """
        Add a record version given did
        """
        urls = urls or []
        acl = acl 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')

            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.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
Beispiel #19
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
Beispiel #20
0
    def update(self, did, rev, changing_fields):
        """
        Updates an existing record with new values.
        """

        composite_fields = ['urls', 'acl', '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')

            # 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 changing_fields['acl']
                ]

            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
Beispiel #21
0
    def add_version(self,
                    did,
                    form,
                    size=None,
                    file_name=None,
                    metadata=None,
                    version=None,
                    urls=None,
                    hashes=None):
        '''
        Add a record version given did
        '''
        if urls is None:
            urls = []
        if hashes is None:
            hashes = {}
        if metadata is None:
            metadata = {}
        with self.session as session:
            query = session.query(IndexRecord).filter_by(did=did)

            try:
                record = query.one()
            except NoResultFound:
                raise NoRecordFound('no record found')
            except MultipleResultsFound:
                raise MultipleRecordsFound('multiple records found')

            baseid = record.baseid
            record = IndexRecord()
            did = 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.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)
                session.commit()
            except IntegrityError:
                raise UserError('{did} already exists'.format(did=did), 400)

            return record.did, record.baseid, record.rev