This commit is contained in:
babolivier 2022-06-13 18:16:55 +00:00
parent ac0825a719
commit e59ecd1890
5 changed files with 396 additions and 112 deletions

View File

@ -175,46 +175,70 @@ be used. If this happens, Synapse will not call any of the subsequent implementa
this callback.</p> this callback.</p>
<h3 id="user_may_join_room"><a class="header" href="#user_may_join_room"><code>user_may_join_room</code></a></h3> <h3 id="user_may_join_room"><a class="header" href="#user_may_join_room"><code>user_may_join_room</code></a></h3>
<p><em>First introduced in Synapse v1.37.0</em></p> <p><em>First introduced in Synapse v1.37.0</em></p>
<pre><code class="language-python">async def user_may_join_room(user: str, room: str, is_invited: bool) -&gt; bool <p><em>Changed in Synapse v1.61.0: <code>synapse.module_api.NOT_SPAM</code> and <code>synapse.module_api.errors.Codes</code> can be returned by this callback. Returning a boolean is now deprecated.</em> </p>
<pre><code class="language-python">async def user_may_join_room(user: str, room: str, is_invited: bool) -&gt; Union[&quot;synapse.module_api.NOT_SPAM&quot;, &quot;synapse.module_api.errors.Codes&quot;, bool]
</code></pre> </code></pre>
<p>Called when a user is trying to join a room. The module must return a <code>bool</code> to indicate <p>Called when a user is trying to join a room. The user is represented by their Matrix user ID (e.g.
whether the user can join the room. Return <code>False</code> to prevent the user from joining the
room; otherwise return <code>True</code> to permit the joining.</p>
<p>The user is represented by their Matrix user ID (e.g.
<code>@alice:example.com</code>) and the room is represented by its Matrix ID (e.g. <code>@alice:example.com</code>) and the room is represented by its Matrix ID (e.g.
<code>!room:example.com</code>). The module is also given a boolean to indicate whether the user <code>!room:example.com</code>). The module is also given a boolean to indicate whether the user
currently has a pending invite in the room.</p> currently has a pending invite in the room.</p>
<p>This callback isn't called if the join is performed by a server administrator, or in the <p>This callback isn't called if the join is performed by a server administrator, or in the
context of a room creation.</p> context of a room creation.</p>
<p>The callback must return one of:</p>
<ul>
<li><code>synapse.module_api.NOT_SPAM</code>, to allow the operation. Other callbacks may still
decide to reject it.</li>
<li><code>synapse.module_api.errors.Codes</code> to reject the operation with an error code. In case
of doubt, <code>synapse.module_api.errors.Codes.FORBIDDEN</code> is a good error code.</li>
<li>(deprecated) <code>False</code>, which is the same as returning <code>synapse.module_api.NOT_SPAM</code>.</li>
<li>(deprecated) <code>True</code>, which is the same as returning <code>synapse.module_api.errors.Codes.FORBIDDEN</code>.</li>
</ul>
<p>If multiple modules implement this callback, they will be considered in order. If a <p>If multiple modules implement this callback, they will be considered in order. If a
callback returns <code>True</code>, Synapse falls through to the next one. The value of the first callback returns <code>synapse.module_api.NOT_SPAM</code>, Synapse falls through to the next one.
callback that does not return <code>True</code> will be used. If this happens, Synapse will not call The value of the first callback that does not return <code>synapse.module_api.NOT_SPAM</code> will
any of the subsequent implementations of this callback.</p> be used. If this happens, Synapse will not call any of the subsequent implementations of
this callback.</p>
<h3 id="user_may_invite"><a class="header" href="#user_may_invite"><code>user_may_invite</code></a></h3> <h3 id="user_may_invite"><a class="header" href="#user_may_invite"><code>user_may_invite</code></a></h3>
<p><em>First introduced in Synapse v1.37.0</em></p> <p><em>First introduced in Synapse v1.37.0</em></p>
<pre><code class="language-python">async def user_may_invite(inviter: str, invitee: str, room_id: str) -&gt; bool <p><em>Changed in Synapse v1.61.0: <code>synapse.module_api.NOT_SPAM</code> and <code>synapse.module_api.errors.Codes</code> can be returned by this callback. Returning a boolean is now deprecated.</em> </p>
<pre><code class="language-python">async def user_may_invite(inviter: str, invitee: str, room_id: str) -&gt; Union[&quot;synapse.module_api.NOT_SPAM&quot;, &quot;synapse.module_api.errors.Codes&quot;, bool]
</code></pre> </code></pre>
<p>Called when processing an invitation. The module must return a <code>bool</code> indicating whether <p>Called when processing an invitation. Both inviter and invitee are
the inviter can invite the invitee to the given room. Both inviter and invitee are represented by their Matrix user ID (e.g. <code>@alice:example.com</code>).</p>
represented by their Matrix user ID (e.g. <code>@alice:example.com</code>). Return <code>False</code> to prevent <p>The callback must return one of:</p>
the invitation; otherwise return <code>True</code> to permit it.</p> <ul>
<li>
<p><code>synapse.module_api.NOT_SPAM</code>, to allow the operation. Other callbacks may still
decide to reject it.</p>
</li>
<li>
<p><code>synapse.module_api.errors.Codes</code> to reject the operation with an error code. In case
of doubt, <code>synapse.module_api.errors.Codes.FORBIDDEN</code> is a good error code.</p>
</li>
<li>
<p>(deprecated) <code>False</code>, which is the same as returning <code>synapse.module_api.NOT_SPAM</code>.</p>
</li>
<li>
<p>(deprecated) <code>True</code>, which is the same as returning <code>synapse.module_api.errors.Codes.FORBIDDEN</code>.</p>
</li>
</ul>
<p>If multiple modules implement this callback, they will be considered in order. If a <p>If multiple modules implement this callback, they will be considered in order. If a
callback returns <code>True</code>, Synapse falls through to the next one. The value of the first callback returns <code>synapse.module_api.NOT_SPAM</code>, Synapse falls through to the next one.
callback that does not return <code>True</code> will be used. If this happens, Synapse will not call The value of the first callback that does not return <code>synapse.module_api.NOT_SPAM</code> will
any of the subsequent implementations of this callback.</p> be used. If this happens, Synapse will not call any of the subsequent implementations of
this callback.</p>
<h3 id="user_may_send_3pid_invite"><a class="header" href="#user_may_send_3pid_invite"><code>user_may_send_3pid_invite</code></a></h3> <h3 id="user_may_send_3pid_invite"><a class="header" href="#user_may_send_3pid_invite"><code>user_may_send_3pid_invite</code></a></h3>
<p><em>First introduced in Synapse v1.45.0</em></p> <p><em>First introduced in Synapse v1.45.0</em></p>
<p><em>Changed in Synapse v1.61.0: <code>synapse.module_api.NOT_SPAM</code> and <code>synapse.module_api.errors.Codes</code> can be returned by this callback. Returning a boolean is now deprecated.</em> </p>
<pre><code class="language-python">async def user_may_send_3pid_invite( <pre><code class="language-python">async def user_may_send_3pid_invite(
inviter: str, inviter: str,
medium: str, medium: str,
address: str, address: str,
room_id: str, room_id: str,
) -&gt; bool ) -&gt; Union[&quot;synapse.module_api.NOT_SPAM&quot;, &quot;synapse.module_api.errors.Codes&quot;, bool]
</code></pre> </code></pre>
<p>Called when processing an invitation using a third-party identifier (also called a 3PID, <p>Called when processing an invitation using a third-party identifier (also called a 3PID,
e.g. an email address or a phone number). The module must return a <code>bool</code> indicating e.g. an email address or a phone number). </p>
whether the inviter can invite the invitee to the given room. Return <code>False</code> to prevent
the invitation; otherwise return <code>True</code> to permit it.</p>
<p>The inviter is represented by their Matrix user ID (e.g. <code>@alice:example.com</code>), and the <p>The inviter is represented by their Matrix user ID (e.g. <code>@alice:example.com</code>), and the
invitee is represented by its medium (e.g. &quot;email&quot;) and its address invitee is represented by its medium (e.g. &quot;email&quot;) and its address
(e.g. <code>alice@example.com</code>). See <a href="https://matrix.org/docs/spec/appendices#pid-types">the Matrix specification</a> (e.g. <code>alice@example.com</code>). See <a href="https://matrix.org/docs/spec/appendices#pid-types">the Matrix specification</a>
@ -230,45 +254,112 @@ for more information regarding third-party identifiers.</p>
</code></pre> </code></pre>
<p><strong>Note</strong>: If the third-party identifier is already associated with a matrix user ID, <p><strong>Note</strong>: If the third-party identifier is already associated with a matrix user ID,
<a href="#user_may_invite"><code>user_may_invite</code></a> will be used instead.</p> <a href="#user_may_invite"><code>user_may_invite</code></a> will be used instead.</p>
<p>The callback must return one of:</p>
<ul>
<li>
<p><code>synapse.module_api.NOT_SPAM</code>, to allow the operation. Other callbacks may still
decide to reject it.</p>
</li>
<li>
<p><code>synapse.module_api.errors.Codes</code> to reject the operation with an error code. In case
of doubt, <code>synapse.module_api.errors.Codes.FORBIDDEN</code> is a good error code.</p>
</li>
<li>
<p>(deprecated) <code>False</code>, which is the same as returning <code>synapse.module_api.NOT_SPAM</code>.</p>
</li>
<li>
<p>(deprecated) <code>True</code>, which is the same as returning <code>synapse.module_api.errors.Codes.FORBIDDEN</code>.</p>
</li>
</ul>
<p>If multiple modules implement this callback, they will be considered in order. If a <p>If multiple modules implement this callback, they will be considered in order. If a
callback returns <code>True</code>, Synapse falls through to the next one. The value of the first callback returns <code>synapse.module_api.NOT_SPAM</code>, Synapse falls through to the next one.
callback that does not return <code>True</code> will be used. If this happens, Synapse will not call The value of the first callback that does not return <code>synapse.module_api.NOT_SPAM</code> will
any of the subsequent implementations of this callback.</p> be used. If this happens, Synapse will not call any of the subsequent implementations of
this callback.</p>
<h3 id="user_may_create_room"><a class="header" href="#user_may_create_room"><code>user_may_create_room</code></a></h3> <h3 id="user_may_create_room"><a class="header" href="#user_may_create_room"><code>user_may_create_room</code></a></h3>
<p><em>First introduced in Synapse v1.37.0</em></p> <p><em>First introduced in Synapse v1.37.0</em></p>
<pre><code class="language-python">async def user_may_create_room(user: str) -&gt; bool <p><em>Changed in Synapse v1.61.0: <code>synapse.module_api.NOT_SPAM</code> and <code>synapse.module_api.errors.Codes</code> can be returned by this callback. Returning a boolean is now deprecated.</em> </p>
<pre><code class="language-python">async def user_may_create_room(user_id: str) -&gt; Union[&quot;synapse.module_api.NOT_SPAM&quot;, &quot;synapse.module_api.errors.Codes&quot;, bool]
</code></pre> </code></pre>
<p>Called when processing a room creation request. The module must return a <code>bool</code> indicating <p>Called when processing a room creation request.</p>
whether the given user (represented by their Matrix user ID) is allowed to create a room. <p>The callback must return one of:</p>
Return <code>False</code> to prevent room creation; otherwise return <code>True</code> to permit it.</p> <ul>
<li>
<p><code>synapse.module_api.NOT_SPAM</code>, to allow the operation. Other callbacks may still
decide to reject it.</p>
</li>
<li>
<p><code>synapse.module_api.errors.Codes</code> to reject the operation with an error code. In case
of doubt, <code>synapse.module_api.errors.Codes.FORBIDDEN</code> is a good error code.</p>
</li>
<li>
<p>(deprecated) <code>False</code>, which is the same as returning <code>synapse.module_api.NOT_SPAM</code>.</p>
</li>
<li>
<p>(deprecated) <code>True</code>, which is the same as returning <code>synapse.module_api.errors.Codes.FORBIDDEN</code>.</p>
</li>
</ul>
<p>If multiple modules implement this callback, they will be considered in order. If a <p>If multiple modules implement this callback, they will be considered in order. If a
callback returns <code>True</code>, Synapse falls through to the next one. The value of the first callback returns <code>synapse.module_api.NOT_SPAM</code>, Synapse falls through to the next one.
callback that does not return <code>True</code> will be used. If this happens, Synapse will not call The value of the first callback that does not return <code>synapse.module_api.NOT_SPAM</code> will
any of the subsequent implementations of this callback.</p> be used. If this happens, Synapse will not call any of the subsequent implementations of
this callback.</p>
<h3 id="user_may_create_room_alias"><a class="header" href="#user_may_create_room_alias"><code>user_may_create_room_alias</code></a></h3> <h3 id="user_may_create_room_alias"><a class="header" href="#user_may_create_room_alias"><code>user_may_create_room_alias</code></a></h3>
<p><em>First introduced in Synapse v1.37.0</em></p> <p><em>First introduced in Synapse v1.37.0</em></p>
<pre><code class="language-python">async def user_may_create_room_alias(user: str, room_alias: &quot;synapse.types.RoomAlias&quot;) -&gt; bool <p><em>Changed in Synapse v1.61.0: <code>synapse.module_api.NOT_SPAM</code> and <code>synapse.module_api.errors.Codes</code> can be returned by this callback. Returning a boolean is now deprecated.</em> </p>
<pre><code class="language-python">async def user_may_create_room_alias(user_id: str, room_alias: &quot;synapse.module_api.RoomAlias&quot;) -&gt; Union[&quot;synapse.module_api.NOT_SPAM&quot;, &quot;synapse.module_api.errors.Codes&quot;, bool]
</code></pre> </code></pre>
<p>Called when trying to associate an alias with an existing room. The module must return a <p>Called when trying to associate an alias with an existing room.</p>
<code>bool</code> indicating whether the given user (represented by their Matrix user ID) is allowed <p>The callback must return one of:</p>
to set the given alias. Return <code>False</code> to prevent the alias creation; otherwise return <ul>
<code>True</code> to permit it.</p> <li>
<p><code>synapse.module_api.NOT_SPAM</code>, to allow the operation. Other callbacks may still
decide to reject it.</p>
</li>
<li>
<p><code>synapse.module_api.errors.Codes</code> to reject the operation with an error code. In case
of doubt, <code>synapse.module_api.errors.Codes.FORBIDDEN</code> is a good error code.</p>
</li>
<li>
<p>(deprecated) <code>False</code>, which is the same as returning <code>synapse.module_api.NOT_SPAM</code>.</p>
</li>
<li>
<p>(deprecated) <code>True</code>, which is the same as returning <code>synapse.module_api.errors.Codes.FORBIDDEN</code>.</p>
</li>
</ul>
<p>If multiple modules implement this callback, they will be considered in order. If a <p>If multiple modules implement this callback, they will be considered in order. If a
callback returns <code>True</code>, Synapse falls through to the next one. The value of the first callback returns <code>synapse.module_api.NOT_SPAM</code>, Synapse falls through to the next one.
callback that does not return <code>True</code> will be used. If this happens, Synapse will not call The value of the first callback that does not return <code>synapse.module_api.NOT_SPAM</code> will
any of the subsequent implementations of this callback.</p> be used. If this happens, Synapse will not call any of the subsequent implementations of
this callback.</p>
<h3 id="user_may_publish_room"><a class="header" href="#user_may_publish_room"><code>user_may_publish_room</code></a></h3> <h3 id="user_may_publish_room"><a class="header" href="#user_may_publish_room"><code>user_may_publish_room</code></a></h3>
<p><em>First introduced in Synapse v1.37.0</em></p> <p><em>First introduced in Synapse v1.37.0</em></p>
<pre><code class="language-python">async def user_may_publish_room(user: str, room_id: str) -&gt; bool <p><em>Changed in Synapse v1.61.0: <code>synapse.module_api.NOT_SPAM</code> and <code>synapse.module_api.errors.Codes</code> can be returned by this callback. Returning a boolean is now deprecated.</em> </p>
<pre><code class="language-python">async def user_may_publish_room(user_id: str, room_id: str) -&gt; Union[&quot;synapse.module_api.NOT_SPAM&quot;, &quot;synapse.module_api.errors.Codes&quot;, bool]
</code></pre> </code></pre>
<p>Called when trying to publish a room to the homeserver's public rooms directory. The <p>Called when trying to publish a room to the homeserver's public rooms directory.</p>
module must return a <code>bool</code> indicating whether the given user (represented by their <p>The callback must return one of:</p>
Matrix user ID) is allowed to publish the given room. Return <code>False</code> to prevent the <ul>
room from being published; otherwise return <code>True</code> to permit its publication.</p> <li>
<p><code>synapse.module_api.NOT_SPAM</code>, to allow the operation. Other callbacks may still
decide to reject it.</p>
</li>
<li>
<p><code>synapse.module_api.errors.Codes</code> to reject the operation with an error code. In case
of doubt, <code>synapse.module_api.errors.Codes.FORBIDDEN</code> is a good error code.</p>
</li>
<li>
<p>(deprecated) <code>False</code>, which is the same as returning <code>synapse.module_api.NOT_SPAM</code>.</p>
</li>
<li>
<p>(deprecated) <code>True</code>, which is the same as returning <code>synapse.module_api.errors.Codes.FORBIDDEN</code>.</p>
</li>
</ul>
<p>If multiple modules implement this callback, they will be considered in order. If a <p>If multiple modules implement this callback, they will be considered in order. If a
callback returns <code>True</code>, Synapse falls through to the next one. The value of the first callback returns <code>synapse.module_api.NOT_SPAM</code>, Synapse falls through to the next one.
callback that does not return <code>True</code> will be used. If this happens, Synapse will not call The value of the first callback that does not return <code>synapse.module_api.NOT_SPAM</code> will
any of the subsequent implementations of this callback.</p> be used. If this happens, Synapse will not call any of the subsequent implementations of
this callback.</p>
<h3 id="check_username_for_spam"><a class="header" href="#check_username_for_spam"><code>check_username_for_spam</code></a></h3> <h3 id="check_username_for_spam"><a class="header" href="#check_username_for_spam"><code>check_username_for_spam</code></a></h3>
<p><em>First introduced in Synapse v1.37.0</em></p> <p><em>First introduced in Synapse v1.37.0</em></p>
<pre><code class="language-python">async def check_username_for_spam(user_profile: synapse.module_api.UserProfile) -&gt; bool <pre><code class="language-python">async def check_username_for_spam(user_profile: synapse.module_api.UserProfile) -&gt; bool
@ -320,18 +411,35 @@ be used. If this happens, Synapse will not call any of the subsequent implementa
this callback.</p> this callback.</p>
<h3 id="check_media_file_for_spam"><a class="header" href="#check_media_file_for_spam"><code>check_media_file_for_spam</code></a></h3> <h3 id="check_media_file_for_spam"><a class="header" href="#check_media_file_for_spam"><code>check_media_file_for_spam</code></a></h3>
<p><em>First introduced in Synapse v1.37.0</em></p> <p><em>First introduced in Synapse v1.37.0</em></p>
<p><em>Changed in Synapse v1.61.0: <code>synapse.module_api.NOT_SPAM</code> and <code>synapse.module_api.errors.Codes</code> can be returned by this callback. Returning a boolean is now deprecated.</em> </p>
<pre><code class="language-python">async def check_media_file_for_spam( <pre><code class="language-python">async def check_media_file_for_spam(
file_wrapper: &quot;synapse.rest.media.v1.media_storage.ReadableFileWrapper&quot;, file_wrapper: &quot;synapse.rest.media.v1.media_storage.ReadableFileWrapper&quot;,
file_info: &quot;synapse.rest.media.v1._base.FileInfo&quot;, file_info: &quot;synapse.rest.media.v1._base.FileInfo&quot;,
) -&gt; bool ) -&gt; Union[&quot;synapse.module_api.NOT_SPAM&quot;, &quot;synapse.module_api.errors.Codes&quot;, bool]
</code></pre> </code></pre>
<p>Called when storing a local or remote file. The module must return a <code>bool</code> indicating <p>Called when storing a local or remote file.</p>
whether the given file should be excluded from the homeserver's media store. Return <p>The callback must return one of:</p>
<code>True</code> to prevent this file from being stored; otherwise return <code>False</code>.</p> <ul>
<li>
<p><code>synapse.module_api.NOT_SPAM</code>, to allow the operation. Other callbacks may still
decide to reject it.</p>
</li>
<li>
<p><code>synapse.module_api.errors.Codes</code> to reject the operation with an error code. In case
of doubt, <code>synapse.module_api.errors.Codes.FORBIDDEN</code> is a good error code.</p>
</li>
<li>
<p>(deprecated) <code>False</code>, which is the same as returning <code>synapse.module_api.NOT_SPAM</code>.</p>
</li>
<li>
<p>(deprecated) <code>True</code>, which is the same as returning <code>synapse.module_api.errors.Codes.FORBIDDEN</code>.</p>
</li>
</ul>
<p>If multiple modules implement this callback, they will be considered in order. If a <p>If multiple modules implement this callback, they will be considered in order. If a
callback returns <code>False</code>, Synapse falls through to the next one. The value of the first callback returns <code>synapse.module_api.NOT_SPAM</code>, Synapse falls through to the next one.
callback that does not return <code>False</code> will be used. If this happens, Synapse will not call The value of the first callback that does not return <code>synapse.module_api.NOT_SPAM</code> will
any of the subsequent implementations of this callback.</p> be used. If this happens, Synapse will not call any of the subsequent implementations of
this callback.</p>
<h3 id="should_drop_federated_event"><a class="header" href="#should_drop_federated_event"><code>should_drop_federated_event</code></a></h3> <h3 id="should_drop_federated_event"><a class="header" href="#should_drop_federated_event"><code>should_drop_federated_event</code></a></h3>
<p><em>First introduced in Synapse v1.60.0</em></p> <p><em>First introduced in Synapse v1.60.0</em></p>
<pre><code class="language-python">async def should_drop_federated_event(event: &quot;synapse.events.EventBase&quot;) -&gt; bool <pre><code class="language-python">async def should_drop_federated_event(event: &quot;synapse.events.EventBase&quot;) -&gt; bool
@ -384,8 +492,11 @@ class ListSpamChecker:
resource=IsUserEvilResource(config), resource=IsUserEvilResource(config),
) )
async def check_event_for_spam(self, event: &quot;synapse.events.EventBase&quot;) -&gt; Union[bool, str]: async def check_event_for_spam(self, event: &quot;synapse.events.EventBase&quot;) -&gt; Union[Literal[&quot;NOT_SPAM&quot;], Codes]:
return event.sender not in self.evil_users if event.sender in self.evil_users:
return Codes.FORBIDDEN
else:
return synapse.module_api.NOT_SPAM
</code></pre> </code></pre>
</main> </main>

