11package  csapi_tests
22
33import  (
4+ 	"fmt" 
5+ 	"net/http" 
6+ 	"net/url" 
47	"testing" 
58
9+ 	"github.com/tidwall/gjson" 
10+ 
611	"github.com/matrix-org/complement/internal/b" 
12+ 	"github.com/matrix-org/complement/internal/client" 
13+ 	"github.com/matrix-org/complement/internal/match" 
14+ 	"github.com/matrix-org/complement/internal/must" 
715)
816
917// Check if this homeserver supports Synapse-style admin registration. 
@@ -13,3 +21,113 @@ func TestCanRegisterAdmin(t *testing.T) {
1321	defer  deployment .Destroy (t )
1422	deployment .RegisterUser (t , "hs1" , "admin" , "adminpassword" , true )
1523}
24+ 
25+ // Test if the implemented /_synapse/admin/v1/send_server_notice behaves as expected 
26+ func  TestServerNotices (t  * testing.T ) {
27+ 	deployment  :=  Deploy (t , b .BlueprintAlice )
28+ 	defer  deployment .Destroy (t )
29+ 	admin  :=  deployment .RegisterUser (t , "hs1" , "admin" , "adminpassword" , true )
30+ 	alice  :=  deployment .Client (t , "hs1" , "@alice:hs1" )
31+ 
32+ 	reqBody  :=  client .WithJSONBody (t , map [string ]interface {}{
33+ 		"user_id" : "@alice:hs1" ,
34+ 		"content" : map [string ]interface {}{
35+ 			"msgtype" : "m.text" ,
36+ 			"body" :    "hello from server notices!" ,
37+ 		},
38+ 	})
39+ 	var  (
40+ 		eventID  string 
41+ 		roomID   string 
42+ 	)
43+ 	t .Run ("/send_server_notice is not allowed as normal user" , func (t  * testing.T ) {
44+ 		res  :=  alice .DoFunc (t , "POST" , []string {"_synapse" , "admin" , "v1" , "send_server_notice" })
45+ 		must .MatchResponse (t , res , match.HTTPResponse {
46+ 			StatusCode : http .StatusForbidden ,
47+ 			JSON : []match.JSON {
48+ 				match .JSONKeyEqual ("errcode" , "M_FORBIDDEN" ),
49+ 			},
50+ 		})
51+ 	})
52+ 	t .Run ("/send_server_notice as an admin is allowed" , func (t  * testing.T ) {
53+ 		eventID  =  sendServerNotice (t , admin , reqBody , nil )
54+ 	})
55+ 	t .Run ("Alice is invited to the server alert room" , func (t  * testing.T ) {
56+ 		roomID  =  syncUntilInvite (t , alice )
57+ 	})
58+ 	t .Run ("Alice cannot reject the invite" , func (t  * testing.T ) {
59+ 		res  :=  alice .DoFunc (t , "POST" , []string {"_matrix" , "client" , "r0" , "rooms" , roomID , "leave" })
60+ 		must .MatchResponse (t , res , match.HTTPResponse {
61+ 			StatusCode : http .StatusForbidden ,
62+ 			JSON : []match.JSON {
63+ 				match .JSONKeyEqual ("errcode" , "M_CANNOT_LEAVE_SERVER_NOTICE_ROOM" ),
64+ 			},
65+ 		})
66+ 	})
67+ 	t .Run ("Alice can join the alert room" , func (t  * testing.T ) {
68+ 		alice .JoinRoom (t , roomID , []string {})
69+ 		queryParams  :=  url.Values {}
70+ 		queryParams .Set ("dir" , "b" )
71+ 		// check if we received the message 
72+ 		res  :=  alice .DoFunc (t , "GET" , []string {"_matrix" , "client" , "r0" , "rooms" , roomID , "messages" }, client .WithQueries (queryParams ))
73+ 		msgRes  :=  & msgResult {}
74+ 		must .MatchResponse (t , res , match.HTTPResponse {
75+ 			StatusCode : http .StatusOK ,
76+ 			JSON : []match.JSON {
77+ 				findMessageId (eventID , msgRes ),
78+ 			},
79+ 		})
80+ 		if  ! msgRes .found  {
81+ 			t .Errorf ("did not find expected message from server notices" )
82+ 		}
83+ 	})
84+ 	t .Run ("Alice can leave the alert room, after joining it" , func (t  * testing.T ) {
85+ 		alice .LeaveRoom (t , roomID )
86+ 	})
87+ 	t .Run ("After leaving the alert room and on re-invitation, no new room is created" , func (t  * testing.T ) {
88+ 		sendServerNotice (t , admin , reqBody , nil )
89+ 		newRoomID  :=  syncUntilInvite (t , alice )
90+ 		if  roomID  !=  newRoomID  {
91+ 			t .Errorf ("expected a new room, but they are the same" )
92+ 		}
93+ 	})
94+ 	t .Run ("Sending a notice with a transactionID is idempotent" , func (t  * testing.T ) {
95+ 		txnID  :=  "1" 
96+ 		eventID1  :=  sendServerNotice (t , admin , reqBody , & txnID )
97+ 		eventID2  :=  sendServerNotice (t , admin , reqBody , & txnID )
98+ 		if  eventID1  !=  eventID2  {
99+ 			t .Errorf ("expected event IDs to be the same, but got '%s' and '%s'" , eventID1 , eventID2 )
100+ 		}
101+ 	})
102+ 
103+ }
104+ 
105+ func  sendServerNotice (t  * testing.T , admin  * client.CSAPI , reqBody  client.RequestOpt , txnID  * string ) (eventID  string ) {
106+ 	var  res  * http.Response 
107+ 	if  txnID  !=  nil  {
108+ 		res  =  admin .MustDoFunc (t , "PUT" , []string {"_synapse" , "admin" , "v1" , "send_server_notice" , * txnID }, reqBody )
109+ 	} else  {
110+ 		res  =  admin .MustDoFunc (t , "POST" , []string {"_synapse" , "admin" , "v1" , "send_server_notice" }, reqBody )
111+ 	}
112+ 	body  :=  must .MatchResponse (t , res , match.HTTPResponse {
113+ 		StatusCode : http .StatusOK ,
114+ 		JSON : []match.JSON {
115+ 			match .JSONKeyPresent ("event_id" ),
116+ 		},
117+ 	})
118+ 	return  gjson .GetBytes (body , "event_id" ).Str 
119+ }
120+ 
121+ // syncUntilInvite checks if we got an invitation from the server notice sender, as the roomID is unknown. 
122+ // Returns the found roomID on success 
123+ func  syncUntilInvite (t  * testing.T , alice  * client.CSAPI ) string  {
124+ 	var  roomID  string 
125+ 	alice .MustSyncUntil (t , client.SyncReq {}, func (userID  string , res  gjson.Result ) error  {
126+ 		if  res .Get ("rooms.invite.*.invite_state.events.0.sender" ).Str  ==  "@_server:hs1"  {
127+ 			roomID  =  res .Get ("rooms.invite" ).Get ("@keys.0" ).Str 
128+ 			return  nil 
129+ 		}
130+ 		return  fmt .Errorf ("invite not found" )
131+ 	})
132+ 	return  roomID 
133+ }
0 commit comments