Merge branch 'develop' into madlittlemods/optimize-msc2716-v1
Conflicts: synapse/handlers/room_batch.py
This commit is contained in:
1
changelog.d/11909.misc
Normal file
1
changelog.d/11909.misc
Normal file
@@ -0,0 +1 @@
|
||||
Add a test that checks users receive their own device list updates down `/sync`.
|
||||
1
changelog.d/11911.misc
Normal file
1
changelog.d/11911.misc
Normal file
@@ -0,0 +1 @@
|
||||
Various refactors to the application service notifier code.
|
||||
1
changelog.d/11914.misc
Normal file
1
changelog.d/11914.misc
Normal file
@@ -0,0 +1 @@
|
||||
Various refactors to the typing notifications code.
|
||||
1
changelog.d/11927.misc
Normal file
1
changelog.d/11927.misc
Normal file
@@ -0,0 +1 @@
|
||||
Use the proper type for the Content-Length header in the `UploadResource`.
|
||||
@@ -165,23 +165,16 @@ class ApplicationService:
|
||||
return namespace.exclusive
|
||||
return False
|
||||
|
||||
async def _matches_user(
|
||||
self, event: Optional[EventBase], store: Optional["DataStore"] = None
|
||||
) -> bool:
|
||||
if not event:
|
||||
return False
|
||||
|
||||
async def _matches_user(self, event: EventBase, store: "DataStore") -> bool:
|
||||
if self.is_interested_in_user(event.sender):
|
||||
return True
|
||||
|
||||
# also check m.room.member state key
|
||||
if event.type == EventTypes.Member and self.is_interested_in_user(
|
||||
event.state_key
|
||||
):
|
||||
return True
|
||||
|
||||
if not store:
|
||||
return False
|
||||
|
||||
does_match = await self.matches_user_in_member_list(event.room_id, store)
|
||||
return does_match
|
||||
|
||||
@@ -216,21 +209,15 @@ class ApplicationService:
|
||||
return self.is_interested_in_room(event.room_id)
|
||||
return False
|
||||
|
||||
async def _matches_aliases(
|
||||
self, event: EventBase, store: Optional["DataStore"] = None
|
||||
) -> bool:
|
||||
if not store or not event:
|
||||
return False
|
||||
|
||||
async def _matches_aliases(self, event: EventBase, store: "DataStore") -> bool:
|
||||
alias_list = await store.get_aliases_for_room(event.room_id)
|
||||
for alias in alias_list:
|
||||
if self.is_interested_in_alias(alias):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
async def is_interested(
|
||||
self, event: EventBase, store: Optional["DataStore"] = None
|
||||
) -> bool:
|
||||
async def is_interested(self, event: EventBase, store: "DataStore") -> bool:
|
||||
"""Check if this service is interested in this event.
|
||||
|
||||
Args:
|
||||
|
||||
@@ -649,7 +649,7 @@ class ApplicationServicesHandler:
|
||||
"""Retrieve a list of application services interested in this event.
|
||||
|
||||
Args:
|
||||
event: The event to check. Can be None if alias_list is not.
|
||||
event: The event to check.
|
||||
Returns:
|
||||
A list of services interested in this event based on the service regex.
|
||||
"""
|
||||
|
||||
@@ -446,7 +446,7 @@ class TypingWriterHandler(FollowerTypingHandler):
|
||||
|
||||
class TypingNotificationEventSource(EventSource[int, JsonDict]):
|
||||
def __init__(self, hs: "HomeServer"):
|
||||
self.hs = hs
|
||||
self._main_store = hs.get_datastore()
|
||||
self.clock = hs.get_clock()
|
||||
# We can't call get_typing_handler here because there's a cycle:
|
||||
#
|
||||
@@ -487,7 +487,7 @@ class TypingNotificationEventSource(EventSource[int, JsonDict]):
|
||||
continue
|
||||
|
||||
if not await service.matches_user_in_member_list(
|
||||
room_id, handler.store
|
||||
room_id, self._main_store
|
||||
):
|
||||
continue
|
||||
|
||||
|
||||
@@ -49,10 +49,14 @@ class UploadResource(DirectServeJsonResource):
|
||||
|
||||
async def _async_render_POST(self, request: SynapseRequest) -> None:
|
||||
requester = await self.auth.get_user_by_req(request)
|
||||
content_length = request.getHeader("Content-Length")
|
||||
if content_length is None:
|
||||
raw_content_length = request.getHeader("Content-Length")
|
||||
if raw_content_length is None:
|
||||
raise SynapseError(msg="Request must specify a Content-Length", code=400)
|
||||
if int(content_length) > self.max_upload_size:
|
||||
try:
|
||||
content_length = int(raw_content_length)
|
||||
except ValueError:
|
||||
raise SynapseError(msg="Content-Length value is invalid", code=400)
|
||||
if content_length > self.max_upload_size:
|
||||
raise SynapseError(
|
||||
msg="Upload request body is too large",
|
||||
code=413,
|
||||
@@ -66,7 +70,8 @@ class UploadResource(DirectServeJsonResource):
|
||||
upload_name: Optional[str] = upload_name_bytes.decode("utf8")
|
||||
except UnicodeDecodeError:
|
||||
raise SynapseError(
|
||||
msg="Invalid UTF-8 filename parameter: %r" % (upload_name), code=400
|
||||
msg="Invalid UTF-8 filename parameter: %r" % (upload_name_bytes,),
|
||||
code=400,
|
||||
)
|
||||
|
||||
# If the name is falsey (e.g. an empty byte string) ensure it is None.
|
||||
|
||||
@@ -40,13 +40,19 @@ class ApplicationServiceTestCase(unittest.TestCase):
|
||||
)
|
||||
|
||||
self.store = Mock()
|
||||
self.store.get_aliases_for_room = simple_async_mock([])
|
||||
self.store.get_users_in_room = simple_async_mock([])
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def test_regex_user_id_prefix_match(self):
|
||||
self.service.namespaces[ApplicationService.NS_USERS].append(_regex("@irc_.*"))
|
||||
self.event.sender = "@irc_foobar:matrix.org"
|
||||
self.assertTrue(
|
||||
(yield defer.ensureDeferred(self.service.is_interested(self.event)))
|
||||
(
|
||||
yield defer.ensureDeferred(
|
||||
self.service.is_interested(self.event, self.store)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
@@ -54,7 +60,11 @@ class ApplicationServiceTestCase(unittest.TestCase):
|
||||
self.service.namespaces[ApplicationService.NS_USERS].append(_regex("@irc_.*"))
|
||||
self.event.sender = "@someone_else:matrix.org"
|
||||
self.assertFalse(
|
||||
(yield defer.ensureDeferred(self.service.is_interested(self.event)))
|
||||
(
|
||||
yield defer.ensureDeferred(
|
||||
self.service.is_interested(self.event, self.store)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
@@ -64,7 +74,11 @@ class ApplicationServiceTestCase(unittest.TestCase):
|
||||
self.event.type = "m.room.member"
|
||||
self.event.state_key = "@irc_foobar:matrix.org"
|
||||
self.assertTrue(
|
||||
(yield defer.ensureDeferred(self.service.is_interested(self.event)))
|
||||
(
|
||||
yield defer.ensureDeferred(
|
||||
self.service.is_interested(self.event, self.store)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
@@ -74,7 +88,11 @@ class ApplicationServiceTestCase(unittest.TestCase):
|
||||
)
|
||||
self.event.room_id = "!some_prefixs0m3th1nGsome_suffix:matrix.org"
|
||||
self.assertTrue(
|
||||
(yield defer.ensureDeferred(self.service.is_interested(self.event)))
|
||||
(
|
||||
yield defer.ensureDeferred(
|
||||
self.service.is_interested(self.event, self.store)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
@@ -84,7 +102,11 @@ class ApplicationServiceTestCase(unittest.TestCase):
|
||||
)
|
||||
self.event.room_id = "!XqBunHwQIXUiqCaoxq:matrix.org"
|
||||
self.assertFalse(
|
||||
(yield defer.ensureDeferred(self.service.is_interested(self.event)))
|
||||
(
|
||||
yield defer.ensureDeferred(
|
||||
self.service.is_interested(self.event, self.store)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
@@ -183,7 +205,11 @@ class ApplicationServiceTestCase(unittest.TestCase):
|
||||
self.event.content = {"membership": "invite"}
|
||||
self.event.state_key = self.service.sender
|
||||
self.assertTrue(
|
||||
(yield defer.ensureDeferred(self.service.is_interested(self.event)))
|
||||
(
|
||||
yield defer.ensureDeferred(
|
||||
self.service.is_interested(self.event, self.store)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
|
||||
@@ -23,7 +23,7 @@ from synapse.api.constants import (
|
||||
ReadReceiptEventFields,
|
||||
RelationTypes,
|
||||
)
|
||||
from synapse.rest.client import knock, login, read_marker, receipts, room, sync
|
||||
from synapse.rest.client import devices, knock, login, read_marker, receipts, room, sync
|
||||
|
||||
from tests import unittest
|
||||
from tests.federation.transport.test_knocking import (
|
||||
@@ -710,3 +710,58 @@ class SyncCacheTestCase(unittest.HomeserverTestCase):
|
||||
channel.await_result(timeout_ms=9900)
|
||||
channel.await_result(timeout_ms=200)
|
||||
self.assertEqual(channel.code, 200, channel.json_body)
|
||||
|
||||
|
||||
class DeviceListSyncTestCase(unittest.HomeserverTestCase):
|
||||
servlets = [
|
||||
synapse.rest.admin.register_servlets,
|
||||
login.register_servlets,
|
||||
sync.register_servlets,
|
||||
devices.register_servlets,
|
||||
]
|
||||
|
||||
def test_user_with_no_rooms_receives_self_device_list_updates(self):
|
||||
"""Tests that a user with no rooms still receives their own device list updates"""
|
||||
device_id = "TESTDEVICE"
|
||||
|
||||
# Register a user and login, creating a device
|
||||
self.user_id = self.register_user("kermit", "monkey")
|
||||
self.tok = self.login("kermit", "monkey", device_id=device_id)
|
||||
|
||||
# Request an initial sync
|
||||
channel = self.make_request("GET", "/sync", access_token=self.tok)
|
||||
self.assertEqual(channel.code, 200, channel.json_body)
|
||||
next_batch = channel.json_body["next_batch"]
|
||||
|
||||
# Now, make an incremental sync request.
|
||||
# It won't return until something has happened
|
||||
incremental_sync_channel = self.make_request(
|
||||
"GET",
|
||||
f"/sync?since={next_batch}&timeout=30000",
|
||||
access_token=self.tok,
|
||||
await_result=False,
|
||||
)
|
||||
|
||||
# Change our device's display name
|
||||
channel = self.make_request(
|
||||
"PUT",
|
||||
f"devices/{device_id}",
|
||||
{
|
||||
"display_name": "freeze ray",
|
||||
},
|
||||
access_token=self.tok,
|
||||
)
|
||||
self.assertEqual(channel.code, 200, channel.json_body)
|
||||
|
||||
# The sync should now have returned
|
||||
incremental_sync_channel.await_result(timeout_ms=20000)
|
||||
self.assertEqual(incremental_sync_channel.code, 200, channel.json_body)
|
||||
|
||||
# We should have received notification that the (user's) device has changed
|
||||
device_list_changes = incremental_sync_channel.json_body.get(
|
||||
"device_lists", {}
|
||||
).get("changed", [])
|
||||
|
||||
self.assertIn(
|
||||
self.user_id, device_list_changes, incremental_sync_channel.json_body
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user