summary refs log tree commit diff
path: root/docs/modules/third_party_rules_callbacks.md
diff options
context:
space:
mode:
authorBrendan Abolivier <babolivier@matrix.org>2021-09-08 19:14:54 +0200
committerGitHub <noreply@github.com>2021-09-08 17:14:54 +0000
commit03caba65777ab6ec8d089f8975352242e0d7b0af (patch)
treea88495bb8c0f11d55c56ab3c5075673a69e9cf48 /docs/modules/third_party_rules_callbacks.md
parentFix frontend_proxy jinja script in docker workers (#10783) (diff)
downloadsynapse-03caba65777ab6ec8d089f8975352242e0d7b0af.tar.xz
Improve the modules doc (#10758)
* Split up the documentation in several files rather than one huge one
* Add examples for each callback category
* Other niceties like fixing https://github.com/matrix-org/synapse/issues/10632
* Add titles to callbacks so they're easier to find in the navigation panels and link to
Diffstat (limited to 'docs/modules/third_party_rules_callbacks.md')
-rw-r--r--docs/modules/third_party_rules_callbacks.md125
1 files changed, 125 insertions, 0 deletions
diff --git a/docs/modules/third_party_rules_callbacks.md b/docs/modules/third_party_rules_callbacks.md
new file mode 100644
index 0000000000..2ba6f39453
--- /dev/null
+++ b/docs/modules/third_party_rules_callbacks.md
@@ -0,0 +1,125 @@
+# Third party rules callbacks
+
+Third party rules callbacks allow module developers to add extra checks to verify the
+validity of incoming events. Third party event rules callbacks can be registered using
+the module API's `register_third_party_rules_callbacks` method.
+
+## Callbacks
+
+The available third party rules callbacks are:
+
+### `check_event_allowed`
+
+```python
+async def check_event_allowed(
+    event: "synapse.events.EventBase",
+    state_events: "synapse.types.StateMap",
+) -> Tuple[bool, Optional[dict]]
+```
+
+**<span style="color:red">
+This callback is very experimental and can and will break without notice. Module developers
+are encouraged to implement `check_event_for_spam` from the spam checker category instead.
+</span>**
+
+Called when processing any incoming event, with the event and a `StateMap`
+representing the current state of the room the event is being sent into. A `StateMap` is
+a dictionary that maps tuples containing an event type and a state key to the
+corresponding state event. For example retrieving the room's `m.room.create` event from
+the `state_events` argument would look like this: `state_events.get(("m.room.create", ""))`.
+The module must return a boolean indicating whether the event can be allowed.
+
+Note that this callback function processes incoming events coming via federation
+traffic (on top of client traffic). This means denying an event might cause the local
+copy of the room's history to diverge from that of remote servers. This may cause
+federation issues in the room. It is strongly recommended to only deny events using this
+callback function if the sender is a local user, or in a private federation in which all
+servers are using the same module, with the same configuration.
+
+If the boolean returned by the module is `True`, it may also tell Synapse to replace the
+event with new data by returning the new event's data as a dictionary. In order to do
+that, it is recommended the module calls `event.get_dict()` to get the current event as a
+dictionary, and modify the returned dictionary accordingly.
+
+Note that replacing the event only works for events sent by local users, not for events
+received over federation.
+
+### `on_create_room`
+
+```python
+async def on_create_room(
+    requester: "synapse.types.Requester",
+    request_content: dict,
+    is_requester_admin: bool,
+) -> None
+```
+
+Called when processing a room creation request, with the `Requester` object for the user
+performing the request, a dictionary representing the room creation request's JSON body
+(see [the spec](https://matrix.org/docs/spec/client_server/latest#post-matrix-client-r0-createroom)
+for a list of possible parameters), and a boolean indicating whether the user performing
+the request is a server admin.
+
+Modules can modify the `request_content` (by e.g. adding events to its `initial_state`),
+or deny the room's creation by raising a `module_api.errors.SynapseError`.
+
+### `check_threepid_can_be_invited`
+
+```python
+async def check_threepid_can_be_invited(
+    medium: str,
+    address: str,
+    state_events: "synapse.types.StateMap",
+) -> bool:
+```
+
+Called when processing an invite via a third-party identifier (i.e. email or phone number).
+The module must return a boolean indicating whether the invite can go through.
+
+### `check_visibility_can_be_modified`
+
+```python
+async def check_visibility_can_be_modified(
+    room_id: str,
+    state_events: "synapse.types.StateMap",
+    new_visibility: str,
+) -> bool:
+```
+
+Called when changing the visibility of a room in the local public room directory. The
+visibility is a string that's either "public" or "private". The module must return a
+boolean indicating whether the change can go through.
+
+## Example
+
+The example below is a module that implements the third-party rules callback
+`check_event_allowed` to censor incoming messages as dictated by a third-party service.
+
+```python
+from typing import Optional, Tuple
+
+from synapse.module_api import ModuleApi
+
+_DEFAULT_CENSOR_ENDPOINT = "https://my-internal-service.local/censor-event"
+
+class EventCensorer:
+    def __init__(self, config: dict, api: ModuleApi):
+        self.api = api
+        self._endpoint = config.get("endpoint", _DEFAULT_CENSOR_ENDPOINT)
+
+        self.api.register_third_party_rules_callbacks(
+            check_event_allowed=self.check_event_allowed,
+        )
+
+    async def check_event_allowed(
+        self,
+        event: "synapse.events.EventBase",
+        state_events: "synapse.types.StateMap",
+    ) -> Tuple[bool, Optional[dict]]:
+        event_dict = event.get_dict()
+        new_event_content = await self.api.http_client.post_json_get_json(
+            uri=self._endpoint, post_json=event_dict,
+        )
+        event_dict["content"] = new_event_content
+        return event_dict
+```