diff --git a/tests/media/test_media_storage.py b/tests/media/test_media_storage.py
index f262304c3d..f981d1c0d8 100644
--- a/tests/media/test_media_storage.py
+++ b/tests/media/test_media_storage.py
@@ -27,10 +27,11 @@ from typing_extensions import Literal
from twisted.internet import defer
from twisted.internet.defer import Deferred
+from twisted.python.failure import Failure
from twisted.test.proto_helpers import MemoryReactor
from twisted.web.resource import Resource
-from synapse.api.errors import Codes
+from synapse.api.errors import Codes, HttpResponseException
from synapse.events import EventBase
from synapse.http.types import QueryParams
from synapse.logging.context import make_deferred_yieldable
@@ -247,6 +248,7 @@ class MediaRepoTests(unittest.HomeserverTestCase):
retry_on_dns_fail: bool = True,
max_size: Optional[int] = None,
ignore_backoff: bool = False,
+ follow_redirects: bool = False,
) -> "Deferred[Tuple[int, Dict[bytes, List[bytes]]]]":
"""A mock for MatrixFederationHttpClient.get_file."""
@@ -257,10 +259,15 @@ class MediaRepoTests(unittest.HomeserverTestCase):
output_stream.write(data)
return response
+ def write_err(f: Failure) -> Failure:
+ f.trap(HttpResponseException)
+ output_stream.write(f.value.response)
+ return f
+
d: Deferred[Tuple[bytes, Tuple[int, Dict[bytes, List[bytes]]]]] = Deferred()
self.fetches.append((d, destination, path, args))
# Note that this callback changes the value held by d.
- d_after_callback = d.addCallback(write_to)
+ d_after_callback = d.addCallbacks(write_to, write_err)
return make_deferred_yieldable(d_after_callback)
# Mock out the homeserver's MatrixFederationHttpClient
@@ -316,10 +323,11 @@ class MediaRepoTests(unittest.HomeserverTestCase):
self.assertEqual(len(self.fetches), 1)
self.assertEqual(self.fetches[0][1], "example.com")
self.assertEqual(
- self.fetches[0][2], "/_matrix/media/r0/download/" + self.media_id
+ self.fetches[0][2], "/_matrix/media/v3/download/" + self.media_id
)
self.assertEqual(
- self.fetches[0][3], {"allow_remote": "false", "timeout_ms": "20000"}
+ self.fetches[0][3],
+ {"allow_remote": "false", "timeout_ms": "20000", "allow_redirect": "true"},
)
headers = {
@@ -671,6 +679,52 @@ class MediaRepoTests(unittest.HomeserverTestCase):
[b"cross-origin"],
)
+ def test_unknown_v3_endpoint(self) -> None:
+ """
+ If the v3 endpoint fails, try the r0 one.
+ """
+ channel = self.make_request(
+ "GET",
+ f"/_matrix/media/v3/download/{self.media_id}",
+ shorthand=False,
+ await_result=False,
+ )
+ self.pump()
+
+ # We've made one fetch, to example.com, using the media URL, and asking
+ # the other server not to do a remote fetch
+ self.assertEqual(len(self.fetches), 1)
+ self.assertEqual(self.fetches[0][1], "example.com")
+ self.assertEqual(
+ self.fetches[0][2], "/_matrix/media/v3/download/" + self.media_id
+ )
+
+ # The result which says the endpoint is unknown.
+ unknown_endpoint = b'{"errcode":"M_UNRECOGNIZED","error":"Unknown request"}'
+ self.fetches[0][0].errback(
+ HttpResponseException(404, "NOT FOUND", unknown_endpoint)
+ )
+
+ self.pump()
+
+ # There should now be another request to the r0 URL.
+ self.assertEqual(len(self.fetches), 2)
+ self.assertEqual(self.fetches[1][1], "example.com")
+ self.assertEqual(
+ self.fetches[1][2], f"/_matrix/media/r0/download/{self.media_id}"
+ )
+
+ headers = {
+ b"Content-Length": [b"%d" % (len(self.test_image.data))],
+ }
+
+ self.fetches[1][0].callback(
+ (self.test_image.data, (len(self.test_image.data), headers))
+ )
+
+ self.pump()
+ self.assertEqual(channel.code, 200)
+
class TestSpamCheckerLegacy:
"""A spam checker module that rejects all media that includes the bytes
diff --git a/tests/replication/test_multi_media_repo.py b/tests/replication/test_multi_media_repo.py
index 1e9994cc0b..9a7b675f54 100644
--- a/tests/replication/test_multi_media_repo.py
+++ b/tests/replication/test_multi_media_repo.py
@@ -133,7 +133,7 @@ class MediaRepoShardTestCase(BaseMultiWorkerStreamTestCase):
self.assertEqual(request.method, b"GET")
self.assertEqual(
request.path,
- f"/_matrix/media/r0/download/{target}/{media_id}".encode(),
+ f"/_matrix/media/v3/download/{target}/{media_id}".encode(),
)
self.assertEqual(
request.requestHeaders.getRawHeaders(b"host"), [target.encode("utf-8")]
diff --git a/tests/rest/admin/test_server_notice.py b/tests/rest/admin/test_server_notice.py
index dfd14f5751..2398bc503a 100644
--- a/tests/rest/admin/test_server_notice.py
+++ b/tests/rest/admin/test_server_notice.py
@@ -477,6 +477,33 @@ class ServerNoticeTestCase(unittest.HomeserverTestCase):
# second room has new ID
self.assertNotEqual(first_room_id, second_room_id)
+ @override_config(
+ {"server_notices": {"system_mxid_localpart": "notices", "auto_join": True}}
+ )
+ def test_auto_join(self) -> None:
+ """
+ Tests that the user get automatically joined to the notice room
+ when `auto_join` setting is used.
+ """
+ # user has no room memberships
+ self._check_invite_and_join_status(self.other_user, 0, 0)
+
+ # send server notice
+ server_notice_request_content = {
+ "user_id": self.other_user,
+ "content": {"msgtype": "m.text", "body": "test msg one"},
+ }
+
+ self.make_request(
+ "POST",
+ self.url,
+ access_token=self.admin_user_tok,
+ content=server_notice_request_content,
+ )
+
+ # user has joined the room
+ self._check_invite_and_join_status(self.other_user, 0, 1)
+
@override_config({"server_notices": {"system_mxid_localpart": "notices"}})
def test_update_notice_user_name_when_changed(self) -> None:
"""
diff --git a/tests/rest/client/test_profile.py b/tests/rest/client/test_profile.py
index 8f923fd40f..eb0fa00bb3 100644
--- a/tests/rest/client/test_profile.py
+++ b/tests/rest/client/test_profile.py
@@ -312,6 +312,166 @@ class ProfileTestCase(unittest.HomeserverTestCase):
)
self.assertEqual(channel.code, 200, channel.result)
+ @unittest.override_config(
+ {"experimental_features": {"msc4069_profile_inhibit_propagation": True}}
+ )
+ def test_msc4069_inhibit_propagation(self) -> None:
+ """Tests to ensure profile update propagation can be inhibited."""
+ for prop in ["avatar_url", "displayname"]:
+ room_id = self.helper.create_room_as(tok=self.owner_tok)
+
+ channel = self.make_request(
+ "PUT",
+ f"/rooms/{room_id}/state/m.room.member/{self.owner}",
+ content={"membership": "join", prop: "mxc://my.server/existing"},
+ access_token=self.owner_tok,
+ )
+ self.assertEqual(channel.code, 200, channel.result)
+
+ channel = self.make_request(
+ "PUT",
+ f"/profile/{self.owner}/{prop}?org.matrix.msc4069.propagate=false",
+ content={prop: "http://my.server/pic.gif"},
+ access_token=self.owner_tok,
+ )
+ self.assertEqual(channel.code, 200, channel.result)
+
+ res = (
+ self._get_avatar_url()
+ if prop == "avatar_url"
+ else self._get_displayname()
+ )
+ self.assertEqual(res, "http://my.server/pic.gif")
+
+ channel = self.make_request(
+ "GET",
+ f"/rooms/{room_id}/state/m.room.member/{self.owner}",
+ access_token=self.owner_tok,
+ )
+ self.assertEqual(channel.code, 200, channel.result)
+ self.assertEqual(channel.json_body.get(prop), "mxc://my.server/existing")
+
+ def test_msc4069_inhibit_propagation_disabled(self) -> None:
+ """Tests to ensure profile update propagation inhibit flags are ignored when the
+ experimental flag is not enabled.
+ """
+ for prop in ["avatar_url", "displayname"]:
+ room_id = self.helper.create_room_as(tok=self.owner_tok)
+
+ channel = self.make_request(
+ "PUT",
+ f"/rooms/{room_id}/state/m.room.member/{self.owner}",
+ content={"membership": "join", prop: "mxc://my.server/existing"},
+ access_token=self.owner_tok,
+ )
+ self.assertEqual(channel.code, 200, channel.result)
+
+ channel = self.make_request(
+ "PUT",
+ f"/profile/{self.owner}/{prop}?org.matrix.msc4069.propagate=false",
+ content={prop: "http://my.server/pic.gif"},
+ access_token=self.owner_tok,
+ )
+ self.assertEqual(channel.code, 200, channel.result)
+
+ res = (
+ self._get_avatar_url()
+ if prop == "avatar_url"
+ else self._get_displayname()
+ )
+ self.assertEqual(res, "http://my.server/pic.gif")
+
+ channel = self.make_request(
+ "GET",
+ f"/rooms/{room_id}/state/m.room.member/{self.owner}",
+ access_token=self.owner_tok,
+ )
+ self.assertEqual(channel.code, 200, channel.result)
+
+ # The ?propagate=false should be ignored by the server because the config flag
+ # isn't enabled.
+ self.assertEqual(channel.json_body.get(prop), "http://my.server/pic.gif")
+
+ def test_msc4069_inhibit_propagation_default(self) -> None:
+ """Tests to ensure profile update propagation happens by default."""
+ for prop in ["avatar_url", "displayname"]:
+ room_id = self.helper.create_room_as(tok=self.owner_tok)
+
+ channel = self.make_request(
+ "PUT",
+ f"/rooms/{room_id}/state/m.room.member/{self.owner}",
+ content={"membership": "join", prop: "mxc://my.server/existing"},
+ access_token=self.owner_tok,
+ )
+ self.assertEqual(channel.code, 200, channel.result)
+
+ channel = self.make_request(
+ "PUT",
+ f"/profile/{self.owner}/{prop}",
+ content={prop: "http://my.server/pic.gif"},
+ access_token=self.owner_tok,
+ )
+ self.assertEqual(channel.code, 200, channel.result)
+
+ res = (
+ self._get_avatar_url()
+ if prop == "avatar_url"
+ else self._get_displayname()
+ )
+ self.assertEqual(res, "http://my.server/pic.gif")
+
+ channel = self.make_request(
+ "GET",
+ f"/rooms/{room_id}/state/m.room.member/{self.owner}",
+ access_token=self.owner_tok,
+ )
+ self.assertEqual(channel.code, 200, channel.result)
+
+ # The ?propagate=false should be ignored by the server because the config flag
+ # isn't enabled.
+ self.assertEqual(channel.json_body.get(prop), "http://my.server/pic.gif")
+
+ @unittest.override_config(
+ {"experimental_features": {"msc4069_profile_inhibit_propagation": True}}
+ )
+ def test_msc4069_inhibit_propagation_like_default(self) -> None:
+ """Tests to ensure clients can request explicit profile propagation."""
+ for prop in ["avatar_url", "displayname"]:
+ room_id = self.helper.create_room_as(tok=self.owner_tok)
+
+ channel = self.make_request(
+ "PUT",
+ f"/rooms/{room_id}/state/m.room.member/{self.owner}",
+ content={"membership": "join", prop: "mxc://my.server/existing"},
+ access_token=self.owner_tok,
+ )
+ self.assertEqual(channel.code, 200, channel.result)
+
+ channel = self.make_request(
+ "PUT",
+ f"/profile/{self.owner}/{prop}?org.matrix.msc4069.propagate=true",
+ content={prop: "http://my.server/pic.gif"},
+ access_token=self.owner_tok,
+ )
+ self.assertEqual(channel.code, 200, channel.result)
+
+ res = (
+ self._get_avatar_url()
+ if prop == "avatar_url"
+ else self._get_displayname()
+ )
+ self.assertEqual(res, "http://my.server/pic.gif")
+
+ channel = self.make_request(
+ "GET",
+ f"/rooms/{room_id}/state/m.room.member/{self.owner}",
+ access_token=self.owner_tok,
+ )
+ self.assertEqual(channel.code, 200, channel.result)
+
+ # The client requested ?propagate=true, so it should have happened.
+ self.assertEqual(channel.json_body.get(prop), "http://my.server/pic.gif")
+
def _setup_local_files(self, names_and_props: Dict[str, Dict[str, Any]]) -> None:
"""Stores metadata about files in the database.
|