Ejemplo n.º 1
0
    async def read(
        self, organization_id: OrganizationID, author: DeviceID, block_id: BlockID
    ) -> bytes:
        async with self.dbh.pool.acquire() as conn, conn.transaction():
            realm_id_uuid = await conn.fetchval(
                *_q_get_realm_id_from_block_id(
                    organization_id=organization_id.str, block_id=block_id.uuid
                )
            )
            if not realm_id_uuid:
                raise BlockNotFoundError()
            realm_id = RealmID(realm_id_uuid)
            await _check_realm(conn, organization_id, realm_id, OperationKind.DATA_READ)
            ret = await conn.fetchrow(
                *_q_get_block_meta(
                    organization_id=organization_id.str,
                    block_id=block_id.uuid,
                    user_id=author.user_id.str,
                )
            )
            if not ret or ret["deleted_on"]:
                raise BlockNotFoundError()

            elif not ret["has_access"]:
                raise BlockAccessError()

        # We can do the blockstore read outside of the transaction given the block
        # are never modified/removed
        return await self._blockstore_component.read(organization_id, block_id)
Ejemplo n.º 2
0
    async def read(self, organization_id: OrganizationID,
                   block_id: UUID) -> bytes:
        try:
            return self._blocks[(organization_id, block_id)]

        except KeyError:
            raise BlockNotFoundError()
Ejemplo n.º 3
0
    async def read(self, organization_id: OrganizationID, id: UUID) -> bytes:
        async with self.dbh.pool.acquire() as conn:
            ret = await conn.fetchrow(_q_get_block_data, organization_id, id)
            if not ret:
                raise BlockNotFoundError()

            return ret[0]
Ejemplo n.º 4
0
    async def read(
        self, organization_id: OrganizationID, author: DeviceID, block_id: UUID
    ) -> bytes:
        async with self.dbh.pool.acquire() as conn, conn.transaction():
            realm_id = await conn.fetchval(_q_get_realm_id_from_block_id, organization_id, block_id)
            if not realm_id:
                raise BlockNotFoundError(f"Realm `{realm_id}` doesn't exist")
            await _check_realm(conn, organization_id, realm_id)
            ret = await conn.fetchrow(_q_get_block_meta, organization_id, block_id, author.user_id)
            if not ret or ret[0]:
                raise BlockNotFoundError()

            elif not ret[1]:
                raise BlockAccessError()

        return await self._blockstore_component.read(organization_id, block_id)
Ejemplo n.º 5
0
    def _check_realm_access(self, organization_id, realm_id, user_id, operation_kind):
        try:
            realm = self._realm_component._get_realm(organization_id, realm_id)
        except RealmNotFoundError:
            raise BlockNotFoundError(f"Realm `{realm_id}` doesn't exist")

        if operation_kind == operation_kind.DATA_READ:
            allowed_roles = (
                RealmRole.OWNER,
                RealmRole.MANAGER,
                RealmRole.CONTRIBUTOR,
                RealmRole.READER,
            )
        elif operation_kind == operation_kind.DATA_WRITE:
            allowed_roles = (RealmRole.OWNER, RealmRole.MANAGER, RealmRole.CONTRIBUTOR)
        elif operation_kind == operation_kind.MAINTENANCE:
            allowed_roles = (RealmRole.OWNER,)
        else:
            assert False, f"Operation kind {operation_kind} not supported"

        if realm.roles.get(user_id) not in allowed_roles:
            raise BlockAccessError()

        # Special case of reading while in reencryption is authorized
        if realm.status.in_reencryption and operation_kind == OperationKind.DATA_READ:
            pass
        # Access is not allowed while in maintenance
        elif realm.status.in_maintenance:
            raise BlockInMaintenanceError(f"Realm `{realm_id}` is currently under maintenance")
Ejemplo n.º 6
0
async def _check_realm(conn, organization_id, realm_id):
    try:
        rep = await get_realm_status(conn, organization_id, realm_id)

    except RealmNotFoundError as exc:
        raise BlockNotFoundError(*exc.args) from exc

    if rep["maintenance_type"]:
        raise BlockInMaintenanceError("Data realm is currently under maintenance")
