Example #1
0
    async def upload(self, bundle: Bundle, identity: Identity) -> Revision:
        vault = cast(
            Vault, self.vault)  # We can savely cast because of @require_vault

        logger.info("Uploading %s", bundle)
        dest_path = os.path.join(self.path, bundle.store_hash)
        shutil.copyfile(bundle.path, dest_path)

        metadata = await bundle.encrypted_metadata_reader().readall()
        len(metadata)

        if bundle.local_hash is None:
            raise ValueError("Please update bundle before upload.")

        await bundle.load_key()
        s = vault.crypt_engine.read_encrypted_stream(bundle) >> FileWriter(
            dest_path)
        await s.consume()
        # s = bundle.encrypted_metadata_reader() >> FileWriter(dest_path + ".metadata")
        # await s.consume()
        with open(dest_path + ".hash", "w") as hashfile:
            hashfile.write(bundle.local_hash)

        revision = Revision(operation=RevisionOp.Upload)
        revision.vault_id = vault.config.id
        revision.parent_id = vault.revision
        #revision.user_id = "user@localhost"
        revision.file_hash = bundle.store_hash
        revision.revision_metadata = metadata
        revision.crypt_hash = bundle.local_hash
        revision.file_size_crypt = bundle.file_size_crypt
        revision.sign(identity=identity)

        return self.add_revision(revision)
Example #2
0
    async def upload(self, bundle: Bundle, identity: Identity) -> Revision:
        vault = cast(Vault, self.vault) # We can savely cast because of @require_vault

        logger.info("Uploading %s", bundle)
        dest_path = os.path.join(self.path, bundle.store_hash)
        shutil.copyfile(bundle.path, dest_path)

        metadata = await bundle.encrypted_metadata_reader().readall()
        len(metadata)

        if bundle.local_hash is None:
            raise ValueError("Please update bundle before upload.")

        await bundle.load_key()
        s = vault.crypt_engine.read_encrypted_stream(bundle) >> FileWriter(dest_path)
        await s.consume()
        # s = bundle.encrypted_metadata_reader() >> FileWriter(dest_path + ".metadata")
        # await s.consume()
        with open(dest_path + ".hash", "w") as hashfile:
            hashfile.write(bundle.local_hash)

        revision = Revision(operation=RevisionOp.Upload)
        revision.vault_id = vault.config.id
        revision.parent_id = vault.revision
        #revision.user_id = "user@localhost"
        revision.file_hash = bundle.store_hash
        revision.revision_metadata = metadata
        revision.crypt_hash = bundle.local_hash
        revision.file_size_crypt = bundle.file_size_crypt
        revision.sign(identity=identity)

        return self.add_revision(revision)
Example #3
0
    async def upload(self, bundle, identity: Identity) -> Revision:

        vault = self.vault

        if vault is None:
            raise ValueError("Invalid argument")

        self.logger.info('Uploading %s', bundle)

        assert bundle.uptodate

        metadata = await bundle.encrypted_metadata_reader().readall()
        metadata_size = len(metadata)

        while True:
            revision = Revision(operation=RevisionOp.Upload)
            revision.vault_id = vault.config.id
            revision.parent_id = vault.revision
            revision.crypt_hash = bundle.local_hash
            revision.file_hash = bundle.store_hash
            revision.file_size_crypt = bundle.file_size_crypt
            revision.revision_metadata = metadata
            revision.sign(identity=identity)

            # upload key and file
            await self.write_term('upload',
                    revision.file_hash,
                    revision.crypt_hash,
                    revision.revision_metadata,
                    revision.file_size_crypt,
                    revision.user_fingerprint,
                    revision.signature,
                    revision.parent_id
                )

            response = await self.read_term(assert_ok=False)

            if response[0] == Atom('ok'):
                break
            elif response[0] == Atom('error') and \
                    isinstance(response[1], (list, tuple)) and \
                    response[1][0] == Atom('parent_revision_outdated'):
                logger.info('Revision outdated')
                await trio.sleep(10.0)
                continue
            else:
                raise ServerError(response)

        self.logger.debug('Uploading bundle (metadata: {0} bytes, content: {1} bytes)'\
                .format(metadata_size, bundle.file_size_crypt))

        bundle.bytes_written = 0
        upload_id = None
        urls = None
        reader = vault.crypt_engine.read_encrypted_stream(bundle)

        response = response[1] if len(response) > 1 else None

        if isinstance(response, tuple) and len(response) > 0 and response[0] == Atom('url'):
            if isinstance(response[1], tuple) and response[1][0] == Atom('multi'):
                _, upload_id, urls = response[1]
                chunksize = int(math.ceil(bundle.file_size_crypt * 1.0 / len(urls)))
                self.logger.info('Chunked URL upload to %d urls. chunksize=%d', len(urls), chunksize)
                writer = reader >> ChunkedURLWriter([u.decode() for u in urls], chunksize,\
                        total_size=bundle.file_size_crypt)
                url = None
            else:
                url = response[1].decode()
                self.logger.info('Non-chunked URL upload to %s.', url)
                writer = reader >> URLWriter(url, size=bundle.file_size_crypt)
                upload_id = None

            await writer.consume()

            if writer.bytes_written != bundle.file_size_crypt:
                self.logger.error('Uploaded size did not match: should be %d, is %d (diff %d)',
                        bundle.file_size_crypt, writer.bytes_written,
                        writer.bytes_written - bundle.file_size_crypt)
                raise Exception('Uploaded size did not match')

            if upload_id:
                await self.write_term('uploaded', (Atom('multi'), upload_id, writer.etags))
            else:
                await self.write_term('uploaded', url)
        else:
            self.logger.debug('Streaming upload requested.')

            writer = reader >> TrioStreamWriter(self.stream)
            await writer.consume()

            if writer.bytes_written != bundle.file_size_crypt:
                self.logger.error('Uploaded size did not match: should be %d, is %d (diff %d)',
                        bundle.file_size_crypt, writer.bytes_written,
                        writer.bytes_written - bundle.file_size_crypt)
                raise Exception('Uploaded size did not match')

        # server should return the response
        response = await self.read_response()
        ret_revision = self.server_info_to_revision(rewrite_atoms_dict(response), vault)
        revision.revision_id = ret_revision.revision_id
        revision.created_at = ret_revision.created_at
        return revision
