diff --git a/tests/handlers/test_presence.py b/tests/handlers/test_presence.py
index ab763d6284..ba47e801a4 100644
--- a/tests/handlers/test_presence.py
+++ b/tests/handlers/test_presence.py
@@ -36,8 +36,7 @@ from synapse.handlers.presence import (
handle_update,
)
from synapse.rest import admin
-from synapse.rest.admin.experimental_features import ExperimentalFeature
-from synapse.rest.client import room
+from synapse.rest.client import login, room
from synapse.server import HomeServer
from synapse.types import JsonDict, UserID, get_domain_from_id
from synapse.util import Clock
@@ -515,14 +514,13 @@ class PresenceTimeoutTestCase(unittest.TestCase):
class PresenceHandlerTestCase(BaseMultiWorkerStreamTestCase):
- servlets = [
- admin.register_servlets,
- ]
+ servlets = [admin.register_servlets, login.register_servlets]
def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None:
self.presence_handler = hs.get_presence_handler()
self.clock = hs.get_clock()
- self.user = self.register_user("test", "pass")
+ self.user = self.register_user("test", "pass", True)
+ self.admin_user_tok = self.login("test", "pass")
def test_external_process_timeout(self) -> None:
"""Test that if an external process doesn't update the records for a while
@@ -731,10 +729,11 @@ class PresenceHandlerTestCase(BaseMultiWorkerStreamTestCase):
self.assertEqual(state.status_msg, status_msg)
@parameterized.expand([(False,), (True,)])
- def test_set_presence_from_syncing_keeps_busy(
+ def test_set_presence_from_syncing_keeps_busy_via_admin(
self, test_with_workers: bool
) -> None:
- """Test that presence set by syncing doesn't affect busy status
+ """Test that presence set by syncing doesn't affect busy status, with the busy status
+ enabled via the admin api.
Args:
test_with_workers: If True, check the presence state of the user by calling
@@ -742,13 +741,69 @@ class PresenceHandlerTestCase(BaseMultiWorkerStreamTestCase):
"""
status_msg = "I'm busy!"
- # set busy state in db
+ # activate busy state via admin api
+ url = f"/_synapse/admin/v1/experimental_features/{self.user}"
+ channel = self.make_request(
+ "PUT",
+ url,
+ content={
+ "features": {"msc3026": True},
+ },
+ access_token=self.admin_user_tok,
+ )
+ self.assertEqual(channel.code, 200)
+
+ # By default, we call /sync against the main process.
+ worker_to_sync_against = self.hs
+ if test_with_workers:
+ # Create a worker and use it to handle /sync traffic instead.
+ # This is used to test that presence changes get replicated from workers
+ # to the main process correctly.
+ worker_to_sync_against = self.make_worker_hs(
+ "synapse.app.generic_worker", {"worker_name": "presence_writer"}
+ )
+
+ # Set presence to BUSY
+ self._set_presencestate_with_status_msg(
+ self.user, PresenceState.BUSY, status_msg
+ )
+
+ # Perform a sync with a presence state other than busy. This should NOT change
+ # our presence status; we only change from busy if we explicitly set it via
+ # /presence/*.
self.get_success(
- self.hs.get_datastores().main.set_features_for_user(
- self.user, {ExperimentalFeature.MSC3026: True}
+ worker_to_sync_against.get_presence_handler().user_syncing(
+ self.user, True, PresenceState.ONLINE
)
)
+ # Check against the main process that the user's presence did not change.
+ state = self.get_success(
+ self.presence_handler.get_state(UserID.from_string(self.user))
+ )
+ # we should still be busy
+ self.assertEqual(state.state, PresenceState.BUSY)
+
+ @parameterized.expand([(False,), (True,)])
+ @unittest.override_config(
+ {
+ "experimental_features": {
+ "msc3026_enabled": True,
+ },
+ }
+ )
+ def test_set_presence_from_syncing_keeps_busy_via_config(
+ self, test_with_workers: bool
+ ) -> None:
+ """Test that presence set by syncing doesn't affect busy status, with the busy status
+ enabled via the config
+
+ Args:
+ test_with_workers: If True, check the presence state of the user by calling
+ /sync against a worker, rather than the main process.
+ """
+ status_msg = "I'm busy!"
+
# By default, we call /sync against the main process.
worker_to_sync_against = self.hs
if test_with_workers:
diff --git a/tests/push/test_http.py b/tests/push/test_http.py
index 97bc48f246..42f24a530d 100644
--- a/tests/push/test_http.py
+++ b/tests/push/test_http.py
@@ -20,9 +20,9 @@ from twisted.test.proto_helpers import MemoryReactor
import synapse.rest.admin
from synapse.logging.context import make_deferred_yieldable
from synapse.push import PusherConfig, PusherConfigException
-from synapse.rest.admin.experimental_features import ExperimentalFeature
from synapse.rest.client import login, push_rule, pusher, receipts, room
from synapse.server import HomeServer
+from synapse.storage.databases.main.experimental_features import ExperimentalFeature
from synapse.types import JsonDict
from synapse.util import Clock
@@ -37,6 +37,7 @@ class HTTPPusherTests(HomeserverTestCase):
receipts.register_servlets,
push_rule.register_servlets,
pusher.register_servlets,
+ synapse.rest.admin.register_servlets,
]
user_id = True
hijack_auth = False
@@ -820,20 +821,60 @@ class HTTPPusherTests(HomeserverTestCase):
self.helper.send(room, body="Hello", tok=access_token)
self.assertEqual(len(self.push_attempts), 1)
- def test_disable(self) -> None:
- """Tests that disabling a pusher means it's not pushed to anymore."""
+ @override_config({"experimental_features": {"msc3881_enabled": True}})
+ def test_disable_via_config(self) -> None:
+ """Tests that disabling a pusher means it's not pushed to anymore, with the
+ ability to disable a pusher enabled via the config.
+ """
user_id, access_token = self._make_user_with_pusher("user")
other_user_id, other_access_token = self._make_user_with_pusher("otheruser")
room = self.helper.create_room_as(user_id, tok=access_token)
self.helper.join(room=room, user=other_user_id, tok=other_access_token)
- # enable msc3881 per_user flag
- self.get_success(
- self.hs.get_datastores().main.set_features_for_user(
- user_id, {ExperimentalFeature.MSC3881: True}
- )
+ # Send a message and check that it generated a push.
+ self.helper.send(room, body="Hi!", tok=other_access_token)
+ self.assertEqual(len(self.push_attempts), 1)
+
+ # Disable the pusher.
+ self._set_pusher(user_id, access_token, enabled=False)
+
+ # Send another message and check that it did not generate a push.
+ self.helper.send(room, body="Hi!", tok=other_access_token)
+ self.assertEqual(len(self.push_attempts), 1)
+
+ # Get the pushers for the user and check that it is marked as disabled.
+ channel = self.make_request("GET", "/pushers", access_token=access_token)
+ self.assertEqual(channel.code, 200)
+ self.assertEqual(len(channel.json_body["pushers"]), 1)
+
+ enabled = channel.json_body["pushers"][0]["org.matrix.msc3881.enabled"]
+ self.assertFalse(enabled)
+ self.assertTrue(isinstance(enabled, bool))
+
+ def test_disable_via_admin(self) -> None:
+ """Tests that disabling a pusher means it's not pushed to anymore,
+ with the ability to disable a pusher enabled via the admin api.
+ """
+ user_id, access_token = self._make_user_with_pusher("user")
+ other_user_id, other_access_token = self._make_user_with_pusher("otheruser")
+ self.register_user("admin", "pass", True)
+ admin_tok = self.login("admin", "pass")
+
+ room = self.helper.create_room_as(user_id, tok=access_token)
+ self.helper.join(room=room, user=other_user_id, tok=other_access_token)
+
+ # enable msc3881 per_user flag via the admin api
+ url = f"/_synapse/admin/v1/experimental_features/{user_id}"
+ channel = self.make_request(
+ "PUT",
+ url,
+ content={
+ "features": {"msc3881": True},
+ },
+ access_token=admin_tok,
)
+ self.assertEqual(channel.code, 200)
# Send a message and check that it generated a push.
self.helper.send(room, body="Hi!", tok=other_access_token)
diff --git a/tests/rest/client/test_keys.py b/tests/rest/client/test_keys.py
index ef2800ee54..46ab0b505f 100644
--- a/tests/rest/client/test_keys.py
+++ b/tests/rest/client/test_keys.py
@@ -23,7 +23,6 @@ from signedjson.sign import sign_json
from synapse.api.errors import Codes
from synapse.rest import admin
-from synapse.rest.admin.experimental_features import ExperimentalFeature
from synapse.rest.client import keys, login
from synapse.types import JsonDict
@@ -37,6 +36,7 @@ class KeyQueryTestCase(unittest.HomeserverTestCase):
keys.register_servlets,
admin.register_servlets_for_client_rest_resource,
login.register_servlets,
+ admin.register_servlets,
]
def test_rejects_device_id_ice_key_outside_of_list(self) -> None:
@@ -207,21 +207,84 @@ class KeyQueryTestCase(unittest.HomeserverTestCase):
@override_config(
{
"ui_auth": {"session_timeout": "15s"},
+ "experimental_features": {"msc3967_enabled": True},
}
)
- def test_device_signing_with_msc3967(self) -> None:
- """Device signing key follows MSC3967 behaviour when enabled."""
+ def test_device_signing_with_msc3967_via_config(self) -> None:
+ """Device signing key follows MSC3967 behaviour when enabled in config."""
password = "wonderland"
device_id = "ABCDEFGHI"
alice_id = self.register_user("alice", password)
alice_token = self.login("alice", password, device_id=device_id)
- # enable msc3967 in db
- self.get_success(
- self.hs.get_datastores().main.set_features_for_user(
- alice_id, {ExperimentalFeature.MSC3967: True}
- )
+ keys1 = self.make_device_keys(alice_id, device_id)
+
+ # Initial request should succeed as no existing keys are present.
+ channel = self.make_request(
+ "POST",
+ "/_matrix/client/v3/keys/device_signing/upload",
+ keys1,
+ alice_token,
+ )
+ self.assertEqual(channel.code, HTTPStatus.OK, channel.result)
+
+ keys2 = self.make_device_keys(alice_id, device_id)
+
+ # Subsequent request should require UIA as keys already exist even though session_timeout is set.
+ channel = self.make_request(
+ "POST",
+ "/_matrix/client/v3/keys/device_signing/upload",
+ keys2,
+ alice_token,
+ )
+ self.assertEqual(channel.code, HTTPStatus.UNAUTHORIZED, channel.result)
+
+ # Grab the session
+ session = channel.json_body["session"]
+ # Ensure that flows are what is expected.
+ self.assertIn({"stages": ["m.login.password"]}, channel.json_body["flows"])
+
+ # add UI auth
+ keys2["auth"] = {
+ "type": "m.login.password",
+ "identifier": {"type": "m.id.user", "user": alice_id},
+ "password": password,
+ "session": session,
+ }
+
+ # Request should complete
+ channel = self.make_request(
+ "POST",
+ "/_matrix/client/v3/keys/device_signing/upload",
+ keys2,
+ alice_token,
+ )
+ self.assertEqual(channel.code, HTTPStatus.OK, channel.result)
+
+ @override_config(
+ {
+ "ui_auth": {"session_timeout": "15s"},
+ }
+ )
+ def test_device_signing_with_msc3967_via_admin(self) -> None:
+ """Device signing key follows MSC3967 behaviour when enabled for user via admin api."""
+ password = "wonderland"
+ device_id = "ABCDEFGHI"
+ alice_id = self.register_user("alice", password)
+ alice_token = self.login("alice", password, device_id=device_id)
+ self.register_user("admin", "pass", True)
+ admin_tok = self.login("admin", "pass")
+
+ url = f"/_synapse/admin/v1/experimental_features/{alice_id}"
+ channel = self.make_request(
+ "PUT",
+ url,
+ content={
+ "features": {"msc3967": True},
+ },
+ access_token=admin_tok,
)
+ self.assertEqual(channel.code, 200)
keys1 = self.make_device_keys(alice_id, device_id)
|