From 88faf7104c626192ef53175ef6e312d5aff0a184 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Mon, 11 Jan 2021 19:45:27 +0000 Subject: [PATCH] Implement world_readable auth with test --- setup/mscs/msc2946/msc2946.go | 34 +++++++++++--- setup/mscs/msc2946/msc2946_test.go | 71 +++++++++++++++++++----------- 2 files changed, 74 insertions(+), 31 deletions(-) diff --git a/setup/mscs/msc2946/msc2946.go b/setup/mscs/msc2946/msc2946.go index 6d169573d..30dbd9a0a 100644 --- a/setup/mscs/msc2946/msc2946.go +++ b/setup/mscs/msc2946/msc2946.go @@ -288,16 +288,40 @@ func (w *walker) publicRoomsChunk(roomID string) *gomatrixserverlib.PublicRoom { // authorised returns true iff the user is joined this room or the room is world_readable func (w *walker) authorised(roomID string) bool { - var queryRes roomserver.QueryMembershipForUserResponse - err := w.rsAPI.QueryMembershipForUser(w.ctx, &roomserver.QueryMembershipForUserRequest{ + hisVisTuple := gomatrixserverlib.StateKeyTuple{ + EventType: gomatrixserverlib.MRoomHistoryVisibility, + StateKey: "", + } + roomMemberTuple := gomatrixserverlib.StateKeyTuple{ + EventType: gomatrixserverlib.MRoomMember, + StateKey: w.caller.UserID, + } + var queryRes roomserver.QueryCurrentStateResponse + err := w.rsAPI.QueryCurrentState(w.ctx, &roomserver.QueryCurrentStateRequest{ RoomID: roomID, - UserID: w.caller.UserID, + StateTuples: []gomatrixserverlib.StateKeyTuple{ + hisVisTuple, roomMemberTuple, + }, }, &queryRes) if err != nil { - util.GetLogger(w.ctx).WithError(err).Error("failed to QueryMembershipForUser") + util.GetLogger(w.ctx).WithError(err).Error("failed to QueryCurrentState") return false } - return queryRes.IsInRoom + memberEv := queryRes.StateEvents[roomMemberTuple] + hisVisEv := queryRes.StateEvents[hisVisTuple] + if memberEv != nil { + membership, _ := memberEv.Membership() + if membership == gomatrixserverlib.Join { + return true + } + } + if hisVisEv != nil { + hisVis, _ := hisVisEv.HistoryVisibility() + if hisVis == "world_readable" { + return true + } + } + return false } // references returns all references pointing to or from this room. diff --git a/setup/mscs/msc2946/msc2946_test.go b/setup/mscs/msc2946/msc2946_test.go index 1eaf7cf65..a2ae0ae74 100644 --- a/setup/mscs/msc2946/msc2946_test.go +++ b/setup/mscs/msc2946/msc2946_test.go @@ -60,10 +60,10 @@ var ( // | <-- this link is just a parent, not a child // R5 // -// TODO: Alice is not joined to R4, but R4 is "world_readable". +// Alice is not joined to R4, but R4 is "world_readable". func TestMSC2946(t *testing.T) { alice := "@alice:localhost" - // give access tokens to all three users + // give access token to alice nopUserAPI := &testUserAPI{ accessTokens: make(map[string]userapi.Device), } @@ -157,6 +157,31 @@ func TestMSC2946(t *testing.T) { "present": true, }, }) + // history visibility for R4 + r4HisVis := mustCreateEvent(t, fledglingEvent{ + RoomID: room4, + Sender: "@someone:localhost", + Type: gomatrixserverlib.MRoomHistoryVisibility, + StateKey: &empty, + Content: map[string]interface{}{ + "history_visibility": "world_readable", + }, + }) + var joinEvents []*gomatrixserverlib.HeaderedEvent + for _, roomID := range allRooms { + if roomID == room4 { + continue // not joined to that room + } + joinEvents = append(joinEvents, mustCreateEvent(t, fledglingEvent{ + RoomID: roomID, + Sender: alice, + StateKey: &alice, + Type: gomatrixserverlib.MRoomMember, + Content: map[string]interface{}{ + "membership": "join", + }, + })) + } roomNameTuple := gomatrixserverlib.StateKeyTuple{ EventType: "m.room.name", StateKey: "", @@ -166,9 +191,7 @@ func TestMSC2946(t *testing.T) { StateKey: "", } nopRsAPI := &testRoomserverAPI{ - userToJoinedRooms: map[string][]string{ - alice: allRooms, - }, + joinEvents: joinEvents, events: map[string]*gomatrixserverlib.HeaderedEvent{ rootToR1.EventID(): rootToR1, rootToR2.EventID(): rootToR2, @@ -177,6 +200,7 @@ func TestMSC2946(t *testing.T) { s1ToR4.EventID(): s1ToR4, s1ToS2.EventID(): s1ToS2, s2ToR5.EventID(): s2ToR5, + r4HisVis.EventID(): r4HisVis, }, pubRoomState: map[string]map[gomatrixserverlib.StateKeyTuple]string{ rootSpace: { @@ -208,11 +232,13 @@ func TestMSC2946(t *testing.T) { }, }, } - router := injectEvents(t, nopUserAPI, nopRsAPI, []*gomatrixserverlib.HeaderedEvent{ + allEvents := []*gomatrixserverlib.HeaderedEvent{ rootToR1, rootToR2, rootToS1, s1ToR3, s1ToR4, s1ToS2, - s2ToR5, - }) + s2ToR5, r4HisVis, + } + allEvents = append(allEvents, joinEvents...) + router := injectEvents(t, nopUserAPI, nopRsAPI, allEvents) cancel := runServer(t, router) defer cancel() @@ -416,9 +442,9 @@ type testRoomserverAPI struct { // use a trace API as it implements method stubs so we don't need to have them here. // We'll override the functions we care about. roomserver.RoomserverInternalAPITrace - userToJoinedRooms map[string][]string - events map[string]*gomatrixserverlib.HeaderedEvent - pubRoomState map[string]map[gomatrixserverlib.StateKeyTuple]string + joinEvents []*gomatrixserverlib.HeaderedEvent + events map[string]*gomatrixserverlib.HeaderedEvent + pubRoomState map[string]map[gomatrixserverlib.StateKeyTuple]string } func (r *testRoomserverAPI) QueryBulkStateContent(ctx context.Context, req *roomserver.QueryBulkStateContentRequest, res *roomserver.QueryBulkStateContentResponse) error { @@ -434,12 +460,12 @@ func (r *testRoomserverAPI) QueryBulkStateContent(ctx context.Context, req *room func (r *testRoomserverAPI) QueryCurrentState(ctx context.Context, req *roomserver.QueryCurrentStateRequest, res *roomserver.QueryCurrentStateResponse) error { res.StateEvents = make(map[gomatrixserverlib.StateKeyTuple]*gomatrixserverlib.HeaderedEvent) - for _, he := range r.events { + checkEvent := func(he *gomatrixserverlib.HeaderedEvent) { if he.RoomID() != req.RoomID { - continue + return } if he.StateKey() == nil { - continue + return } tuple := gomatrixserverlib.StateKeyTuple{ EventType: he.Type(), @@ -451,18 +477,11 @@ func (r *testRoomserverAPI) QueryCurrentState(ctx context.Context, req *roomserv } } } - return nil -} - -func (r *testRoomserverAPI) QueryMembershipForUser(ctx context.Context, req *roomserver.QueryMembershipForUserRequest, res *roomserver.QueryMembershipForUserResponse) error { - rooms := r.userToJoinedRooms[req.UserID] - for _, roomID := range rooms { - if roomID == req.RoomID { - res.IsInRoom = true - res.HasBeenInRoom = true - res.Membership = "join" - break - } + for _, he := range r.joinEvents { + checkEvent(he) + } + for _, he := range r.events { + checkEvent(he) } return nil }