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.
This commit is contained in:
Tak Wai Wong 2022-11-30 20:12:00 -08:00 committed by GitHub
parent a8127f9bdc
commit 8f4d1828b4
5 changed files with 31 additions and 132 deletions

View file

@ -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)

View file

@ -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,

View file

@ -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()

View file

@ -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,
}
}

View file

@ -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)