Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit 0d5b08a

Browse files
Fix messages from multiple senders in historical chunk (MSC2716) (#10276)
Fix messages from multiple senders in historical chunk. This also means that an app service does not need to define `?user_id` when using this endpoint. Follow-up to #9247 Part of MSC2716: matrix-org/matrix-spec-proposals#2716
1 parent 30b56f6 commit 0d5b08a

File tree

3 files changed

+76
-11
lines changed

3 files changed

+76
-11
lines changed

changelog.d/10276.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix historical batch send endpoint (MSC2716) rejecting batches with messages from multiple senders.

synapse/api/auth.py

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,37 @@ async def get_user_by_req(
240240
except KeyError:
241241
raise MissingClientTokenError()
242242

243+
async def validate_appservice_can_control_user_id(
244+
self, app_service: ApplicationService, user_id: str
245+
):
246+
"""Validates that the app service is allowed to control
247+
the given user.
248+
249+
Args:
250+
app_service: The app service that controls the user
251+
user_id: The author MXID that the app service is controlling
252+
253+
Raises:
254+
AuthError: If the application service is not allowed to control the user
255+
(user namespace regex does not match, wrong homeserver, etc)
256+
or if the user has not been registered yet.
257+
"""
258+
259+
# It's ok if the app service is trying to use the sender from their registration
260+
if app_service.sender == user_id:
261+
pass
262+
# Check to make sure the app service is allowed to control the user
263+
elif not app_service.is_interested_in_user(user_id):
264+
raise AuthError(
265+
403,
266+
"Application service cannot masquerade as this user (%s)." % user_id,
267+
)
268+
# Check to make sure the user is already registered on the homeserver
269+
elif not (await self.store.get_user_by_id(user_id)):
270+
raise AuthError(
271+
403, "Application service has not registered this user (%s)" % user_id
272+
)
273+
243274
async def _get_appservice_user_id(
244275
self, request: Request
245276
) -> Tuple[Optional[str], Optional[ApplicationService]]:
@@ -261,13 +292,11 @@ async def _get_appservice_user_id(
261292
return app_service.sender, app_service
262293

263294
user_id = request.args[b"user_id"][0].decode("utf8")
295+
await self.validate_appservice_can_control_user_id(app_service, user_id)
296+
264297
if app_service.sender == user_id:
265298
return app_service.sender, app_service
266299

267-
if not app_service.is_interested_in_user(user_id):
268-
raise AuthError(403, "Application service cannot masquerade as this user.")
269-
if not (await self.store.get_user_by_id(user_id)):
270-
raise AuthError(403, "Application service has not registered this user")
271300
return user_id, app_service
272301

273302
async def get_user_by_access_token(

synapse/rest/client/v1/room.py

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
SynapseError,
3030
)
3131
from synapse.api.filtering import Filter
32+
from synapse.appservice import ApplicationService
3233
from synapse.events.utils import format_event_for_client_v2
3334
from synapse.http.servlet import (
3435
RestServlet,
@@ -47,11 +48,13 @@
4748
from synapse.streams.config import PaginationConfig
4849
from synapse.types import (
4950
JsonDict,
51+
Requester,
5052
RoomAlias,
5153
RoomID,
5254
StreamToken,
5355
ThirdPartyInstanceID,
5456
UserID,
57+
create_requester,
5558
)
5659
from synapse.util import json_decoder
5760
from synapse.util.stringutils import parse_and_validate_server_name, random_string
@@ -309,7 +312,7 @@ def __init__(self, hs):
309312
self.room_member_handler = hs.get_room_member_handler()
310313
self.auth = hs.get_auth()
311314

312-
async def inherit_depth_from_prev_ids(self, prev_event_ids) -> int:
315+
async def _inherit_depth_from_prev_ids(self, prev_event_ids) -> int:
313316
(
314317
most_recent_prev_event_id,
315318
most_recent_prev_event_depth,
@@ -378,6 +381,25 @@ def _create_insertion_event_dict(
378381

379382
return insertion_event
380383

384+
async def _create_requester_for_user_id_from_app_service(
385+
self, user_id: str, app_service: ApplicationService
386+
) -> Requester:
387+
"""Creates a new requester for the given user_id
388+
and validates that the app service is allowed to control
389+
the given user.
390+
391+
Args:
392+
user_id: The author MXID that the app service is controlling
393+
app_service: The app service that controls the user
394+
395+
Returns:
396+
Requester object
397+
"""
398+
399+
await self.auth.validate_appservice_can_control_user_id(app_service, user_id)
400+
401+
return create_requester(user_id, app_service=app_service)
402+
381403
async def on_POST(self, request, room_id):
382404
requester = await self.auth.get_user_by_req(request, allow_guest=False)
383405

@@ -443,7 +465,9 @@ async def on_POST(self, request, room_id):
443465
if event_dict["type"] == EventTypes.Member:
444466
membership = event_dict["content"].get("membership", None)
445467
event_id, _ = await self.room_member_handler.update_membership(
446-
requester,
468+
await self._create_requester_for_user_id_from_app_service(
469+
state_event["sender"], requester.app_service
470+
),
447471
target=UserID.from_string(event_dict["state_key"]),
448472
room_id=room_id,
449473
action=membership,
@@ -463,7 +487,9 @@ async def on_POST(self, request, room_id):
463487
event,
464488
_,
465489
) = await self.event_creation_handler.create_and_send_nonmember_event(
466-
requester,
490+
await self._create_requester_for_user_id_from_app_service(
491+
state_event["sender"], requester.app_service
492+
),
467493
event_dict,
468494
outlier=True,
469495
prev_event_ids=[fake_prev_event_id],
@@ -479,7 +505,9 @@ async def on_POST(self, request, room_id):
479505
events_to_create = body["events"]
480506

481507
prev_event_ids = prev_events_from_query
482-
inherited_depth = await self.inherit_depth_from_prev_ids(prev_events_from_query)
508+
inherited_depth = await self._inherit_depth_from_prev_ids(
509+
prev_events_from_query
510+
)
483511

484512
# Figure out which chunk to connect to. If they passed in
485513
# chunk_id_from_query let's use it. The chunk ID passed in comes
@@ -509,7 +537,10 @@ async def on_POST(self, request, room_id):
509537
base_insertion_event,
510538
_,
511539
) = await self.event_creation_handler.create_and_send_nonmember_event(
512-
requester,
540+
await self._create_requester_for_user_id_from_app_service(
541+
base_insertion_event_dict["sender"],
542+
requester.app_service,
543+
),
513544
base_insertion_event_dict,
514545
prev_event_ids=base_insertion_event_dict.get("prev_events"),
515546
auth_event_ids=auth_event_ids,
@@ -558,7 +589,9 @@ async def on_POST(self, request, room_id):
558589
}
559590

560591
event, context = await self.event_creation_handler.create_event(
561-
requester,
592+
await self._create_requester_for_user_id_from_app_service(
593+
ev["sender"], requester.app_service
594+
),
562595
event_dict,
563596
prev_event_ids=event_dict.get("prev_events"),
564597
auth_event_ids=auth_event_ids,
@@ -588,7 +621,9 @@ async def on_POST(self, request, room_id):
588621
# where topological_ordering is just depth.
589622
for (event, context) in reversed(events_to_persist):
590623
ev = await self.event_creation_handler.handle_new_client_event(
591-
requester=requester,
624+
await self._create_requester_for_user_id_from_app_service(
625+
event["sender"], requester.app_service
626+
),
592627
event=event,
593628
context=context,
594629
)

0 commit comments

Comments
 (0)