diff --git a/zion/contracts/localhost_space_factory/space-factory.json b/zion/contracts/localhost_space_factory/space-factory.json index 847ee17dc..12484a976 100644 --- a/zion/contracts/localhost_space_factory/space-factory.json +++ b/zion/contracts/localhost_space_factory/space-factory.json @@ -1,2 +1,3 @@ - -{"spaceFactory": "0x5eb3bc0a489c5a8288765d2336659ebca68fcd00"} +{ + "spaceFactory": "0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1" +} \ No newline at end of file diff --git a/zion/contracts/zion_localhost/council.json b/zion/contracts/zion_localhost/council.json index 5ed899d1c..fee736d40 100644 --- a/zion/contracts/zion_localhost/council.json +++ b/zion/contracts/zion_localhost/council.json @@ -1 +1,3 @@ -{"councilnft": "0x9a676e781a523b5d0c0e43731313a708cb607508"} \ No newline at end of file +{ + "councilnft": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e" +} \ No newline at end of file diff --git a/zion/contracts/zion_localhost/space-factory.json b/zion/contracts/zion_localhost/space-factory.json new file mode 100644 index 000000000..12484a976 --- /dev/null +++ b/zion/contracts/zion_localhost/space-factory.json @@ -0,0 +1,3 @@ +{ + "spaceFactory": "0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1" +} \ No newline at end of file diff --git a/zion/contracts/zion_localhost/space-manager.json b/zion/contracts/zion_localhost/space-manager.json index 0f79f43e8..d2cca5c79 100644 --- a/zion/contracts/zion_localhost/space-manager.json +++ b/zion/contracts/zion_localhost/space-manager.json @@ -1 +1,6 @@ -{"spacemanager": "0xa85233c63b9ee964add6f2cffe00fd84eb32338f","usergranted": "0x7a2088a1bfc9d81c55368ae168c2c02570cb814f","tokengranted": "0x09635f643e140090a9a8dcd712ed6285858cebef","rolemanager": "0x322813fd9a801c5507c9de605d63cea4f2ce6c44"} \ No newline at end of file +{ + "spacemanager": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9", + "rolemanager": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0", + "tokengranted": "0x0165878A594ca255338adfa4d48449f69242Eb8F", + "usergranted": "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707" +} \ No newline at end of file diff --git a/zion/util_converters.go b/zion/util_converters.go new file mode 100644 index 000000000..5d4abb950 --- /dev/null +++ b/zion/util_converters.go @@ -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 +} diff --git a/zion/web3_util.go b/zion/util_web3.go similarity index 100% rename from zion/web3_util.go rename to zion/util_web3.go diff --git a/zion/zion_authorization.go b/zion/zion_authorization.go index 169f15d73..41178aadc 100644 --- a/zion/zion_authorization.go +++ b/zion/zion_authorization.go @@ -5,297 +5,58 @@ import ( "errors" "fmt" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" "github.com/matrix-org/dendrite/authorization" roomserver "github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/dendrite/setup/config" - zion_goerli "github.com/matrix-org/dendrite/zion/contracts/zion_goerli" // V1 smart contract - zion_localhost "github.com/matrix-org/dendrite/zion/contracts/zion_localhost" // v1 smart contract - //goerli_space_factory "github.com/matrix-org/dendrite/zion/contracts/goerli_space_factory" // v2 smart contract - //goerli_space "github.com/matrix-org/dendrite/zion/contracts/goerli_space" // v2 smart contract - // v2 smart contract - localhost_space_factory "github.com/matrix-org/dendrite/zion/contracts/localhost_space_factory" // v2 smart contract log "github.com/sirupsen/logrus" ) -// V1 smart contract addresses -// -//go:embed contracts/zion_localhost/space-manager.json -var localhostSpaceManagerJson []byte +type ContractVersion uint8 -//go:embed contracts/zion_goerli/space-manager.json -var goerliSpaceManagerJson []byte - -// V2 smart contract addresses -// -//go:embed contracts/localhost_space_factory/space-factory.json -var localhostSpaceFactoryJson []byte - -// var goerliSpaceFactoryJson []byte +const ( + v1 ContractVersion = 1 + v2 ContractVersion = 2 +) var ErrSpaceDisabled = errors.New("space disabled") var ErrChannelDisabled = errors.New("channel disabled") -type ZionAuthorization struct { - chainId int - ethClient *ethclient.Client - spaceManagerLocalhost *zion_localhost.ZionSpaceManagerLocalhost // v1 smart contract. Deprecating. - spaceManagerGoerli *zion_goerli.ZionSpaceManagerGoerli // v1 smart contract. Deprecating. - localhostSpaceFactory *localhost_space_factory.LocalhostSpaceFactory // v2 localhost SpaceFactory smart contract - //localhostSpaces map[string]localhost_space.LocalhostSpace // v2 localhost map from networkId to a space contract - //goerliSpaceFactory *goerli_space_factory.LocalhostSpaceFactory // v2 goerli SpaceFactory smart contract - //goerliSpaces map[string]goerli_space.LocalhostSpace // v2 goerli map from networkId to a space contract - store Store -} - func NewZionAuthorization(cfg *config.ClientAPI, roomQueryAPI roomserver.QueryEventsAPI) (authorization.Authorization, error) { + // create the authorization states + store := NewStore(roomQueryAPI) + chainId := cfg.PublicKeyAuthentication.Ethereum.GetChainID() + contractVersion := v1 // default + if cfg.PublicKeyAuthentication.Ethereum.ContractVersion == "v2" { + contractVersion = v2 + } + + // initialise the eth client. if cfg.PublicKeyAuthentication.Ethereum.NetworkUrl == "" { log.Errorf("No blockchain network url specified in config\n") 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 } - auth := ZionAuthorization{ - store: NewStore(roomQueryAPI), - chainId: cfg.PublicKeyAuthentication.Ethereum.GetChainID(), - ethClient: ethClient, - } - - if cfg.PublicKeyAuthentication.Ethereum.ContractVersion == "v2" { - err := auth.initializeContractsV2() - if err != nil { - return nil, err - } - } else { - err := auth.initializeContractsV1() - if err != nil { - return nil, err - } - } - - // no errors. return the auth object. - return &auth, nil -} - -func (za *ZionAuthorization) IsAllowed(args authorization.AuthorizationArgs) (bool, error) { - userIdentifier := CreateUserIdentifier(args.UserId) - - // Find out if roomId is a space or a channel. - roomInfo := za.store.GetRoomInfo(args.RoomId, userIdentifier) - - // Owner of the space / channel is always allowed to proceed. - if roomInfo.IsOwner { - return true, nil - } - - switch za.chainId { - case 1337, 31337: - // Check if space / channel is disabled. - disabled, err := za.isSpaceChannelDisabledLocalhost(roomInfo) - if disabled { - return false, ErrSpaceDisabled - } else if err != nil { - return false, err - } - 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) - if disabled { - return false, ErrChannelDisabled - } else if err != nil { - return false, err - } - return za.isAllowedGoerli(roomInfo, userIdentifier.AccountAddress, args.Permission) - default: - log.Errorf("Unsupported chain id: %d", userIdentifier.ChainId) - } - - return false, nil -} - -func newZionSpaceManagerLocalhost(ethClient *ethclient.Client) (*zion_localhost.ZionSpaceManagerLocalhost, error) { - jsonAddresses, err := loadSpaceManagerAddresses(localhostSpaceManagerJson) - if err != nil { - return nil, err - } - - address := common.HexToAddress(jsonAddresses.Spacemanager) - - spaceManager, err := zion_localhost.NewZionSpaceManagerLocalhost(address, ethClient) - if err != nil { - return nil, err - } - - return spaceManager, nil -} - -func newZionSpaceManagerGoerli(ethClient *ethclient.Client) (*zion_goerli.ZionSpaceManagerGoerli, error) { - addresses, err := loadSpaceManagerAddresses(goerliSpaceManagerJson) - if err != nil { - return nil, err - } - - address := common.HexToAddress(addresses.Spacemanager) - - spaceManager, err := zion_goerli.NewZionSpaceManagerGoerli(address, ethClient) - if err != nil { - return nil, err - } - - return spaceManager, nil -} - -func newSpaceFactoryLocalhost(ethClient *ethclient.Client) (*localhost_space_factory.LocalhostSpaceFactory, error) { - jsonAddress, err := loadSpaceFactoryAddress(localhostSpaceFactoryJson) - if err != nil { - return nil, err - } - - address := common.HexToAddress(jsonAddress.SpaceFactory) - - spaceFactory, err := localhost_space_factory.NewLocalhostSpaceFactory(address, ethClient) - if err != nil { - return nil, err - } - - return spaceFactory, nil -} - -func (za *ZionAuthorization) initializeContractsV1() error { - switch za.chainId { - case 1337, 31337: - localhost, err := newZionSpaceManagerLocalhost(za.ethClient) - if err != nil { - log.Errorln("error instantiating ZionSpaceManagerLocalhost", err) - return err - } - za.spaceManagerLocalhost = localhost - - case 5: - goerli, err := newZionSpaceManagerGoerli(za.ethClient) - if err != nil { - log.Errorln("error instantiating ZionSpaceManagerGoerli", err) - return err - } - za.spaceManagerGoerli = goerli - default: - errMsg := fmt.Sprintf("Unsupported chain id: %d", za.chainId) - log.Error(errMsg) - return errors.New(errMsg) - } - // no errors. - return nil -} - -func (za *ZionAuthorization) initializeContractsV2() error { - switch za.chainId { - case 1337, 31337: - localhost, err := newSpaceFactoryLocalhost(za.ethClient) - if err != nil { - log.Errorln("error instantiating ZionSpaceManagerLocalhost", err) - return err - } - za.localhostSpaceFactory = localhost - default: - errMsg := fmt.Sprintf("Unsupported chain id: %d", za.chainId) - log.Error(errMsg) - return errors.New(errMsg) - } - // no errors. - return nil -} - -func (za *ZionAuthorization) isSpaceChannelDisabledLocalhost(roomInfo RoomInfo) (bool, error) { - if za.spaceManagerLocalhost == nil { - return false, errors.New("error fetching space manager contract") - } - switch roomInfo.ChannelNetworkId { - case "": - spInfo, err := za.spaceManagerLocalhost.GetSpaceInfoBySpaceId(nil, roomInfo.SpaceNetworkId) - return spInfo.Disabled, err - default: - chInfo, err := za.spaceManagerLocalhost.GetChannelInfoByChannelId(nil, roomInfo.SpaceNetworkId, roomInfo.ChannelNetworkId) - return chInfo.Disabled, err - } - -} - -func (za *ZionAuthorization) isSpaceChannelDisabledGoerli(roomInfo RoomInfo) (bool, error) { - if za.spaceManagerGoerli == nil { - return false, errors.New("error fetching space manager contract") - } - switch roomInfo.ChannelNetworkId { - case "": - spInfo, err := za.spaceManagerGoerli.GetSpaceInfoBySpaceId(nil, roomInfo.SpaceNetworkId) - return spInfo.Disabled, err - default: - chInfo, err := za.spaceManagerGoerli.GetChannelInfoByChannelId(nil, roomInfo.SpaceNetworkId, roomInfo.ChannelNetworkId) - return chInfo.Disabled, err - } - -} - -func (za *ZionAuthorization) isAllowedLocalhost( - roomInfo RoomInfo, - user common.Address, - permission authorization.Permission, -) (bool, error) { - if za.spaceManagerLocalhost != nil { - permission := zion_localhost.DataTypesPermission{ - Name: permission.String(), - } - - isEntitled, err := za.spaceManagerLocalhost.IsEntitled( - nil, - roomInfo.SpaceNetworkId, - roomInfo.ChannelNetworkId, - user, - permission, + switch contractVersion { + case v1: + return NewZionAuthorizationV1( + chainId, + ethClient, + store, ) - - 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, + case v2: + return NewZionAuthorizationV2( + chainId, + ethClient, + store, ) - - if err != nil { - return false, err - } - - return isEntitled, nil + default: + errMsg := fmt.Sprintf("Unsupported contract version: %d", contractVersion) + return nil, errors.New(errMsg) } - - return false, nil } diff --git a/zion/zion_authorization_v1.go b/zion/zion_authorization_v1.go new file mode 100644 index 000000000..1db2423af --- /dev/null +++ b/zion/zion_authorization_v1.go @@ -0,0 +1,202 @@ +package zion + +import ( + _ "embed" + "errors" + "fmt" + + "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/zion_goerli" // V1 smart contract + "github.com/matrix-org/dendrite/zion/contracts/zion_localhost" // v1 smart contract + log "github.com/sirupsen/logrus" +) + +// v1 smart contract addresses +// +//go:embed contracts/zion_localhost/space-manager.json +var localhostSpaceManagerJson []byte + +//go:embed contracts/zion_goerli/space-manager.json +var goerliSpaceManagerJson []byte + +// v1 smart contracts. Deprecating. +type ZionAuthorizationV1 struct { + chainId int + ethClient *ethclient.Client + spaceManagerLocalhost *zion_localhost.ZionSpaceManagerLocalhost + spaceManagerGoerli *zion_goerli.ZionSpaceManagerGoerli + store Store +} + +func NewZionAuthorizationV1(chainId int, ethClient *ethclient.Client, store Store) (authorization.Authorization, error) { + za := &ZionAuthorizationV1{ + chainId: chainId, + ethClient: ethClient, + store: store, + } + switch za.chainId { + case 1337, 31337: + localhost, err := newZionSpaceManagerLocalhost(za.ethClient) + if err != nil { + log.Errorln("error instantiating ZionSpaceManagerLocalhost", err) + return nil, err + } + za.spaceManagerLocalhost = localhost + case 5: + goerli, err := newZionSpaceManagerGoerli(za.ethClient) + if err != nil { + log.Errorln("error instantiating ZionSpaceManagerGoerli", err) + return nil, err + } + za.spaceManagerGoerli = goerli + default: + errMsg := fmt.Sprintf("Unsupported chain id: %d", za.chainId) + log.Error(errMsg) + return nil, errors.New(errMsg) + } + // no errors. + return za, nil +} + +func newZionSpaceManagerLocalhost(ethClient *ethclient.Client) (*zion_localhost.ZionSpaceManagerLocalhost, error) { + jsonAddresses, err := loadSpaceManagerAddresses(localhostSpaceManagerJson) + if err != nil { + return nil, err + } + address := common.HexToAddress(jsonAddresses.Spacemanager) + spaceManager, err := zion_localhost.NewZionSpaceManagerLocalhost(address, ethClient) + if err != nil { + return nil, err + } + return spaceManager, nil +} + +func newZionSpaceManagerGoerli(ethClient *ethclient.Client) (*zion_goerli.ZionSpaceManagerGoerli, error) { + addresses, err := loadSpaceManagerAddresses(goerliSpaceManagerJson) + if err != nil { + return nil, err + } + address := common.HexToAddress(addresses.Spacemanager) + spaceManager, err := zion_goerli.NewZionSpaceManagerGoerli(address, ethClient) + if err != nil { + return nil, err + } + return spaceManager, nil +} + +func (za *ZionAuthorizationV1) IsAllowed(args authorization.AuthorizationArgs) (bool, error) { + userIdentifier := CreateUserIdentifier(args.UserId) + + // Find out if roomId is a space or a channel. + roomInfo := za.store.GetRoomInfo(args.RoomId, userIdentifier) + + // Owner of the space / channel is always allowed to proceed. + if roomInfo.IsOwner { + return true, nil + } + + switch za.chainId { + case 1337, 31337: + // Check if space / channel is disabled. + disabled, err := za.isSpaceChannelDisabledLocalhost(roomInfo) + if disabled { + return false, ErrSpaceDisabled + } else if err != nil { + return false, err + } + 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) + if disabled { + return false, ErrChannelDisabled + } else if err != nil { + return false, err + } + return za.isAllowedGoerli(roomInfo, userIdentifier.AccountAddress, args.Permission) + default: + errMsg := fmt.Sprintf("Unsupported chain id: %d", za.chainId) + return false, errors.New(errMsg) + } +} + +func (za *ZionAuthorizationV1) isSpaceChannelDisabledLocalhost(roomInfo RoomInfo) (bool, error) { + if za.spaceManagerLocalhost == nil { + return false, errors.New("error fetching localhost space manager contract") + } + switch roomInfo.ChannelNetworkId { + case "": + spInfo, err := za.spaceManagerLocalhost.GetSpaceInfoBySpaceId(nil, roomInfo.SpaceNetworkId) + return spInfo.Disabled, err + default: + chInfo, err := za.spaceManagerLocalhost.GetChannelInfoByChannelId(nil, roomInfo.SpaceNetworkId, roomInfo.ChannelNetworkId) + return chInfo.Disabled, err + } +} + +func (za *ZionAuthorizationV1) isSpaceChannelDisabledGoerli(roomInfo RoomInfo) (bool, error) { + if za.spaceManagerGoerli == nil { + return false, errors.New("error fetching goerli space manager contract") + } + switch roomInfo.ChannelNetworkId { + case "": + spInfo, err := za.spaceManagerGoerli.GetSpaceInfoBySpaceId(nil, roomInfo.SpaceNetworkId) + return spInfo.Disabled, err + default: + chInfo, err := za.spaceManagerGoerli.GetChannelInfoByChannelId(nil, roomInfo.SpaceNetworkId, roomInfo.ChannelNetworkId) + return chInfo.Disabled, err + } +} + +func (za *ZionAuthorizationV1) isAllowedLocalhost( + roomInfo RoomInfo, + user common.Address, + _permission authorization.Permission, +) (bool, error) { + if za.spaceManagerLocalhost == nil { + return false, errors.New("error fetching localhost space manager contract") + } + + permission := zion_localhost.DataTypesPermission{ + Name: _permission.String(), + } + isEntitled, err := za.spaceManagerLocalhost.IsEntitled( + nil, + roomInfo.SpaceNetworkId, + roomInfo.ChannelNetworkId, + user, + permission, + ) + if err != nil { + return false, err + } + return isEntitled, nil +} + +func (za *ZionAuthorizationV1) isAllowedGoerli( + roomInfo RoomInfo, + user common.Address, + _permission authorization.Permission, +) (bool, error) { + if za.spaceManagerGoerli == nil { + return false, errors.New("error fetching goerli space manager contract") + } + + 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 +} diff --git a/zion/zion_authorization_v2.go b/zion/zion_authorization_v2.go new file mode 100644 index 000000000..f3ae0d6c9 --- /dev/null +++ b/zion/zion_authorization_v2.go @@ -0,0 +1,186 @@ +package zion + +import ( + _ "embed" + "errors" + "fmt" + + "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" + + //goerli_space_factory "github.com/matrix-org/dendrite/zion/contracts/goerli_space_factory" // v2 smart contract + //goerli_space "github.com/matrix-org/dendrite/zion/contracts/goerli_space" // v2 smart contract + + log "github.com/sirupsen/logrus" +) + +// v2 smart contract addresses +// +//go:embed contracts/localhost_space_factory/space-factory.json +var localhostSpaceFactoryJson []byte + +// var goerliSpaceFactoryJson []byte + +// v2 smart contracts +type ZionAuthorizationV2 struct { + chainId int + ethClient *ethclient.Client + store Store + localhostSpaceFactory *localhost_space_factory.LocalhostSpaceFactory + localhostSpaces map[string]*localhost_space.LocalhostSpace + //goerliSpaceFactory *goerli_space_factory.LocalhostSpaceFactory + //goerliSpaces map[string]*goerli_space.LocalhostSpace +} + +func NewZionAuthorizationV2(chainId int, ethClient *ethclient.Client, store Store) (authorization.Authorization, error) { + za := &ZionAuthorizationV2{ + chainId: chainId, + ethClient: ethClient, + store: store, + } + switch za.chainId { + case 1337, 31337: + localhost, err := newSpaceFactoryLocalhost(za.ethClient) + if err != nil { + log.Errorln("error instantiating ZionSpaceManagerLocalhost", err) + return nil, err + } + za.localhostSpaceFactory = localhost + default: + errMsg := fmt.Sprintf("Unsupported chain id: %d", za.chainId) + log.Error(errMsg) + return nil, errors.New(errMsg) + } + // no errors. + return za, nil +} + +func newSpaceFactoryLocalhost(ethClient *ethclient.Client) (*localhost_space_factory.LocalhostSpaceFactory, error) { + jsonAddress, err := loadSpaceFactoryAddress(localhostSpaceFactoryJson) + if err != nil { + return nil, err + } + address := common.HexToAddress(jsonAddress.SpaceFactory) + spaceFactory, err := localhost_space_factory.NewLocalhostSpaceFactory(address, ethClient) + if err != nil { + return nil, err + } + return spaceFactory, nil +} + +func (za *ZionAuthorizationV2) IsAllowed(args authorization.AuthorizationArgs) (bool, error) { + userIdentifier := CreateUserIdentifier(args.UserId) + + // Find out if roomId is a space or a channel. + roomInfo := za.store.GetRoomInfo(args.RoomId, userIdentifier) + + // Owner of the space / channel is always allowed to proceed. + if roomInfo.IsOwner { + return true, nil + } + + switch za.chainId { + case 1337, 31337: + isAllowed, err := za.isAllowedLocalhost(roomInfo, userIdentifier.AccountAddress, args.Permission) + return isAllowed, err + default: + errMsg := fmt.Sprintf("Unsupported chain id: %d", za.chainId) + return false, errors.New(errMsg) + } +} + +func (za *ZionAuthorizationV2) getSpaceLocalhost(networkId string) (*localhost_space.LocalhostSpace, error) { + space := za.localhostSpaces[networkId] + if space == nil { + // convert the networkId to keccak256 spaceIdHash + spaceIdHash := NetworkIdToHash(networkId) + // then use the spaceFactory to fetch the space address + spaceAddress, err := za.localhostSpaceFactory.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.localhostSpaces[networkId] = space + } + return space, nil +} + +func (za *ZionAuthorizationV2) isSpaceChannelDisabledLocalhost(roomInfo RoomInfo) (bool, error) { + if za.localhostSpaceFactory == nil { + return false, errors.New("error fetching localhost space factory contract") + } + + space, err := za.getSpaceLocalhost(roomInfo.SpaceNetworkId) + if err != nil { + return false, err + } + + switch roomInfo.ChannelNetworkId { + case "": + isDisabled, err := space.Disabled(nil) + return isDisabled, err + default: + channelIdHash := NetworkIdToHash(roomInfo.ChannelNetworkId) + channel, err := space.GetChannelByHash(nil, channelIdHash) + return channel.Disabled, err + } +} + +func (za *ZionAuthorizationV2) isAllowedLocalhost( + roomInfo RoomInfo, + user common.Address, + permission authorization.Permission, +) (bool, error) { + if za.localhostSpaceFactory != nil { + return false, errors.New("localhost SpaceFactory is not initialised") + } + + // check if space / channel is disabled. + disabled, err := za.isSpaceChannelDisabledLocalhost(roomInfo) + if disabled { + return false, ErrSpaceDisabled + } else if err != nil { + return false, err + } + + // get the space and check if user is entitled. + space, err := za.getSpaceLocalhost(roomInfo.SpaceNetworkId) + if err != nil { + return false, err + } + + isEntitled := false // default to false always. + switch roomInfo.ChannelNetworkId { + case "": + // ChannelNetworkId is empty. Space entitlement check. + isEntitled, err = space.IsEntitled( + nil, + user, + permission.String(), + ) + if err != nil { + return false, err + } + default: + // channel entitlement check + isEntitled, err = space.IsEntitled0( + nil, + roomInfo.ChannelNetworkId, + user, + permission.String(), + ) + if err != nil { + return false, err + } + } + + return isEntitled, nil +}