async def _realm_get_clear_role_certifs(sock, realm_id): rep = await realm_get_role_certificates(sock, realm_id) assert rep["status"] == "ok" cooked = [ RealmRoleCertificateContent.unsecure_load(certif) for certif in rep["certificates"] ] return [item for item in sorted(cooked, key=lambda x: x.timestamp)]
async def _load_realm_role_certificates(self, realm_id: Optional[EntryID] = None ): rep = await self._backend_cmds("realm_get_role_certificates", realm_id or self.workspace_id) if rep["status"] == "not_allowed": # Seems we lost the access to the realm raise FSWorkspaceNoReadAccess( "Cannot get workspace roles: no read access") elif rep["status"] != "ok": raise FSError( f"Cannot retrieve workspace roles: `{rep['status']}`") try: # Must read unverified certificates to access metadata unsecure_certifs = sorted( [(RealmRoleCertificateContent.unsecure_load(uv_role), uv_role) for uv_role in rep["certificates"]], key=lambda x: x[0].timestamp, ) current_roles = {} owner_only = (RealmRole.OWNER, ) owner_or_manager = (RealmRole.OWNER, RealmRole.MANAGER) # Now verify each certif for unsecure_certif, raw_certif in unsecure_certifs: author = await self.remote_device_manager.get_device( unsecure_certif.author) RealmRoleCertificateContent.verify_and_load( raw_certif, author_verify_key=author.verify_key, expected_author=author.device_id, ) # Make sure author had the right to do this existing_user_role = current_roles.get(unsecure_certif.user_id) if not current_roles and unsecure_certif.user_id == author.device_id.user_id: # First user is autosigned needed_roles = (None, ) elif (existing_user_role in owner_or_manager or unsecure_certif.role in owner_or_manager): needed_roles = owner_only else: needed_roles = owner_or_manager if current_roles.get( unsecure_certif.author.user_id) not in needed_roles: raise FSError( f"Invalid realm role certificates: " f"{unsecure_certif.author} has not right to give " f"{unsecure_certif.role} role to {unsecure_certif.user_id} " f"on {unsecure_certif.timestamp}") if unsecure_certif.role is None: current_roles.pop(unsecure_certif.user_id, None) else: current_roles[ unsecure_certif.user_id] = unsecure_certif.role # Decryption error except DataError as exc: raise FSError(f"Invalid realm role certificates: {exc}") from exc # Now unsecure_certifs is no longer unsecure we have valided it items return [c for c, _ in unsecure_certifs], current_roles