Ejemplo n.º 7
0
    async def read(self, organization_id: OrganizationID, author: DeviceID,
                   block_id: BlockID) -> bytes:
        try:
            blockmeta = self._blockmetas[(organization_id, block_id)]

        except KeyError:
            raise BlockNotFoundError()

        self._check_realm_read_access(organization_id, blockmeta.realm_id,
                                      author.user_id)

        return await self._blockstore_component.read(organization_id, block_id)
Ejemplo n.º 8
0
    def _check_realm_access(self, organization_id, realm_id, user_id,
                            allowed_roles):
        try:
            realm = self._realm_component._get_realm(organization_id, realm_id)
        except RealmNotFoundError:
            raise BlockNotFoundError(f"Realm `{realm_id}` doesn't exist")

        if realm.roles.get(user_id) not in allowed_roles:
            raise BlockAccessError()

        if realm.status.in_maintenance:
            raise BlockInMaintenanceError(
                f"Realm `{realm_id}` is currently under maintenance")
Ejemplo n.º 9
0
    async def read(
        self, organization_id: OrganizationID, author: DeviceID, block_id: UUID
    ) -> bytes:
        async with self.dbh.pool.acquire() as conn, conn.transaction():
            realm_id = await conn.fetchval(
                *_q_get_realm_id_from_block_id(organization_id=organization_id, block_id=block_id)
            )
            if not realm_id:
                raise BlockNotFoundError(f"Realm `{realm_id}` doesn't exist")
            await _check_realm(conn, organization_id, realm_id, OperationKind.DATA_READ)
            ret = await conn.fetchrow(
                *_q_get_block_meta(
                    organization_id=organization_id, block_id=block_id, user_id=author.user_id
                )
            )
            if not ret or ret["deleted_on"]:
                raise BlockNotFoundError()

            elif not ret["has_access"]:
                raise BlockAccessError()

        return await self._blockstore_component.read(organization_id, block_id)
Ejemplo n.º 10
0
    async def read(self, organization_id: OrganizationID, id: UUID) -> bytes:
        slug = f"{organization_id}/{id}"
        try:
            headers, obj = await trio.to_thread.run_sync(
                self.swift_client.get_object, self._container, slug)

        except ClientException as exc:
            if exc.http_status == 404:
                raise BlockNotFoundError() from exc

            else:
                raise BlockTimeoutError() from exc

        return obj
Ejemplo n.º 11
0
async def _check_realm(conn, organization_id, realm_id, operation_kind):
    # Fetch the realm status maintenance type
    try:
        status = await get_realm_status(conn, organization_id, realm_id)
    except RealmNotFoundError as exc:
        raise BlockNotFoundError(*exc.args) from exc

    # Special case of reading while in reencryption is authorized
    if operation_kind == OperationKind.DATA_READ and status.in_reencryption:
        pass

    # Access is not allowed while in maintenance
    elif status.in_maintenance:
        raise BlockInMaintenanceError("Data realm is currently under maintenance")
Ejemplo n.º 12
0
    async def read(self, organization_id: OrganizationID, id: UUID) -> bytes:
        slug = f"{organization_id}/{id}"
        try:
            obj = self._s3.get_object(Bucket=self._s3_bucket, Key=slug)

        except S3ClientError as exc:
            if exc.response["Error"]["Code"] == "404":
                raise BlockNotFoundError() from exc

            else:
                raise BlockTimeoutError() from exc

        except S3EndpointConnectionError as exc:
            raise BlockTimeoutError() from exc

        return obj["Body"].read()
Ejemplo n.º 13
0
    async def read(self, organization_id: OrganizationID, id: UUID) -> bytes:
        async def _single_blockstore_read(nursery, blockstore):
            nonlocal value
            try:
                value = await blockstore.read(organization_id, id)
                nursery.cancel_scope.cancel()
            except (BlockNotFoundError, BlockTimeoutError):
                pass

        value = None
        async with trio.open_service_nursery() as nursery:
            for blockstore in self.blockstores:
                nursery.start_soon(_single_blockstore_read, nursery, blockstore)

        if not value:
            raise BlockNotFoundError()

        return value
Ejemplo n.º 14
0
 async def mock_backend_block_create(*args, **kwargs):
     nonlocal blocks_create_before_crash
     if blocks_create_before_crash == 0:
         raise BlockNotFoundError()
     blocks_create_before_crash -= 1
     return await vanilla_backend_block_create(*args, **kwargs)