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)
async def read(self, organization_id: OrganizationID, block_id: UUID) -> bytes: try: return self._blocks[(organization_id, block_id)] except KeyError: raise BlockNotFoundError()
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]
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)
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")
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")
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)
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")
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)
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
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")
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()
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
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)