Skip to content

Commit 53e90f7

Browse files
authored
Add tests for server notices (#322)
* Add tests for server notices * goimports to make the linter happy * Enable server notices for synapse * Use correct errcode * Fix copy & paste error * Update tests & add comment * Use existing room
1 parent a931b4b commit 53e90f7

File tree

3 files changed

+130
-0
lines changed

3 files changed

+130
-0
lines changed

dockerfiles/synapse/homeserver.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,9 @@ experimental_features:
112112
msc2716_enabled: true
113113
# server-side support for partial state in /send_join
114114
msc3706_enabled: true
115+
116+
server_notices:
117+
system_mxid_localpart: _server
118+
system_mxid_display_name: "Server Alert"
119+
system_mxid_avatar_url: ""
120+
room_name: "Server Alert"

dockerfiles/synapse/workers-shared.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,9 @@ experimental_features:
6868
msc2716_enabled: true
6969
# Enable spaces support
7070
spaces_enabled: true
71+
72+
server_notices:
73+
system_mxid_localpart: _server
74+
system_mxid_display_name: "Server Alert"
75+
system_mxid_avatar_url: ""
76+
room_name: "Server Alert"

tests/csapi/admin_test.go

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
package csapi_tests
22

33
import (
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

Comments
 (0)