@@ -2,10 +2,12 @@ package clientapi
2
2
3
3
import (
4
4
"context"
5
+ "encoding/json"
5
6
"fmt"
6
7
"net/http"
7
8
"net/http/httptest"
8
9
"reflect"
10
+ "strings"
9
11
"testing"
10
12
"time"
11
13
@@ -1092,3 +1094,245 @@ func TestAdminMarkAsStale(t *testing.T) {
1092
1094
}
1093
1095
})
1094
1096
}
1097
+
1098
+ func TestAdminQueryEventReports (t * testing.T ) {
1099
+ alice := test .NewUser (t , test .WithAccountType (uapi .AccountTypeAdmin ))
1100
+ bob := test .NewUser (t )
1101
+ room := test .NewRoom (t , alice )
1102
+ room2 := test .NewRoom (t , alice )
1103
+
1104
+ // room2 has a name and canonical alias
1105
+ room2 .CreateAndInsert (t , alice , spec .MRoomName , map [string ]string {"name" : "Testing" }, test .WithStateKey ("" ))
1106
+ room2 .CreateAndInsert (t , alice , spec .MRoomCanonicalAlias , map [string ]string {"alias" : "#testing" }, test .WithStateKey ("" ))
1107
+
1108
+ // Join the rooms with Bob
1109
+ room .CreateAndInsert (t , bob , spec .MRoomMember , map [string ]interface {}{
1110
+ "membership" : "join" ,
1111
+ }, test .WithStateKey (bob .ID ))
1112
+ room2 .CreateAndInsert (t , bob , spec .MRoomMember , map [string ]interface {}{
1113
+ "membership" : "join" ,
1114
+ }, test .WithStateKey (bob .ID ))
1115
+
1116
+ // Create a few events to report
1117
+ eventsToReportPerRoom := make (map [string ][]string )
1118
+ for i := 0 ; i < 10 ; i ++ {
1119
+ ev1 := room .CreateAndInsert (t , alice , "m.room.message" , map [string ]interface {}{"body" : "hello world" })
1120
+ ev2 := room2 .CreateAndInsert (t , alice , "m.room.message" , map [string ]interface {}{"body" : "hello world" })
1121
+ eventsToReportPerRoom [room .ID ] = append (eventsToReportPerRoom [room .ID ], ev1 .EventID ())
1122
+ eventsToReportPerRoom [room2 .ID ] = append (eventsToReportPerRoom [room2 .ID ], ev2 .EventID ())
1123
+ }
1124
+
1125
+ test .WithAllDatabases (t , func (t * testing.T , dbType test.DBType ) {
1126
+ /*if dbType == test.DBTypeSQLite {
1127
+ t.Skip()
1128
+ }*/
1129
+ cfg , processCtx , close := testrig .CreateConfig (t , dbType )
1130
+ routers := httputil .NewRouters ()
1131
+ cm := sqlutil .NewConnectionManager (processCtx , cfg .Global .DatabaseOptions )
1132
+ caches := caching .NewRistrettoCache (128 * 1024 * 1024 , time .Hour , caching .DisableMetrics )
1133
+ defer close ()
1134
+ natsInstance := jetstream.NATSInstance {}
1135
+ jsctx , _ := natsInstance .Prepare (processCtx , & cfg .Global .JetStream )
1136
+ defer jetstream .DeleteAllStreams (jsctx , & cfg .Global .JetStream )
1137
+
1138
+ // Use an actual roomserver for this
1139
+ rsAPI := roomserver .NewInternalAPI (processCtx , cfg , cm , & natsInstance , caches , caching .DisableMetrics )
1140
+ rsAPI .SetFederationAPI (nil , nil )
1141
+ userAPI := userapi .NewInternalAPI (processCtx , cfg , cm , & natsInstance , rsAPI , nil , caching .DisableMetrics , testIsBlacklistedOrBackingOff )
1142
+
1143
+ if err := api .SendEvents (context .Background (), rsAPI , api .KindNew , room .Events (), "test" , "test" , "test" , nil , false ); err != nil {
1144
+ t .Fatalf ("failed to send events: %v" , err )
1145
+ }
1146
+ if err := api .SendEvents (context .Background (), rsAPI , api .KindNew , room2 .Events (), "test" , "test" , "test" , nil , false ); err != nil {
1147
+ t .Fatalf ("failed to send events: %v" , err )
1148
+ }
1149
+
1150
+ // We mostly need the rsAPI for this test, so nil for other APIs/caches etc.
1151
+ AddPublicRoutes (processCtx , routers , cfg , & natsInstance , nil , rsAPI , nil , nil , nil , userAPI , nil , nil , caching .DisableMetrics )
1152
+
1153
+ accessTokens := map [* test.User ]userDevice {
1154
+ alice : {},
1155
+ bob : {},
1156
+ }
1157
+ createAccessTokens (t , accessTokens , userAPI , processCtx .Context (), routers )
1158
+
1159
+ reqBody := map [string ]any {
1160
+ "reason" : "baaad" ,
1161
+ "score" : - 100 ,
1162
+ }
1163
+ body , err := json .Marshal (reqBody )
1164
+ if err != nil {
1165
+ t .Fatal (err )
1166
+ }
1167
+
1168
+ w := httptest .NewRecorder ()
1169
+
1170
+ var req * http.Request
1171
+ // Report all events
1172
+ for roomID , eventIDs := range eventsToReportPerRoom {
1173
+ for _ , eventID := range eventIDs {
1174
+ req = httptest .NewRequest (http .MethodPost , fmt .Sprintf ("/_matrix/client/v3/rooms/%s/report/%s" , roomID , eventID ), strings .NewReader (string (body )))
1175
+ req .Header .Set ("Authorization" , "Bearer " + accessTokens [bob ].accessToken )
1176
+
1177
+ routers .Client .ServeHTTP (w , req )
1178
+
1179
+ if w .Code != http .StatusOK {
1180
+ t .Fatalf ("expected report to succeed, got HTTP %d instead: %s" , w .Code , w .Body .String ())
1181
+ }
1182
+ }
1183
+ }
1184
+
1185
+ type response struct {
1186
+ EventReports []api.QueryAdminEventReportsResponse `json:"event_reports"`
1187
+ Total int64 `json:"total"`
1188
+ NextToken * int64 `json:"next_token,omitempty"`
1189
+ }
1190
+
1191
+ t .Run ("Can query all reports" , func (t * testing.T ) {
1192
+ w = httptest .NewRecorder ()
1193
+ req = httptest .NewRequest (http .MethodGet , "/_synapse/admin/v1/event_reports" , strings .NewReader (string (body )))
1194
+ req .Header .Set ("Authorization" , "Bearer " + accessTokens [alice ].accessToken )
1195
+
1196
+ routers .SynapseAdmin .ServeHTTP (w , req )
1197
+
1198
+ if w .Code != http .StatusOK {
1199
+ t .Fatalf ("expected getting reports to succeed, got HTTP %d instead: %s" , w .Code , w .Body .String ())
1200
+ }
1201
+ var resp response
1202
+ if err := json .Unmarshal (w .Body .Bytes (), & resp ); err != nil {
1203
+ t .Fatal (err )
1204
+ }
1205
+ wantCount := 20
1206
+ // Only validating the count
1207
+ if len (resp .EventReports ) != wantCount {
1208
+ t .Fatalf ("expected %d events, got %d" , wantCount , len (resp .EventReports ))
1209
+ }
1210
+ if resp .Total != int64 (wantCount ) {
1211
+ t .Fatalf ("expected total to be %d, got %d" , wantCount , resp .Total )
1212
+ }
1213
+ })
1214
+
1215
+ t .Run ("Can filter on room" , func (t * testing.T ) {
1216
+ w = httptest .NewRecorder ()
1217
+ req = httptest .NewRequest (http .MethodGet , fmt .Sprintf ("/_synapse/admin/v1/event_reports?room_id=%s" , room .ID ), strings .NewReader (string (body )))
1218
+ req .Header .Set ("Authorization" , "Bearer " + accessTokens [alice ].accessToken )
1219
+
1220
+ routers .SynapseAdmin .ServeHTTP (w , req )
1221
+
1222
+ if w .Code != http .StatusOK {
1223
+ t .Fatalf ("expected getting reports to succeed, got HTTP %d instead: %s" , w .Code , w .Body .String ())
1224
+ }
1225
+ var resp response
1226
+ if err := json .Unmarshal (w .Body .Bytes (), & resp ); err != nil {
1227
+ t .Fatal (err )
1228
+ }
1229
+ wantCount := 10
1230
+ // Only validating the count
1231
+ if len (resp .EventReports ) != wantCount {
1232
+ t .Fatalf ("expected %d events, got %d" , wantCount , len (resp .EventReports ))
1233
+ }
1234
+ if resp .Total != int64 (wantCount ) {
1235
+ t .Fatalf ("expected total to be %d, got %d" , wantCount , resp .Total )
1236
+ }
1237
+ })
1238
+
1239
+ t .Run ("Can filter on user_id" , func (t * testing.T ) {
1240
+ w = httptest .NewRecorder ()
1241
+ req = httptest .NewRequest (http .MethodGet , fmt .Sprintf ("/_synapse/admin/v1/event_reports?user_id=%s" , "@doesnotexist:test" ), strings .NewReader (string (body )))
1242
+ req .Header .Set ("Authorization" , "Bearer " + accessTokens [alice ].accessToken )
1243
+
1244
+ routers .SynapseAdmin .ServeHTTP (w , req )
1245
+
1246
+ if w .Code != http .StatusOK {
1247
+ t .Fatalf ("expected getting reports to succeed, got HTTP %d instead: %s" , w .Code , w .Body .String ())
1248
+ }
1249
+ var resp response
1250
+ if err := json .Unmarshal (w .Body .Bytes (), & resp ); err != nil {
1251
+ t .Fatal (err )
1252
+ }
1253
+
1254
+ // The user does not exist, so we expect no results
1255
+ wantCount := 0
1256
+ // Only validating the count
1257
+ if len (resp .EventReports ) != wantCount {
1258
+ t .Fatalf ("expected %d events, got %d" , wantCount , len (resp .EventReports ))
1259
+ }
1260
+ if resp .Total != int64 (wantCount ) {
1261
+ t .Fatalf ("expected total to be %d, got %d" , wantCount , resp .Total )
1262
+ }
1263
+ })
1264
+
1265
+ t .Run ("Can set direction=f" , func (t * testing.T ) {
1266
+ w = httptest .NewRecorder ()
1267
+ req = httptest .NewRequest (http .MethodGet , fmt .Sprintf ("/_synapse/admin/v1/event_reports?room_id=%s&dir=f" , room .ID ), strings .NewReader (string (body )))
1268
+ req .Header .Set ("Authorization" , "Bearer " + accessTokens [alice ].accessToken )
1269
+
1270
+ routers .SynapseAdmin .ServeHTTP (w , req )
1271
+
1272
+ if w .Code != http .StatusOK {
1273
+ t .Fatalf ("expected getting reports to succeed, got HTTP %d instead: %s" , w .Code , w .Body .String ())
1274
+ }
1275
+ var resp response
1276
+ if err := json .Unmarshal (w .Body .Bytes (), & resp ); err != nil {
1277
+ t .Fatal (err )
1278
+ }
1279
+ wantCount := 10
1280
+ // Only validating the count
1281
+ if len (resp .EventReports ) != wantCount {
1282
+ t .Fatalf ("expected %d events, got %d" , wantCount , len (resp .EventReports ))
1283
+ }
1284
+ if resp .Total != int64 (wantCount ) {
1285
+ t .Fatalf ("expected total to be %d, got %d" , wantCount , resp .Total )
1286
+ }
1287
+ // we now should have the first reported event
1288
+ wantEventID := eventsToReportPerRoom [room .ID ][0 ]
1289
+ gotEventID := resp .EventReports [0 ].EventID
1290
+ if gotEventID != wantEventID {
1291
+ t .Fatalf ("expected eventID to be %v, got %v" , wantEventID , gotEventID )
1292
+ }
1293
+ })
1294
+
1295
+ t .Run ("Can limit and paginate" , func (t * testing.T ) {
1296
+ var from int64 = 0
1297
+ var limit int64 = 5
1298
+ var wantTotal int64 = 10 // We expect there to be 10 events in total
1299
+ var resp response
1300
+ for from + limit <= wantTotal {
1301
+ resp = response {}
1302
+ t .Logf ("Getting reports starting from %d" , from )
1303
+ w = httptest .NewRecorder ()
1304
+ req = httptest .NewRequest (http .MethodGet , fmt .Sprintf ("/_synapse/admin/v1/event_reports?room_id=%s&limit=%d&from=%d" , room2 .ID , limit , from ), strings .NewReader (string (body )))
1305
+ req .Header .Set ("Authorization" , "Bearer " + accessTokens [alice ].accessToken )
1306
+
1307
+ routers .SynapseAdmin .ServeHTTP (w , req )
1308
+
1309
+ if w .Code != http .StatusOK {
1310
+ t .Fatalf ("expected getting reports to succeed, got HTTP %d instead: %s" , w .Code , w .Body .String ())
1311
+ }
1312
+
1313
+ if err := json .Unmarshal (w .Body .Bytes (), & resp ); err != nil {
1314
+ t .Fatal (err )
1315
+ }
1316
+
1317
+ wantCount := 5 // we are limited to 5
1318
+ if len (resp .EventReports ) != wantCount {
1319
+ t .Fatalf ("expected %d events, got %d" , wantCount , len (resp .EventReports ))
1320
+ }
1321
+ if resp .Total != int64 (wantTotal ) {
1322
+ t .Fatalf ("expected total to be %d, got %d" , wantCount , resp .Total )
1323
+ }
1324
+
1325
+ // We've reached the end
1326
+ if (from + int64 (len (resp .EventReports ))) == wantTotal {
1327
+ return
1328
+ }
1329
+
1330
+ // The next_token should be set
1331
+ if resp .NextToken == nil {
1332
+ t .Fatal ("expected nextToken to be set" )
1333
+ }
1334
+ from = * resp .NextToken
1335
+ }
1336
+ })
1337
+ })
1338
+ }
0 commit comments