Merge pull request #56 from HereNotThere/jterzis/hnt-272-gate-msg-sync

message sync gating
This commit is contained in:
John Terzis 2022-11-01 19:14:44 -07:00 committed by GitHub
commit f2d6888452
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 173 additions and 18 deletions

View file

@ -2,13 +2,13 @@ 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 NewAuthorization(cfg *config.ClientAPI, rsAPI roomserver.ClientRoomserverAPI) authorization.Authorization {
func NewRoomserverAuthorization(cfg *config.ClientAPI, rsAPI zion.RoomserverStoreAPI) authorization.Authorization {
// Load authorization manager for Zion
if cfg.PublicKeyAuthentication.Ethereum.GetEnableAuthZ() {
auth, err := zion.NewZionAuthorization(cfg, rsAPI)

View file

@ -42,6 +42,7 @@ 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
@ -76,7 +77,8 @@ func Setup(
rateLimits := httputil.NewRateLimits(&cfg.RateLimiting)
userInteractiveAuth := auth.NewUserInteractive(userAPI, userAPI, cfg)
authorization := clientApiAuthz.NewAuthorization(cfg, rsAPI)
clientAuthz := zion.ClientRoomserverStruct{ClientRoomserverAPI: rsAPI}
authorization := clientApiAuthz.NewRoomserverAuthorization(cfg, clientAuthz)
unstableFeatures := map[string]bool{
"org.matrix.e2e_cross_signing": true,
@ -396,6 +398,20 @@ func Setup(
v3mux.Handle("/rooms/{roomID}/send/{eventType}",
httputil.MakeAuthAPI("send_message", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
isAllowed, _ := authorization.IsAllowed(authz.AuthorizationArgs{
RoomId: vars["roomID"],
UserId: device.UserID,
Permission: authz.PermissionWrite,
})
if !isAllowed {
return util.JSONResponse{
Code: http.StatusUnauthorized,
JSON: jsonerror.Forbidden("Unauthorised"),
}
}
if err != nil {
return util.ErrorResponse(err)
}
@ -405,6 +421,20 @@ func Setup(
v3mux.Handle("/rooms/{roomID}/send/{eventType}/{txnID}",
httputil.MakeAuthAPI("send_message", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
isAllowed, _ := authorization.IsAllowed(authz.AuthorizationArgs{
RoomId: vars["roomID"],
UserId: device.UserID,
Permission: authz.PermissionWrite,
})
if !isAllowed {
return util.JSONResponse{
Code: http.StatusUnauthorized,
JSON: jsonerror.Forbidden("Unauthorised to send event"),
}
}
if err != nil {
return util.ErrorResponse(err)
}
@ -525,7 +555,6 @@ func Setup(
return GetVisibility(req, rsAPI, vars["roomID"])
}),
).Methods(http.MethodGet, http.MethodOptions)
v3mux.Handle("/directory/list/room/{roomID}",
httputil.MakeAuthAPI("directory_list", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))

View file

@ -29,7 +29,11 @@ import (
"github.com/matrix-org/dendrite/setup/config"
"github.com/matrix-org/dendrite/syncapi/storage"
"github.com/matrix-org/dendrite/syncapi/sync"
authz "github.com/matrix-org/dendrite/authorization"
clientApiAuthz "github.com/matrix-org/dendrite/clientapi/authorization"
userapi "github.com/matrix-org/dendrite/userapi/api"
zion "github.com/matrix-org/dendrite/zion"
)
// Setup configures the given mux with sync-server listeners
@ -42,9 +46,12 @@ func Setup(
userAPI userapi.SyncUserAPI,
rsAPI api.SyncRoomserverAPI,
cfg *config.SyncAPI,
clientCfg *config.ClientAPI,
lazyLoadCache caching.LazyLoadCache,
fts *fulltext.Search,
) {
syncAuthz := zion.SyncRoomserverStruct{SyncRoomserverAPI: rsAPI}
authorization := clientApiAuthz.NewRoomserverAuthorization(clientCfg, syncAuthz)
v1unstablemux := csMux.PathPrefix("/{apiversion:(?:v1|unstable)}/").Subrouter()
v3mux := csMux.PathPrefix("/{apiversion:(?:r0|v3)}/").Subrouter()
@ -55,6 +62,19 @@ func Setup(
v3mux.Handle("/rooms/{roomID}/messages", httputil.MakeAuthAPI("room_messages", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
isAllowed, _ := authorization.IsAllowed(authz.AuthorizationArgs{
RoomId: vars["roomID"],
UserId: device.UserID,
Permission: authz.PermissionRead,
})
if !isAllowed {
return util.JSONResponse{
Code: http.StatusUnauthorized,
JSON: jsonerror.Forbidden("Unauthorised"),
}
}
if err != nil {
return util.ErrorResponse(err)
}

View file

@ -45,6 +45,7 @@ func AddPublicRoutes(
keyAPI keyapi.SyncKeyAPI,
) {
cfg := &base.Cfg.SyncAPI
clientCfg := &base.Cfg.ClientAPI
js, natsClient := base.NATS.Prepare(base.ProcessContext, &cfg.Matrix.JetStream)
@ -132,6 +133,6 @@ func AddPublicRoutes(
routing.Setup(
base.PublicClientAPIMux, requestPool, syncDB, userAPI,
rsAPI, cfg, base.Caches, base.Fulltext,
rsAPI, cfg, clientCfg, base.Caches, base.Fulltext,
)
}

View file

@ -12,17 +12,19 @@ import (
"github.com/matrix-org/gomatrixserverlib"
)
type Store struct {
type ClientRoomserverStore struct {
rsAPI roomserver.ClientRoomserverAPI
}
func NewStore(rsAPI roomserver.ClientRoomserverAPI) Store {
return Store{
rsAPI: rsAPI,
}
type SyncRoomserverStore struct {
rsAPI roomserver.SyncRoomserverAPI
}
func (s *Store) GetRoomInfo(roomId string, userId UserIdentifier) RoomInfo {
type StoreAPI interface {
GetRoomInfo(roomId string, userId UserIdentifier) RoomInfo
}
func (s *ClientRoomserverStore) GetRoomInfo(roomId string, userId UserIdentifier) RoomInfo {
result := RoomInfo{
QueryUserId: userId.MatrixUserId,
SpaceNetworkId: "",
@ -60,7 +62,7 @@ func (s *Store) GetRoomInfo(roomId string, userId UserIdentifier) RoomInfo {
if err != nil {
return result
}
//TODO: replace with HydrateRoomInfoWithStateEvents when you have a practical way to flatten roomEvents map
for _, state := range roomEvents.StateEvents {
switch state.Type() {
case gomatrixserverlib.MRoomCreate:
@ -86,3 +88,85 @@ func (s *Store) GetRoomInfo(roomId string, userId UserIdentifier) RoomInfo {
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

@ -19,16 +19,37 @@ var localhostJson []byte
var goerliJson []byte
type ZionAuthorization struct {
store Store
store StoreAPI
spaceManagerLocalhost *zion_localhost.ZionSpaceManagerLocalhost
spaceManagerGoerli *zion_goerli.ZionSpaceManagerGoerli
chainId int
}
type ClientRoomserverStruct struct {
roomserver.ClientRoomserverAPI
}
func NewZionAuthorization(
cfg *config.ClientAPI,
rsAPI roomserver.ClientRoomserverAPI,
) (authorization.Authorization, error) {
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) {
if cfg.PublicKeyAuthentication.Ethereum.NetworkUrl == "" {
log.Errorf("No blockchain network url specified in config\n")
return nil, nil
@ -37,7 +58,7 @@ func NewZionAuthorization(
var auth ZionAuthorization
auth.chainId = cfg.PublicKeyAuthentication.Ethereum.GetChainID()
auth.store = NewStore(rsAPI)
auth.store = rsAPI.NewRoomserverStore()
switch auth.chainId {
case 1337, 31337: