3434from twisted .internet .abstract import isIPAddress
3535from twisted .python import failure
3636
37- from synapse .api .constants import EduTypes , EventTypes
37+ from synapse .api .constants import EduTypes , EventTypes , Membership
3838from synapse .api .errors import (
3939 AuthError ,
4040 Codes ,
4646)
4747from synapse .api .room_versions import KNOWN_ROOM_VERSIONS
4848from synapse .events import EventBase
49+ from synapse .events .snapshot import EventContext
4950from synapse .federation .federation_base import FederationBase , event_from_pdu_json
5051from synapse .federation .persistence import TransactionActions
5152from synapse .federation .units import Edu , Transaction
@@ -537,26 +538,21 @@ async def on_invite_request(
537538 return {"event" : ret_pdu .get_pdu_json (time_now )}
538539
539540 async def on_send_join_request (
540- self , origin : str , content : JsonDict
541+ self , origin : str , content : JsonDict , room_id : str
541542 ) -> Dict [str , Any ]:
542- logger .debug ("on_send_join_request: content: %s" , content )
543-
544- assert_params_in_dict (content , ["room_id" ])
545- room_version = await self .store .get_room_version (content ["room_id" ])
546- pdu = event_from_pdu_json (content , room_version )
547-
548- origin_host , _ = parse_server_name (origin )
549- await self .check_server_matches_acl (origin_host , pdu .room_id )
550-
551- logger .debug ("on_send_join_request: pdu sigs: %s" , pdu .signatures )
543+ context = await self ._on_send_membership_event (
544+ origin , content , Membership .JOIN , room_id
545+ )
552546
553- pdu = await self ._check_sigs_and_hash (room_version , pdu )
547+ prev_state_ids = await context .get_prev_state_ids ()
548+ state_ids = list (prev_state_ids .values ())
549+ auth_chain = await self .store .get_auth_chain (room_id , state_ids )
550+ state = await self .store .get_events (state_ids )
554551
555- res_pdus = await self .handler .on_send_join_request (origin , pdu )
556552 time_now = self ._clock .time_msec ()
557553 return {
558- "state" : [p .get_pdu_json (time_now ) for p in res_pdus [ " state" ] ],
559- "auth_chain" : [p .get_pdu_json (time_now ) for p in res_pdus [ " auth_chain" ] ],
554+ "state" : [p .get_pdu_json (time_now ) for p in state . values () ],
555+ "auth_chain" : [p .get_pdu_json (time_now ) for p in auth_chain ],
560556 }
561557
562558 async def on_make_leave_request (
@@ -571,21 +567,11 @@ async def on_make_leave_request(
571567 time_now = self ._clock .time_msec ()
572568 return {"event" : pdu .get_pdu_json (time_now ), "room_version" : room_version }
573569
574- async def on_send_leave_request (self , origin : str , content : JsonDict ) -> dict :
570+ async def on_send_leave_request (
571+ self , origin : str , content : JsonDict , room_id : str
572+ ) -> dict :
575573 logger .debug ("on_send_leave_request: content: %s" , content )
576-
577- assert_params_in_dict (content , ["room_id" ])
578- room_version = await self .store .get_room_version (content ["room_id" ])
579- pdu = event_from_pdu_json (content , room_version )
580-
581- origin_host , _ = parse_server_name (origin )
582- await self .check_server_matches_acl (origin_host , pdu .room_id )
583-
584- logger .debug ("on_send_leave_request: pdu sigs: %s" , pdu .signatures )
585-
586- pdu = await self ._check_sigs_and_hash (room_version , pdu )
587-
588- await self .handler .on_send_leave_request (origin , pdu )
574+ await self ._on_send_membership_event (origin , content , Membership .LEAVE , room_id )
589575 return {}
590576
591577 async def on_make_knock_request (
@@ -651,39 +637,76 @@ async def on_send_knock_request(
651637 Returns:
652638 The stripped room state.
653639 """
654- logger .debug ("on_send_knock_request: content: %s" , content )
640+ event_context = await self ._on_send_membership_event (
641+ origin , content , Membership .KNOCK , room_id
642+ )
643+
644+ # Retrieve stripped state events from the room and send them back to the remote
645+ # server. This will allow the remote server's clients to display information
646+ # related to the room while the knock request is pending.
647+ stripped_room_state = (
648+ await self .store .get_stripped_room_state_from_event_context (
649+ event_context , self ._room_prejoin_state_types
650+ )
651+ )
652+ return {"knock_state_events" : stripped_room_state }
653+
654+ async def _on_send_membership_event (
655+ self , origin : str , content : JsonDict , membership_type : str , room_id : str
656+ ) -> EventContext :
657+ """Handle an on_send_{join,leave,knock} request
658+
659+ Does some preliminary validation before passing the request on to the
660+ federation handler.
661+
662+ Args:
663+ origin: The (authenticated) requesting server
664+ content: The body of the send_* request - a complete membership event
665+ membership_type: The expected membership type (join or leave, depending
666+ on the endpoint)
667+ room_id: The room_id from the request, to be validated against the room_id
668+ in the event
669+
670+ Returns:
671+ The context of the event after inserting it into the room graph.
672+
673+ Raises:
674+ SynapseError if there is a problem with the request, including things like
675+ the room_id not matching or the event not being authorized.
676+ """
677+ assert_params_in_dict (content , ["room_id" ])
678+ if content ["room_id" ] != room_id :
679+ raise SynapseError (
680+ 400 ,
681+ "Room ID in body does not match that in request path" ,
682+ Codes .BAD_JSON ,
683+ )
655684
656685 room_version = await self .store .get_room_version (room_id )
657686
658- # Check that this room supports knocking as defined by its room version
659- if not room_version .msc2403_knocking :
687+ if membership_type == Membership .KNOCK and not room_version .msc2403_knocking :
660688 raise SynapseError (
661689 403 ,
662690 "This room version does not support knocking" ,
663691 errcode = Codes .FORBIDDEN ,
664692 )
665693
666- pdu = event_from_pdu_json (content , room_version )
694+ event = event_from_pdu_json (content , room_version )
667695
668- origin_host , _ = parse_server_name ( origin )
669- await self . check_server_matches_acl ( origin_host , pdu . room_id )
696+ if event . type != EventTypes . Member or not event . is_state ():
697+ raise SynapseError ( 400 , "Not an m.room.member event" , Codes . BAD_JSON )
670698
671- logger .debug ("on_send_knock_request: pdu sigs: %s" , pdu .signatures )
699+ if event .content .get ("membership" ) != membership_type :
700+ raise SynapseError (400 , "Not a %s event" % membership_type , Codes .BAD_JSON )
672701
673- pdu = await self ._check_sigs_and_hash (room_version , pdu )
702+ origin_host , _ = parse_server_name (origin )
703+ await self .check_server_matches_acl (origin_host , event .room_id )
674704
675- # Handle the event, and retrieve the EventContext
676- event_context = await self .handler .on_send_knock_request (origin , pdu )
705+ logger .debug ("_on_send_membership_event: pdu sigs: %s" , event .signatures )
677706
678- # Retrieve stripped state events from the room and send them back to the remote
679- # server. This will allow the remote server's clients to display information
680- # related to the room while the knock request is pending.
681- stripped_room_state = (
682- await self .store .get_stripped_room_state_from_event_context (
683- event_context , self ._room_prejoin_state_types
684- )
685- )
686- return {"knock_state_events" : stripped_room_state }
707+ event = await self ._check_sigs_and_hash (room_version , event )
708+
709+ return await self .handler .on_send_membership_event (origin , event )
687710
688711 async def on_event_auth (
689712 self , origin : str , room_id : str , event_id : str
0 commit comments