diff --git a/synapse/events/third_party_rules.py b/synapse/events/third_party_rules.py index 72ab696898..0577085be8 100644 --- a/synapse/events/third_party_rules.py +++ b/synapse/events/third_party_rules.py @@ -45,6 +45,7 @@ CHECK_CAN_DEACTIVATE_USER_CALLBACK = Callable[[str, bool], Awaitable[bool]] ON_PROFILE_UPDATE_CALLBACK = Callable[[str, ProfileInfo, bool, bool], Awaitable] ON_USER_DEACTIVATION_STATUS_CHANGED_CALLBACK = Callable[[str, bool, bool], Awaitable] ON_THREEPID_BIND_CALLBACK = Callable[[str, str, str], Awaitable] +ON_UPDATE_IDENTITY_SERVER_BINDING_CALLBACK = Callable[[str, str, str, Optional[str]], Awaitable[bool]] def load_legacy_third_party_event_rules(hs: "HomeServer") -> None: @@ -174,6 +175,7 @@ class ThirdPartyEventRules: ON_USER_DEACTIVATION_STATUS_CHANGED_CALLBACK ] = [] self._on_threepid_bind_callbacks: List[ON_THREEPID_BIND_CALLBACK] = [] + self._on_update_identity_server_binding: List[ON_UPDATE_IDENTITY_SERVER_BINDING_CALLBACK] = [] def register_third_party_rules_callbacks( self, @@ -193,6 +195,7 @@ class ThirdPartyEventRules: ON_USER_DEACTIVATION_STATUS_CHANGED_CALLBACK ] = None, on_threepid_bind: Optional[ON_THREEPID_BIND_CALLBACK] = None, + on_update_identity_server_binding: Optional[ON_UPDATE_IDENTITY_SERVER_BINDING_CALLBACK] = None, ) -> None: """Register callbacks from modules for each hook.""" if check_event_allowed is not None: @@ -230,6 +233,9 @@ class ThirdPartyEventRules: if on_threepid_bind is not None: self._on_threepid_bind_callbacks.append(on_threepid_bind) + if on_update_identity_server_binding is not None: + self._on_update_identity_server_binding.append(on_update_identity_server_binding) + async def check_event_allowed( self, event: EventBase, context: EventContext ) -> Tuple[bool, Optional[dict]]: @@ -523,3 +529,24 @@ class ThirdPartyEventRules: logger.exception( "Failed to run module API callback %s: %s", callback, e ) + async def on_update_identity_server_binding(self, user_id: str, medium: str, address: str, id_server: Optional[str]) -> bool: + """Called before a binding between a third-party ID and a Matrix ID is made + against an identity server. + + Note that this callback is not called if a user only requests for an association + to be made between a third-party ID and their Matrix on their local homeserver. + It is only called if an identity server is to receive the binding as well. + + Args: + user_id: the ID of the user to include in the association. + medium: the medium of the third-party ID (email, msisdn). + address: the address of the third-party ID (i.e. an email address). + id_server: + """ + for callback in self._on_threepid_bind_callbacks: + try: + await callback(user_id, medium, address) + except Exception as e: + logger.exception( + "Failed to run module API callback %s: %s", callback, e + ) diff --git a/synapse/module_api/__init__.py b/synapse/module_api/__init__.py index d22dd19d38..ec7495bf40 100644 --- a/synapse/module_api/__init__.py +++ b/synapse/module_api/__init__.py @@ -68,6 +68,7 @@ from synapse.events.third_party_rules import ( ON_NEW_EVENT_CALLBACK, ON_PROFILE_UPDATE_CALLBACK, ON_THREEPID_BIND_CALLBACK, + ON_UPDATE_IDENTITY_SERVER_BINDING_CALLBACK, ON_USER_DEACTIVATION_STATUS_CHANGED_CALLBACK, ) from synapse.handlers.account_data import ON_ACCOUNT_DATA_UPDATED_CALLBACK @@ -357,6 +358,7 @@ class ModuleApi: ON_USER_DEACTIVATION_STATUS_CHANGED_CALLBACK ] = None, on_threepid_bind: Optional[ON_THREEPID_BIND_CALLBACK] = None, + on_update_identity_server_binding: Optional[ON_UPDATE_IDENTITY_SERVER_BINDING_CALLBACK] = None, ) -> None: """Registers callbacks for third party event rules capabilities. @@ -373,6 +375,7 @@ class ModuleApi: on_profile_update=on_profile_update, on_user_deactivation_status_changed=on_user_deactivation_status_changed, on_threepid_bind=on_threepid_bind, + on_update_identity_server_binding=on_update_identity_server_binding, ) def register_presence_router_callbacks(