Merge pull request #71 from HereNotThere/main-merge

Main merge
This commit is contained in:
Brian Meek 2023-02-08 08:25:21 -08:00 committed by GitHub
commit 823b675bce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 7408 additions and 2637 deletions

View file

@ -33,4 +33,5 @@ func AddRoutes(a api.AppServiceInternalAPI, internalAPIMux *mux.Router, enableMe
AppServiceUserPath, AppServiceUserPath,
httputil.MakeInternalRPCAPI("AppserviceUser", enableMetrics, a.User), httputil.MakeInternalRPCAPI("AppserviceUser", enableMetrics, a.User),
) )
} }

View file

@ -21,6 +21,8 @@ LABEL org.opencontainers.image.licenses="Apache-2.0"
COPY --from=base /build/bin/* /usr/bin/ COPY --from=base /build/bin/* /usr/bin/
COPY --from=base /build/dendrite-zion.yaml /usr/config/dendrite-zion.yaml
VOLUME /etc/dendrite VOLUME /etc/dendrite
WORKDIR /etc/dendrite WORKDIR /etc/dendrite

View file

@ -17,12 +17,17 @@ import (
"github.com/matrix-org/util" "github.com/matrix-org/util"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
rsapi "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/dendrite/test" "github.com/matrix-org/dendrite/test"
"github.com/matrix-org/dendrite/test/testrig" "github.com/matrix-org/dendrite/test/testrig"
"github.com/matrix-org/dendrite/userapi" "github.com/matrix-org/dendrite/userapi"
uapi "github.com/matrix-org/dendrite/userapi/api" uapi "github.com/matrix-org/dendrite/userapi/api"
) )
type clientRoomserverAPI struct {
rsapi.ClientRoomserverAPI
}
func TestAdminResetPassword(t *testing.T) { func TestAdminResetPassword(t *testing.T) {
aliceAdmin := test.NewUser(t, test.WithAccountType(uapi.AccountTypeAdmin)) aliceAdmin := test.NewUser(t, test.WithAccountType(uapi.AccountTypeAdmin))
bob := test.NewUser(t, test.WithAccountType(uapi.AccountTypeUser)) bob := test.NewUser(t, test.WithAccountType(uapi.AccountTypeUser))
@ -159,7 +164,7 @@ func TestPurgeRoom(t *testing.T) {
userAPI := userapi.NewInternalAPI(base, &base.Cfg.UserAPI, nil, keyAPI, rsAPI, nil) userAPI := userapi.NewInternalAPI(base, &base.Cfg.UserAPI, nil, keyAPI, rsAPI, nil)
// this starts the JetStream consumers // this starts the JetStream consumers
syncapi.AddPublicRoutes(base, userAPI, rsAPI, keyAPI) syncapi.AddPublicRoutes(base, userAPI, rsAPI, &clientRoomserverAPI{}, keyAPI)
federationapi.NewInternalAPI(base, fedClient, rsAPI, base.Caches, nil, true) federationapi.NewInternalAPI(base, fedClient, rsAPI, base.Caches, nil, true)
rsAPI.SetFederationAPI(nil, nil) rsAPI.SetFederationAPI(nil, nil)
keyAPI.SetUserAPI(userAPI) keyAPI.SetUserAPI(userAPI)

View file

@ -1,24 +1,29 @@
package authorization package authorization
import ( import (
"flag"
"github.com/matrix-org/dendrite/authorization" "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/setup/config"
"github.com/matrix-org/dendrite/zion" "github.com/matrix-org/dendrite/zion"
log "github.com/sirupsen/logrus" 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 // Load authorization manager for Zion
if cfg.PublicKeyAuthentication.Ethereum.GetEnableAuthZ() { if flag.Lookup("test.v") == nil {
auth, err := zion.NewZionAuthorization(cfg, rsAPI) // normal run
// Load authorization manager for Zion
auth, err := zion.NewZionAuthorization(cfg, roomQueryAPI)
if err != nil { if err != nil {
log.Errorln("Failed to initialise Zion authorization manager. Using default.", err) // Cannot proceed without an authorization manager
} else { log.Fatalf("failed to initialise Zion authorization manager, using default. Error: %v", err)
return auth
}
} }
return auth
} else {
// run under go test
return &authorization.DefaultAuthorization{} return &authorization.DefaultAuthorization{}
} }
}

View file

@ -171,6 +171,15 @@ func LeaveServerNoticeError() *MatrixError {
} }
} }
// ServerDisabledNoticeError is an error returned when trying to sync a server
// that is disabled
func ServerDisabledNoticeError() *MatrixError {
return &MatrixError{
ErrCode: "Z_UNAUTHORISED_SERVER_DISABLED",
Err: "You cannot remain in a disabled server",
}
}
type IncompatibleRoomVersionError struct { type IncompatibleRoomVersionError struct {
RoomVersion string `json:"room_version"` RoomVersion string `json:"room_version"`
Error string `json:"error"` Error string `json:"error"`

View file

@ -44,7 +44,6 @@ import (
"github.com/matrix-org/dendrite/setup/config" "github.com/matrix-org/dendrite/setup/config"
"github.com/matrix-org/dendrite/setup/jetstream" "github.com/matrix-org/dendrite/setup/jetstream"
userapi "github.com/matrix-org/dendrite/userapi/api" userapi "github.com/matrix-org/dendrite/userapi/api"
zion "github.com/matrix-org/dendrite/zion"
) )
var ReleaseVersion string var ReleaseVersion string
@ -86,8 +85,7 @@ func Setup(
rateLimits := httputil.NewRateLimits(&cfg.RateLimiting) rateLimits := httputil.NewRateLimits(&cfg.RateLimiting)
userInteractiveAuth := auth.NewUserInteractive(userAPI, userAPI, cfg) userInteractiveAuth := auth.NewUserInteractive(userAPI, userAPI, cfg)
clientAuthz := zion.ClientRoomserverStruct{ClientRoomserverAPI: rsAPI} authorization := clientApiAuthz.NewRoomserverAuthorization(cfg, rsAPI)
authorization := clientApiAuthz.NewRoomserverAuthorization(cfg, clientAuthz)
unstableFeatures := map[string]bool{ unstableFeatures := map[string]bool{
"org.matrix.e2e_cross_signing": true, "org.matrix.e2e_cross_signing": true,

View file

@ -22,12 +22,13 @@ import (
func SyncAPI(base *basepkg.BaseDendrite, cfg *config.Dendrite) { func SyncAPI(base *basepkg.BaseDendrite, cfg *config.Dendrite) {
userAPI := base.UserAPIClient() userAPI := base.UserAPIClient()
base.RoomserverHTTPClient()
rsAPI := base.RoomserverHTTPClient() rsAPI := base.RoomserverHTTPClient()
syncapi.AddPublicRoutes( syncapi.AddPublicRoutes(
base, base,
userAPI, rsAPI, userAPI, rsAPI, rsAPI,
base.KeyServerHTTPClient(), base.KeyServerHTTPClient(),
) )

3
get-version.sh Normal file
View file

@ -0,0 +1,3 @@
#!/usr/bin/env bash
echo $(git log -1 --pretty=%h)

View file

@ -22,12 +22,17 @@ import (
"github.com/matrix-org/dendrite/roomserver" "github.com/matrix-org/dendrite/roomserver"
"github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/dendrite/roomserver/api"
rsapi "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/dendrite/roomserver/inthttp" "github.com/matrix-org/dendrite/roomserver/inthttp"
"github.com/matrix-org/dendrite/roomserver/storage" "github.com/matrix-org/dendrite/roomserver/storage"
"github.com/matrix-org/dendrite/test" "github.com/matrix-org/dendrite/test"
"github.com/matrix-org/dendrite/test/testrig" "github.com/matrix-org/dendrite/test/testrig"
) )
type clientRoomserverAPI struct {
rsapi.ClientRoomserverAPI
}
func mustCreateDatabase(t *testing.T, dbType test.DBType) (*base.BaseDendrite, storage.Database, func()) { func mustCreateDatabase(t *testing.T, dbType test.DBType) (*base.BaseDendrite, storage.Database, func()) {
t.Helper() t.Helper()
base, close := testrig.CreateBaseDendrite(t, dbType) base, close := testrig.CreateBaseDendrite(t, dbType)
@ -253,7 +258,7 @@ func TestPurgeRoom(t *testing.T) {
userAPI := userapi.NewInternalAPI(base, &base.Cfg.UserAPI, nil, keyAPI, rsAPI, nil) userAPI := userapi.NewInternalAPI(base, &base.Cfg.UserAPI, nil, keyAPI, rsAPI, nil)
// this starts the JetStream consumers // this starts the JetStream consumers
syncapi.AddPublicRoutes(base, userAPI, rsAPI, keyAPI) syncapi.AddPublicRoutes(base, userAPI, rsAPI, &clientRoomserverAPI{}, keyAPI)
federationapi.NewInternalAPI(base, fedClient, rsAPI, base.Caches, nil, true) federationapi.NewInternalAPI(base, fedClient, rsAPI, base.Caches, nil, true)
rsAPI.SetFederationAPI(nil, nil) rsAPI.SetFederationAPI(nil, nil)

View file

@ -630,14 +630,10 @@ func (config *Dendrite) replaceWithEnvVariables() {
config.ClientAPI.PublicKeyAuthentication.Ethereum.NetworkUrl = config.ClientAPI.PublicKeyAuthentication.Ethereum.NetworkUrl =
replaceWithEnvVariables(config.ClientAPI.PublicKeyAuthentication.Ethereum.NetworkUrl) replaceWithEnvVariables(config.ClientAPI.PublicKeyAuthentication.Ethereum.NetworkUrl)
config.ClientAPI.PublicKeyAuthentication.Ethereum.ConfigEnableAuthz =
replaceWithEnvVariables(config.ClientAPI.PublicKeyAuthentication.Ethereum.ConfigEnableAuthz)
logrus.Infof( logrus.Infof(
"Supported Ethereum chain_id=%v, network_url=%v, enable_authz=%v", "Supported Ethereum chain_id=%v, network_url=%v",
config.ClientAPI.PublicKeyAuthentication.Ethereum.ConfigChainID, config.ClientAPI.PublicKeyAuthentication.Ethereum.ConfigChainID,
config.ClientAPI.PublicKeyAuthentication.Ethereum.NetworkUrl, config.ClientAPI.PublicKeyAuthentication.Ethereum.NetworkUrl,
config.ClientAPI.PublicKeyAuthentication.Ethereum.ConfigEnableAuthz,
) )
} }
} }

View file

@ -25,9 +25,7 @@ type EthereumAuthConfig struct {
Version uint `yaml:"version"` Version uint `yaml:"version"`
NetworkUrl string `yaml:"network_url"` // Blockchain network provider URL NetworkUrl string `yaml:"network_url"` // Blockchain network provider URL
ConfigChainID string `yaml:"chain_id"` // Blockchain chain ID. Env variable can replace this property. ConfigChainID string `yaml:"chain_id"` // Blockchain chain ID. Env variable can replace this property.
ConfigEnableAuthz string `yaml:"enable_authz"` // Enable / disable authorization during development. Will be removed when feature is done.
chainID int chainID int
enableAuthz bool
} }
func (c *EthereumAuthConfig) GetChainID() int { func (c *EthereumAuthConfig) GetChainID() int {
@ -43,19 +41,6 @@ func (c *EthereumAuthConfig) GetChainID() int {
return c.chainID return c.chainID
} }
func (c *EthereumAuthConfig) GetEnableAuthZ() bool {
if c.ConfigEnableAuthz != "" {
v := strings.TrimSpace(c.ConfigEnableAuthz)
boolValue, err := strconv.ParseBool(v)
if err == nil {
c.enableAuthz = boolValue
}
// No need to do this again.
c.ConfigEnableAuthz = ""
}
return c.enableAuthz
}
type PublicKeyAuthentication struct { type PublicKeyAuthentication struct {
Ethereum EthereumAuthConfig `yaml:"ethereum"` Ethereum EthereumAuthConfig `yaml:"ethereum"`
} }

View file

@ -72,7 +72,7 @@ func (m *Monolith) AddAllPublicRoutes(base *base.BaseDendrite) {
base, m.UserAPI, m.Client, base, m.UserAPI, m.Client,
) )
syncapi.AddPublicRoutes( syncapi.AddPublicRoutes(
base, m.UserAPI, m.RoomserverAPI, m.KeyAPI, base, m.UserAPI, m.RoomserverAPI, m.RoomserverAPI, m.KeyAPI,
) )
if m.RelayAPI != nil { if m.RelayAPI != nil {

View file

@ -22,6 +22,7 @@ import (
"github.com/matrix-org/util" "github.com/matrix-org/util"
"github.com/matrix-org/dendrite/clientapi/jsonerror" "github.com/matrix-org/dendrite/clientapi/jsonerror"
"github.com/matrix-org/dendrite/clientapi/routing"
"github.com/matrix-org/dendrite/internal/caching" "github.com/matrix-org/dendrite/internal/caching"
"github.com/matrix-org/dendrite/internal/fulltext" "github.com/matrix-org/dendrite/internal/fulltext"
"github.com/matrix-org/dendrite/internal/httputil" "github.com/matrix-org/dendrite/internal/httputil"
@ -45,13 +46,13 @@ func Setup(
csMux *mux.Router, srp *sync.RequestPool, syncDB storage.Database, csMux *mux.Router, srp *sync.RequestPool, syncDB storage.Database,
userAPI userapi.SyncUserAPI, userAPI userapi.SyncUserAPI,
rsAPI api.SyncRoomserverAPI, rsAPI api.SyncRoomserverAPI,
crsAPI api.ClientRoomserverAPI,
cfg *config.SyncAPI, cfg *config.SyncAPI,
clientCfg *config.ClientAPI, clientCfg *config.ClientAPI,
lazyLoadCache caching.LazyLoadCache, lazyLoadCache caching.LazyLoadCache,
fts *fulltext.Search, fts *fulltext.Search,
) { ) {
syncAuthz := zion.SyncRoomserverStruct{SyncRoomserverAPI: rsAPI} authorization := clientApiAuthz.NewRoomserverAuthorization(clientCfg, crsAPI)
authorization := clientApiAuthz.NewRoomserverAuthorization(clientCfg, syncAuthz)
v1unstablemux := csMux.PathPrefix("/{apiversion:(?:v1|unstable)}/").Subrouter() v1unstablemux := csMux.PathPrefix("/{apiversion:(?:v1|unstable)}/").Subrouter()
v3mux := csMux.PathPrefix("/{apiversion:(?:r0|v3)}/").Subrouter() v3mux := csMux.PathPrefix("/{apiversion:(?:r0|v3)}/").Subrouter()
@ -63,12 +64,36 @@ func Setup(
v3mux.Handle("/rooms/{roomID}/messages", httputil.MakeAuthAPI("room_messages", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse { 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)) vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
isAllowed, _ := authorization.IsAllowed(authz.AuthorizationArgs{ if err != nil {
return util.ErrorResponse(err)
}
isAllowed, err := authorization.IsAllowed(authz.AuthorizationArgs{
RoomId: vars["roomID"], RoomId: vars["roomID"],
UserId: device.UserID, UserId: device.UserID,
Permission: authz.PermissionRead, Permission: authz.PermissionRead,
}) })
if err != nil {
switch err {
case zion.ErrSpaceDisabled, zion.ErrChannelDisabled:
// leave space / channel if it is disabled
resp := routing.LeaveRoomByID(req, device, crsAPI, vars["roomID"])
if resp.Code == 200 {
return util.JSONResponse{
Code: http.StatusUnauthorized,
JSON: jsonerror.ServerDisabledNoticeError(),
}
}
return resp
default:
// error client if something else is awry
return util.JSONResponse{
Code: http.StatusUnauthorized,
JSON: jsonerror.Forbidden("Unauthorised"),
}
}
}
if !isAllowed { if !isAllowed {
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusUnauthorized, Code: http.StatusUnauthorized,

View file

@ -42,6 +42,7 @@ func AddPublicRoutes(
base *base.BaseDendrite, base *base.BaseDendrite,
userAPI userapi.SyncUserAPI, userAPI userapi.SyncUserAPI,
rsAPI api.SyncRoomserverAPI, rsAPI api.SyncRoomserverAPI,
crsAPI api.ClientRoomserverAPI,
keyAPI keyapi.SyncKeyAPI, keyAPI keyapi.SyncKeyAPI,
) { ) {
cfg := &base.Cfg.SyncAPI cfg := &base.Cfg.SyncAPI
@ -133,6 +134,6 @@ func AddPublicRoutes(
routing.Setup( routing.Setup(
base.PublicClientAPIMux, requestPool, syncDB, userAPI, base.PublicClientAPIMux, requestPool, syncDB, userAPI,
rsAPI, cfg, clientCfg, base.Caches, base.Fulltext, rsAPI, crsAPI, cfg, clientCfg, base.Caches, base.Fulltext,
) )
} }

View file

@ -33,6 +33,10 @@ type syncRoomserverAPI struct {
rooms []*test.Room rooms []*test.Room
} }
type clientRoomserverAPI struct {
rsapi.ClientRoomserverAPI
}
func (s *syncRoomserverAPI) QueryLatestEventsAndState(ctx context.Context, req *rsapi.QueryLatestEventsAndStateRequest, res *rsapi.QueryLatestEventsAndStateResponse) error { func (s *syncRoomserverAPI) QueryLatestEventsAndState(ctx context.Context, req *rsapi.QueryLatestEventsAndStateRequest, res *rsapi.QueryLatestEventsAndStateResponse) error {
var room *test.Room var room *test.Room
for _, r := range s.rooms { for _, r := range s.rooms {
@ -121,7 +125,7 @@ func testSyncAccessTokens(t *testing.T, dbType test.DBType) {
jsctx, _ := base.NATS.Prepare(base.ProcessContext, &base.Cfg.Global.JetStream) jsctx, _ := base.NATS.Prepare(base.ProcessContext, &base.Cfg.Global.JetStream)
defer jetstream.DeleteAllStreams(jsctx, &base.Cfg.Global.JetStream) defer jetstream.DeleteAllStreams(jsctx, &base.Cfg.Global.JetStream)
msgs := toNATSMsgs(t, base, room.Events()...) msgs := toNATSMsgs(t, base, room.Events()...)
AddPublicRoutes(base, &syncUserAPI{accounts: []userapi.Device{alice}}, &syncRoomserverAPI{rooms: []*test.Room{room}}, &syncKeyAPI{}) AddPublicRoutes(base, &syncUserAPI{accounts: []userapi.Device{alice}}, &syncRoomserverAPI{rooms: []*test.Room{room}}, &clientRoomserverAPI{}, &syncKeyAPI{})
testrig.MustPublishMsgs(t, jsctx, msgs...) testrig.MustPublishMsgs(t, jsctx, msgs...)
testCases := []struct { testCases := []struct {
@ -220,7 +224,7 @@ func testSyncAPICreateRoomSyncEarly(t *testing.T, dbType test.DBType) {
// m.room.history_visibility // m.room.history_visibility
msgs := toNATSMsgs(t, base, room.Events()...) msgs := toNATSMsgs(t, base, room.Events()...)
sinceTokens := make([]string, len(msgs)) sinceTokens := make([]string, len(msgs))
AddPublicRoutes(base, &syncUserAPI{accounts: []userapi.Device{alice}}, &syncRoomserverAPI{rooms: []*test.Room{room}}, &syncKeyAPI{}) AddPublicRoutes(base, &syncUserAPI{accounts: []userapi.Device{alice}}, &syncRoomserverAPI{rooms: []*test.Room{room}}, &clientRoomserverAPI{}, &syncKeyAPI{})
for i, msg := range msgs { for i, msg := range msgs {
testrig.MustPublishMsgs(t, jsctx, msg) testrig.MustPublishMsgs(t, jsctx, msg)
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
@ -304,7 +308,7 @@ func testSyncAPIUpdatePresenceImmediately(t *testing.T, dbType test.DBType) {
jsctx, _ := base.NATS.Prepare(base.ProcessContext, &base.Cfg.Global.JetStream) jsctx, _ := base.NATS.Prepare(base.ProcessContext, &base.Cfg.Global.JetStream)
defer jetstream.DeleteAllStreams(jsctx, &base.Cfg.Global.JetStream) defer jetstream.DeleteAllStreams(jsctx, &base.Cfg.Global.JetStream)
AddPublicRoutes(base, &syncUserAPI{accounts: []userapi.Device{alice}}, &syncRoomserverAPI{}, &syncKeyAPI{}) AddPublicRoutes(base, &syncUserAPI{accounts: []userapi.Device{alice}}, &syncRoomserverAPI{}, &clientRoomserverAPI{}, &syncKeyAPI{})
w := httptest.NewRecorder() w := httptest.NewRecorder()
base.PublicClientAPIMux.ServeHTTP(w, test.NewRequest(t, "GET", "/_matrix/client/v3/sync", test.WithQueryParams(map[string]string{ base.PublicClientAPIMux.ServeHTTP(w, test.NewRequest(t, "GET", "/_matrix/client/v3/sync", test.WithQueryParams(map[string]string{
"access_token": alice.AccessToken, "access_token": alice.AccessToken,
@ -422,7 +426,7 @@ func testHistoryVisibility(t *testing.T, dbType test.DBType) {
rsAPI := roomserver.NewInternalAPI(base) rsAPI := roomserver.NewInternalAPI(base)
rsAPI.SetFederationAPI(nil, nil) rsAPI.SetFederationAPI(nil, nil)
AddPublicRoutes(base, &syncUserAPI{accounts: []userapi.Device{aliceDev, bobDev}}, rsAPI, &syncKeyAPI{}) AddPublicRoutes(base, &syncUserAPI{accounts: []userapi.Device{aliceDev, bobDev}}, rsAPI, rsAPI, &syncKeyAPI{})
for _, tc := range testCases { for _, tc := range testCases {
testname := fmt.Sprintf("%s - %s", tc.historyVisibility, userType) testname := fmt.Sprintf("%s - %s", tc.historyVisibility, userType)
@ -722,7 +726,7 @@ func TestGetMembership(t *testing.T) {
rsAPI := roomserver.NewInternalAPI(base) rsAPI := roomserver.NewInternalAPI(base)
rsAPI.SetFederationAPI(nil, nil) rsAPI.SetFederationAPI(nil, nil)
AddPublicRoutes(base, &syncUserAPI{accounts: []userapi.Device{aliceDev, bobDev}}, rsAPI, &syncKeyAPI{}) AddPublicRoutes(base, &syncUserAPI{accounts: []userapi.Device{aliceDev, bobDev}}, rsAPI, &clientRoomserverAPI{}, &syncKeyAPI{})
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
@ -789,7 +793,7 @@ func testSendToDevice(t *testing.T, dbType test.DBType) {
jsctx, _ := base.NATS.Prepare(base.ProcessContext, &base.Cfg.Global.JetStream) jsctx, _ := base.NATS.Prepare(base.ProcessContext, &base.Cfg.Global.JetStream)
defer jetstream.DeleteAllStreams(jsctx, &base.Cfg.Global.JetStream) defer jetstream.DeleteAllStreams(jsctx, &base.Cfg.Global.JetStream)
AddPublicRoutes(base, &syncUserAPI{accounts: []userapi.Device{alice}}, &syncRoomserverAPI{}, &syncKeyAPI{}) AddPublicRoutes(base, &syncUserAPI{accounts: []userapi.Device{alice}}, &syncRoomserverAPI{}, &clientRoomserverAPI{}, &syncKeyAPI{})
producer := producers.SyncAPIProducer{ producer := producers.SyncAPIProducer{
TopicSendToDeviceEvent: base.Cfg.Global.JetStream.Prefixed(jetstream.OutputSendToDeviceEvent), TopicSendToDeviceEvent: base.Cfg.Global.JetStream.Prefixed(jetstream.OutputSendToDeviceEvent),
@ -1008,7 +1012,7 @@ func testContext(t *testing.T, dbType test.DBType) {
rsAPI := roomserver.NewInternalAPI(base) rsAPI := roomserver.NewInternalAPI(base)
rsAPI.SetFederationAPI(nil, nil) rsAPI.SetFederationAPI(nil, nil)
AddPublicRoutes(base, &syncUserAPI{accounts: []userapi.Device{alice}}, rsAPI, &syncKeyAPI{}) AddPublicRoutes(base, &syncUserAPI{accounts: []userapi.Device{alice}}, rsAPI, &clientRoomserverAPI{}, &syncKeyAPI{})
room := test.NewRoom(t, user) room := test.NewRoom(t, user)

View file

@ -173,7 +173,7 @@ func WithAllDatabases(t *testing.T, testFn func(t *testing.T, db DBType)) {
for dbName, dbType := range dbs { for dbName, dbType := range dbs {
dbt := dbType dbt := dbType
t.Run(dbName, func(tt *testing.T) { t.Run(dbName, func(tt *testing.T) {
tt.Parallel() //tt.Parallel()
testFn(tt, dbt) testFn(tt, dbt)
}) })
} }

View file

@ -10,13 +10,15 @@ type SpaceManagerContractAddresses struct {
Tokengranted string `json:"tokengranted"` Tokengranted string `json:"tokengranted"`
} }
func loadSpaceManagerAddresses(byteValue []byte) (*SpaceManagerContractAddresses, error) { type SpaceFactoryContractAddress struct {
var addresses SpaceManagerContractAddresses SpaceFactory string `json:"spaceFactory"`
}
err := json.Unmarshal(byteValue, &addresses) func loadSpaceFactoryAddress(byteValue []byte) (*SpaceFactoryContractAddress, error) {
var address SpaceFactoryContractAddress
err := json.Unmarshal(byteValue, &address)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &address, nil
return &addresses, nil
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,4 @@
{
"spaceFactory": "0x173b6a4Ec998A0e72656e0fc9Af2408B017C12f9",
"spaceToken": "0xD7efA82c6CEa706B396F4FfA23f0D01726F675cc"
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,4 @@
{
"spaceFactory": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
"spaceToken": "0x0165878A594ca255338adfa4d48449f69242Eb8F"
}

View file

@ -1 +0,0 @@
{"spacemanager": "0xb194C2E006aEeC94BC8bAa39B8578992134deF80","usergranted": "0x68dc242a7E1Da4d72D5eCE53e055D1E6e44Bb288","tokengranted": "0x9B424DAd142087168ECB8C3809d4B7187d4110ce", "spacenft": "0x17Bb2187E5Dd062Da0dbA3A097943343cABfCD8E", "permission": "0x07e71c115aE5F2929E13940148015284242c3f07", "rolemanager": "0xf941F1f08E0EA9A747E7Eef53C57dc13425aA8af"}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,3 @@
{
"councilnft": "0x5FbDB2315678afecb367f032d93F642f64180aa3"
}

View file

@ -0,0 +1,4 @@
{
"spaceFactory": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
"spaceToken": "0x0165878A594ca255338adfa4d48449f69242Eb8F"
}

View file

@ -1 +1,6 @@
{"spacemanager": "0xdc64a140aa3e981100a9beca4e685f962f0cf6c9","usergranted": "0x0165878a594ca255338adfa4d48449f69242eb8f","tokengranted": "0xa513e6e4b8f2a923d98304ec87f64353c4d5c853"} {
"spacemanager": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
"usergranted": "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707",
"tokengranted": "0x0165878A594ca255338adfa4d48449f69242Eb8F",
"rolemanager": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0"
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,3 @@
{
"zioneer": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82"
}

25
zion/space_contract.go Normal file
View file

@ -0,0 +1,25 @@
package zion
import (
"github.com/ethereum/go-ethereum/common"
"github.com/matrix-org/dendrite/authorization"
)
type SpaceContract interface {
IsSpaceDisabled(spaceNetworkId string) (bool, error)
IsChannelDisabled(
spaceNetworkId string,
channelNetworkId string,
) (bool, error)
IsEntitledToSpace(
spaceNetworkId string,
user common.Address,
permission authorization.Permission,
) (bool, error)
IsEntitledToChannel(
spaceNetworkId string,
channelNetworkId string,
user common.Address,
permission authorization.Permission,
) (bool, error)
}

View file

@ -0,0 +1,125 @@
package zion
import (
_ "embed"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/gologme/log"
"github.com/matrix-org/dendrite/authorization"
"github.com/matrix-org/dendrite/zion/contracts/goerli_space"
"github.com/matrix-org/dendrite/zion/contracts/goerli_space_factory"
)
//go:embed contracts/goerli_space_factory/space-factory.json
var goerliSpaceFactoryJson []byte
type SpaceContractGoerli struct {
ethClient *ethclient.Client
spaceFactory *goerli_space_factory.GoerliSpaceFactory
spaces map[string]*goerli_space.GoerliSpace
}
func NewSpaceContractGoerli(ethClient *ethclient.Client) (*SpaceContractGoerli, error) {
jsonAddress, err := loadSpaceFactoryAddress(goerliSpaceFactoryJson)
if err != nil {
log.Errorf("error parsing goerli space factory contract address %v. Error: %v", jsonAddress, err)
return nil, err
}
address := common.HexToAddress(jsonAddress.SpaceFactory)
spaceFactory, err := goerli_space_factory.NewGoerliSpaceFactory(address, ethClient)
if err != nil {
log.Errorf("error fetching goerli space factory contract with address %v. Error: %v", jsonAddress, err)
return nil, err
}
// no errors.
var spaceContract = &SpaceContractGoerli{
ethClient: ethClient,
spaceFactory: spaceFactory,
spaces: make(map[string]*goerli_space.GoerliSpace),
}
return spaceContract, nil
}
func (za *SpaceContractGoerli) IsEntitledToSpace(
spaceNetworkId string,
user common.Address,
permission authorization.Permission,
) (bool, error) {
// get the space and check if user is entitled.
space, err := za.getSpace(spaceNetworkId)
if err != nil {
return false, err
}
isEntitled, err := space.IsEntitledToSpace(
nil,
user,
permission.String(),
)
if err != nil {
return false, err
}
return isEntitled, nil
}
func (za *SpaceContractGoerli) IsEntitledToChannel(
spaceNetworkId string,
channelNetworkId string,
user common.Address,
permission authorization.Permission,
) (bool, error) {
// get the space and check if user is entitled.
space, err := za.getSpace(spaceNetworkId)
if err != nil {
return false, err
}
// channel entitlement check
isEntitled, err := space.IsEntitledToChannel(
nil,
channelNetworkId,
user,
permission.String(),
)
return isEntitled, err
}
func (za *SpaceContractGoerli) IsSpaceDisabled(spaceNetworkId string) (bool, error) {
space, err := za.getSpace(spaceNetworkId)
if err != nil {
return false, err
}
isDisabled, err := space.Disabled(nil)
return isDisabled, err
}
func (za *SpaceContractGoerli) IsChannelDisabled(spaceNetworkId string, channelNetworkId string) (bool, error) {
space, err := za.getSpace(spaceNetworkId)
if err != nil {
return false, err
}
channelIdHash := NetworkIdToHash(channelNetworkId)
channel, err := space.GetChannelByHash(nil, channelIdHash)
if err != nil {
return false, err
}
return channel.Disabled, err
}
func (za *SpaceContractGoerli) getSpace(networkId string) (*goerli_space.GoerliSpace, error) {
if za.spaces[networkId] == nil {
// convert the networkId to keccak256 spaceIdHash
spaceIdHash := NetworkIdToHash(networkId)
// then use the spaceFactory to fetch the space address
spaceAddress, err := za.spaceFactory.SpaceByHash(nil, spaceIdHash)
if err != nil {
return nil, err
}
// cache the space for future use
space, err := goerli_space.NewGoerliSpace(spaceAddress, za.ethClient)
if err != nil {
return nil, err
}
za.spaces[networkId] = space
}
return za.spaces[networkId], nil
}

View file

@ -0,0 +1,120 @@
package zion
import (
_ "embed"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/matrix-org/dendrite/authorization"
"github.com/matrix-org/dendrite/zion/contracts/localhost_space"
"github.com/matrix-org/dendrite/zion/contracts/localhost_space_factory"
log "github.com/sirupsen/logrus"
)
//go:embed contracts/localhost_space_factory/space-factory.json
var localhostSpaceFactoryJson []byte
type SpaceContractLocalhost struct {
ethClient *ethclient.Client
spaceFactory *localhost_space_factory.LocalhostSpaceFactory
spaces map[string]*localhost_space.LocalhostSpace
}
func NewSpaceContractLocalhost(ethClient *ethclient.Client) (*SpaceContractLocalhost, error) {
jsonAddress, err := loadSpaceFactoryAddress(localhostSpaceFactoryJson)
if err != nil {
log.Errorf("error parsing localhost space factory contract address %v. Error: %v", jsonAddress, err)
return nil, err
}
address := common.HexToAddress(jsonAddress.SpaceFactory)
spaceFactory, err := localhost_space_factory.NewLocalhostSpaceFactory(address, ethClient)
if err != nil {
log.Errorf("error fetching localhost space factory contract with address %v. Error: %v", jsonAddress, err)
return nil, err
}
// no errors.
var spaceContract = &SpaceContractLocalhost{
ethClient: ethClient,
spaceFactory: spaceFactory,
spaces: make(map[string]*localhost_space.LocalhostSpace),
}
return spaceContract, nil
}
func (za *SpaceContractLocalhost) IsEntitledToSpace(
spaceNetworkId string,
user common.Address,
permission authorization.Permission,
) (bool, error) {
// get the space and check if user is entitled.
space, err := za.getSpace(spaceNetworkId)
if err != nil {
return false, err
}
isEntitled, err := space.IsEntitledToSpace(
nil,
user,
permission.String(),
)
return isEntitled, err
}
func (za *SpaceContractLocalhost) IsEntitledToChannel(
spaceNetworkId string,
channelNetworkId string,
user common.Address,
permission authorization.Permission,
) (bool, error) {
// get the space and check if user is entitled.
space, err := za.getSpace(spaceNetworkId)
if err != nil {
return false, err
}
// channel entitlement check
isEntitled, err := space.IsEntitledToChannel(
nil,
channelNetworkId,
user,
permission.String(),
)
return isEntitled, err
}
func (za *SpaceContractLocalhost) IsSpaceDisabled(spaceNetworkId string) (bool, error) {
space, err := za.getSpace(spaceNetworkId)
if err != nil {
return false, err
}
isDisabled, err := space.Disabled(nil)
return isDisabled, err
}
func (za *SpaceContractLocalhost) IsChannelDisabled(spaceNetworkId string, channelNetworkId string) (bool, error) {
space, err := za.getSpace(spaceNetworkId)
if err != nil {
return false, err
}
channelIdHash := NetworkIdToHash(channelNetworkId)
channel, err := space.GetChannelByHash(nil, channelIdHash)
return channel.Disabled, err
}
func (za *SpaceContractLocalhost) getSpace(networkId string) (*localhost_space.LocalhostSpace, error) {
if za.spaces[networkId] == nil {
// convert the networkId to keccak256 spaceIdHash
spaceIdHash := NetworkIdToHash(networkId)
// then use the spaceFactory to fetch the space address
spaceAddress, err := za.spaceFactory.SpaceByHash(nil, spaceIdHash)
if err != nil {
return nil, err
}
// cache the space for future use
space, err := localhost_space.NewLocalhostSpace(spaceAddress, za.ethClient)
if err != nil {
return nil, err
}
za.spaces[networkId] = space
}
return za.spaces[networkId], nil
}

View file

@ -12,19 +12,17 @@ import (
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
) )
type ClientRoomserverStore struct { type Store struct {
rsAPI roomserver.ClientRoomserverAPI roomQuery roomserver.QueryEventsAPI
} }
type SyncRoomserverStore struct { func NewStore(roomQuery roomserver.QueryEventsAPI) Store {
rsAPI roomserver.SyncRoomserverAPI return Store{
roomQuery: roomQuery,
}
} }
type StoreAPI interface { func (s *Store) GetRoomInfo(roomId string, userId UserIdentifier) RoomInfo {
GetRoomInfo(roomId string, userId UserIdentifier) RoomInfo
}
func (s *ClientRoomserverStore) GetRoomInfo(roomId string, userId UserIdentifier) RoomInfo {
result := RoomInfo{ result := RoomInfo{
QueryUserId: userId.MatrixUserId, QueryUserId: userId.MatrixUserId,
SpaceNetworkId: "", SpaceNetworkId: "",
@ -49,7 +47,7 @@ func (s *ClientRoomserverStore) GetRoomInfo(roomId string, userId UserIdentifier
} }
var roomEvents roomserver.QueryCurrentStateResponse var roomEvents roomserver.QueryCurrentStateResponse
err := s.rsAPI.QueryCurrentState(context.Background(), &roomserver.QueryCurrentStateRequest{ err := s.roomQuery.QueryCurrentState(context.Background(), &roomserver.QueryCurrentStateRequest{
RoomID: roomId, RoomID: roomId,
AllowWildcards: true, AllowWildcards: true,
StateTuples: []gomatrixserverlib.StateKeyTuple{ StateTuples: []gomatrixserverlib.StateKeyTuple{
@ -63,9 +61,11 @@ func (s *ClientRoomserverStore) GetRoomInfo(roomId string, userId UserIdentifier
return result return result
} }
//TODO: replace with HydrateRoomInfoWithStateEvents when you have a practical way to flatten roomEvents map //TODO: replace with HydrateRoomInfoWithStateEvents when you have a practical way to flatten roomEvents map
doneSearching := false
for _, state := range roomEvents.StateEvents { for _, state := range roomEvents.StateEvents {
switch state.Type() { switch state.Type() {
case gomatrixserverlib.MRoomCreate: case gomatrixserverlib.MRoomCreate:
// Space is created with no children yet.
var creatorEvent CreatorEvent var creatorEvent CreatorEvent
err := json.Unmarshal(roomEvents.StateEvents[createTuple].Content(), &creatorEvent) err := json.Unmarshal(roomEvents.StateEvents[createTuple].Content(), &creatorEvent)
result.IsOwner = strings.HasPrefix( result.IsOwner = strings.HasPrefix(
@ -77,96 +77,21 @@ func (s *ClientRoomserverStore) GetRoomInfo(roomId string, userId UserIdentifier
result.SpaceNetworkId = roomId result.SpaceNetworkId = roomId
} }
case ConstSpaceChildEventType: case ConstSpaceChildEventType:
// Space is created and has one or more children.
result.RoomType = Space result.RoomType = Space
result.SpaceNetworkId = roomId result.SpaceNetworkId = roomId
doneSearching = true
case ConstSpaceParentEventType: case ConstSpaceParentEventType:
// Channel is created and has a reference to the parent.
result.RoomType = Channel result.RoomType = Channel
result.SpaceNetworkId = *state.StateKey() result.SpaceNetworkId = *state.StateKey()
result.ChannelNetworkId = roomId result.ChannelNetworkId = roomId
doneSearching = true
}
if doneSearching {
break
} }
} }
return result 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,
}
}

18
zion/util_converters.go Normal file
View file

@ -0,0 +1,18 @@
package zion
import (
"github.com/ethereum/go-ethereum/crypto"
)
func NetworkIdToHash(networkId string) [32]byte {
hash := crypto.Keccak256Hash([]byte(networkId))
return sliceBytesToBytes32(hash.Bytes())
}
func sliceBytesToBytes32(bytes []byte) [32]byte {
bytes32 := [32]byte{}
for i := 0; i < 32; i++ {
bytes32[i] = bytes[i]
}
return bytes32
}

View file

@ -2,84 +2,71 @@ package zion
import ( import (
_ "embed" _ "embed"
"errors"
"fmt"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/matrix-org/dendrite/authorization" "github.com/matrix-org/dendrite/authorization"
roomserver "github.com/matrix-org/dendrite/roomserver/api" roomserver "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/dendrite/setup/config" "github.com/matrix-org/dendrite/setup/config"
zion_goerli "github.com/matrix-org/dendrite/zion/contracts/zion_goerli"
zion_localhost "github.com/matrix-org/dendrite/zion/contracts/zion_localhost"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
//go:embed contracts/zion_localhost/space-manager.json var ErrSpaceDisabled = errors.New("space disabled")
var localhostJson []byte var ErrChannelDisabled = errors.New("channel disabled")
//go:embed contracts/zion_goerli/space-manager.json
var goerliJson []byte
type ZionAuthorization struct { type ZionAuthorization struct {
store StoreAPI
spaceManagerLocalhost *zion_localhost.ZionSpaceManagerLocalhost
spaceManagerGoerli *zion_goerli.ZionSpaceManagerGoerli
chainId int chainId int
} ethClient *ethclient.Client
type ClientRoomserverStruct struct { store Store
roomserver.ClientRoomserverAPI spaceContract SpaceContract
} }
type SyncRoomserverStruct struct { func NewZionAuthorization(cfg *config.ClientAPI, roomQueryAPI roomserver.QueryEventsAPI) (authorization.Authorization, error) {
roomserver.SyncRoomserverAPI // create the authorization states
} store := NewStore(roomQueryAPI)
chainId := cfg.PublicKeyAuthentication.Ethereum.GetChainID()
type RoomserverStoreAPI interface { // initialise the eth client.
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 == "" { if cfg.PublicKeyAuthentication.Ethereum.NetworkUrl == "" {
log.Errorf("No blockchain network url specified in config\n") log.Errorf("No blockchain network url specified in config\n")
return nil, nil return nil, nil
} }
ethClient, err := GetEthClient(cfg.PublicKeyAuthentication.Ethereum.NetworkUrl)
if err != nil {
log.Errorf("Cannot connect to eth client %v\n", cfg.PublicKeyAuthentication.Ethereum.NetworkUrl)
return nil, err
}
var auth ZionAuthorization za := &ZionAuthorization{
chainId: chainId,
auth.chainId = cfg.PublicKeyAuthentication.Ethereum.GetChainID() ethClient: ethClient,
auth.store = rsAPI.NewRoomserverStore() store: store,
}
switch auth.chainId { switch za.chainId {
case 1337, 31337: case 1337, 31337:
localhost, err := newZionSpaceManagerLocalhost(cfg.PublicKeyAuthentication.Ethereum.NetworkUrl) localhost, err := NewSpaceContractLocalhost(za.ethClient)
if err != nil { if err != nil {
log.Errorln("error instantiating ZionSpaceManagerLocalhost", err) log.Errorf("error instantiating SpaceContractLocalhost. Error: %v", err)
return nil, err
} }
auth.spaceManagerLocalhost = localhost za.spaceContract = localhost
case 5: case 5:
goerli, err := newZionSpaceManagerGoerli(cfg.PublicKeyAuthentication.Ethereum.NetworkUrl) goerli, err := NewSpaceContractGoerli(za.ethClient)
if err != nil { if err != nil {
log.Errorln("error instantiating ZionSpaceManagerGoerli", err) log.Errorf("error instantiating SpaceContractGoerli. Error: %v", err)
return nil, err
} }
auth.spaceManagerGoerli = goerli za.spaceContract = goerli
default: default:
log.Errorf("Unsupported chain id: %d\n", auth.chainId) errMsg := fmt.Sprintf("unsupported chain id: %d", za.chainId)
log.Error(errMsg)
return nil, errors.New(errMsg)
} }
// no errors.
return &auth, nil return za, nil
} }
func (za *ZionAuthorization) IsAllowed(args authorization.AuthorizationArgs) (bool, error) { func (za *ZionAuthorization) IsAllowed(args authorization.AuthorizationArgs) (bool, error) {
@ -93,112 +80,54 @@ func (za *ZionAuthorization) IsAllowed(args authorization.AuthorizationArgs) (bo
return true, nil return true, nil
} }
switch za.chainId { // Check if user is entitled to space / channel.
case 1337, 31337: switch roomInfo.RoomType {
return za.isAllowedLocalhost(roomInfo, userIdentifier.AccountAddress, args.Permission) case Space:
case 5: isEntitled, err := za.isEntitledToSpace(roomInfo, userIdentifier.AccountAddress, args.Permission)
return za.isAllowedGoerli(roomInfo, userIdentifier.AccountAddress, args.Permission) return isEntitled, err
case Channel:
isEntitled, err := za.isEntitledToChannel(roomInfo, userIdentifier.AccountAddress, args.Permission)
return isEntitled, err
default: default:
log.Errorf("Unsupported chain id: %d", userIdentifier.ChainId) errMsg := fmt.Sprintf("unhandled room type: %s", roomInfo.RoomType)
log.Error("IsAllowed", errMsg)
return false, errors.New(errMsg)
}
} }
return false, nil func (za *ZionAuthorization) isEntitledToSpace(roomInfo RoomInfo, user common.Address, permission authorization.Permission) (bool, error) {
// space disabled check.
isDisabled, err := za.spaceContract.IsSpaceDisabled(roomInfo.SpaceNetworkId)
if err != nil {
return false, err
} else if isDisabled {
return false, ErrSpaceDisabled
} }
func (za *ZionAuthorization) isAllowedLocalhost( // space entitlement check.
roomInfo RoomInfo, isEntitled, err := za.spaceContract.IsEntitledToSpace(
user common.Address, roomInfo.SpaceNetworkId,
permission authorization.Permission, user,
) (bool, error) { permission,
if za.spaceManagerLocalhost != nil { )
permission := zion_localhost.DataTypesPermission{ return isEntitled, err
Name: permission.String(),
} }
isEntitled, err := za.spaceManagerLocalhost.IsEntitled( func (za *ZionAuthorization) isEntitledToChannel(roomInfo RoomInfo, user common.Address, permission authorization.Permission) (bool, error) {
nil, // channel disabled check.
isDisabled, err := za.spaceContract.IsChannelDisabled(roomInfo.SpaceNetworkId, roomInfo.ChannelNetworkId)
if err != nil {
return false, err
} else if isDisabled {
return false, ErrSpaceDisabled
}
// channel entitlement check.
isEntitled, err := za.spaceContract.IsEntitledToChannel(
roomInfo.SpaceNetworkId, roomInfo.SpaceNetworkId,
roomInfo.ChannelNetworkId, roomInfo.ChannelNetworkId,
user, user,
permission, permission,
) )
return isEntitled, err
if err != nil {
return false, err
}
return isEntitled, nil
}
return false, nil
}
func (za *ZionAuthorization) isAllowedGoerli(
roomInfo RoomInfo,
user common.Address,
permission authorization.Permission,
) (bool, error) {
if za.spaceManagerGoerli != nil {
permission := zion_goerli.DataTypesPermission{
Name: permission.String(),
}
isEntitled, err := za.spaceManagerGoerli.IsEntitled(
nil,
roomInfo.SpaceNetworkId,
roomInfo.ChannelNetworkId,
user,
permission,
)
if err != nil {
return false, err
}
return isEntitled, nil
}
return false, nil
}
func newZionSpaceManagerLocalhost(endpointUrl string) (*zion_localhost.ZionSpaceManagerLocalhost, error) {
addresses, err := loadSpaceManagerAddresses(localhostJson)
if err != nil {
return nil, err
}
address := common.HexToAddress(addresses.Spacemanager)
client, err := GetEthClient(endpointUrl)
if err != nil {
return nil, err
}
spaceManager, err := zion_localhost.NewZionSpaceManagerLocalhost(address, client)
if err != nil {
return nil, err
}
return spaceManager, nil
}
func newZionSpaceManagerGoerli(endpointUrl string) (*zion_goerli.ZionSpaceManagerGoerli, error) {
addresses, err := loadSpaceManagerAddresses(goerliJson)
if err != nil {
return nil, err
}
address := common.HexToAddress((addresses.Spacemanager))
client, err := GetEthClient(endpointUrl)
if err != nil {
return nil, err
}
spaceManager, err := zion_goerli.NewZionSpaceManagerGoerli(address, client)
if err != nil {
return nil, err
}
return spaceManager, nil
} }