View File

@ -1631,6 +1631,37 @@ dpkg -i matrix-synapse-py3_1.3.0+stretch1_amd64.deb
</code></pre> </code></pre>
</li> </li>
</ul> </ul>
<h1 id="upgrading-to-v1610"><a class="header" href="#upgrading-to-v1610">Upgrading to v1.61.0</a></h1>
<h2 id="new-signatures-for-spam-checker-callbacks"><a class="header" href="#new-signatures-for-spam-checker-callbacks">New signatures for spam checker callbacks</a></h2>
<p>As a followup to changes in v1.60.0, the following spam-checker callbacks have changed signature:</p>
<ul>
<li><code>user_may_join_room</code></li>
<li><code>user_may_invite</code></li>
<li><code>user_may_send_3pid_invite</code></li>
<li><code>user_may_create_room</code></li>
<li><code>user_may_create_room_alias</code></li>
<li><code>user_may_publish_room</code></li>
<li><code>check_media_file_for_spam</code></li>
</ul>
<p>For each of these methods, the previous callback signature has been deprecated.</p>
<p>Whereas callbacks used to return <code>bool</code>, they should now return <code>Union[&quot;synapse.module_api.NOT_SPAM&quot;, &quot;synapse.module_api.errors.Codes&quot;]</code>.</p>
<p>For instance, if your module implements <code>user_may_join_room</code> as follows:</p>
<pre><code class="language-python">async def user_may_join_room(self, user_id: str, room_id: str, is_invited: bool)
if ...:
# Request is spam
return False
# Request is not spam
return True
</code></pre>
<p>you should rewrite it as follows:</p>
<pre><code class="language-python">async def user_may_join_room(self, user_id: str, room_id: str, is_invited: bool)
if ...:
# Request is spam, mark it as forbidden (you may use some more precise error
# code if it is useful).
return synapse.module_api.errors.Codes.FORBIDDEN
# Request is not spam, mark it as such.
return synapse.module_api.NOT_SPAM
</code></pre>
<h1 id="upgrading-to-v1600"><a class="header" href="#upgrading-to-v1600">Upgrading to v1.60.0</a></h1> <h1 id="upgrading-to-v1600"><a class="header" href="#upgrading-to-v1600">Upgrading to v1.60.0</a></h1>
<h2 id="adding-a-new-unique-index-to-state_group_edges-could-fail-if-your-database-is-corrupted"><a class="header" href="#adding-a-new-unique-index-to-state_group_edges-could-fail-if-your-database-is-corrupted">Adding a new unique index to <code>state_group_edges</code> could fail if your database is corrupted</a></h2> <h2 id="adding-a-new-unique-index-to-state_group_edges-could-fail-if-your-database-is-corrupted"><a class="header" href="#adding-a-new-unique-index-to-state_group_edges-could-fail-if-your-database-is-corrupted">Adding a new unique index to <code>state_group_edges</code> could fail if your database is corrupted</a></h2>
<p>This release of Synapse will add a unique index to the <code>state_group_edges</code> table, in order <p>This release of Synapse will add a unique index to the <code>state_group_edges</code> table, in order
@ -11262,46 +11293,70 @@ be used. If this happens, Synapse will not call any of the subsequent implementa
this callback.</p> this callback.</p>
<h3 id="user_may_join_room"><a class="header" href="#user_may_join_room"><code>user_may_join_room</code></a></h3> <h3 id="user_may_join_room"><a class="header" href="#user_may_join_room"><code>user_may_join_room</code></a></h3>
<p><em>First introduced in Synapse v1.37.0</em></p> <p><em>First introduced in Synapse v1.37.0</em></p>
<pre><code class="language-python">async def user_may_join_room(user: str, room: str, is_invited: bool) -&gt; bool <p><em>Changed in Synapse v1.61.0: <code>synapse.module_api.NOT_SPAM</code> and <code>synapse.module_api.errors.Codes</code> can be returned by this callback. Returning a boolean is now deprecated.</em> </p>
<pre><code class="language-python">async def user_may_join_room(user: str, room: str, is_invited: bool) -&gt; Union[&quot;synapse.module_api.NOT_SPAM&quot;, &quot;synapse.module_api.errors.Codes&quot;, bool]
</code></pre> </code></pre>
<p>Called when a user is trying to join a room. The module must return a <code>bool</code> to indicate <p>Called when a user is trying to join a room. The user is represented by their Matrix user ID (e.g.
whether the user can join the room. Return <code>False</code> to prevent the user from joining the
room; otherwise return <code>True</code> to permit the joining.</p>
<p>The user is represented by their Matrix user ID (e.g.
<code>@alice:example.com</code>) and the room is represented by its Matrix ID (e.g. <code>@alice:example.com</code>) and the room is represented by its Matrix ID (e.g.
<code>!room:example.com</code>). The module is also given a boolean to indicate whether the user <code>!room:example.com</code>). The module is also given a boolean to indicate whether the user
currently has a pending invite in the room.</p> currently has a pending invite in the room.</p>
<p>This callback isn't called if the join is performed by a server administrator, or in the <p>This callback isn't called if the join is performed by a server administrator, or in the
context of a room creation.</p> context of a room creation.</p>
<p>The callback must return one of:</p>
<ul>
<li><code>synapse.module_api.NOT_SPAM</code>, to allow the operation. Other callbacks may still
decide to reject it.</li>
<li><code>synapse.module_api.errors.Codes</code> to reject the operation with an error code. In case
of doubt, <code>synapse.module_api.errors.Codes.FORBIDDEN</code> is a good error code.</li>
<li>(deprecated) <code>False</code>, which is the same as returning <code>synapse.module_api.NOT_SPAM</code>.</li>
<li>(deprecated) <code>True</code>, which is the same as returning <code>synapse.module_api.errors.Codes.FORBIDDEN</code>.</li>
</ul>
<p>If multiple modules implement this callback, they will be considered in order. If a <p>If multiple modules implement this callback, they will be considered in order. If a
callback returns <code>True</code>, Synapse falls through to the next one. The value of the first callback returns <code>synapse.module_api.NOT_SPAM</code>, Synapse falls through to the next one.
callback that does not return <code>True</code> will be used. If this happens, Synapse will not call The value of the first callback that does not return <code>synapse.module_api.NOT_SPAM</code> will
any of the subsequent implementations of this callback.</p> be used. If this happens, Synapse will not call any of the subsequent implementations of
this callback.</p>
<h3 id="user_may_invite"><a class="header" href="#user_may_invite"><code>user_may_invite</code></a></h3> <h3 id="user_may_invite"><a class="header" href="#user_may_invite"><code>user_may_invite</code></a></h3>
<p><em>First introduced in Synapse v1.37.0</em></p> <p><em>First introduced in Synapse v1.37.0</em></p>
<pre><code class="language-python">async def user_may_invite(inviter: str, invitee: str, room_id: str) -&gt; bool <p><em>Changed in Synapse v1.61.0: <code>synapse.module_api.NOT_SPAM</code> and <code>synapse.module_api.errors.Codes</code> can be returned by this callback. Returning a boolean is now deprecated.</em> </p>
<pre><code class="language-python">async def user_may_invite(inviter: str, invitee: str, room_id: str) -&gt; Union[&quot;synapse.module_api.NOT_SPAM&quot;, &quot;synapse.module_api.errors.Codes&quot;, bool]
</code></pre> </code></pre>
<p>Called when processing an invitation. The module must return a <code>bool</code> indicating whether <p>Called when processing an invitation. Both inviter and invitee are
the inviter can invite the invitee to the given room. Both inviter and invitee are represented by their Matrix user ID (e.g. <code>@alice:example.com</code>).</p>
represented by their Matrix user ID (e.g. <code>@alice:example.com</code>). Return <code>False</code> to prevent <p>The callback must return one of:</p>
the invitation; otherwise return <code>True</code> to permit it.</p> <ul>
<li>
<p><code>synapse.module_api.NOT_SPAM</code>, to allow the operation. Other callbacks may still
decide to reject it.</p>
</li>
<li>
<p><code>synapse.module_api.errors.Codes</code> to reject the operation with an error code. In case
of doubt, <code>synapse.module_api.errors.Codes.FORBIDDEN</code> is a good error code.</p>
</li>
<li>
<p>(deprecated) <code>False</code>, which is the same as returning <code>synapse.module_api.NOT_SPAM</code>.</p>
</li>
<li>
<p>(deprecated) <code>True</code>, which is the same as returning <code>synapse.module_api.errors.Codes.FORBIDDEN</code>.</p>
</li>
</ul>
<p>If multiple modules implement this callback, they will be considered in order. If a <p>If multiple modules implement this callback, they will be considered in order. If a
callback returns <code>True</code>, Synapse falls through to the next one. The value of the first callback returns <code>synapse.module_api.NOT_SPAM</code>, Synapse falls through to the next one.
callback that does not return <code>True</code> will be used. If this happens, Synapse will not call The value of the first callback that does not return <code>synapse.module_api.NOT_SPAM</code> will
any of the subsequent implementations of this callback.</p> be used. If this happens, Synapse will not call any of the subsequent implementations of
this callback.</p>
<h3 id="user_may_send_3pid_invite"><a class="header" href="#user_may_send_3pid_invite"><code>user_may_send_3pid_invite</code></a></h3> <h3 id="user_may_send_3pid_invite"><a class="header" href="#user_may_send_3pid_invite"><code>user_may_send_3pid_invite</code></a></h3>
<p><em>First introduced in Synapse v1.45.0</em></p> <p><em>First introduced in Synapse v1.45.0</em></p>
<p><em>Changed in Synapse v1.61.0: <code>synapse.module_api.NOT_SPAM</code> and <code>synapse.module_api.errors.Codes</code> can be returned by this callback. Returning a boolean is now deprecated.</em> </p>
<pre><code class="language-python">async def user_may_send_3pid_invite( <pre><code class="language-python">async def user_may_send_3pid_invite(
inviter: str, inviter: str,
medium: str, medium: str,
address: str, address: str,
room_id: str, room_id: str,
) -&gt; bool ) -&gt; Union[&quot;synapse.module_api.NOT_SPAM&quot;, &quot;synapse.module_api.errors.Codes&quot;, bool]
</code></pre> </code></pre>
<p>Called when processing an invitation using a third-party identifier (also called a 3PID, <p>Called when processing an invitation using a third-party identifier (also called a 3PID,
e.g. an email address or a phone number). The module must return a <code>bool</code> indicating e.g. an email address or a phone number). </p>
whether the inviter can invite the invitee to the given room. Return <code>False</code> to prevent
the invitation; otherwise return <code>True</code> to permit it.</p>
<p>The inviter is represented by their Matrix user ID (e.g. <code>@alice:example.com</code>), and the <p>The inviter is represented by their Matrix user ID (e.g. <code>@alice:example.com</code>), and the
invitee is represented by its medium (e.g. &quot;email&quot;) and its address invitee is represented by its medium (e.g. &quot;email&quot;) and its address
(e.g. <code>alice@example.com</code>). See <a href="https://matrix.org/docs/spec/appendices#pid-types">the Matrix specification</a> (e.g. <code>alice@example.com</code>). See <a href="https://matrix.org/docs/spec/appendices#pid-types">the Matrix specification</a>
@ -11317,45 +11372,112 @@ for more information regarding third-party identifiers.</p>
</code></pre> </code></pre>
<p><strong>Note</strong>: If the third-party identifier is already associated with a matrix user ID, <p><strong>Note</strong>: If the third-party identifier is already associated with a matrix user ID,
<a href="modules/spam_checker_callbacks.html#user_may_invite"><code>user_may_invite</code></a> will be used instead.</p> <a href="modules/spam_checker_callbacks.html#user_may_invite"><code>user_may_invite</code></a> will be used instead.</p>
<p>The callback must return one of:</p>
<ul>
<li>
<p><code>synapse.module_api.NOT_SPAM</code>, to allow the operation. Other callbacks may still
decide to reject it.</p>
</li>
<li>
<p><code>synapse.module_api.errors.Codes</code> to reject the operation with an error code. In case
of doubt, <code>synapse.module_api.errors.Codes.FORBIDDEN</code> is a good error code.</p>
</li>
<li>
<p>(deprecated) <code>False</code>, which is the same as returning <code>synapse.module_api.NOT_SPAM</code>.</p>
</li>
<li>
<p>(deprecated) <code>True</code>, which is the same as returning <code>synapse.module_api.errors.Codes.FORBIDDEN</code>.</p>
</li>
</ul>
<p>If multiple modules implement this callback, they will be considered in order. If a <p>If multiple modules implement this callback, they will be considered in order. If a
callback returns <code>True</code>, Synapse falls through to the next one. The value of the first callback returns <code>synapse.module_api.NOT_SPAM</code>, Synapse falls through to the next one.
callback that does not return <code>True</code> will be used. If this happens, Synapse will not call The value of the first callback that does not return <code>synapse.module_api.NOT_SPAM</code> will
any of the subsequent implementations of this callback.</p> be used. If this happens, Synapse will not call any of the subsequent implementations of
this callback.</p>
<h3 id="user_may_create_room"><a class="header" href="#user_may_create_room"><code>user_may_create_room</code></a></h3> <h3 id="user_may_create_room"><a class="header" href="#user_may_create_room"><code>user_may_create_room</code></a></h3>
<p><em>First introduced in Synapse v1.37.0</em></p> <p><em>First introduced in Synapse v1.37.0</em></p>
<pre><code class="language-python">async def user_may_create_room(user: str) -&gt; bool <p><em>Changed in Synapse v1.61.0: <code>synapse.module_api.NOT_SPAM</code> and <code>synapse.module_api.errors.Codes</code> can be returned by this callback. Returning a boolean is now deprecated.</em> </p>
<pre><code class="language-python">async def user_may_create_room(user_id: str) -&gt; Union[&quot;synapse.module_api.NOT_SPAM&quot;, &quot;synapse.module_api.errors.Codes&quot;, bool]
</code></pre> </code></pre>
<p>Called when processing a room creation request. The module must return a <code>bool</code> indicating <p>Called when processing a room creation request.</p>
whether the given user (represented by their Matrix user ID) is allowed to create a room. <p>The callback must return one of:</p>
Return <code>False</code> to prevent room creation; otherwise return <code>True</code> to permit it.</p> <ul>
<li>
<p><code>synapse.module_api.NOT_SPAM</code>, to allow the operation. Other callbacks may still
decide to reject it.</p>
</li>
<li>
<p><code>synapse.module_api.errors.Codes</code> to reject the operation with an error code. In case
of doubt, <code>synapse.module_api.errors.Codes.FORBIDDEN</code> is a good error code.</p>
</li>
<li>
<p>(deprecated) <code>False</code>, which is the same as returning <code>synapse.module_api.NOT_SPAM</code>.</p>
</li>
<li>
<p>(deprecated) <code>True</code>, which is the same as returning <code>synapse.module_api.errors.Codes.FORBIDDEN</code>.</p>
</li>
</ul>
<p>If multiple modules implement this callback, they will be considered in order. If a <p>If multiple modules implement this callback, they will be considered in order. If a
callback returns <code>True</code>, Synapse falls through to the next one. The value of the first callback returns <code>synapse.module_api.NOT_SPAM</code>, Synapse falls through to the next one.
callback that does not return <code>True</code> will be used. If this happens, Synapse will not call The value of the first callback that does not return <code>synapse.module_api.NOT_SPAM</code> will
any of the subsequent implementations of this callback.</p> be used. If this happens, Synapse will not call any of the subsequent implementations of
this callback.</p>
<h3 id="user_may_create_room_alias"><a class="header" href="#user_may_create_room_alias"><code>user_may_create_room_alias</code></a></h3> <h3 id="user_may_create_room_alias"><a class="header" href="#user_may_create_room_alias"><code>user_may_create_room_alias</code></a></h3>
<p><em>First introduced in Synapse v1.37.0</em></p> <p><em>First introduced in Synapse v1.37.0</em></p>
<pre><code class="language-python">async def user_may_create_room_alias(user: str, room_alias: &quot;synapse.types.RoomAlias&quot;) -&gt; bool <p><em>Changed in Synapse v1.61.0: <code>synapse.module_api.NOT_SPAM</code> and <code>synapse.module_api.errors.Codes</code> can be returned by this callback. Returning a boolean is now deprecated.</em> </p>
<pre><code class="language-python">async def user_may_create_room_alias(user_id: str, room_alias: &quot;synapse.module_api.RoomAlias&quot;) -&gt; Union[&quot;synapse.module_api.NOT_SPAM&quot;, &quot;synapse.module_api.errors.Codes&quot;, bool]
</code></pre> </code></pre>
<p>Called when trying to associate an alias with an existing room. The module must return a <p>Called when trying to associate an alias with an existing room.</p>
<code>bool</code> indicating whether the given user (represented by their Matrix user ID) is allowed <p>The callback must return one of:</p>
to set the given alias. Return <code>False</code> to prevent the alias creation; otherwise return <ul>
<code>True</code> to permit it.</p> <li>
<p><code>synapse.module_api.NOT_SPAM</code>, to allow the operation. Other callbacks may still
decide to reject it.</p>
</li>
<li>
<p><code>synapse.module_api.errors.Codes</code> to reject the operation with an error code. In case
of doubt, <code>synapse.module_api.errors.Codes.FORBIDDEN</code> is a good error code.</p>
</li>
<li>
<p>(deprecated) <code>False</code>, which is the same as returning <code>synapse.module_api.NOT_SPAM</code>.</p>
</li>
<li>
<p>(deprecated) <code>True</code>, which is the same as returning <code>synapse.module_api.errors.Codes.FORBIDDEN</code>.</p>
</li>
</ul>
<p>If multiple modules implement this callback, they will be considered in order. If a <p>If multiple modules implement this callback, they will be considered in order. If a
callback returns <code>True</code>, Synapse falls through to the next one. The value of the first callback returns <code>synapse.module_api.NOT_SPAM</code>, Synapse falls through to the next one.
callback that does not return <code>True</code> will be used. If this happens, Synapse will not call The value of the first callback that does not return <code>synapse.module_api.NOT_SPAM</code> will
any of the subsequent implementations of this callback.</p> be used. If this happens, Synapse will not call any of the subsequent implementations of
this callback.</p>
<h3 id="user_may_publish_room"><a class="header" href="#user_may_publish_room"><code>user_may_publish_room</code></a></h3> <h3 id="user_may_publish_room"><a class="header" href="#user_may_publish_room"><code>user_may_publish_room</code></a></h3>
<p><em>First introduced in Synapse v1.37.0</em></p> <p><em>First introduced in Synapse v1.37.0</em></p>
<pre><code class="language-python">async def user_may_publish_room(user: str, room_id: str) -&gt; bool <p><em>Changed in Synapse v1.61.0: <code>synapse.module_api.NOT_SPAM</code> and <code>synapse.module_api.errors.Codes</code> can be returned by this callback. Returning a boolean is now deprecated.</em> </p>
<pre><code class="language-python">async def user_may_publish_room(user_id: str, room_id: str) -&gt; Union[&quot;synapse.module_api.NOT_SPAM&quot;, &quot;synapse.module_api.errors.Codes&quot;, bool]
</code></pre> </code></pre>
<p>Called when trying to publish a room to the homeserver's public rooms directory. The <p>Called when trying to publish a room to the homeserver's public rooms directory.</p>
module must return a <code>bool</code> indicating whether the given user (represented by their <p>The callback must return one of:</p>
Matrix user ID) is allowed to publish the given room. Return <code>False</code> to prevent the <ul>
room from being published; otherwise return <code>True</code> to permit its publication.</p> <li>
<p><code>synapse.module_api.NOT_SPAM</code>, to allow the operation. Other callbacks may still
decide to reject it.</p>
</li>
<li>
<p><code>synapse.module_api.errors.Codes</code> to reject the operation with an error code. In case
of doubt, <code>synapse.module_api.errors.Codes.FORBIDDEN</code> is a good error code.</p>
</li>
<li>
<p>(deprecated) <code>False</code>, which is the same as returning <code>synapse.module_api.NOT_SPAM</code>.</p>
</li>
<li>
<p>(deprecated) <code>True</code>, which is the same as returning <code>synapse.module_api.errors.Codes.FORBIDDEN</code>.</p>
</li>
</ul>
<p>If multiple modules implement this callback, they will be considered in order. If a <p>If multiple modules implement this callback, they will be considered in order. If a
callback returns <code>True</code>, Synapse falls through to the next one. The value of the first callback returns <code>synapse.module_api.NOT_SPAM</code>, Synapse falls through to the next one.
callback that does not return <code>True</code> will be used. If this happens, Synapse will not call The value of the first callback that does not return <code>synapse.module_api.NOT_SPAM</code> will
any of the subsequent implementations of this callback.</p> be used. If this happens, Synapse will not call any of the subsequent implementations of
this callback.</p>
<h3 id="check_username_for_spam"><a class="header" href="#check_username_for_spam"><code>check_username_for_spam</code></a></h3> <h3 id="check_username_for_spam"><a class="header" href="#check_username_for_spam"><code>check_username_for_spam</code></a></h3>
<p><em>First introduced in Synapse v1.37.0</em></p> <p><em>First introduced in Synapse v1.37.0</em></p>
<pre><code class="language-python">async def check_username_for_spam(user_profile: synapse.module_api.UserProfile) -&gt; bool <pre><code class="language-python">async def check_username_for_spam(user_profile: synapse.module_api.UserProfile) -&gt; bool
@ -11407,18 +11529,35 @@ be used. If this happens, Synapse will not call any of the subsequent implementa
this callback.</p> this callback.</p>
<h3 id="check_media_file_for_spam"><a class="header" href="#check_media_file_for_spam"><code>check_media_file_for_spam</code></a></h3> <h3 id="check_media_file_for_spam"><a class="header" href="#check_media_file_for_spam"><code>check_media_file_for_spam</code></a></h3>
<p><em>First introduced in Synapse v1.37.0</em></p> <p><em>First introduced in Synapse v1.37.0</em></p>
<p><em>Changed in Synapse v1.61.0: <code>synapse.module_api.NOT_SPAM</code> and <code>synapse.module_api.errors.Codes</code> can be returned by this callback. Returning a boolean is now deprecated.</em> </p>
<pre><code class="language-python">async def check_media_file_for_spam( <pre><code class="language-python">async def check_media_file_for_spam(
file_wrapper: &quot;synapse.rest.media.v1.media_storage.ReadableFileWrapper&quot;, file_wrapper: &quot;synapse.rest.media.v1.media_storage.ReadableFileWrapper&quot;,
file_info: &quot;synapse.rest.media.v1._base.FileInfo&quot;, file_info: &quot;synapse.rest.media.v1._base.FileInfo&quot;,
) -&gt; bool ) -&gt; Union[&quot;synapse.module_api.NOT_SPAM&quot;, &quot;synapse.module_api.errors.Codes&quot;, bool]
</code></pre> </code></pre>
<p>Called when storing a local or remote file. The module must return a <code>bool</code> indicating <p>Called when storing a local or remote file.</p>
whether the given file should be excluded from the homeserver's media store. Return <p>The callback must return one of:</p>
<code>True</code> to prevent this file from being stored; otherwise return <code>False</code>.</p> <ul>
<li>
<p><code>synapse.module_api.NOT_SPAM</code>, to allow the operation. Other callbacks may still
decide to reject it.</p>
</li>
<li>
<p><code>synapse.module_api.errors.Codes</code> to reject the operation with an error code. In case
of doubt, <code>synapse.module_api.errors.Codes.FORBIDDEN</code> is a good error code.</p>
</li>
<li>
<p>(deprecated) <code>False</code>, which is the same as returning <code>synapse.module_api.NOT_SPAM</code>.</p>
</li>
<li>
<p>(deprecated) <code>True</code>, which is the same as returning <code>synapse.module_api.errors.Codes.FORBIDDEN</code>.</p>
</li>
</ul>
<p>If multiple modules implement this callback, they will be considered in order. If a <p>If multiple modules implement this callback, they will be considered in order. If a
callback returns <code>False</code>, Synapse falls through to the next one. The value of the first callback returns <code>synapse.module_api.NOT_SPAM</code>, Synapse falls through to the next one.
callback that does not return <code>False</code> will be used. If this happens, Synapse will not call The value of the first callback that does not return <code>synapse.module_api.NOT_SPAM</code> will
any of the subsequent implementations of this callback.</p> be used. If this happens, Synapse will not call any of the subsequent implementations of
this callback.</p>
<h3 id="should_drop_federated_event"><a class="header" href="#should_drop_federated_event"><code>should_drop_federated_event</code></a></h3> <h3 id="should_drop_federated_event"><a class="header" href="#should_drop_federated_event"><code>should_drop_federated_event</code></a></h3>
<p><em>First introduced in Synapse v1.60.0</em></p> <p><em>First introduced in Synapse v1.60.0</em></p>
<pre><code class="language-python">async def should_drop_federated_event(event: &quot;synapse.events.EventBase&quot;) -&gt; bool <pre><code class="language-python">async def should_drop_federated_event(event: &quot;synapse.events.EventBase&quot;) -&gt; bool
@ -11471,8 +11610,11 @@ class ListSpamChecker:
resource=IsUserEvilResource(config), resource=IsUserEvilResource(config),
) )
async def check_event_for_spam(self, event: &quot;synapse.events.EventBase&quot;) -&gt; Union[bool, str]: async def check_event_for_spam(self, event: &quot;synapse.events.EventBase&quot;) -&gt; Union[Literal[&quot;NOT_SPAM&quot;], Codes]:
return event.sender not in self.evil_users if event.sender in self.evil_users:
return Codes.FORBIDDEN
else:
return synapse.module_api.NOT_SPAM
</code></pre> </code></pre>
<div style="break-before: page; page-break-before: always;"></div><h1 id="third-party-rules-callbacks"><a class="header" href="#third-party-rules-callbacks">Third party rules callbacks</a></h1> <div style="break-before: page; page-break-before: always;"></div><h1 id="third-party-rules-callbacks"><a class="header" href="#third-party-rules-callbacks">Third party rules callbacks</a></h1>
<p>Third party rules callbacks allow module developers to add extra checks to verify the <p>Third party rules callbacks allow module developers to add extra checks to verify the

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -232,6 +232,37 @@ dpkg -i matrix-synapse-py3_1.3.0+stretch1_amd64.deb
</code></pre> </code></pre>
</li> </li>
</ul> </ul>
<h1 id="upgrading-to-v1610"><a class="header" href="#upgrading-to-v1610">Upgrading to v1.61.0</a></h1>
<h2 id="new-signatures-for-spam-checker-callbacks"><a class="header" href="#new-signatures-for-spam-checker-callbacks">New signatures for spam checker callbacks</a></h2>
<p>As a followup to changes in v1.60.0, the following spam-checker callbacks have changed signature:</p>
<ul>
<li><code>user_may_join_room</code></li>
<li><code>user_may_invite</code></li>
<li><code>user_may_send_3pid_invite</code></li>
<li><code>user_may_create_room</code></li>
<li><code>user_may_create_room_alias</code></li>
<li><code>user_may_publish_room</code></li>
<li><code>check_media_file_for_spam</code></li>
</ul>
<p>For each of these methods, the previous callback signature has been deprecated.</p>
<p>Whereas callbacks used to return <code>bool</code>, they should now return <code>Union[&quot;synapse.module_api.NOT_SPAM&quot;, &quot;synapse.module_api.errors.Codes&quot;]</code>.</p>
<p>For instance, if your module implements <code>user_may_join_room</code> as follows:</p>
<pre><code class="language-python">async def user_may_join_room(self, user_id: str, room_id: str, is_invited: bool)
if ...:
# Request is spam
return False
# Request is not spam
return True
</code></pre>
<p>you should rewrite it as follows:</p>
<pre><code class="language-python">async def user_may_join_room(self, user_id: str, room_id: str, is_invited: bool)
if ...:
# Request is spam, mark it as forbidden (you may use some more precise error
# code if it is useful).
return synapse.module_api.errors.Codes.FORBIDDEN
# Request is not spam, mark it as such.
return synapse.module_api.NOT_SPAM
</code></pre>
<h1 id="upgrading-to-v1600"><a class="header" href="#upgrading-to-v1600">Upgrading to v1.60.0</a></h1> <h1 id="upgrading-to-v1600"><a class="header" href="#upgrading-to-v1600">Upgrading to v1.60.0</a></h1>
<h2 id="adding-a-new-unique-index-to-state_group_edges-could-fail-if-your-database-is-corrupted"><a class="header" href="#adding-a-new-unique-index-to-state_group_edges-could-fail-if-your-database-is-corrupted">Adding a new unique index to <code>state_group_edges</code> could fail if your database is corrupted</a></h2> <h2 id="adding-a-new-unique-index-to-state_group_edges-could-fail-if-your-database-is-corrupted"><a class="header" href="#adding-a-new-unique-index-to-state_group_edges-could-fail-if-your-database-is-corrupted">Adding a new unique index to <code>state_group_edges</code> could fail if your database is corrupted</a></h2>
<p>This release of Synapse will add a unique index to the <code>state_group_edges</code> table, in order <p>This release of Synapse will add a unique index to the <code>state_group_edges</code> table, in order