mirror of
https://github.com/matrix-org/dendrite.git
synced 2026-01-16 18:43:10 -06:00
Figure out space vs channel from roomid (#43)
* pass in roomserver API so that we have access to the db * interface to get db info for spaceid and channelid * determine space or channel by querying the room db * Add authorization check to the JOIN endpoint * fix lint errors
This commit is contained in:
parent
c5a753d6e2
commit
18db428c23
|
|
@ -2,15 +2,16 @@ package authorization
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"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/zion"
|
"github.com/matrix-org/dendrite/zion"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewAuthorization(cfg *config.ClientAPI) authorization.Authorization {
|
func NewAuthorization(cfg *config.ClientAPI, rsAPI roomserver.ClientRoomserverAPI) authorization.Authorization {
|
||||||
// Load authorization manager for Zion
|
// Load authorization manager for Zion
|
||||||
if cfg.PublicKeyAuthentication.Ethereum.EnableAuthz {
|
if cfg.PublicKeyAuthentication.Ethereum.EnableAuthz {
|
||||||
auth, err := zion.NewZionAuthorization()
|
auth, err := zion.NewZionAuthorization(rsAPI)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln("Failed to initialise Zion authorization manager. Using default.", err)
|
log.Errorln("Failed to initialise Zion authorization manager. Using default.", err)
|
||||||
|
|
|
||||||
|
|
@ -76,8 +76,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)
|
||||||
authorization := clientApiAuthz.NewAuthorization(cfg)
|
authorization := clientApiAuthz.NewAuthorization(cfg, rsAPI)
|
||||||
_ = authorization // todo: use this in httputil.MakeAuthAPI
|
|
||||||
|
|
||||||
unstableFeatures := map[string]bool{
|
unstableFeatures := map[string]bool{
|
||||||
"org.matrix.e2e_cross_signing": true,
|
"org.matrix.e2e_cross_signing": true,
|
||||||
|
|
@ -262,7 +261,12 @@ func Setup(
|
||||||
Permission: authz.PermissionRead,
|
Permission: authz.PermissionRead,
|
||||||
})
|
})
|
||||||
|
|
||||||
logrus.Debugf("/join/%s isAllowed = %t", vars["roomIDOrAlias"], isAllowed)
|
if !isAllowed {
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusUnauthorized,
|
||||||
|
JSON: jsonerror.Forbidden(""),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return JoinRoomByIDOrAlias(
|
return JoinRoomByIDOrAlias(
|
||||||
req, device, rsAPI, userAPI, vars["roomIDOrAlias"],
|
req, device, rsAPI, userAPI, vars["roomIDOrAlias"],
|
||||||
|
|
@ -348,6 +352,7 @@ func Setup(
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return util.ErrorResponse(err)
|
return util.ErrorResponse(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return SendInvite(req, userAPI, device, vars["roomID"], cfg, rsAPI, asAPI)
|
return SendInvite(req, userAPI, device, vars["roomID"], cfg, rsAPI, asAPI)
|
||||||
}),
|
}),
|
||||||
).Methods(http.MethodPost, http.MethodOptions)
|
).Methods(http.MethodPost, http.MethodOptions)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
# Purpose
|
||||||
|
|
||||||
Additional packaages added for the Zion project, nothing in here should be in the Matrix Dendrite upstream, nor in the herenotthere/dendrite-fork.
|
Additional packaages added for the Zion project, nothing in here should be in the Matrix Dendrite upstream, nor in the herenotthere/dendrite-fork.
|
||||||
|
|
||||||
The zion_space_manager_(mainnet|rinkeby|localhost).go files are generated as new versions of the smart contracts are build and deployed. The bindings are in this location so they can be built alongside the dendrite server in the build process.
|
The zion_space_manager_(mainnet|rinkeby|localhost).go files are generated as new versions of the smart contracts are build and deployed. The bindings are in this location so they can be built alongside the dendrite server in the build process.
|
||||||
|
|
|
||||||
88
zion/store.go
Normal file
88
zion/store.go
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
Convenient function for space info mapping between Matrix room and Space contract
|
||||||
|
*/
|
||||||
|
package zion
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
roomserver "github.com/matrix-org/dendrite/roomserver/api"
|
||||||
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Store struct {
|
||||||
|
rsAPI roomserver.ClientRoomserverAPI
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStore(rsAPI roomserver.ClientRoomserverAPI) Store {
|
||||||
|
return Store{
|
||||||
|
rsAPI: rsAPI,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Store) 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.QueryCurrentStateResponse
|
||||||
|
err := s.rsAPI.QueryCurrentState(context.Background(), &roomserver.QueryCurrentStateRequest{
|
||||||
|
RoomID: roomId,
|
||||||
|
AllowWildcards: true,
|
||||||
|
StateTuples: []gomatrixserverlib.StateKeyTuple{
|
||||||
|
createTuple,
|
||||||
|
spaceParentTuple,
|
||||||
|
spaceChildTuple,
|
||||||
|
},
|
||||||
|
}, &roomEvents)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, state := range roomEvents.StateEvents {
|
||||||
|
switch state.Type() {
|
||||||
|
case gomatrixserverlib.MRoomCreate:
|
||||||
|
var creatorEvent CreatorEvent
|
||||||
|
err := json.Unmarshal(roomEvents.StateEvents[createTuple].Content(), &creatorEvent)
|
||||||
|
result.IsOwner = strings.HasPrefix(
|
||||||
|
creatorEvent.Creator,
|
||||||
|
userId.LocalPart,
|
||||||
|
)
|
||||||
|
if err == nil {
|
||||||
|
result.RoomType = Space
|
||||||
|
result.SpaceNetworkId = roomId
|
||||||
|
}
|
||||||
|
case ConstSpaceChildEventType:
|
||||||
|
result.RoomType = Space
|
||||||
|
result.SpaceNetworkId = roomId
|
||||||
|
case ConstSpaceParentEventType:
|
||||||
|
result.RoomType = Channel
|
||||||
|
result.SpaceNetworkId = *state.StateKey()
|
||||||
|
result.ChannelNetworkId = roomId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
42
zion/store_types.go
Normal file
42
zion/store_types.go
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
Store types
|
||||||
|
*/
|
||||||
|
package zion
|
||||||
|
|
||||||
|
const (
|
||||||
|
ConstSpaceChildEventType = "m.space.child"
|
||||||
|
ConstSpaceParentEventType = "m.space.parent"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Define enum for RoomType
|
||||||
|
type RoomType int64
|
||||||
|
|
||||||
|
const (
|
||||||
|
Space RoomType = iota
|
||||||
|
Channel
|
||||||
|
Unknown
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r RoomType) String() string {
|
||||||
|
switch r {
|
||||||
|
case Space:
|
||||||
|
return "space"
|
||||||
|
case Channel:
|
||||||
|
return "channel"
|
||||||
|
}
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
|
||||||
|
type RoomInfo struct {
|
||||||
|
QueryUserId string // Matrix User ID
|
||||||
|
SpaceNetworkId string
|
||||||
|
ChannelNetworkId string
|
||||||
|
RoomType RoomType
|
||||||
|
IsOwner bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreatorEvent struct {
|
||||||
|
Creator string `json:"creator"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
RoomVersion string `json:"room_version"`
|
||||||
|
}
|
||||||
|
|
@ -1,38 +1,45 @@
|
||||||
package zion
|
package zion
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
var regexpMatrixId = regexp.MustCompile(`^@eip155=3a(?P<ChainId>[0-9]+)=3a(?P<LocalPart>0x[0-9a-fA-F]+):(?P<HomeServer>.*)$`)
|
var regexpMatrixId = regexp.MustCompile(`^@eip155=3a(?P<ChainId>[0-9]+)=3a(?P<Address>0x[0-9a-fA-F]+):(?P<HomeServer>.*)$`)
|
||||||
var chainIdIndex = regexpMatrixId.SubexpIndex("ChainId")
|
var chainIdIndex = regexpMatrixId.SubexpIndex("ChainId")
|
||||||
var localPartIndex = regexpMatrixId.SubexpIndex("LocalPart")
|
var addressIndex = regexpMatrixId.SubexpIndex("Address")
|
||||||
|
|
||||||
//var homeServerIndex = regexpMatrixId.SubexpIndex("HomeServer")
|
//var homeServerIndex = regexpMatrixId.SubexpIndex("HomeServer")
|
||||||
|
|
||||||
type UserIdentifier struct {
|
type UserIdentifier struct {
|
||||||
accountAddress common.Address
|
AccountAddress common.Address
|
||||||
chainId int
|
ChainId int
|
||||||
|
MatrixUserId string
|
||||||
|
LocalPart string
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateUserIdentifier(matrixUserId string) UserIdentifier {
|
func CreateUserIdentifier(matrixUserId string) UserIdentifier {
|
||||||
matches := regexpMatrixId.FindStringSubmatch(matrixUserId)
|
matches := regexpMatrixId.FindStringSubmatch(matrixUserId)
|
||||||
accountAddress := ""
|
address := ""
|
||||||
chainId := -1
|
chainId := -1
|
||||||
|
localPart := ""
|
||||||
|
|
||||||
if chainIdIndex < len(matches) {
|
if chainIdIndex < len(matches) {
|
||||||
chainId, _ = strconv.Atoi(matches[chainIdIndex])
|
chainId, _ = strconv.Atoi(matches[chainIdIndex])
|
||||||
}
|
}
|
||||||
|
|
||||||
if localPartIndex < len(matches) {
|
if addressIndex < len(matches) {
|
||||||
accountAddress = matches[localPartIndex]
|
address = matches[addressIndex]
|
||||||
|
localPart = fmt.Sprintf("@eip155=3a%d=3a%s", chainId, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
return UserIdentifier{
|
return UserIdentifier{
|
||||||
accountAddress: common.HexToAddress(accountAddress),
|
AccountAddress: common.HexToAddress(address),
|
||||||
chainId: chainId,
|
ChainId: chainId,
|
||||||
|
MatrixUserId: matrixUserId,
|
||||||
|
LocalPart: localPart,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
"github.com/matrix-org/dendrite/authorization"
|
"github.com/matrix-org/dendrite/authorization"
|
||||||
|
roomserver "github.com/matrix-org/dendrite/roomserver/api"
|
||||||
zion_goerli "github.com/matrix-org/dendrite/zion/contracts/goerli/zion_goerli"
|
zion_goerli "github.com/matrix-org/dendrite/zion/contracts/goerli/zion_goerli"
|
||||||
zion_localhost "github.com/matrix-org/dendrite/zion/contracts/localhost/zion_localhost"
|
zion_localhost "github.com/matrix-org/dendrite/zion/contracts/localhost/zion_localhost"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
@ -24,11 +25,12 @@ var localhostJson []byte
|
||||||
var goerliJson []byte
|
var goerliJson []byte
|
||||||
|
|
||||||
type ZionAuthorization struct {
|
type ZionAuthorization struct {
|
||||||
|
store Store
|
||||||
spaceManagerLocalhost *zion_localhost.ZionSpaceManagerLocalhost
|
spaceManagerLocalhost *zion_localhost.ZionSpaceManagerLocalhost
|
||||||
spaceManagerGoerli *zion_goerli.ZionSpaceManagerGoerli
|
spaceManagerGoerli *zion_goerli.ZionSpaceManagerGoerli
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewZionAuthorization() (authorization.Authorization, error) {
|
func NewZionAuthorization(rsAPI roomserver.ClientRoomserverAPI) (authorization.Authorization, error) {
|
||||||
err := godotenv.Load(".env")
|
err := godotenv.Load(".env")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln("error loading .env file", err)
|
log.Errorln("error loading .env file", err)
|
||||||
|
|
@ -36,6 +38,8 @@ func NewZionAuthorization() (authorization.Authorization, error) {
|
||||||
|
|
||||||
var auth ZionAuthorization
|
var auth ZionAuthorization
|
||||||
|
|
||||||
|
auth.store = NewStore(rsAPI)
|
||||||
|
|
||||||
localhost, err := newZionSpaceManagerLocalhost(os.Getenv(localhostEndpointUrl))
|
localhost, err := newZionSpaceManagerLocalhost(os.Getenv(localhostEndpointUrl))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln("error instantiating ZionSpaceManagerLocalhost", err)
|
log.Errorln("error instantiating ZionSpaceManagerLocalhost", err)
|
||||||
|
|
@ -54,31 +58,40 @@ func NewZionAuthorization() (authorization.Authorization, error) {
|
||||||
func (za *ZionAuthorization) IsAllowed(args authorization.AuthorizationArgs) (bool, error) {
|
func (za *ZionAuthorization) IsAllowed(args authorization.AuthorizationArgs) (bool, error) {
|
||||||
userIdentifier := CreateUserIdentifier(args.UserId)
|
userIdentifier := CreateUserIdentifier(args.UserId)
|
||||||
|
|
||||||
switch userIdentifier.chainId {
|
// 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 userIdentifier.ChainId {
|
||||||
case 1337, 31337:
|
case 1337, 31337:
|
||||||
return za.IsAllowedLocalhost(args.RoomId, userIdentifier.accountAddress, args.Permission)
|
return za.isAllowedLocalhost(roomInfo, userIdentifier.AccountAddress, args.Permission)
|
||||||
case 5:
|
case 5:
|
||||||
return za.IsAllowedGoerli(args.RoomId, userIdentifier.accountAddress, args.Permission)
|
return za.isAllowedGoerli(roomInfo, userIdentifier.AccountAddress, args.Permission)
|
||||||
default:
|
default:
|
||||||
log.Errorf("Unsupported chain id: %d\n", userIdentifier.chainId)
|
log.Errorf("Unsupported chain id: %d\n", userIdentifier.ChainId)
|
||||||
}
|
}
|
||||||
|
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (za *ZionAuthorization) IsAllowedLocalhost(roomId string, user common.Address, permission authorization.Permission) (bool, error) {
|
func (za *ZionAuthorization) isAllowedLocalhost(
|
||||||
|
roomInfo RoomInfo,
|
||||||
|
user common.Address,
|
||||||
|
permission authorization.Permission,
|
||||||
|
) (bool, error) {
|
||||||
if za.spaceManagerLocalhost != nil {
|
if za.spaceManagerLocalhost != nil {
|
||||||
permission := zion_localhost.DataTypesPermission{
|
permission := zion_localhost.DataTypesPermission{
|
||||||
Name: permission.String(),
|
Name: permission.String(),
|
||||||
}
|
}
|
||||||
|
|
||||||
addr := user.Hex()
|
|
||||||
_ = addr
|
|
||||||
|
|
||||||
isEntitled, err := za.spaceManagerLocalhost.IsEntitled(
|
isEntitled, err := za.spaceManagerLocalhost.IsEntitled(
|
||||||
nil,
|
nil,
|
||||||
roomId,
|
roomInfo.SpaceNetworkId,
|
||||||
"", // todo: Support channelId
|
roomInfo.ChannelNetworkId,
|
||||||
user,
|
user,
|
||||||
permission,
|
permission,
|
||||||
)
|
)
|
||||||
|
|
@ -93,7 +106,11 @@ func (za *ZionAuthorization) IsAllowedLocalhost(roomId string, user common.Addre
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (za *ZionAuthorization) IsAllowedGoerli(roomId string, user common.Address, permission authorization.Permission) (bool, error) {
|
func (za *ZionAuthorization) isAllowedGoerli(
|
||||||
|
roomInfo RoomInfo,
|
||||||
|
user common.Address,
|
||||||
|
permission authorization.Permission,
|
||||||
|
) (bool, error) {
|
||||||
if za.spaceManagerGoerli != nil {
|
if za.spaceManagerGoerli != nil {
|
||||||
permission := zion_goerli.DataTypesPermission{
|
permission := zion_goerli.DataTypesPermission{
|
||||||
Name: permission.String(),
|
Name: permission.String(),
|
||||||
|
|
@ -101,8 +118,8 @@ func (za *ZionAuthorization) IsAllowedGoerli(roomId string, user common.Address,
|
||||||
|
|
||||||
isEntitled, err := za.spaceManagerGoerli.IsEntitled(
|
isEntitled, err := za.spaceManagerGoerli.IsEntitled(
|
||||||
nil,
|
nil,
|
||||||
roomId,
|
roomInfo.SpaceNetworkId,
|
||||||
"", // todo: support channelId
|
roomInfo.ChannelNetworkId,
|
||||||
user,
|
user,
|
||||||
permission,
|
permission,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue