mirror of
https://github.com/matrix-org/dendrite
synced 2024-06-01 03:59:03 +02:00
Fix spaces over federation
This commit is contained in:
parent
d204c7a17c
commit
8192936c44
|
@ -189,7 +189,7 @@ func PopulatePublicRooms(ctx context.Context, roomIDs []string, rsAPI QueryBulkS
|
|||
RoomID: roomID,
|
||||
}
|
||||
joinCount := 0
|
||||
var joinRule, guestAccess string
|
||||
var guestAccess string
|
||||
for tuple, contentVal := range data {
|
||||
if tuple.EventType == spec.MRoomMember && contentVal == "join" {
|
||||
joinCount++
|
||||
|
@ -210,12 +210,12 @@ func PopulatePublicRooms(ctx context.Context, roomIDs []string, rsAPI QueryBulkS
|
|||
pub.WorldReadable = contentVal == "world_readable"
|
||||
// need both of these to determine whether guests can join
|
||||
case joinRuleTuple:
|
||||
joinRule = contentVal
|
||||
pub.JoinRule = contentVal
|
||||
case guestTuple:
|
||||
guestAccess = contentVal
|
||||
}
|
||||
}
|
||||
if joinRule == spec.Public && guestAccess == "can_join" {
|
||||
if pub.JoinRule == spec.Public && guestAccess == "can_join" {
|
||||
pub.GuestCanJoin = true
|
||||
}
|
||||
pub.JoinedMembersCount = joinCount
|
||||
|
|
|
@ -45,8 +45,8 @@ func (querier *Queryer) QueryNextRoomHierarchyPage(ctx context.Context, walker r
|
|||
*roomserver.RoomHierarchyWalker,
|
||||
error,
|
||||
) {
|
||||
if authorised, _ := authorised(ctx, querier, walker.Caller, walker.RootRoomID, nil); !authorised {
|
||||
return nil, []string{}, nil, roomserver.ErrRoomUnknownOrNotAllowed{Err: fmt.Errorf("room is unknown/forbidden")}
|
||||
if authorised, _, _ := authorised(ctx, querier, walker.Caller, walker.RootRoomID, nil); !authorised {
|
||||
return nil, []string{walker.RootRoomID.String()}, nil, roomserver.ErrRoomUnknownOrNotAllowed{Err: fmt.Errorf("room is unknown/forbidden")}
|
||||
}
|
||||
|
||||
discoveredRooms := []fclient.RoomHierarchyRoom{}
|
||||
|
@ -55,6 +55,7 @@ func (querier *Queryer) QueryNextRoomHierarchyPage(ctx context.Context, walker r
|
|||
unvisited := make([]roomserver.RoomHierarchyWalkerQueuedRoom, len(walker.Unvisited))
|
||||
copy(unvisited, walker.Unvisited)
|
||||
processed := walker.Processed.Copy()
|
||||
inaccessible := []string{}
|
||||
|
||||
// Depth first -> stack data structure
|
||||
for len(unvisited) > 0 {
|
||||
|
@ -113,7 +114,7 @@ func (querier *Queryer) QueryNextRoomHierarchyPage(ctx context.Context, walker r
|
|||
// as these children may be rooms we do know about.
|
||||
roomType = spec.MSpace
|
||||
}
|
||||
} else if authorised, isJoinedOrInvited := authorised(ctx, querier, walker.Caller, queuedRoom.RoomID, queuedRoom.ParentRoomID); authorised {
|
||||
} else if authorised, isJoinedOrInvited, allowedRoomIDs := authorised(ctx, querier, walker.Caller, queuedRoom.RoomID, queuedRoom.ParentRoomID); authorised {
|
||||
// Get all `m.space.child` state events for this room
|
||||
events, err := childReferences(ctx, querier, walker.SuggestedOnly, queuedRoom.RoomID)
|
||||
if err != nil {
|
||||
|
@ -130,14 +131,17 @@ func (querier *Queryer) QueryNextRoomHierarchyPage(ctx context.Context, walker r
|
|||
}
|
||||
|
||||
discoveredRooms = append(discoveredRooms, fclient.RoomHierarchyRoom{
|
||||
PublicRoom: *pubRoom,
|
||||
RoomType: roomType,
|
||||
ChildrenState: events,
|
||||
PublicRoom: *pubRoom,
|
||||
RoomType: roomType,
|
||||
ChildrenState: events,
|
||||
AllowedRoomIDs: allowedRoomIDs,
|
||||
})
|
||||
// don't walk children if the user is not joined/invited to the space
|
||||
if !isJoinedOrInvited {
|
||||
continue
|
||||
}
|
||||
} else if !authorised {
|
||||
inaccessible = append(inaccessible, queuedRoom.RoomID.String())
|
||||
} else {
|
||||
// room exists but user is not authorised
|
||||
continue
|
||||
|
@ -178,7 +182,7 @@ func (querier *Queryer) QueryNextRoomHierarchyPage(ctx context.Context, walker r
|
|||
|
||||
if len(unvisited) == 0 {
|
||||
// If no more rooms to walk, then don't return a walker for future pages
|
||||
return discoveredRooms, []string{}, nil, nil
|
||||
return discoveredRooms, inaccessible, nil, nil
|
||||
} else {
|
||||
// If there are more rooms to walk, then return a new walker to resume walking from (for querying more pages)
|
||||
newWalker := roomserver.RoomHierarchyWalker{
|
||||
|
@ -190,24 +194,25 @@ func (querier *Queryer) QueryNextRoomHierarchyPage(ctx context.Context, walker r
|
|||
Processed: processed,
|
||||
}
|
||||
|
||||
return discoveredRooms, []string{}, &newWalker, nil
|
||||
return discoveredRooms, inaccessible, &newWalker, nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// authorised returns true iff the user is joined this room or the room is world_readable
|
||||
func authorised(ctx context.Context, querier *Queryer, caller types.DeviceOrServerName, roomID spec.RoomID, parentRoomID *spec.RoomID) (authed, isJoinedOrInvited bool) {
|
||||
func authorised(ctx context.Context, querier *Queryer, caller types.DeviceOrServerName, roomID spec.RoomID, parentRoomID *spec.RoomID) (authed, isJoinedOrInvited bool, resultAllowedRoomIDs []string) {
|
||||
if clientCaller := caller.Device(); clientCaller != nil {
|
||||
return authorisedUser(ctx, querier, clientCaller, roomID, parentRoomID)
|
||||
}
|
||||
if serverCaller := caller.ServerName(); serverCaller != nil {
|
||||
return authorisedServer(ctx, querier, roomID, *serverCaller), false
|
||||
authed, resultAllowedRoomIDs = authorisedServer(ctx, querier, roomID, *serverCaller)
|
||||
return authed, false, resultAllowedRoomIDs
|
||||
}
|
||||
return false, false
|
||||
return false, false, resultAllowedRoomIDs
|
||||
}
|
||||
|
||||
// authorisedServer returns true iff the server is joined this room or the room is world_readable, public, or knockable
|
||||
func authorisedServer(ctx context.Context, querier *Queryer, roomID spec.RoomID, callerServerName spec.ServerName) bool {
|
||||
func authorisedServer(ctx context.Context, querier *Queryer, roomID spec.RoomID, callerServerName spec.ServerName) (bool, []string) {
|
||||
// Check history visibility / join rules first
|
||||
hisVisTuple := gomatrixserverlib.StateKeyTuple{
|
||||
EventType: spec.MRoomHistoryVisibility,
|
||||
|
@ -226,13 +231,13 @@ func authorisedServer(ctx context.Context, querier *Queryer, roomID spec.RoomID,
|
|||
}, &queryRoomRes)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("failed to QueryCurrentState")
|
||||
return false
|
||||
return false, []string{}
|
||||
}
|
||||
hisVisEv := queryRoomRes.StateEvents[hisVisTuple]
|
||||
if hisVisEv != nil {
|
||||
hisVis, _ := hisVisEv.HistoryVisibility()
|
||||
if hisVis == "world_readable" {
|
||||
return true
|
||||
return true, []string{}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,11 +250,11 @@ func authorisedServer(ctx context.Context, querier *Queryer, roomID spec.RoomID,
|
|||
rule, ruleErr := joinRuleEv.JoinRule()
|
||||
if ruleErr != nil {
|
||||
util.GetLogger(ctx).WithError(ruleErr).WithField("parent_room_id", roomID).Warn("failed to get join rule")
|
||||
return false
|
||||
return false, []string{}
|
||||
}
|
||||
|
||||
if rule == spec.Public || rule == spec.Knock {
|
||||
return true
|
||||
return true, []string{}
|
||||
}
|
||||
|
||||
if rule == spec.Restricted {
|
||||
|
@ -258,6 +263,10 @@ func authorisedServer(ctx context.Context, querier *Queryer, roomID spec.RoomID,
|
|||
}
|
||||
|
||||
// check if server is joined to any allowed room
|
||||
resultAllowedRoomIDs := make([]string, 0, len(allowJoinedToRoomIDs))
|
||||
for _, allowedRoomID := range allowJoinedToRoomIDs {
|
||||
resultAllowedRoomIDs = append(resultAllowedRoomIDs, allowedRoomID.String())
|
||||
}
|
||||
for _, allowedRoomID := range allowJoinedToRoomIDs {
|
||||
var queryRes fs.QueryJoinedHostServerNamesInRoomResponse
|
||||
err = querier.FSAPI.QueryJoinedHostServerNamesInRoom(ctx, &fs.QueryJoinedHostServerNamesInRoomRequest{
|
||||
|
@ -269,18 +278,18 @@ func authorisedServer(ctx context.Context, querier *Queryer, roomID spec.RoomID,
|
|||
}
|
||||
for _, srv := range queryRes.ServerNames {
|
||||
if srv == callerServerName {
|
||||
return true
|
||||
return true, resultAllowedRoomIDs[1:]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
return false, resultAllowedRoomIDs[1:]
|
||||
}
|
||||
|
||||
// authorisedUser returns true iff the user is invited/joined this room or the room is world_readable
|
||||
// or if the room has a public or knock join rule.
|
||||
// Failing that, if the room has a restricted join rule and belongs to the space parent listed, it will return true.
|
||||
func authorisedUser(ctx context.Context, querier *Queryer, clientCaller *userapi.Device, roomID spec.RoomID, parentRoomID *spec.RoomID) (authed bool, isJoinedOrInvited bool) {
|
||||
func authorisedUser(ctx context.Context, querier *Queryer, clientCaller *userapi.Device, roomID spec.RoomID, parentRoomID *spec.RoomID) (authed bool, isJoinedOrInvited bool, resultAllowedRoomIDs []string) {
|
||||
hisVisTuple := gomatrixserverlib.StateKeyTuple{
|
||||
EventType: spec.MRoomHistoryVisibility,
|
||||
StateKey: "",
|
||||
|
@ -302,20 +311,20 @@ func authorisedUser(ctx context.Context, querier *Queryer, clientCaller *userapi
|
|||
}, &queryRes)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("failed to QueryCurrentState")
|
||||
return false, false
|
||||
return false, false, resultAllowedRoomIDs
|
||||
}
|
||||
memberEv := queryRes.StateEvents[roomMemberTuple]
|
||||
if memberEv != nil {
|
||||
membership, _ := memberEv.Membership()
|
||||
if membership == spec.Join || membership == spec.Invite {
|
||||
return true, true
|
||||
return true, true, resultAllowedRoomIDs
|
||||
}
|
||||
}
|
||||
hisVisEv := queryRes.StateEvents[hisVisTuple]
|
||||
if hisVisEv != nil {
|
||||
hisVis, _ := hisVisEv.HistoryVisibility()
|
||||
if hisVis == "world_readable" {
|
||||
return true, false
|
||||
return true, false, resultAllowedRoomIDs
|
||||
}
|
||||
}
|
||||
joinRuleEv := queryRes.StateEvents[joinRuleTuple]
|
||||
|
@ -330,6 +339,7 @@ func authorisedUser(ctx context.Context, querier *Queryer, clientCaller *userapi
|
|||
allowedRoomIDs := restrictedJoinRuleAllowedRooms(ctx, joinRuleEv)
|
||||
// check parent is in the allowed set
|
||||
for _, a := range allowedRoomIDs {
|
||||
resultAllowedRoomIDs = append(resultAllowedRoomIDs, a.String())
|
||||
if *parentRoomID == a {
|
||||
allowed = true
|
||||
break
|
||||
|
@ -352,13 +362,13 @@ func authorisedUser(ctx context.Context, querier *Queryer, clientCaller *userapi
|
|||
if memberEv != nil {
|
||||
membership, _ := memberEv.Membership()
|
||||
if membership == spec.Join {
|
||||
return true, false
|
||||
return true, false, resultAllowedRoomIDs
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false, false
|
||||
return false, false, resultAllowedRoomIDs
|
||||
}
|
||||
|
||||
// helper function to fetch a state event
|
||||
|
|
Loading…
Reference in a new issue