1
0

Merge branch 'develop' into madlittlemods/optimize-msc2716-v1

Conflicts:
	synapse/handlers/room_batch.py
This commit is contained in:
Eric Eastwood
2022-02-07 18:28:56 -06:00
10 changed files with 109 additions and 32 deletions

1
changelog.d/11909.misc Normal file
View 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
View File

@@ -0,0 +1 @@
Various refactors to the application service notifier code.

1
changelog.d/11914.misc Normal file
View File

@@ -0,0 +1 @@
Various refactors to the typing notifications code.

1
changelog.d/11927.misc Normal file
View File

@@ -0,0 +1 @@
Use the proper type for the Content-Length header in the `UploadResource`.

View File

@@ -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:

View File

@@ -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.
"""

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -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
)