From 958282749391a13dc6f03c1dd13a9554fb5db3ae Mon Sep 17 00:00:00 2001 From: Sam Wedgwood <28223854+swedgwood@users.noreply.github.com> Date: Thu, 20 Jul 2023 15:06:05 +0100 Subject: de-MSC-ifying space summaries (MSC2946) (#3134) - This PR moves and refactors the [code](https://github.com/matrix-org/dendrite/blob/main/setup/mscs/msc2946/msc2946.go) for [MSC2946](https://github.com/matrix-org/matrix-spec-proposals/pull/2946) ('Space Summaries') to integrate it into the rest of the codebase. - Means space summaries are no longer hidden behind an MSC flag - Solves #3096 Signed-off-by: Sam Wedgwood --- roomserver/api/api.go | 24 ++++++++++++++++ roomserver/api/query.go | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) (limited to 'roomserver/api') diff --git a/roomserver/api/api.go b/roomserver/api/api.go index c29406a1..28b381d3 100644 --- a/roomserver/api/api.go +++ b/roomserver/api/api.go @@ -34,6 +34,17 @@ func (e ErrNotAllowed) Error() string { return e.Err.Error() } +// ErrRoomUnknownOrNotAllowed is an error return if either the provided +// room ID does not exist, or points to a room that the requester does +// not have access to. +type ErrRoomUnknownOrNotAllowed struct { + Err error +} + +func (e ErrRoomUnknownOrNotAllowed) Error() string { + return e.Err.Error() +} + type RestrictedJoinAPI interface { CurrentStateEvent(ctx context.Context, roomID spec.RoomID, eventType string, stateKey string) (gomatrixserverlib.PDU, error) InvitePending(ctx context.Context, roomID spec.RoomID, senderID spec.SenderID) (bool, error) @@ -113,6 +124,17 @@ type QueryEventsAPI interface { QueryCurrentState(ctx context.Context, req *QueryCurrentStateRequest, res *QueryCurrentStateResponse) error } +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.RoomHierarchyRoom, *RoomHierarchyWalker, error) +} + // API functions required by the syncapi type SyncRoomserverAPI interface { QueryLatestEventsAndStateAPI @@ -187,6 +209,7 @@ type ClientRoomserverAPI interface { QueryEventsAPI QuerySenderIDAPI UserRoomPrivateKeyCreator + QueryRoomHierarchyAPI QueryMembershipForUser(ctx context.Context, req *QueryMembershipForUserRequest, res *QueryMembershipForUserResponse) error QueryMembershipsForRoom(ctx context.Context, req *QueryMembershipsForRoomRequest, res *QueryMembershipsForRoomResponse) error QueryRoomsForUser(ctx context.Context, req *QueryRoomsForUserRequest, res *QueryRoomsForUserResponse) error @@ -236,6 +259,7 @@ type FederationRoomserverAPI interface { QueryLatestEventsAndStateAPI QueryBulkStateContentAPI QuerySenderIDAPI + QueryRoomHierarchyAPI UserRoomPrivateKeyCreator AssignRoomNID(ctx context.Context, roomID spec.RoomID, roomVersion gomatrixserverlib.RoomVersion) (roomNID types.RoomNID, err error) SigningIdentityFor(ctx context.Context, roomID spec.RoomID, senderID spec.UserID) (fclient.SigningIdentity, error) diff --git a/roomserver/api/query.go b/roomserver/api/query.go index b6140afd..57bac2df 100644 --- a/roomserver/api/query.go +++ b/roomserver/api/query.go @@ -503,3 +503,79 @@ func (mq *MembershipQuerier) CurrentMembership(ctx context.Context, roomID spec. } return membership, err } + +type QueryRoomHierarchyRequest struct { + SuggestedOnly bool `json:"suggested_only"` + Limit int `json:"limit"` + MaxDepth int `json:"max_depth"` + From int `json:"json"` +} + +// A struct storing the intermediate state of a room hierarchy query for pagination purposes. +// +// Used for implementing space summaries / room hierarchies +// +// Use NewRoomHierarchyWalker to construct this, and QueryNextRoomHierarchyPage on the roomserver API +// to traverse the room hierarchy. +type RoomHierarchyWalker struct { + RootRoomID spec.RoomID + Caller types.DeviceOrServerName + SuggestedOnly bool + MaxDepth int + Processed RoomSet + Unvisited []RoomHierarchyWalkerQueuedRoom +} + +type RoomHierarchyWalkerQueuedRoom struct { + RoomID spec.RoomID + ParentRoomID *spec.RoomID + Depth int + 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 { + walker := RoomHierarchyWalker{ + RootRoomID: roomID, + Caller: caller, + SuggestedOnly: suggestedOnly, + MaxDepth: maxDepth, + Unvisited: []RoomHierarchyWalkerQueuedRoom{{ + RoomID: roomID, + ParentRoomID: nil, + Depth: 0, + }}, + Processed: NewRoomSet(), + } + + return walker +} + +// A set of room IDs. +type RoomSet map[spec.RoomID]struct{} + +// Create a new empty room set. +func NewRoomSet() RoomSet { + return RoomSet{} +} + +// Check if a room ID is in a room set. +func (s RoomSet) Contains(val spec.RoomID) bool { + _, ok := s[val] + return ok +} + +// Add a room ID to a room set. +func (s RoomSet) Add(val spec.RoomID) { + s[val] = struct{}{} +} + +func (s RoomSet) Copy() RoomSet { + copied := make(RoomSet, len(s)) + for k := range s { + copied.Add(k) + } + return copied +} -- cgit v1.2.3