Example #4
0
    async def upload(self, bundle, identity: Identity) -> Revision:

        vault = self.vault

        if vault is None:
            raise ValueError("Invalid argument")

        self.logger.info('Uploading %s', bundle)

        assert bundle.uptodate

        metadata = await bundle.encrypted_metadata_reader().readall()
        metadata_size = len(metadata)

        while True:
            revision = Revision(operation=RevisionOp.Upload)
            revision.vault_id = vault.config.id
            revision.parent_id = vault.revision
            revision.crypt_hash = bundle.local_hash
            revision.file_hash = bundle.store_hash
            revision.file_size_crypt = bundle.file_size_crypt
            revision.revision_metadata = metadata
            revision.sign(identity=identity)

            # upload key and file
            await self.write_term('upload', revision.file_hash,
                                  revision.crypt_hash,
                                  revision.revision_metadata,
                                  revision.file_size_crypt,
                                  revision.user_fingerprint,
                                  revision.signature, revision.parent_id)

            response = await self.read_term(assert_ok=False)

            if response[0] == Atom('ok'):
                break
            elif response[0] == Atom('error') and \
                    isinstance(response[1], (list, tuple)) and \
                    response[1][0] == Atom('parent_revision_outdated'):
                logger.info('Revision outdated')
                await trio.sleep(10.0)
                continue
            else:
                raise ServerError(response)

        self.logger.debug('Uploading bundle (metadata: {0} bytes, content: {1} bytes)'\
                .format(metadata_size, bundle.file_size_crypt))

        bundle.bytes_written = 0
        upload_id = None
        urls = None
        reader = vault.crypt_engine.read_encrypted_stream(bundle)

        response = response[1] if len(response) > 1 else None

        if isinstance(
                response,
                tuple) and len(response) > 0 and response[0] == Atom('url'):
            if isinstance(response[1],
                          tuple) and response[1][0] == Atom('multi'):
                _, upload_id, urls = response[1]
                chunksize = int(
                    math.ceil(bundle.file_size_crypt * 1.0 / len(urls)))
                self.logger.info('Chunked URL upload to %d urls. chunksize=%d',
                                 len(urls), chunksize)
                writer = reader >> ChunkedURLWriter([u.decode() for u in urls], chunksize,\
                        total_size=bundle.file_size_crypt)
                url = None
            else:
                url = response[1].decode()
                self.logger.info('Non-chunked URL upload to %s.', url)
                writer = reader >> URLWriter(url, size=bundle.file_size_crypt)
                upload_id = None

            await writer.consume()

            if writer.bytes_written != bundle.file_size_crypt:
                self.logger.error(
                    'Uploaded size did not match: should be %d, is %d (diff %d)',
                    bundle.file_size_crypt, writer.bytes_written,
                    writer.bytes_written - bundle.file_size_crypt)
                raise Exception('Uploaded size did not match')

            if upload_id:
                await self.write_term('uploaded',
                                      (Atom('multi'), upload_id, writer.etags))
            else:
                await self.write_term('uploaded', url)
        else:
            self.logger.debug('Streaming upload requested.')

            writer = reader >> TrioStreamWriter(self.stream)
            await writer.consume()

            if writer.bytes_written != bundle.file_size_crypt:
                self.logger.error(
                    'Uploaded size did not match: should be %d, is %d (diff %d)',
                    bundle.file_size_crypt, writer.bytes_written,
                    writer.bytes_written - bundle.file_size_crypt)
                raise Exception('Uploaded size did not match')

        # server should return the response
        response = await self.read_response()
        ret_revision = self.server_info_to_revision(
            rewrite_atoms_dict(response), vault)
        revision.revision_id = ret_revision.revision_id
        revision.created_at = ret_revision.created_at
        return revision