34
34
from twisted .internet .abstract import isIPAddress
35
35
from twisted .python import failure
36
36
37
- from synapse .api .constants import EduTypes , EventTypes
37
+ from synapse .api .constants import EduTypes , EventTypes , Membership
38
38
from synapse .api .errors import (
39
39
AuthError ,
40
40
Codes ,
46
46
)
47
47
from synapse .api .room_versions import KNOWN_ROOM_VERSIONS
48
48
from synapse .events import EventBase
49
+ from synapse .events .snapshot import EventContext
49
50
from synapse .federation .federation_base import FederationBase , event_from_pdu_json
50
51
from synapse .federation .persistence import TransactionActions
51
52
from synapse .federation .units import Edu , Transaction
@@ -537,26 +538,21 @@ async def on_invite_request(
537
538
return {"event" : ret_pdu .get_pdu_json (time_now )}
538
539
539
540
async def on_send_join_request (
540
- self , origin : str , content : JsonDict
541
+ self , origin : str , content : JsonDict , room_id : str
541
542
) -> 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
+ )
552
546
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 )
554
551
555
- res_pdus = await self .handler .on_send_join_request (origin , pdu )
556
552
time_now = self ._clock .time_msec ()
557
553
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 ],
560
556
}
561
557
562
558
async def on_make_leave_request (
@@ -571,21 +567,11 @@ async def on_make_leave_request(
571
567
time_now = self ._clock .time_msec ()
572
568
return {"event" : pdu .get_pdu_json (time_now ), "room_version" : room_version }
573
569
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 :
575
573
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 )
589
575
return {}
590
576
591
577
async def on_make_knock_request (
@@ -651,39 +637,76 @@ async def on_send_knock_request(
651
637
Returns:
652
638
The stripped room state.
653
639
"""
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
+ )
655
684
656
685
room_version = await self .store .get_room_version (room_id )
657
686
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 :
660
688
raise SynapseError (
661
689
403 ,
662
690
"This room version does not support knocking" ,
663
691
errcode = Codes .FORBIDDEN ,
664
692
)
665
693
666
- pdu = event_from_pdu_json (content , room_version )
694
+ event = event_from_pdu_json (content , room_version )
667
695
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 )
670
698
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 )
672
701
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 )
674
704
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 )
677
706
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 )
687
710
688
711
async def on_event_auth (
689
712
self , origin : str , room_id : str , event_id : str
0 commit comments