add comments

This commit is contained in:
Sam Wedgwood 2023-07-13 14:47:10 +01:00
parent 97f2befd1b
commit ad1de7d9bb
4 changed files with 36 additions and 8 deletions

View file

@ -29,17 +29,20 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
// For storing pagination information for room hierarchies
type RoomHierarchyPaginationCache struct { type RoomHierarchyPaginationCache struct {
cache map[string]roomserverAPI.RoomHierarchyWalker cache map[string]roomserverAPI.RoomHierarchyWalker
mu sync.Mutex mu sync.Mutex
} }
// Create a new, empty, pagination cache.
func NewRoomHierarchyPaginationCache() RoomHierarchyPaginationCache { func NewRoomHierarchyPaginationCache() RoomHierarchyPaginationCache {
return RoomHierarchyPaginationCache{ return RoomHierarchyPaginationCache{
cache: map[string]roomserverAPI.RoomHierarchyWalker{}, cache: map[string]roomserverAPI.RoomHierarchyWalker{},
} }
} }
// Get a cached page, or nil if there is no associated page in the cache.
func (c *RoomHierarchyPaginationCache) Get(token string) *roomserverAPI.RoomHierarchyWalker { func (c *RoomHierarchyPaginationCache) Get(token string) *roomserverAPI.RoomHierarchyWalker {
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
@ -51,6 +54,7 @@ func (c *RoomHierarchyPaginationCache) Get(token string) *roomserverAPI.RoomHier
} }
} }
// Add a cache line to the pagination cache.
func (c *RoomHierarchyPaginationCache) AddLine(line roomserverAPI.RoomHierarchyWalker) string { func (c *RoomHierarchyPaginationCache) AddLine(line roomserverAPI.RoomHierarchyWalker) string {
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
@ -166,6 +170,7 @@ func QueryRoomHierarchy(req *http.Request, device *userapi.Device, roomIDStr str
} }
// Success response for /_matrix/client/v1/rooms/{roomID}/hierarchy
type RoomHierarchyClientResponse struct { type RoomHierarchyClientResponse struct {
Rooms []fclient.MSC2946Room `json:"rooms"` Rooms []fclient.MSC2946Room `json:"rooms"`
NextBatch string `json:"next_batch,omitempty"` NextBatch string `json:"next_batch,omitempty"`

View file

@ -125,6 +125,13 @@ type QueryEventsAPI interface {
} }
type QueryRoomHierarchyAPI interface { type QueryRoomHierarchyAPI interface {
// Traverse the room hierarchy using the provided walker up to the provided limit,
// returning a new walker which can be used to fetch the next page.
//
// If limit is -1, this is treated as no limit, and the entire hierarchy will be traversed.
//
// If returned walker is nil, then there are no more rooms left to traverse. This method does not modify the provided walker, so it
// can be cached.
QueryNextRoomHierarchyPage(ctx context.Context, walker RoomHierarchyWalker, limit int) ([]fclient.MSC2946Room, *RoomHierarchyWalker, error) QueryNextRoomHierarchyPage(ctx context.Context, walker RoomHierarchyWalker, limit int) ([]fclient.MSC2946Room, *RoomHierarchyWalker, error)
} }

View file

@ -515,7 +515,8 @@ type QueryRoomHierarchyRequest struct {
// //
// Used for implementing space summaries / room hierarchies // Used for implementing space summaries / room hierarchies
// //
// Use NewRoomHierarchyWalker on the roomserver API to construct this. // Use NewRoomHierarchyWalker to construct this, and QueryNextRoomHierarchyPage on the roomserver API
// to traverse the room hierarchy.
type RoomHierarchyWalker struct { type RoomHierarchyWalker struct {
RootRoomID spec.RoomID RootRoomID spec.RoomID
Caller types.DeviceOrServerName Caller types.DeviceOrServerName
@ -532,6 +533,9 @@ type RoomHierarchyWalkerQueuedRoom struct {
Vias []string // vias to query this room by Vias []string // vias to query this room by
} }
// Create a new room hierarchy walker, starting from the provided root room ID.
//
// Use the resulting struct with QueryNextRoomHierarchyPage on the roomserver API to traverse the room hierarchy.
func NewRoomHierarchyWalker(caller types.DeviceOrServerName, roomID spec.RoomID, suggestedOnly bool, maxDepth int) RoomHierarchyWalker { func NewRoomHierarchyWalker(caller types.DeviceOrServerName, roomID spec.RoomID, suggestedOnly bool, maxDepth int) RoomHierarchyWalker {
walker := RoomHierarchyWalker{ walker := RoomHierarchyWalker{
RootRoomID: roomID, RootRoomID: roomID,
@ -549,17 +553,21 @@ func NewRoomHierarchyWalker(caller types.DeviceOrServerName, roomID spec.RoomID,
return walker return walker
} }
// A set of room IDs.
type RoomSet map[spec.RoomID]struct{} type RoomSet map[spec.RoomID]struct{}
// Create a new empty room set.
func NewRoomSet() RoomSet { func NewRoomSet() RoomSet {
return RoomSet{} return RoomSet{}
} }
// Check if a room ID is in a room set.
func (s RoomSet) Contains(val spec.RoomID) bool { func (s RoomSet) Contains(val spec.RoomID) bool {
_, ok := s[val] _, ok := s[val]
return ok return ok
} }
// Add a room ID to a room set.
func (s RoomSet) Add(val spec.RoomID) { func (s RoomSet) Add(val spec.RoomID) {
s[val] = struct{}{} s[val] = struct{}{}
} }

View file

@ -39,9 +39,13 @@ const (
ConstSpaceParentEventType = "m.space.parent" ConstSpaceParentEventType = "m.space.parent"
) )
// Walk the room hierarchy to retrieve room information until either // Traverse the room hierarchy using the provided walker up to the provided limit,
// no room left, or provided limit reached. If limit provided is -1, then this is // returning a new walker which can be used to fetch the next page.
// treated as no limit. //
// If limit is -1, this is treated as no limit, and the entire hierarchy will be traversed.
//
// If returned walker is nil, then there are no more rooms left to traverse. This method does not modify the provided walker, so it
// can be cached.
func (querier *Queryer) QueryNextRoomHierarchyPage(ctx context.Context, walker roomserver.RoomHierarchyWalker, limit int) ([]fclient.MSC2946Room, *roomserver.RoomHierarchyWalker, error) { func (querier *Queryer) QueryNextRoomHierarchyPage(ctx context.Context, walker roomserver.RoomHierarchyWalker, limit int) ([]fclient.MSC2946Room, *roomserver.RoomHierarchyWalker, error) {
if authorised, _ := authorised(ctx, querier, walker.Caller, walker.RootRoomID, nil); !authorised { if authorised, _ := authorised(ctx, querier, walker.Caller, walker.RootRoomID, nil); !authorised {
return nil, nil, roomserver.ErrRoomUnknownOrNotAllowed{Err: fmt.Errorf("room is unknown/forbidden")} return nil, nil, roomserver.ErrRoomUnknownOrNotAllowed{Err: fmt.Errorf("room is unknown/forbidden")}
@ -234,7 +238,7 @@ func authorisedServer(ctx context.Context, querier *Queryer, roomID spec.RoomID,
} }
if rule == spec.Restricted { if rule == spec.Restricted {
allowJoinedToRoomIDs = append(allowJoinedToRoomIDs, restrictedJoinRuleAllowedRooms(ctx, joinRuleEv, "m.room_membership")...) allowJoinedToRoomIDs = append(allowJoinedToRoomIDs, restrictedJoinRuleAllowedRooms(ctx, joinRuleEv)...)
} }
} }
@ -308,7 +312,7 @@ func authorisedUser(ctx context.Context, querier *Queryer, clientCaller *userapi
} else if rule == spec.Public || rule == spec.Knock { } else if rule == spec.Public || rule == spec.Knock {
allowed = true allowed = true
} else if rule == spec.Restricted { } else if rule == spec.Restricted {
allowedRoomIDs := restrictedJoinRuleAllowedRooms(ctx, joinRuleEv, "m.room_membership") allowedRoomIDs := restrictedJoinRuleAllowedRooms(ctx, joinRuleEv)
// check parent is in the allowed set // check parent is in the allowed set
for _, a := range allowedRoomIDs { for _, a := range allowedRoomIDs {
if *parentRoomID == a { if *parentRoomID == a {
@ -342,6 +346,7 @@ func authorisedUser(ctx context.Context, querier *Queryer, clientCaller *userapi
return false, false return false, false
} }
// helper function to fetch a state event
func stateEvent(ctx context.Context, querier *Queryer, roomID spec.RoomID, evType, stateKey string) *types.HeaderedEvent { func stateEvent(ctx context.Context, querier *Queryer, roomID spec.RoomID, evType, stateKey string) *types.HeaderedEvent {
var queryRes roomserver.QueryCurrentStateResponse var queryRes roomserver.QueryCurrentStateResponse
tuple := gomatrixserverlib.StateKeyTuple{ tuple := gomatrixserverlib.StateKeyTuple{
@ -358,6 +363,7 @@ func stateEvent(ctx context.Context, querier *Queryer, roomID spec.RoomID, evTyp
return queryRes.StateEvents[tuple] return queryRes.StateEvents[tuple]
} }
// returns true if the current server is participating in the provided room
func roomExists(ctx context.Context, querier *Queryer, roomID spec.RoomID) bool { func roomExists(ctx context.Context, querier *Queryer, roomID spec.RoomID) bool {
var queryRes roomserver.QueryServerJoinedToRoomResponse var queryRes roomserver.QueryServerJoinedToRoomResponse
err := querier.QueryServerJoinedToRoom(ctx, &roomserver.QueryServerJoinedToRoomRequest{ err := querier.QueryServerJoinedToRoom(ctx, &roomserver.QueryServerJoinedToRoomRequest{
@ -473,6 +479,7 @@ func childReferences(querier *Queryer, suggestedOnly bool, roomID spec.RoomID) (
return el, nil return el, nil
} }
// fetch public room information for provided room
func publicRoomsChunk(ctx context.Context, querier *Queryer, roomID spec.RoomID) *fclient.PublicRoom { func publicRoomsChunk(ctx context.Context, querier *Queryer, roomID spec.RoomID) *fclient.PublicRoom {
pubRooms, err := roomserver.PopulatePublicRooms(ctx, []string{roomID.String()}, querier) pubRooms, err := roomserver.PopulatePublicRooms(ctx, []string{roomID.String()}, querier)
if err != nil { if err != nil {
@ -498,7 +505,8 @@ func stripped(ev gomatrixserverlib.PDU) *fclient.MSC2946StrippedEvent {
} }
} }
func restrictedJoinRuleAllowedRooms(ctx context.Context, joinRuleEv *types.HeaderedEvent, allowType string) (allows []spec.RoomID) { // given join_rule event, return list of rooms where membership of that room allows joining.
func restrictedJoinRuleAllowedRooms(ctx context.Context, joinRuleEv *types.HeaderedEvent) (allows []spec.RoomID) {
rule, _ := joinRuleEv.JoinRule() rule, _ := joinRuleEv.JoinRule()
if rule != spec.Restricted { if rule != spec.Restricted {
return nil return nil
@ -509,7 +517,7 @@ func restrictedJoinRuleAllowedRooms(ctx context.Context, joinRuleEv *types.Heade
return nil return nil
} }
for _, allow := range jrContent.Allow { for _, allow := range jrContent.Allow {
if allow.Type == allowType { if allow.Type == spec.MRoomMembership {
allowedRoomID, err := spec.NewRoomID(allow.RoomID) allowedRoomID, err := spec.NewRoomID(allow.RoomID)
if err != nil { if err != nil {
util.GetLogger(ctx).Warnf("invalid room ID '%s' found in join_rule on room %s: %s", allow.RoomID, joinRuleEv.RoomID(), err) util.GetLogger(ctx).Warnf("invalid room ID '%s' found in join_rule on room %s: %s", allow.RoomID, joinRuleEv.RoomID(), err)