-
Notifications
You must be signed in to change notification settings - Fork 69
MSC4163: Apply server ACLs to receipt and typing EDUs #862
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -12,6 +12,7 @@ import ( | |||||||
| "github.com/matrix-org/complement/runtime" | ||||||||
| "github.com/matrix-org/complement/should" | ||||||||
| "github.com/matrix-org/gomatrixserverlib/spec" | ||||||||
| "github.com/tidwall/gjson" | ||||||||
| ) | ||||||||
|
|
||||||||
| // Test for https://github.com/matrix-org/dendrite/issues/3004 | ||||||||
|
|
@@ -120,3 +121,115 @@ func TestACLs(t *testing.T) { | |||||||
| ) | ||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| // MSC4163: TestACLsForEDUs checks that ACLs are applied to EDUs (typing notifications and read receipts) | ||||||||
| func TestACLsForEDUs(t *testing.T) { | ||||||||
| runtime.SkipIf(t, runtime.Dendrite) | ||||||||
| deployment := complement.Deploy(t, 3) | ||||||||
| defer deployment.Destroy(t) | ||||||||
|
|
||||||||
| alice := deployment.Register(t, "hs1", helpers.RegistrationOpts{}) | ||||||||
| bob := deployment.Register(t, "hs2", helpers.RegistrationOpts{}) | ||||||||
| charlie := deployment.Register(t, "hs3", helpers.RegistrationOpts{}) | ||||||||
|
|
||||||||
| // Create a room where hs2 will be blocked by ACL | ||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| roomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat"}) | ||||||||
| aliceSince := alice.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(alice.UserID, roomID)) | ||||||||
|
|
||||||||
| bob.MustJoinRoom(t, roomID, []spec.ServerName{ | ||||||||
| deployment.GetFullyQualifiedHomeserverName(t, "hs1"), | ||||||||
| }) | ||||||||
| aliceSince = alice.MustSyncUntil(t, client.SyncReq{Since: aliceSince}, client.SyncJoinedTo(bob.UserID, roomID)) | ||||||||
| bobSince := bob.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(bob.UserID, roomID)) | ||||||||
|
|
||||||||
| // Create a sentinel room without ACLs to confirm federation is working | ||||||||
| sentinelRoom := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat"}) | ||||||||
| aliceSince = alice.MustSyncUntil(t, client.SyncReq{Since: aliceSince}, client.SyncJoinedTo(alice.UserID, sentinelRoom)) | ||||||||
| bob.MustJoinRoom(t, sentinelRoom, []spec.ServerName{ | ||||||||
| deployment.GetFullyQualifiedHomeserverName(t, "hs1"), | ||||||||
| }) | ||||||||
| charlie.MustJoinRoom(t, sentinelRoom, []spec.ServerName{ | ||||||||
| deployment.GetFullyQualifiedHomeserverName(t, "hs1"), | ||||||||
| }) | ||||||||
| aliceSince = alice.MustSyncUntil(t, client.SyncReq{Since: aliceSince}, | ||||||||
| client.SyncJoinedTo(bob.UserID, sentinelRoom), | ||||||||
| client.SyncJoinedTo(charlie.UserID, sentinelRoom), | ||||||||
| ) | ||||||||
|
|
||||||||
| // Block hs2 from participating in room with id roomID | ||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| stateKey := "" | ||||||||
| aclEventID := alice.SendEventSynced(t, roomID, b.Event{ | ||||||||
| Type: "m.room.server_acl", | ||||||||
| Sender: alice.UserID, | ||||||||
| StateKey: &stateKey, | ||||||||
| Content: map[string]interface{}{ | ||||||||
| "allow": []string{"*"}, | ||||||||
| "allow_ip_literals": true, | ||||||||
| "deny": []string{ | ||||||||
| string(deployment.GetFullyQualifiedHomeserverName(t, "hs2")), | ||||||||
| }, | ||||||||
| }, | ||||||||
| }) | ||||||||
| // Wait for the ACL to reach hs2 before sending EDUs | ||||||||
| bob.MustSyncUntil(t, client.SyncReq{Since: bobSince}, client.SyncTimelineHasEventID(roomID, aclEventID)) | ||||||||
|
|
||||||||
| // Join charlie to roomID after the ACL is set up | ||||||||
| charlie.MustJoinRoom(t, roomID, []spec.ServerName{ | ||||||||
| deployment.GetFullyQualifiedHomeserverName(t, "hs1"), | ||||||||
| }) | ||||||||
| aliceSince = alice.MustSyncUntil(t, client.SyncReq{Since: aliceSince}, client.SyncJoinedTo(charlie.UserID, roomID)) | ||||||||
| charlieSince := charlie.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(charlie.UserID, roomID)) | ||||||||
|
|
||||||||
| // Bob starts typing in both rooms; typing in roomID should be dropped by ACLs | ||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| bob.SendTyping(t, roomID, true, 10000) | ||||||||
| bob.SendTyping(t, sentinelRoom, true, 10000) | ||||||||
|
|
||||||||
| // Bob sets read receipts on both rooms; receipts in roomID should be dropped by ACLs | ||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| bob.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "read_markers"}, | ||||||||
| client.WithJSONBody(t, map[string]interface{}{"m.read": aclEventID})) | ||||||||
|
|
||||||||
| // Send a sentinel message to sentinelRoom to use as a receipt anchor | ||||||||
| sentinelEventID := bob.SendEventSynced(t, sentinelRoom, b.Event{ | ||||||||
| Type: "m.room.message", | ||||||||
| Sender: bob.UserID, | ||||||||
| Content: map[string]interface{}{ | ||||||||
| "msgtype": "m.text", | ||||||||
| "body": "sentinel", | ||||||||
| }, | ||||||||
| }) | ||||||||
| bob.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", sentinelRoom, "read_markers"}, | ||||||||
| client.WithJSONBody(t, map[string]interface{}{"m.read": sentinelEventID})) | ||||||||
|
|
||||||||
| // Wait for the sentinel message and EDUs in sentinelRoom to arrive, proving the federation | ||||||||
| // transaction containing hs2's EDUs was processed | ||||||||
| alice.MustSyncUntil(t, client.SyncReq{Since: aliceSince}, | ||||||||
| client.SyncTimelineHasEventID(sentinelRoom, sentinelEventID), | ||||||||
| client.SyncEphemeralHas(sentinelRoom, func(result gjson.Result) bool { | ||||||||
| return result.Get("type").Str == "m.receipt" | ||||||||
| }), | ||||||||
| client.SyncEphemeralHas(sentinelRoom, func(result gjson.Result) bool { | ||||||||
| return result.Get("type").Str == "m.typing" | ||||||||
| }), | ||||||||
| ) | ||||||||
| charlie.MustSyncUntil(t, client.SyncReq{Since: charlieSince}, | ||||||||
| client.SyncTimelineHasEventID(sentinelRoom, sentinelEventID), | ||||||||
| client.SyncEphemeralHas(sentinelRoom, func(result gjson.Result) bool { | ||||||||
| return result.Get("type").Str == "m.receipt" | ||||||||
| }), | ||||||||
| client.SyncEphemeralHas(sentinelRoom, func(result gjson.Result) bool { | ||||||||
| return result.Get("type").Str == "m.typing" | ||||||||
| }), | ||||||||
| ) | ||||||||
|
|
||||||||
| for _, user := range []*client.CSAPI{alice, charlie} { | ||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| syncResp, _ := user.MustSync(t, client.SyncReq{}) | ||||||||
|
|
||||||||
| // No typing or read receipts from the blocked server should appear in room with id roomID | ||||||||
| ephemerals := syncResp.Get("rooms.join." + client.GjsonEscape(roomID) + ".ephemeral") | ||||||||
| must.MatchGJSON(t, ephemerals, match.JSONKeyArrayOfSize("events", 0)) | ||||||||
|
|
||||||||
| // sentinelRoom should have received the read receipt and typing notification | ||||||||
| ephemerals = syncResp.Get("rooms.join." + client.GjsonEscape(sentinelRoom) + ".ephemeral") | ||||||||
| must.MatchGJSON(t, ephemerals, match.JSONKeyArrayOfSize("events", 2)) | ||||||||
| } | ||||||||
| } | ||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this comment from the other
TestACLsstill relevant?(both places should be wrapped like this)