From 8f4d1828b4457ae209e552b91a1bc05910b25971 Mon Sep 17 00:00:00 2001 From: Tak Wai Wong <64229756+tak-hntlabs@users.noreply.github.com> Date: Wed, 30 Nov 2022 20:12:00 -0800 Subject: [PATCH] matrix room Id does not resolve to channelId or spaceId correctly (#1010) Issue: matrix room id does not always resolve to spaceId or channelId correctly. Root cause: The clientApi routing endpoint and the syncapi routing endpoint uses different stores to query for the current room states. One is correct, the other has incomplete events. Fix the issue by using the correct store in both routing code paths. --- clientapi/authorization/authorization.go | 6 +- clientapi/routing/routing.go | 4 +- syncapi/routing/routing.go | 3 +- zion/store.go | 109 ++++------------------- zion/zion_authorization.go | 41 ++------- 5 files changed, 31 insertions(+), 132 deletions(-) diff --git a/clientapi/authorization/authorization.go b/clientapi/authorization/authorization.go index a520d48b5..498313996 100644 --- a/clientapi/authorization/authorization.go +++ b/clientapi/authorization/authorization.go @@ -2,16 +2,16 @@ package authorization import ( "github.com/matrix-org/dendrite/authorization" + roomserver "github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/dendrite/setup/config" - _ "github.com/matrix-org/dendrite/setup/config" "github.com/matrix-org/dendrite/zion" log "github.com/sirupsen/logrus" ) -func NewRoomserverAuthorization(cfg *config.ClientAPI, rsAPI zion.RoomserverStoreAPI) authorization.Authorization { +func NewRoomserverAuthorization(cfg *config.ClientAPI, roomQueryAPI roomserver.QueryEventsAPI) authorization.Authorization { // Load authorization manager for Zion if cfg.PublicKeyAuthentication.Ethereum.GetEnableAuthZ() { - auth, err := zion.NewZionAuthorization(cfg, rsAPI) + auth, err := zion.NewZionAuthorization(cfg, roomQueryAPI) if err != nil { log.Errorln("Failed to initialise Zion authorization manager. Using default.", err) diff --git a/clientapi/routing/routing.go b/clientapi/routing/routing.go index efc4210f5..c537c3607 100644 --- a/clientapi/routing/routing.go +++ b/clientapi/routing/routing.go @@ -42,7 +42,6 @@ import ( "github.com/matrix-org/dendrite/setup/config" "github.com/matrix-org/dendrite/setup/jetstream" userapi "github.com/matrix-org/dendrite/userapi/api" - zion "github.com/matrix-org/dendrite/zion" ) var ReleaseVersion string @@ -77,8 +76,7 @@ func Setup( rateLimits := httputil.NewRateLimits(&cfg.RateLimiting) userInteractiveAuth := auth.NewUserInteractive(userAPI, userAPI, cfg) - clientAuthz := zion.ClientRoomserverStruct{ClientRoomserverAPI: rsAPI} - authorization := clientApiAuthz.NewRoomserverAuthorization(cfg, clientAuthz) + authorization := clientApiAuthz.NewRoomserverAuthorization(cfg, rsAPI) unstableFeatures := map[string]bool{ "org.matrix.e2e_cross_signing": true, diff --git a/syncapi/routing/routing.go b/syncapi/routing/routing.go index 666ee0b29..1df5d0104 100644 --- a/syncapi/routing/routing.go +++ b/syncapi/routing/routing.go @@ -52,8 +52,7 @@ func Setup( lazyLoadCache caching.LazyLoadCache, fts *fulltext.Search, ) { - syncAuthz := zion.SyncRoomserverStruct{SyncRoomserverAPI: rsAPI} - authorization := clientApiAuthz.NewRoomserverAuthorization(clientCfg, syncAuthz) + authorization := clientApiAuthz.NewRoomserverAuthorization(clientCfg, crsAPI) v1unstablemux := csMux.PathPrefix("/{apiversion:(?:v1|unstable)}/").Subrouter() v3mux := csMux.PathPrefix("/{apiversion:(?:r0|v3)}/").Subrouter() diff --git a/zion/store.go b/zion/store.go index 6089ff81b..e9350519c 100644 --- a/zion/store.go +++ b/zion/store.go @@ -12,19 +12,17 @@ import ( "github.com/matrix-org/gomatrixserverlib" ) -type ClientRoomserverStore struct { - rsAPI roomserver.ClientRoomserverAPI +type Store struct { + roomQuery roomserver.QueryEventsAPI } -type SyncRoomserverStore struct { - rsAPI roomserver.SyncRoomserverAPI +func NewStore(roomQuery roomserver.QueryEventsAPI) Store { + return Store{ + roomQuery: roomQuery, + } } -type StoreAPI interface { - GetRoomInfo(roomId string, userId UserIdentifier) RoomInfo -} - -func (s *ClientRoomserverStore) GetRoomInfo(roomId string, userId UserIdentifier) RoomInfo { +func (s *Store) GetRoomInfo(roomId string, userId UserIdentifier) RoomInfo { result := RoomInfo{ QueryUserId: userId.MatrixUserId, SpaceNetworkId: "", @@ -49,7 +47,7 @@ func (s *ClientRoomserverStore) GetRoomInfo(roomId string, userId UserIdentifier } var roomEvents roomserver.QueryCurrentStateResponse - err := s.rsAPI.QueryCurrentState(context.Background(), &roomserver.QueryCurrentStateRequest{ + err := s.roomQuery.QueryCurrentState(context.Background(), &roomserver.QueryCurrentStateRequest{ RoomID: roomId, AllowWildcards: true, StateTuples: []gomatrixserverlib.StateKeyTuple{ @@ -63,9 +61,11 @@ func (s *ClientRoomserverStore) GetRoomInfo(roomId string, userId UserIdentifier return result } //TODO: replace with HydrateRoomInfoWithStateEvents when you have a practical way to flatten roomEvents map + doneSearching := false for _, state := range roomEvents.StateEvents { switch state.Type() { case gomatrixserverlib.MRoomCreate: + // Space is created with no children yet. var creatorEvent CreatorEvent err := json.Unmarshal(roomEvents.StateEvents[createTuple].Content(), &creatorEvent) result.IsOwner = strings.HasPrefix( @@ -77,96 +77,21 @@ func (s *ClientRoomserverStore) GetRoomInfo(roomId string, userId UserIdentifier result.SpaceNetworkId = roomId } case ConstSpaceChildEventType: + // Space is created and has one or more children. result.RoomType = Space result.SpaceNetworkId = roomId + doneSearching = true case ConstSpaceParentEventType: + // Channel is created and has a reference to the parent. result.RoomType = Channel result.SpaceNetworkId = *state.StateKey() result.ChannelNetworkId = roomId + doneSearching = true + } + if doneSearching { + break } } return result } - -func (s *SyncRoomserverStore) GetRoomInfo(roomId string, userId UserIdentifier) RoomInfo { - result := RoomInfo{ - QueryUserId: userId.MatrixUserId, - SpaceNetworkId: "", - ChannelNetworkId: "", - RoomType: Unknown, - IsOwner: false, - } - - createTuple := gomatrixserverlib.StateKeyTuple{ - EventType: gomatrixserverlib.MRoomCreate, - StateKey: "", - } - - spaceChildTuple := gomatrixserverlib.StateKeyTuple{ - EventType: ConstSpaceChildEventType, - StateKey: "*", - } - - spaceParentTuple := gomatrixserverlib.StateKeyTuple{ - EventType: ConstSpaceParentEventType, - StateKey: "*", - } - - var roomEvents roomserver.QueryLatestEventsAndStateResponse - err := s.rsAPI.QueryLatestEventsAndState(context.Background(), - &roomserver.QueryLatestEventsAndStateRequest{ - RoomID: roomId, - StateToFetch: []gomatrixserverlib.StateKeyTuple{ - createTuple, - spaceParentTuple, - spaceChildTuple, - }, - }, &roomEvents) - - if err != nil { - return result - } - - HydrateRoomInfoWithStateEvents(roomId, userId, &result, roomEvents.StateEvents) - - return result -} - -func HydrateRoomInfoWithStateEvents(roomId string, userId UserIdentifier, r *RoomInfo, stateEvents []*gomatrixserverlib.HeaderedEvent) { - for _, state := range stateEvents { - switch state.Type() { - case gomatrixserverlib.MRoomCreate: - var creatorEvent CreatorEvent - err := json.Unmarshal(state.Content(), &creatorEvent) - r.IsOwner = strings.HasPrefix( - creatorEvent.Creator, - userId.LocalPart, - ) - if err == nil { - r.RoomType = Space - r.SpaceNetworkId = roomId - } - case ConstSpaceChildEventType: - r.RoomType = Space - r.SpaceNetworkId = roomId - case ConstSpaceParentEventType: - r.RoomType = Channel - r.SpaceNetworkId = *state.StateKey() - r.ChannelNetworkId = roomId - } - } - -} - -func NewClientRoomserverStore(rsAPI roomserver.ClientRoomserverAPI) StoreAPI { - return &ClientRoomserverStore{ - rsAPI: rsAPI, - } -} - -func NewSyncRoomserverStore(rsAPI roomserver.SyncRoomserverAPI) StoreAPI { - return &SyncRoomserverStore{ - rsAPI: rsAPI, - } -} diff --git a/zion/zion_authorization.go b/zion/zion_authorization.go index 01219ebcc..a88b350bd 100644 --- a/zion/zion_authorization.go +++ b/zion/zion_authorization.go @@ -23,46 +23,22 @@ var ErrSpaceDisabled = errors.New("space disabled") var ErrChannelDisabled = errors.New("channel disabled") type ZionAuthorization struct { - store StoreAPI + chainId int spaceManagerLocalhost *zion_localhost.ZionSpaceManagerLocalhost spaceManagerGoerli *zion_goerli.ZionSpaceManagerGoerli - chainId int -} -type ClientRoomserverStruct struct { - roomserver.ClientRoomserverAPI + store Store } -type SyncRoomserverStruct struct { - roomserver.SyncRoomserverAPI -} - -type RoomserverStoreAPI interface { - roomserver.QueryLatestEventsAndStateAPI - NewRoomserverStore() StoreAPI -} - -func (c ClientRoomserverStruct) NewRoomserverStore() StoreAPI { - return &ClientRoomserverStore{ - rsAPI: c, - } -} - -func (c SyncRoomserverStruct) NewRoomserverStore() StoreAPI { - return &SyncRoomserverStore{ - rsAPI: c, - } -} - -func NewZionAuthorization(cfg *config.ClientAPI, rsAPI RoomserverStoreAPI) (authorization.Authorization, error) { +func NewZionAuthorization(cfg *config.ClientAPI, roomQueryAPI roomserver.QueryEventsAPI) (authorization.Authorization, error) { if cfg.PublicKeyAuthentication.Ethereum.NetworkUrl == "" { log.Errorf("No blockchain network url specified in config\n") return nil, nil } - var auth ZionAuthorization - - auth.chainId = cfg.PublicKeyAuthentication.Ethereum.GetChainID() - auth.store = rsAPI.NewRoomserverStore() + auth := ZionAuthorization{ + store: NewStore(roomQueryAPI), + chainId: cfg.PublicKeyAuthentication.Ethereum.GetChainID(), + } switch auth.chainId { case 1337, 31337: @@ -106,7 +82,8 @@ func (za *ZionAuthorization) IsAllowed(args authorization.AuthorizationArgs) (bo } else if err != nil { return false, err } - return za.isAllowedLocalhost(roomInfo, userIdentifier.AccountAddress, args.Permission) + isAllowed, err := za.isAllowedLocalhost(roomInfo, userIdentifier.AccountAddress, args.Permission) + return isAllowed, err case 5: // Check if space / channel is disabled. disabled, err := za.isSpaceChannelDisabledGoerli(roomInfo)