31
31
Membership ,
32
32
RelationTypes ,
33
33
)
34
- from synapse .api .errors import Codes , HttpResponseException
34
+ from synapse .api .errors import Code , Codes , HttpResponseException
35
35
from synapse .handlers .pagination import PurgeStatus
36
36
from synapse .rest import admin
37
37
from synapse .rest .client import account , directory , login , profile , room , sync
38
38
from synapse .server import HomeServer
39
+ from synapse .spam_checker_api import ALLOW , Decision
39
40
from synapse .types import JsonDict , RoomAlias , UserID , create_requester
40
41
from synapse .util import Clock
41
42
from synapse .util .stringutils import random_string
@@ -676,9 +677,9 @@ def test_post_room_invitees_ratelimit(self) -> None:
676
677
channel = self .make_request ("POST" , "/createRoom" , content )
677
678
self .assertEqual (200 , channel .code )
678
679
679
- def test_spam_checker_may_join_room (self ) -> None :
680
+ def test_spam_checker_may_join_room_old (self ) -> None :
680
681
"""Tests that the user_may_join_room spam checker callback is correctly bypassed
681
- when creating a new room.
682
+ when creating a new room (old-style API, returning a boolean) .
682
683
"""
683
684
684
685
async def user_may_join_room (
@@ -700,6 +701,30 @@ async def user_may_join_room(
700
701
701
702
self .assertEqual (join_mock .call_count , 0 )
702
703
704
+ def test_spam_checker_may_join_room (self ) -> None :
705
+ """Tests that the user_may_join_room spam checker callback is correctly bypassed
706
+ when creating a new room.
707
+ """
708
+
709
+ async def user_may_join_room (
710
+ mxid : str ,
711
+ room_id : str ,
712
+ is_invite : bool ,
713
+ ) -> Decision :
714
+ return Code .FORBIDDEN
715
+
716
+ join_mock = Mock (side_effect = user_may_join_room )
717
+ self .hs .get_spam_checker ()._user_may_join_room_callbacks .append (join_mock )
718
+
719
+ channel = self .make_request (
720
+ "POST" ,
721
+ "/createRoom" ,
722
+ {},
723
+ )
724
+ self .assertEqual (channel .code , 200 , channel .json_body )
725
+
726
+ self .assertEqual (join_mock .call_count , 0 )
727
+
703
728
704
729
class RoomTopicTestCase (RoomBase ):
705
730
"""Tests /rooms/$room_id/topic REST events."""
@@ -910,9 +935,9 @@ def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None:
910
935
self .room2 = self .helper .create_room_as (room_creator = self .user1 , tok = self .tok1 )
911
936
self .room3 = self .helper .create_room_as (room_creator = self .user1 , tok = self .tok1 )
912
937
913
- def test_spam_checker_may_join_room (self ) -> None :
938
+ def test_spam_checker_may_join_room_old (self ) -> None :
914
939
"""Tests that the user_may_join_room spam checker callback is correctly called
915
- and blocks room joins when needed.
940
+ and blocks room joins when needed (old-style API, return a boolean) .
916
941
"""
917
942
918
943
# Register a dummy callback. Make it allow all room joins for now.
@@ -967,6 +992,63 @@ async def user_may_join_room(
967
992
return_value = False
968
993
self .helper .join (self .room3 , self .user2 , expect_code = 403 , tok = self .tok2 )
969
994
995
+ def test_spam_checker_may_join_room (self ) -> None :
996
+ """Tests that the user_may_join_room spam checker callback is correctly called
997
+ and blocks room joins when needed.
998
+ """
999
+
1000
+ # Register a dummy callback. Make it allow all room joins for now.
1001
+ return_value : Decision = ALLOW
1002
+
1003
+ async def user_may_join_room (
1004
+ userid : str ,
1005
+ room_id : str ,
1006
+ is_invited : bool ,
1007
+ ) -> Decision :
1008
+ return return_value
1009
+
1010
+ callback_mock = Mock (side_effect = user_may_join_room )
1011
+ self .hs .get_spam_checker ()._user_may_join_room_callbacks .append (callback_mock )
1012
+
1013
+ # Join a first room, without being invited to it.
1014
+ self .helper .join (self .room1 , self .user2 , tok = self .tok2 )
1015
+
1016
+ # Check that the callback was called with the right arguments.
1017
+ expected_call_args = (
1018
+ (
1019
+ self .user2 ,
1020
+ self .room1 ,
1021
+ False ,
1022
+ ),
1023
+ )
1024
+ self .assertEqual (
1025
+ callback_mock .call_args ,
1026
+ expected_call_args ,
1027
+ callback_mock .call_args ,
1028
+ )
1029
+
1030
+ # Join a second room, this time with an invite for it.
1031
+ self .helper .invite (self .room2 , self .user1 , self .user2 , tok = self .tok1 )
1032
+ self .helper .join (self .room2 , self .user2 , tok = self .tok2 )
1033
+
1034
+ # Check that the callback was called with the right arguments.
1035
+ expected_call_args = (
1036
+ (
1037
+ self .user2 ,
1038
+ self .room2 ,
1039
+ True ,
1040
+ ),
1041
+ )
1042
+ self .assertEqual (
1043
+ callback_mock .call_args ,
1044
+ expected_call_args ,
1045
+ callback_mock .call_args ,
1046
+ )
1047
+
1048
+ # Now make the callback deny all room joins, and check that a join actually fails.
1049
+ return_value = Code .FORBIDDEN
1050
+ self .helper .join (self .room3 , self .user2 , expect_code = 403 , tok = self .tok2 )
1051
+
970
1052
971
1053
class RoomJoinRatelimitTestCase (RoomBase ):
972
1054
user_id = "@sid1:red"
@@ -2586,7 +2668,7 @@ def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None:
2586
2668
2587
2669
self .room_id = self .helper .create_room_as (self .user_id , tok = self .tok )
2588
2670
2589
- def test_threepid_invite_spamcheck (self ) -> None :
2671
+ def test_threepid_invite_spamcheck_old (self ) -> None :
2590
2672
# Mock a few functions to prevent the test from failing due to failing to talk to
2591
2673
# a remote IS. We keep the mock for _mock_make_and_store_3pid_invite around so we
2592
2674
# can check its call_count later on during the test.
@@ -2640,3 +2722,58 @@ def test_threepid_invite_spamcheck(self) -> None:
2640
2722
2641
2723
# Also check that it stopped before calling _make_and_store_3pid_invite.
2642
2724
make_invite_mock .assert_called_once ()
2725
+
2726
+ def test_threepid_invite_spamcheck (self ) -> None :
2727
+ # Mock a few functions to prevent the test from failing due to failing to talk to
2728
+ # a remote IS. We keep the mock for _mock_make_and_store_3pid_invite around so we
2729
+ # can check its call_count later on during the test.
2730
+ make_invite_mock = Mock (return_value = make_awaitable (0 ))
2731
+ self .hs .get_room_member_handler ()._make_and_store_3pid_invite = make_invite_mock
2732
+ self .hs .get_identity_handler ().lookup_3pid = Mock (
2733
+ return_value = make_awaitable (None ),
2734
+ )
2735
+
2736
+ # Add a mock to the spamchecker callbacks for user_may_send_3pid_invite. Make it
2737
+ # allow everything for now.
2738
+ mock = Mock (return_value = make_awaitable (ALLOW ))
2739
+ self .hs .get_spam_checker ()._user_may_send_3pid_invite_callbacks .append (mock )
2740
+
2741
+ # Send a 3PID invite into the room and check that it succeeded.
2742
+ email_to_invite = "[email protected] "
2743
+ channel = self .make_request (
2744
+ method = "POST" ,
2745
+ path = "/rooms/" + self .room_id + "/invite" ,
2746
+ content = {
2747
+ "id_server" : "example.com" ,
2748
+ "id_access_token" : "sometoken" ,
2749
+ "medium" : "email" ,
2750
+ "address" : email_to_invite ,
2751
+ },
2752
+ access_token = self .tok ,
2753
+ )
2754
+ self .assertEqual (channel .code , 200 )
2755
+
2756
+ # Check that the callback was called with the right params.
2757
+ mock .assert_called_with (self .user_id , "email" , email_to_invite , self .room_id )
2758
+
2759
+ # Check that the call to send the invite was made.
2760
+ make_invite_mock .assert_called_once ()
2761
+
2762
+ # Now change the return value of the callback to deny any invite and test that
2763
+ # we can't send the invite.
2764
+ mock .return_value = make_awaitable (Code .FORBIDDEN )
2765
+ channel = self .make_request (
2766
+ method = "POST" ,
2767
+ path = "/rooms/" + self .room_id + "/invite" ,
2768
+ content = {
2769
+ "id_server" : "example.com" ,
2770
+ "id_access_token" : "sometoken" ,
2771
+ "medium" : "email" ,
2772
+ "address" : email_to_invite ,
2773
+ },
2774
+ access_token = self .tok ,
2775
+ )
2776
+ self .assertEqual (channel .code , 403 )
2777
+
2778
+ # Also check that it stopped before calling _make_and_store_3pid_invite.
2779
+ make_invite_mock .assert_called_once ()
0 commit comments