async def check_event_allowed(self, event: EventBase, context: EventContext) -> Union[bool, dict]: """Check if a provided event should be allowed in the given context. The module can return: * True: the event is allowed. * False: the event is not allowed, and should be rejected with M_FORBIDDEN. * a dict: replacement event data. Args: event: The event to be checked. context: The context of the event. Returns: The result from the ThirdPartyRules module, as above """ if self.third_party_rules is None: return True prev_state_ids = await context.get_prev_state_ids() # Retrieve the state events from the database. events = await self.store.get_events(prev_state_ids.values()) state_events = {(ev.type, ev.state_key): ev for ev in events.values()} # Ensure that the event is frozen, to make sure that the module is not tempted # to try to modify it. Any attempt to modify it at this point will invalidate # the hashes and signatures. event.freeze() return await self.third_party_rules.check_event_allowed( event, state_events)
async def check_event_allowed( self, event: EventBase, context: EventContext ) -> Tuple[bool, Optional[dict]]: """Check if a provided event should be allowed in the given context. The module can return: * True: the event is allowed. * False: the event is not allowed, and should be rejected with M_FORBIDDEN. If the event is allowed, the module can also return a dictionary to use as a replacement for the event. Args: event: The event to be checked. context: The context of the event. Returns: The result from the ThirdPartyRules module, as above. """ # Bail out early without hitting the store if we don't have any callbacks to run. if len(self._check_event_allowed_callbacks) == 0: return True, None prev_state_ids = await context.get_prev_state_ids() # Retrieve the state events from the database. events = await self.store.get_events(prev_state_ids.values()) state_events = {(ev.type, ev.state_key): ev for ev in events.values()} # Ensure that the event is frozen, to make sure that the module is not tempted # to try to modify it. Any attempt to modify it at this point will invalidate # the hashes and signatures. event.freeze() for callback in self._check_event_allowed_callbacks: try: res, replacement_data = await callback(event, state_events) except SynapseError as e: # FIXME: Being able to throw SynapseErrors is relied upon by # some modules. PR #10386 accidentally broke this ability. # That said, we aren't keen on exposing this implementation detail # to modules and we should one day have a proper way to do what # is wanted. # This module callback needs a rework so that hacks such as # this one are not necessary. raise e except Exception: raise ModuleFailedException( "Failed to run `check_event_allowed` module API callback" ) # Return if the event shouldn't be allowed or if the module came up with a # replacement dict for the event. if res is False: return res, None elif isinstance(replacement_data, dict): return True, replacement_data return True, None
async def check_event_allowed( self, event: EventBase, context: EventContext) -> Tuple[bool, Optional[dict]]: """Check if a provided event should be allowed in the given context. The module can return: * True: the event is allowed. * False: the event is not allowed, and should be rejected with M_FORBIDDEN. If the event is allowed, the module can also return a dictionary to use as a replacement for the event. Args: event: The event to be checked. context: The context of the event. Returns: The result from the ThirdPartyRules module, as above. """ # Bail out early without hitting the store if we don't have any callbacks to run. if len(self._check_event_allowed_callbacks) == 0: return True, None prev_state_ids = await context.get_prev_state_ids() # Retrieve the state events from the database. events = await self.store.get_events(prev_state_ids.values()) state_events = {(ev.type, ev.state_key): ev for ev in events.values()} # Ensure that the event is frozen, to make sure that the module is not tempted # to try to modify it. Any attempt to modify it at this point will invalidate # the hashes and signatures. event.freeze() for callback in self._check_event_allowed_callbacks: try: res, replacement_data = await callback(event, state_events) except Exception as e: logger.warning("Failed to run module API callback %s: %s", callback, e) continue # Return if the event shouldn't be allowed or if the module came up with a # replacement dict for the event. if res is False: return res, None elif isinstance(replacement_data, dict): return True, replacement_data return True, None