def _test_bundle_delete(self, replica: Replica, fixtures_bucket: str, authorized: bool):
        schema = replica.storage_schema

        # prep existing bundle
        bundle_uuid = str(uuid.uuid4())
        file_uuid = str(uuid.uuid4())
        resp_obj = self.upload_file_wait(
            f"{schema}://{fixtures_bucket}/test_good_source_data/0",
            replica,
            file_uuid,
            bundle_uuid=bundle_uuid,
        )
        file_version = resp_obj.json['version']

        bundle_version = datetime_to_version_format(datetime.datetime.utcnow())
        self.put_bundle(
            replica,
            bundle_uuid,
            [(file_uuid, file_version, "LICENSE")],
            bundle_version,
        )

        handle = Config.get_blobstore_handle(replica)
        bucket = replica.bucket

        self.delete_bundle(replica, bundle_uuid, authorized=authorized)
        tombstone_exists = test_object_exists(handle, bucket, f"bundles/{bundle_uuid}.dead")
        self.assertEquals(tombstone_exists, authorized)

        self.delete_bundle(replica, bundle_uuid, bundle_version, authorized=authorized)
        tombstone_exists = test_object_exists(handle, bucket, f"bundles/{bundle_uuid}.{bundle_version}.dead")
        self.assertEquals(tombstone_exists, authorized)
Beispiel #2
0
def get_impl(uuid: str, replica: str, version: str = None):
    uuid = uuid.lower()
    bucket = Replica[replica].bucket
    handle = Config.get_blobstore_handle(Replica[replica])

    tombstone_key = CollectionTombstoneID(uuid, version=None).to_key()
    if test_object_exists(handle, bucket, tombstone_key):
        raise DSSException(
            404, "not_found",
            "Could not find collection for UUID {}".format(uuid))

    if version is None:
        # list the collections and find the one that is the most recent.
        prefix = CollectionFQID(uuid, version=None).to_key_prefix()
        for matching_key in handle.list(bucket, prefix):
            matching_key = matching_key[len(prefix):]
            if version is None or matching_key > version:
                version = matching_key
    try:
        collection_blob = handle.get(bucket,
                                     CollectionFQID(uuid, version).to_key())
    except BlobNotFoundError:
        raise DSSException(
            404, "not_found",
            "Could not find collection for UUID {}".format(uuid))
    return json.loads(collection_blob)
Beispiel #3
0
def _idempotent_save(blobstore: BlobStore, bucket: str, key: str,
                     data: dict) -> typing.Tuple[bool, bool]:
    """
    _idempotent_save attempts to save an object to the BlobStore. Its return values indicate whether the save was made
    successfully and whether the operation could be completed idempotently. If the data in the blobstore does not match
    the data parameter, the data in the blobstore is _not_ overwritten.

    :param blobstore: the blobstore to save the data to
    :param bucket: the bucket in the blobstore to save the data to
    :param key: the key of the object to save
    :param data: the data to save
    :return: a tuple of booleans (was the data saved?, was the save idempotent?)
    """
    if test_object_exists(blobstore, bucket, key):
        # fetch the file metadata, compare it to what we have.
        existing_data = json.loads(blobstore.get(bucket, key).decode("utf-8"))
        return False, existing_data == data
    else:
        # write manifest to persistent store
        blobstore.upload_file_handle(
            bucket,
            key,
            io.BytesIO(json.dumps(data).encode("utf-8")),
        )
        return True, True
Beispiel #4
0
def delete(uuid: str,
           replica: str,
           json_request_body: dict,
           version: str = None):
    email = request.token_info['email']

    if email not in ADMIN_USER_EMAILS:
        raise DSSException(
            requests.codes.forbidden,
            "forbidden",
            f"You can't delete bundles with these credentials!",
        )

    uuid = uuid.lower()
    version = datetime_to_version_format(
        iso8601.parse_date(version)) if version else None

    tombstone_id = TombstoneID(uuid=uuid, version=version)
    bundle_prefix = tombstone_id.to_key_prefix()
    tombstone_object_data = _create_tombstone_data(
        email=email,
        reason=json_request_body.get('reason'),
        version=version,
    )

    handle = Config.get_blobstore_handle(Replica[replica])
    bucket = Replica[replica].bucket

    if test_object_exists(handle,
                          bucket,
                          bundle_prefix,
                          test_type=ObjectTest.PREFIX):
        created, idempotent = _idempotent_save(handle, bucket,
                                               tombstone_id.to_key(),
                                               tombstone_object_data)
        if not idempotent:
            raise DSSException(
                requests.codes.conflict,
                f"bundle_tombstone_already_exists",
                f"bundle tombstone with UUID {uuid} and version {version} already exists",
            )
        status_code = requests.codes.ok
        response_body = dict()  # type: dict
    else:
        status_code = requests.codes.not_found
        response_body = dict(title="bundle not found")

    return jsonify(response_body), status_code
Beispiel #5
0
def delete(uuid: str,
           replica: str,
           json_request_body: dict,
           version: str = None):
    email = security.get_token_email(request.token_info)

    if email not in ADMIN_USER_EMAILS:
        raise DSSForbiddenException(
            "You can't delete bundles with these credentials!")

    uuid = uuid.lower()
    tombstone_id = BundleTombstoneID(uuid=uuid, version=version)
    bundle_prefix = tombstone_id.to_key_prefix()
    tombstone_object_data = _create_tombstone_data(
        email=email,
        reason=json_request_body.get('reason'),
        version=version,
    )

    handle = Config.get_blobstore_handle(Replica[replica])
    if not test_object_exists(handle,
                              Replica[replica].bucket,
                              bundle_prefix,
                              test_type=ObjectTest.PREFIX):
        raise DSSException(404, "not_found", "Cannot find bundle!")

    created, idempotent = idempotent_save(
        handle, Replica[replica].bucket, tombstone_id.to_key(),
        json.dumps(tombstone_object_data).encode("utf-8"))
    if not idempotent:
        raise DSSException(
            requests.codes.conflict,
            f"bundle_tombstone_already_exists",
            f"bundle tombstone with UUID {uuid} and version {version} already exists",
        )

    return dict(), requests.codes.ok
Beispiel #6
0
 def tombstone_exists(uuid: str, version: typing.Optional[str]):
     return test_object_exists(
         handle, bucket,
         TombstoneID(uuid=uuid, version=version).to_key())