dendrite/zion/zion_authorization.go
2022-11-01 18:07:15 -07:00

205 lines
4.9 KiB
Go

package zion
import (
_ "embed"
"github.com/ethereum/go-ethereum/common"
"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/goerli/zion_goerli"
zion_localhost "github.com/matrix-org/dendrite/zion/contracts/localhost/zion_localhost"
log "github.com/sirupsen/logrus"
)
//go:embed contracts/localhost/addresses/space-manager.json
var localhostJson []byte
//go:embed contracts/goerli/addresses/space-manager.json
var goerliJson []byte
type ZionAuthorization struct {
store StoreAPI
spaceManagerLocalhost *zion_localhost.ZionSpaceManagerLocalhost
spaceManagerGoerli *zion_goerli.ZionSpaceManagerGoerli
chainId int
}
type ClientRoomserverStruct struct {
roomserver.ClientRoomserverAPI
}
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
}
var auth ZionAuthorization
auth.chainId = cfg.PublicKeyAuthentication.Ethereum.GetChainID()
auth.store = rsAPI.NewRoomserverStore()
switch auth.chainId {
case 1337, 31337:
localhost, err := newZionSpaceManagerLocalhost(cfg.PublicKeyAuthentication.Ethereum.NetworkUrl)
if err != nil {
log.Errorln("error instantiating ZionSpaceManagerLocalhost", err)
}
auth.spaceManagerLocalhost = localhost
case 5:
goerli, err := newZionSpaceManagerGoerli(cfg.PublicKeyAuthentication.Ethereum.NetworkUrl)
if err != nil {
log.Errorln("error instantiating ZionSpaceManagerGoerli", err)
}
auth.spaceManagerGoerli = goerli
default:
log.Errorf("Unsupported chain id: %d\n", auth.chainId)
}
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:
return za.isAllowedLocalhost(roomInfo, userIdentifier.AccountAddress, args.Permission)
case 5:
return za.isAllowedGoerli(roomInfo, userIdentifier.AccountAddress, args.Permission)
default:
log.Errorf("Unsupported chain id: %d", userIdentifier.ChainId)
}
return false, nil
}
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,
)
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
}