feat: allow owner without community private key to manage privileged community permissions (#3861)

feat: allow owner without community private key to manage privileged permissions
This commit is contained in:
Mykhailo Prakhov 2023-08-08 17:02:56 +02:00 committed by GitHub
parent 248e4a7f24
commit ebadfb3e7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 359 additions and 360 deletions

View File

@ -1096,6 +1096,10 @@ func (o *Community) IsTokenMaster() bool {
return o.IsMemberTokenMaster(o.config.MemberIdentity)
}
func (o *Community) IsAdmin() bool {
return o.IsMemberAdmin(o.config.MemberIdentity)
}
func (o *Community) GetPrivilegedMembers() []*ecdsa.PublicKey {
privilegedMembers := make([]*ecdsa.PublicKey, 0)
members := o.GetMemberPubkeys()
@ -1437,9 +1441,11 @@ func (o *Community) AddTokenPermission(permission *protobuf.CommunityTokenPermis
defer o.mutex.Unlock()
isControlNode := o.IsControlNode()
allowedToSendEvents := o.HasPermissionToSendCommunityEvents()
allowedToManageMemberPermissions := o.IsTokenMaster() || o.IsAdmin()
allowedToManageAllPermissions := o.IsOwnerWithoutCommunityKey()
if !isControlNode && !allowedToSendEvents || (allowedToSendEvents && permission.Type == protobuf.CommunityTokenPermission_BECOME_ADMIN) {
if (!isControlNode && !allowedToManageMemberPermissions && !allowedToManageAllPermissions) ||
(allowedToManageMemberPermissions && permission.Type != protobuf.CommunityTokenPermission_BECOME_MEMBER) {
return nil, ErrNotEnoughPermissions
}
@ -1448,7 +1454,7 @@ func (o *Community) AddTokenPermission(permission *protobuf.CommunityTokenPermis
return nil, err
}
if allowedToSendEvents {
if allowedToManageMemberPermissions || allowedToManageAllPermissions {
err := o.addNewCommunityEvent(o.ToCommunityTokenPermissionChangeCommunityEvent(permission))
if err != nil {
return nil, err
@ -1468,9 +1474,11 @@ func (o *Community) UpdateTokenPermission(permissionID string, tokenPermission *
defer o.mutex.Unlock()
isControlNode := o.IsControlNode()
allowedToSendEvents := o.HasPermissionToSendCommunityEvents()
allowedToManageMemberPermissions := o.IsTokenMaster() || o.IsAdmin()
allowedToManageAllPermissions := o.IsOwnerWithoutCommunityKey()
if !isControlNode && !allowedToSendEvents || (allowedToSendEvents && tokenPermission.Type == protobuf.CommunityTokenPermission_BECOME_ADMIN) {
if (!isControlNode && !allowedToManageMemberPermissions && !allowedToManageAllPermissions) ||
(allowedToManageMemberPermissions && tokenPermission.Type != protobuf.CommunityTokenPermission_BECOME_MEMBER) {
return nil, ErrNotEnoughPermissions
}
@ -1479,7 +1487,7 @@ func (o *Community) UpdateTokenPermission(permissionID string, tokenPermission *
return nil, err
}
if allowedToSendEvents {
if allowedToManageMemberPermissions || allowedToManageAllPermissions {
err := o.addNewCommunityEvent(o.ToCommunityTokenPermissionChangeCommunityEvent(tokenPermission))
if err != nil {
return nil, err
@ -1505,9 +1513,11 @@ func (o *Community) DeleteTokenPermission(permissionID string) (*CommunityChange
}
isControlNode := o.IsControlNode()
allowedToSendEvents := o.HasPermissionToSendCommunityEvents()
allowedToManageMemberPermissions := o.IsTokenMaster() || o.IsAdmin()
allowedToManageAllPermissions := o.IsOwnerWithoutCommunityKey()
if !isControlNode && !allowedToSendEvents || (allowedToSendEvents && permission.Type == protobuf.CommunityTokenPermission_BECOME_ADMIN) {
if (!isControlNode && !allowedToManageMemberPermissions && !allowedToManageAllPermissions) ||
(allowedToManageMemberPermissions && permission.Type != protobuf.CommunityTokenPermission_BECOME_MEMBER) {
return nil, ErrNotEnoughPermissions
}
@ -1516,7 +1526,7 @@ func (o *Community) DeleteTokenPermission(permissionID string) (*CommunityChange
return nil, err
}
if allowedToSendEvents {
if allowedToManageMemberPermissions || allowedToManageAllPermissions {
err := o.addNewCommunityEvent(o.ToCommunityTokenPermissionDeleteCommunityEvent(permission))
if err != nil {
return nil, err

View File

@ -1,18 +1,18 @@
package protocol
import (
"crypto/ecdsa"
"testing"
"github.com/stretchr/testify/suite"
"go.uber.org/zap"
gethcommon "github.com/ethereum/go-ethereum/common"
hexutil "github.com/ethereum/go-ethereum/common/hexutil"
gethbridge "github.com/status-im/status-go/eth-node/bridge/geth"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/protocol/common"
"github.com/status-im/status-go/protocol/protobuf"
"github.com/status-im/status-go/protocol/requests"
"github.com/status-im/status-go/protocol/tt"
"github.com/status-im/status-go/waku"
)
@ -28,8 +28,9 @@ type OwnerWithoutCommunityKeyCommunityEventsSuite struct {
alice *Messenger
// If one wants to send messages between different instances of Messenger,
// a single Waku service should be shared.
shh types.Waku
logger *zap.Logger
shh types.Waku
logger *zap.Logger
mockedBalances map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big // chainID, account, token, balance
}
func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) GetControlNode() *Messenger {
@ -57,15 +58,17 @@ func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) SetupTest() {
s.shh = gethbridge.NewGethWakuWrapper(shh)
s.Require().NoError(shh.Start())
s.controlNode = s.newMessenger()
s.ownerWithoutCommunityKey = s.newMessenger()
s.alice = s.newMessenger()
s.controlNode = s.newMessenger("", []string{})
s.ownerWithoutCommunityKey = s.newMessenger("qwerty", []string{commmunitiesEventsEventSenderAddress})
s.alice = s.newMessenger("", []string{})
_, err := s.controlNode.Start()
s.Require().NoError(err)
_, err = s.ownerWithoutCommunityKey.Start()
s.Require().NoError(err)
_, err = s.alice.Start()
s.Require().NoError(err)
s.mockedBalances = createMockedWalletBalance(&s.Suite)
}
func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TearDownTest() {
@ -75,18 +78,8 @@ func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TearDownTest() {
_ = s.logger.Sync()
}
func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) newMessengerWithKey(shh types.Waku, privateKey *ecdsa.PrivateKey) *Messenger {
messenger, err := newCommunitiesTestMessenger(shh, privateKey, s.logger, nil, nil)
s.Require().NoError(err)
return messenger
}
func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) newMessenger() *Messenger {
privateKey, err := crypto.GenerateKey()
s.Require().NoError(err)
return s.newMessengerWithKey(s.shh, privateKey)
func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) newMessenger(password string, walletAddresses []string) *Messenger {
return newMessenger(&s.Suite, s.shh, s.logger, password, walletAddresses, &s.mockedBalances)
}
func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerEditCommunityDescription() {
@ -102,114 +95,31 @@ func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerCreateEditDelete
func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerCreateEditDeleteBecomeMemberPermission() {
community := setUpCommunityAndRoles(s, protobuf.CommunityMember_ROLE_OWNER)
testCreateEditDeleteBecomeMemberPermission(s, community)
testCreateEditDeleteBecomeMemberPermission(s, community, protobuf.CommunityTokenPermission_BECOME_MEMBER)
}
func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerCannotCreateBecomeAdminPermission() {
func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerCreateEditDeleteBecomeAdminPermission() {
community := setUpCommunityAndRoles(s, protobuf.CommunityMember_ROLE_OWNER)
permissionRequest := createTestPermissionRequest(community)
permissionRequest.Type = protobuf.CommunityTokenPermission_BECOME_ADMIN
response, err := s.ownerWithoutCommunityKey.CreateCommunityTokenPermission(permissionRequest)
s.Require().Nil(response)
s.Require().Error(err)
testCreateEditDeleteBecomeMemberPermission(s, community, protobuf.CommunityTokenPermission_BECOME_ADMIN)
}
func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerCannotEditBecomeAdminPermission() {
func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerCreateEditDeleteBecomeTokenMasterPermission() {
community := setUpCommunityAndRoles(s, protobuf.CommunityMember_ROLE_OWNER)
permissionRequest := createTestPermissionRequest(community)
permissionRequest.Type = protobuf.CommunityTokenPermission_BECOME_ADMIN
// control node creates BECOME_ADMIN permission
response, err := s.controlNode.CreateCommunityTokenPermission(permissionRequest)
s.Require().NoError(err)
var tokenPermissionID string
for id := range response.CommunityChanges[0].TokenPermissionsAdded {
tokenPermissionID = id
}
s.Require().NotEqual(tokenPermissionID, "")
ownerCommunity, err := s.controlNode.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
assertCheckTokenPermissionCreated(&s.Suite, ownerCommunity)
// then, ensure event sender receives updated community
_, err = WaitOnMessengerResponse(
s.ownerWithoutCommunityKey,
func(r *MessengerResponse) bool { return len(r.Communities()) > 0 },
"event sender did not receive updated community",
)
s.Require().NoError(err)
eventSenderCommunity, err := s.ownerWithoutCommunityKey.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
assertCheckTokenPermissionCreated(&s.Suite, eventSenderCommunity)
permissionRequest.TokenCriteria[0].Symbol = "UPDATED"
permissionRequest.TokenCriteria[0].Amount = "200"
permissionEditRequest := &requests.EditCommunityTokenPermission{
PermissionID: tokenPermissionID,
CreateCommunityTokenPermission: *permissionRequest,
}
// then, event sender tries to edit permission
response, err = s.ownerWithoutCommunityKey.EditCommunityTokenPermission(permissionEditRequest)
s.Require().Error(err)
s.Require().Nil(response)
}
func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerCannotDeleteBecomeAdminPermission() {
community := setUpCommunityAndRoles(s, protobuf.CommunityMember_ROLE_OWNER)
permissionRequest := createTestPermissionRequest(community)
permissionRequest.Type = protobuf.CommunityTokenPermission_BECOME_ADMIN
// control node creates BECOME_ADMIN permission
response, err := s.controlNode.CreateCommunityTokenPermission(permissionRequest)
s.Require().NoError(err)
var tokenPermissionID string
for id := range response.CommunityChanges[0].TokenPermissionsAdded {
tokenPermissionID = id
}
s.Require().NotEqual(tokenPermissionID, "")
// then, ensure event sender receives updated community
_, err = WaitOnMessengerResponse(
s.ownerWithoutCommunityKey,
func(r *MessengerResponse) bool { return len(r.Communities()) > 0 },
"event sender did not receive updated community",
)
s.Require().NoError(err)
eventSenderCommunity, err := s.ownerWithoutCommunityKey.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
assertCheckTokenPermissionCreated(&s.Suite, eventSenderCommunity)
deleteTokenPermission := &requests.DeleteCommunityTokenPermission{
CommunityID: community.ID(),
PermissionID: tokenPermissionID,
}
// then event sender tries to delete BECOME_ADMIN permission which should fail
response, err = s.ownerWithoutCommunityKey.DeleteCommunityTokenPermission(deleteTokenPermission)
s.Require().Error(err)
s.Require().Nil(response)
testCreateEditDeleteBecomeMemberPermission(s, community, protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER)
}
func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders() {
additionalOwner := s.newMessenger()
additionalOwner := s.newMessenger("", []string{})
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_OWNER, []*Messenger{additionalOwner})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders(s, community, user, additionalOwner)
}
func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerAcceptMemberRequestToJoinNotConfirmedByControlNode() {
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_OWNER, []*Messenger{})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testAcceptMemberRequestToJoinNotConfirmedByControlNode(s, community, user)
}
@ -217,22 +127,22 @@ func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerAcceptMemberRequ
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_OWNER, []*Messenger{})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testAcceptMemberRequestToJoin(s, community, user)
}
func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerRejectMemberRequestToJoinResponseSharedWithOtherEventSenders() {
additionalOwner := s.newMessenger()
additionalOwner := s.newMessenger("", []string{})
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_OWNER, []*Messenger{additionalOwner})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders(s, community, user, additionalOwner)
}
func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerRejectMemberRequestToJoinNotConfirmedByControlNode() {
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_OWNER, []*Messenger{})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testRejectMemberRequestToJoinNotConfirmedByControlNode(s, community, user)
}
@ -240,25 +150,25 @@ func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerRejectMemberRequ
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_OWNER, []*Messenger{})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testRejectMemberRequestToJoin(s, community, user)
}
func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerRequestToJoinStateCannotBeOverridden() {
additionalOwner := s.newMessenger()
additionalOwner := s.newMessenger("", []string{})
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_OWNER, []*Messenger{additionalOwner})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testEventSenderCannotOverrideRequestToJoinState(s, community, user, additionalOwner)
}
func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerControlNodeHandlesMultipleEventSenderRequestToJoinDecisions() {
additionalOwner := s.newMessenger()
additionalOwner := s.newMessenger("", []string{})
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_OWNER, []*Messenger{additionalOwner})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testControlNodeHandlesMultipleEventSenderRequestToJoinDecisions(s, community, user, additionalOwner)
}

View File

@ -1,14 +1,15 @@
package protocol
import (
"crypto/ecdsa"
"testing"
"github.com/stretchr/testify/suite"
"go.uber.org/zap"
gethcommon "github.com/ethereum/go-ethereum/common"
hexutil "github.com/ethereum/go-ethereum/common/hexutil"
gethbridge "github.com/status-im/status-go/eth-node/bridge/geth"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/protocol/common"
"github.com/status-im/status-go/protocol/protobuf"
@ -27,8 +28,9 @@ type TokenMasterCommunityEventsSuite struct {
alice *Messenger
// If one wants to send messages between different instances of Messenger,
// a single Waku service should be shared.
shh types.Waku
logger *zap.Logger
shh types.Waku
logger *zap.Logger
mockedBalances map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big // chainID, account, token, balance
}
func (s *TokenMasterCommunityEventsSuite) GetControlNode() *Messenger {
@ -56,15 +58,17 @@ func (s *TokenMasterCommunityEventsSuite) SetupTest() {
s.shh = gethbridge.NewGethWakuWrapper(shh)
s.Require().NoError(shh.Start())
s.controlNode = s.newMessenger()
s.tokenMaster = s.newMessenger()
s.alice = s.newMessenger()
s.controlNode = s.newMessenger("", []string{})
s.tokenMaster = s.newMessenger("qwerty", []string{commmunitiesEventsEventSenderAddress})
s.alice = s.newMessenger("", []string{})
_, err := s.controlNode.Start()
s.Require().NoError(err)
_, err = s.tokenMaster.Start()
s.Require().NoError(err)
_, err = s.alice.Start()
s.Require().NoError(err)
s.mockedBalances = createMockedWalletBalance(&s.Suite)
}
func (s *TokenMasterCommunityEventsSuite) TearDownTest() {
@ -74,18 +78,8 @@ func (s *TokenMasterCommunityEventsSuite) TearDownTest() {
_ = s.logger.Sync()
}
func (s *TokenMasterCommunityEventsSuite) newMessengerWithKey(shh types.Waku, privateKey *ecdsa.PrivateKey) *Messenger {
messenger, err := newCommunitiesTestMessenger(shh, privateKey, s.logger, nil, nil)
s.Require().NoError(err)
return messenger
}
func (s *TokenMasterCommunityEventsSuite) newMessenger() *Messenger {
privateKey, err := crypto.GenerateKey()
s.Require().NoError(err)
return s.newMessengerWithKey(s.shh, privateKey)
func (s *TokenMasterCommunityEventsSuite) newMessenger(password string, walletAddresses []string) *Messenger {
return newMessenger(&s.Suite, s.shh, s.logger, password, walletAddresses, &s.mockedBalances)
}
func (s *TokenMasterCommunityEventsSuite) TestTokenMasterEditCommunityDescription() {
@ -100,89 +94,102 @@ func (s *TokenMasterCommunityEventsSuite) TestTokenMasterCreateEditDeleteChannel
func (s *TokenMasterCommunityEventsSuite) TestTokenMasterCreateEditDeleteBecomeMemberPermission() {
community := setUpCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER)
testCreateEditDeleteBecomeMemberPermission(s, community)
testCreateEditDeleteBecomeMemberPermission(s, community, protobuf.CommunityTokenPermission_BECOME_MEMBER)
}
func (s *TokenMasterCommunityEventsSuite) TestTokenMasterCannotCreateBecomeAdminPermission() {
community := setUpCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER)
testEventSenderCannotCreatePrivilegedCommunityPermission(s, community, protobuf.CommunityTokenPermission_BECOME_ADMIN)
}
permissionRequest := createTestPermissionRequest(community)
permissionRequest.Type = protobuf.CommunityTokenPermission_BECOME_ADMIN
response, err := s.tokenMaster.CreateCommunityTokenPermission(permissionRequest)
s.Require().Nil(response)
s.Require().Error(err)
func (s *TokenMasterCommunityEventsSuite) TestTokenMasterCannotCreateBecomeTokenMasterPermission() {
community := setUpCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER)
testEventSenderCannotCreatePrivilegedCommunityPermission(s, community, protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER)
}
func (s *TokenMasterCommunityEventsSuite) TestTokenMasterCannotEditBecomeAdminPermission() {
community := setUpCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER)
testEventSenderCannotEditBecomeAdminPermission(s, community)
testEventSenderCannotEditPrivilegedCommunityPermission(
s, community, protobuf.CommunityTokenPermission_BECOME_ADMIN, protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER)
}
func (s *TokenMasterCommunityEventsSuite) TestTokenMasterCannotEditBecomeTokenMasterPermission() {
community := setUpCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER)
testEventSenderCannotEditPrivilegedCommunityPermission(
s, community, protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER, protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER)
}
func (s *TokenMasterCommunityEventsSuite) TestTokenMasterCannotDeleteBecomeAdminPermission() {
community := setUpCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER)
testEventSenderCannotDeleteBecomeAdminPermission(s, community)
testEventSenderCannotDeletePrivilegedCommunityPermission(
s, community, protobuf.CommunityTokenPermission_BECOME_ADMIN, protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER)
}
func (s *TokenMasterCommunityEventsSuite) TestTokenMasterCannotDeleteBecomeTokenMasterPermission() {
community := setUpCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER)
testEventSenderCannotDeletePrivilegedCommunityPermission(
s, community, protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER, protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER)
}
func (s *TokenMasterCommunityEventsSuite) TestTokenMasterAcceptMemberRequestToJoinNotConfirmedByControlNode() {
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER, []*Messenger{})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testAcceptMemberRequestToJoinNotConfirmedByControlNode(s, community, user)
}
func (s *TokenMasterCommunityEventsSuite) TestTokenMasterAcceptMemberRequestToJoin() {
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER, []*Messenger{})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testAcceptMemberRequestToJoin(s, community, user)
}
func (s *TokenMasterCommunityEventsSuite) TestTokenMasterAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders() {
additionalTokenMaster := s.newMessenger()
additionalTokenMaster := s.newMessenger("qwerty", []string{commmunitiesEventsEventSenderAddress})
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER, []*Messenger{additionalTokenMaster})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders(s, community, user, additionalTokenMaster)
}
func (s *TokenMasterCommunityEventsSuite) TestTokenMasterRejectMemberRequestToJoinResponseSharedWithOtherEventSenders() {
additionalTokenMaster := s.newMessenger()
additionalTokenMaster := s.newMessenger("qwerty", []string{commmunitiesEventsEventSenderAddress})
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER, []*Messenger{additionalTokenMaster})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders(s, community, user, additionalTokenMaster)
}
func (s *TokenMasterCommunityEventsSuite) TestTokenMasterRejectMemberRequestToJoinNotConfirmedByControlNode() {
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER, []*Messenger{})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testRejectMemberRequestToJoinNotConfirmedByControlNode(s, community, user)
}
func (s *TokenMasterCommunityEventsSuite) TestTokenMasterRejectMemberRequestToJoin() {
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER, []*Messenger{})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testRejectMemberRequestToJoin(s, community, user)
}
func (s *TokenMasterCommunityEventsSuite) TestTokenMasterRequestToJoinStateCannotBeOverridden() {
additionalTokenMaster := s.newMessenger()
additionalTokenMaster := s.newMessenger("", []string{})
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER, []*Messenger{additionalTokenMaster})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testEventSenderCannotOverrideRequestToJoinState(s, community, user, additionalTokenMaster)
}
func (s *TokenMasterCommunityEventsSuite) TestTokenMasterControlNodeHandlesMultipleEventSenderRequestToJoinDecisions() {
additionalTokenMaster := s.newMessenger()
additionalTokenMaster := s.newMessenger("qwerty", []string{commmunitiesEventsEventSenderAddress})
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER, []*Messenger{additionalTokenMaster})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testControlNodeHandlesMultipleEventSenderRequestToJoinDecisions(s, community, user, additionalTokenMaster)
}

View File

@ -7,6 +7,9 @@ import (
"github.com/stretchr/testify/suite"
gethcommon "github.com/ethereum/go-ethereum/common"
hexutil "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/protocol/common"
"github.com/status-im/status-go/protocol/communities"
@ -22,6 +25,10 @@ type CommunityEventsTestsInterface interface {
GetSuite() *suite.Suite
}
const commmunitiesEventsTestTokenAddress = "0x0400000000000000000000000000000000000000"
const commmunitiesEventsTestChainID = 1
const commmunitiesEventsEventSenderAddress = "0x0200000000000000000000000000000000000000"
type MessageResponseValidator func(*MessengerResponse) error
type WaitResponseValidator func(*MessengerResponse) bool
@ -77,6 +84,24 @@ func refreshMessengerResponses(base CommunityEventsTestsInterface) {
base.GetSuite().Require().NoError(err)
}
func createMockedWalletBalance(s *suite.Suite) map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big {
eventSenderAddress := gethcommon.HexToAddress(commmunitiesEventsEventSenderAddress)
mockedBalances := make(map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big)
mockedBalances[testChainID1] = make(map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big)
mockedBalances[testChainID1][eventSenderAddress] = make(map[gethcommon.Address]*hexutil.Big)
// event sender will have token with `commmunitiesEventsTestTokenAddress``
contractAddress := gethcommon.HexToAddress(commmunitiesEventsTestTokenAddress)
balance, ok := new(big.Int).SetString("200", 10)
s.Require().True(ok)
decimalsFactor := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(18)), nil)
balance.Mul(balance, decimalsFactor)
mockedBalances[commmunitiesEventsTestChainID][eventSenderAddress][contractAddress] = (*hexutil.Big)(balance)
return mockedBalances
}
func setUpCommunityAndRoles(base CommunityEventsTestsInterface, role protobuf.CommunityMember_Roles) *communities.Community {
tcs2, err := base.GetControlNode().communitiesManager.All()
suite := base.GetSuite()
@ -91,9 +116,21 @@ func setUpCommunityAndRoles(base CommunityEventsTestsInterface, role protobuf.Co
advertiseCommunityTo(suite, community, base.GetControlNode(), base.GetEventSender())
advertiseCommunityTo(suite, community, base.GetControlNode(), base.GetMember())
request := &requests.RequestToJoinCommunity{CommunityID: community.ID()}
request := &requests.RequestToJoinCommunity{
CommunityID: community.ID(),
AddressesToReveal: []string{commmunitiesEventsEventSenderAddress},
Password: "qwerty1",
AirdropAddress: commmunitiesEventsEventSenderAddress,
}
joinCommunity(suite, community, base.GetControlNode(), base.GetEventSender(), request)
refreshMessengerResponses(base)
request = &requests.RequestToJoinCommunity{
CommunityID: community.ID(),
AddressesToReveal: []string{"0x0300000000000000000000000000000000000000"},
Password: "qwerty2",
AirdropAddress: "0x0300000000000000000000000000000000000000",
}
joinCommunity(suite, community, base.GetControlNode(), base.GetMember(), request)
refreshMessengerResponses(base)
@ -220,14 +257,14 @@ func deleteCommunityChannel(base CommunityEventsTestsInterface, community *commu
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkChannelDeleted)
}
func createTestPermissionRequest(community *communities.Community) *requests.CreateCommunityTokenPermission {
func createTestPermissionRequest(community *communities.Community, pType protobuf.CommunityTokenPermission_Type) *requests.CreateCommunityTokenPermission {
return &requests.CreateCommunityTokenPermission{
CommunityID: community.ID(),
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
Type: pType,
TokenCriteria: []*protobuf.TokenCriteria{
{
Type: protobuf.CommunityTokenType_ERC20,
ContractAddresses: map[uint64]string{uint64(1): "0x123"},
ContractAddresses: map[uint64]string{uint64(commmunitiesEventsTestChainID): commmunitiesEventsTestTokenAddress},
Symbol: "TEST",
Amount: "100",
Decimals: uint64(18),
@ -243,7 +280,7 @@ func createTokenPermission(base CommunityEventsTestsInterface, community *commun
return err
}
if !modifiedCommmunity.HasTokenPermissions() {
if len(modifiedCommmunity.TokenPermissionsByType(request.Type)) == 0 {
return errors.New("new token permission was not found")
}
@ -267,8 +304,8 @@ func createTokenPermission(base CommunityEventsTestsInterface, community *commun
return tokenPermissionID, request
}
func createTestTokenPermission(base CommunityEventsTestsInterface, community *communities.Community) (string, *requests.CreateCommunityTokenPermission) {
createTokenPermissionRequest := createTestPermissionRequest(community)
func createTestTokenPermission(base CommunityEventsTestsInterface, community *communities.Community, pType protobuf.CommunityTokenPermission_Type) (string, *requests.CreateCommunityTokenPermission) {
createTokenPermissionRequest := createTestPermissionRequest(community, pType)
return createTokenPermission(base, community, createTokenPermissionRequest)
}
@ -280,7 +317,7 @@ func editTokenPermission(base CommunityEventsTestsInterface, community *communit
return err
}
assertCheckTokenPermissionEdited(s, modifiedCommmunity)
assertCheckTokenPermissionEdited(s, modifiedCommmunity, request.CreateCommunityTokenPermission.Type)
return nil
}
@ -292,8 +329,8 @@ func editTokenPermission(base CommunityEventsTestsInterface, community *communit
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkTokenPermissionEdit)
}
func assertCheckTokenPermissionEdited(s *suite.Suite, community *communities.Community) {
permissions := community.TokenPermissionsByType(protobuf.CommunityTokenPermission_BECOME_MEMBER)
func assertCheckTokenPermissionEdited(s *suite.Suite, community *communities.Community, pType protobuf.CommunityTokenPermission_Type) {
permissions := community.TokenPermissionsByType(pType)
s.Require().Len(permissions, 1)
s.Require().Len(permissions[0].TokenCriteria, 1)
s.Require().Equal(permissions[0].TokenCriteria[0].Type, protobuf.CommunityTokenType_ERC20)
@ -324,12 +361,8 @@ func deleteTokenPermission(base CommunityEventsTestsInterface, community *commun
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkTokenPermissionDeleted)
}
func assertCheckTokenPermissionCreated(s *suite.Suite, community *communities.Community) {
permissions := make([]*protobuf.CommunityTokenPermission, 0)
tokenPermissions := community.TokenPermissions()
for _, p := range tokenPermissions {
permissions = append(permissions, p)
}
func assertCheckTokenPermissionCreated(s *suite.Suite, community *communities.Community, pType protobuf.CommunityTokenPermission_Type) {
permissions := community.TokenPermissionsByType(pType)
s.Require().Len(permissions, 1)
s.Require().Len(permissions[0].TokenCriteria, 1)
s.Require().Equal(permissions[0].TokenCriteria[0].Type, protobuf.CommunityTokenType_ERC20)
@ -712,6 +745,40 @@ func editCommunityDescription(base CommunityEventsTestsInterface, community *com
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkCommunityEdit)
}
func controlNodeCreatesCommunityPermission(base CommunityEventsTestsInterface, community *communities.Community, permissionRequest *requests.CreateCommunityTokenPermission) string {
// control node creates permission
response, err := base.GetControlNode().CreateCommunityTokenPermission(permissionRequest)
s := base.GetSuite()
s.Require().NoError(err)
var tokenPermissionID string
for id := range response.CommunityChanges[0].TokenPermissionsAdded {
tokenPermissionID = id
}
s.Require().NotEqual(tokenPermissionID, "")
ownerCommunity, err := base.GetControlNode().communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
assertCheckTokenPermissionCreated(s, ownerCommunity, permissionRequest.Type)
// then, ensure event sender receives updated community
_, err = WaitOnMessengerResponse(
base.GetEventSender(),
func(r *MessengerResponse) bool {
return len(r.Communities()) > 0 &&
len(r.Communities()[0].TokenPermissionsByType(permissionRequest.Type)) > 0
},
"event sender did not receive community token permission",
)
s.Require().NoError(err)
eventSenderCommunity, err := base.GetEventSender().communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
assertCheckTokenPermissionCreated(s, eventSenderCommunity, permissionRequest.Type)
s.Require().True(eventSenderCommunity.HasPermissionToSendCommunityEvents())
return tokenPermissionID
}
func testCreateEditDeleteChannels(base CommunityEventsTestsInterface, community *communities.Community) {
newChat := &protobuf.CommunityChat{
Permissions: &protobuf.CommunityPermissions{
@ -731,9 +798,9 @@ func testCreateEditDeleteChannels(base CommunityEventsTestsInterface, community
deleteCommunityChannel(base, community, newChatID)
}
func testCreateEditDeleteBecomeMemberPermission(base CommunityEventsTestsInterface, community *communities.Community) {
func testCreateEditDeleteBecomeMemberPermission(base CommunityEventsTestsInterface, community *communities.Community, pType protobuf.CommunityTokenPermission_Type) {
// first, create token permission
tokenPermissionID, createTokenPermission := createTestTokenPermission(base, community)
tokenPermissionID, createTokenPermission := createTestTokenPermission(base, community, pType)
createTokenPermission.TokenCriteria[0].Symbol = "UPDATED"
createTokenPermission.TokenCriteria[0].Amount = "200"
@ -784,6 +851,15 @@ func testAcceptMemberRequestToJoin(base CommunityEventsTestsInterface, community
s.Require().NoError(err)
s.Require().Len(response.RequestsToJoinCommunity, 1)
// control node receives request to join
response, err = WaitOnMessengerResponse(
base.GetControlNode(),
func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity) > 0 },
"event sender did not receive community request to join",
)
s.Require().NoError(err)
s.Require().Len(response.RequestsToJoinCommunity, 1)
// event sender has not accepted request yet
eventSenderCommunity, err := base.GetEventSender().GetCommunityByID(community.ID())
s.Require().NoError(err)
@ -1560,72 +1636,42 @@ func testMemberReceiveEventsWhenControlNodeOffline(base CommunityEventsTestsInte
waitOnMessengerResponse(s, WaitCommunityCondition, checkChannelDeleted, eventSender)
}
func testEventSenderCannotDeleteBecomeAdminPermission(base CommunityEventsTestsInterface, community *communities.Community) {
permissionRequest := createTestPermissionRequest(community)
permissionRequest.Type = protobuf.CommunityTokenPermission_BECOME_ADMIN
// control node creates BECOME_ADMIN permission
response, err := base.GetControlNode().CreateCommunityTokenPermission(permissionRequest)
s := base.GetSuite()
s.Require().NoError(err)
var tokenPermissionID string
for id := range response.CommunityChanges[0].TokenPermissionsAdded {
tokenPermissionID = id
func testEventSenderCannotDeletePrivilegedCommunityPermission(base CommunityEventsTestsInterface, community *communities.Community,
testPermissionType protobuf.CommunityTokenPermission_Type, rolePermissionType protobuf.CommunityTokenPermission_Type) {
// Community should have eventSenderRole permission or eventSender will loose his role
// after control node create a new community permission
if testPermissionType != rolePermissionType {
rolePermission := createTestPermissionRequest(community, rolePermissionType)
controlNodeCreatesCommunityPermission(base, community, rolePermission)
}
s.Require().NotEqual(tokenPermissionID, "")
// then, ensure event sender receives updated community
_, err = WaitOnMessengerResponse(
base.GetEventSender(),
func(r *MessengerResponse) bool { return len(r.Communities()) > 0 },
"event sender did not receive updated community",
)
s.Require().NoError(err)
eventSenderCommunity, err := base.GetEventSender().communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
assertCheckTokenPermissionCreated(s, eventSenderCommunity)
permissionRequest := createTestPermissionRequest(community, testPermissionType)
tokenPermissionID := controlNodeCreatesCommunityPermission(base, community, permissionRequest)
deleteTokenPermission := &requests.DeleteCommunityTokenPermission{
CommunityID: community.ID(),
PermissionID: tokenPermissionID,
}
// then event sender tries to delete BECOME_ADMIN permission which should fail
response, err = base.GetEventSender().DeleteCommunityTokenPermission(deleteTokenPermission)
// then event sender tries to delete permission which should fail
response, err := base.GetEventSender().DeleteCommunityTokenPermission(deleteTokenPermission)
s := base.GetSuite()
s.Require().Error(err)
s.Require().Nil(response)
}
func testEventSenderCannotEditBecomeAdminPermission(base CommunityEventsTestsInterface, community *communities.Community) {
permissionRequest := createTestPermissionRequest(community)
permissionRequest.Type = protobuf.CommunityTokenPermission_BECOME_ADMIN
func testEventSenderCannotEditPrivilegedCommunityPermission(base CommunityEventsTestsInterface, community *communities.Community,
testPermissionType protobuf.CommunityTokenPermission_Type, rolePermissionType protobuf.CommunityTokenPermission_Type) {
// control node creates BECOME_ADMIN permission
response, err := base.GetControlNode().CreateCommunityTokenPermission(permissionRequest)
s := base.GetSuite()
s.Require().NoError(err)
var tokenPermissionID string
for id := range response.CommunityChanges[0].TokenPermissionsAdded {
tokenPermissionID = id
// Community should have eventSenderRole permission or eventSender will loose his role
// after control node create a new community permission
if testPermissionType != rolePermissionType {
rolePermission := createTestPermissionRequest(community, rolePermissionType)
controlNodeCreatesCommunityPermission(base, community, rolePermission)
}
s.Require().NotEqual(tokenPermissionID, "")
ownerCommunity, err := base.GetControlNode().communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
assertCheckTokenPermissionCreated(s, ownerCommunity)
// then, ensure event sender receives updated community
_, err = WaitOnMessengerResponse(
base.GetEventSender(),
func(r *MessengerResponse) bool { return len(r.Communities()) > 0 },
"event sender did not receive updated community",
)
s.Require().NoError(err)
eventSenderCommunity, err := base.GetEventSender().communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
assertCheckTokenPermissionCreated(s, eventSenderCommunity)
permissionRequest := createTestPermissionRequest(community, testPermissionType)
tokenPermissionID := controlNodeCreatesCommunityPermission(base, community, permissionRequest)
permissionRequest.TokenCriteria[0].Symbol = "UPDATED"
permissionRequest.TokenCriteria[0].Amount = "200"
@ -1636,7 +1682,8 @@ func testEventSenderCannotEditBecomeAdminPermission(base CommunityEventsTestsInt
}
// then, event sender tries to edit permission
response, err = base.GetEventSender().EditCommunityTokenPermission(permissionEditRequest)
response, err := base.GetEventSender().EditCommunityTokenPermission(permissionEditRequest)
s := base.GetSuite()
s.Require().Error(err)
s.Require().Nil(response)
}
@ -1683,3 +1730,12 @@ func testEventSenderAddedCommunityToken(base CommunityEventsTestsInterface, comm
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkTokenAdded)
}
func testEventSenderCannotCreatePrivilegedCommunityPermission(base CommunityEventsTestsInterface, community *communities.Community, pType protobuf.CommunityTokenPermission_Type) {
permissionRequest := createTestPermissionRequest(community, pType)
response, err := base.GetEventSender().CreateCommunityTokenPermission(permissionRequest)
s := base.GetSuite()
s.Require().Nil(response)
s.Require().Error(err)
}

View File

@ -1,15 +1,16 @@
package protocol
import (
"crypto/ecdsa"
"math/big"
"testing"
"github.com/stretchr/testify/suite"
"go.uber.org/zap"
gethcommon "github.com/ethereum/go-ethereum/common"
hexutil "github.com/ethereum/go-ethereum/common/hexutil"
gethbridge "github.com/status-im/status-go/eth-node/bridge/geth"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/protocol/common"
"github.com/status-im/status-go/protocol/communities"
@ -30,8 +31,9 @@ type AdminCommunityEventsSuite struct {
alice *Messenger
// If one wants to send messages between different instances of Messenger,
// a single Waku service should be shared.
shh types.Waku
logger *zap.Logger
shh types.Waku
logger *zap.Logger
mockedBalances map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big // chainID, account, token, balance
}
func (s *AdminCommunityEventsSuite) GetControlNode() *Messenger {
@ -59,15 +61,17 @@ func (s *AdminCommunityEventsSuite) SetupTest() {
s.shh = gethbridge.NewGethWakuWrapper(shh)
s.Require().NoError(shh.Start())
s.owner = s.newMessenger()
s.admin = s.newMessenger()
s.alice = s.newMessenger()
s.owner = s.newMessenger("", []string{})
s.admin = s.newMessenger("qwerty", []string{commmunitiesEventsEventSenderAddress})
s.alice = s.newMessenger("", []string{})
_, err := s.owner.Start()
s.Require().NoError(err)
_, err = s.admin.Start()
s.Require().NoError(err)
_, err = s.alice.Start()
s.Require().NoError(err)
s.mockedBalances = createMockedWalletBalance(&s.Suite)
}
func (s *AdminCommunityEventsSuite) TearDownTest() {
@ -77,18 +81,8 @@ func (s *AdminCommunityEventsSuite) TearDownTest() {
_ = s.logger.Sync()
}
func (s *AdminCommunityEventsSuite) newMessengerWithKey(shh types.Waku, privateKey *ecdsa.PrivateKey) *Messenger {
messenger, err := newCommunitiesTestMessenger(shh, privateKey, s.logger, nil, nil)
s.Require().NoError(err)
return messenger
}
func (s *AdminCommunityEventsSuite) newMessenger() *Messenger {
privateKey, err := crypto.GenerateKey()
s.Require().NoError(err)
return s.newMessengerWithKey(s.shh, privateKey)
func (s *AdminCommunityEventsSuite) newMessenger(password string, walletAddresses []string) *Messenger {
return newMessenger(&s.Suite, s.shh, s.logger, password, walletAddresses, &s.mockedBalances)
}
func (s *AdminCommunityEventsSuite) TestAdminEditCommunityDescription() {
@ -104,42 +98,55 @@ func (s *AdminCommunityEventsSuite) TestAdminCreateEditDeleteChannels() {
func (s *AdminCommunityEventsSuite) TestAdminCreateEditDeleteBecomeMemberPermission() {
community := setUpCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN)
testCreateEditDeleteBecomeMemberPermission(s, community)
testCreateEditDeleteBecomeMemberPermission(s, community, protobuf.CommunityTokenPermission_BECOME_MEMBER)
}
func (s *AdminCommunityEventsSuite) TestAdminCannotCreateBecomeAdminPermission() {
community := setUpCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN)
testEventSenderCannotCreatePrivilegedCommunityPermission(s, community, protobuf.CommunityTokenPermission_BECOME_ADMIN)
}
permissionRequest := createTestPermissionRequest(community)
permissionRequest.Type = protobuf.CommunityTokenPermission_BECOME_ADMIN
response, err := s.admin.CreateCommunityTokenPermission(permissionRequest)
s.Require().Nil(response)
s.Require().Error(err)
func (s *AdminCommunityEventsSuite) TestAdminCannotCreateBecomeTokenMasterPermission() {
community := setUpCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN)
testEventSenderCannotCreatePrivilegedCommunityPermission(s, community, protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER)
}
func (s *AdminCommunityEventsSuite) TestAdminCannotEditBecomeAdminPermission() {
community := setUpCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN)
testEventSenderCannotEditBecomeAdminPermission(s, community)
testEventSenderCannotEditPrivilegedCommunityPermission(
s, community, protobuf.CommunityTokenPermission_BECOME_ADMIN, protobuf.CommunityTokenPermission_BECOME_ADMIN)
}
func (s *AdminCommunityEventsSuite) TestAdminCannotEditBecomeTokenMasterPermission() {
community := setUpCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN)
testEventSenderCannotEditPrivilegedCommunityPermission(
s, community, protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER, protobuf.CommunityTokenPermission_BECOME_ADMIN)
}
func (s *AdminCommunityEventsSuite) TestAdminCannotDeleteBecomeAdminPermission() {
community := setUpCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN)
testEventSenderCannotDeleteBecomeAdminPermission(s, community)
testEventSenderCannotDeletePrivilegedCommunityPermission(
s, community, protobuf.CommunityTokenPermission_BECOME_ADMIN, protobuf.CommunityTokenPermission_BECOME_ADMIN)
}
func (s *AdminCommunityEventsSuite) TestAdminCannotDeleteBecomeTokenMasterPermission() {
community := setUpCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN)
testEventSenderCannotDeletePrivilegedCommunityPermission(
s, community, protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER, protobuf.CommunityTokenPermission_BECOME_ADMIN)
}
func (s *AdminCommunityEventsSuite) TestAdminAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders() {
additionalAdmin := s.newMessenger()
additionalAdmin := s.newMessenger("qwerty", []string{commmunitiesEventsEventSenderAddress})
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN, []*Messenger{additionalAdmin})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders(s, community, user, additionalAdmin)
}
func (s *AdminCommunityEventsSuite) TestAdminAcceptMemberRequestToJoinNotConfirmedByControlNode() {
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN, []*Messenger{})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testAcceptMemberRequestToJoinNotConfirmedByControlNode(s, community, user)
}
@ -147,15 +154,15 @@ func (s *AdminCommunityEventsSuite) TestAdminAcceptMemberRequestToJoin() {
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN, []*Messenger{})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testAcceptMemberRequestToJoin(s, community, user)
}
func (s *AdminCommunityEventsSuite) TestAdminRejectMemberRequestToJoinResponseSharedWithOtherEventSenders() {
additionalAdmin := s.newMessenger()
additionalAdmin := s.newMessenger("qwerty", []string{commmunitiesEventsEventSenderAddress})
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN, []*Messenger{additionalAdmin})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders(s, community, user, additionalAdmin)
}
@ -163,7 +170,7 @@ func (s *AdminCommunityEventsSuite) TestAdminRejectMemberRequestToJoinNotConfirm
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN, []*Messenger{})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testRejectMemberRequestToJoinNotConfirmedByControlNode(s, community, user)
}
@ -171,25 +178,25 @@ func (s *AdminCommunityEventsSuite) TestAdminRejectMemberRequestToJoin() {
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN, []*Messenger{})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testRejectMemberRequestToJoin(s, community, user)
}
func (s *AdminCommunityEventsSuite) TestAdminRequestToJoinStateCannotBeOverridden() {
additionalAdmin := s.newMessenger()
additionalAdmin := s.newMessenger("qwerty", []string{commmunitiesEventsEventSenderAddress})
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN, []*Messenger{additionalAdmin})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testEventSenderCannotOverrideRequestToJoinState(s, community, user, additionalAdmin)
}
func (s *AdminCommunityEventsSuite) TestAdminControlNodeHandlesMultipleEventSenderRequestToJoinDecisions() {
additionalAdmin := s.newMessenger()
additionalAdmin := s.newMessenger("qwerty", []string{commmunitiesEventsEventSenderAddress})
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN, []*Messenger{additionalAdmin})
// set up additional user that will send request to join
user := s.newMessenger()
user := s.newMessenger("", []string{})
testControlNodeHandlesMultipleEventSenderRequestToJoinDecisions(s, community, user, additionalAdmin)
}

View File

@ -6,15 +6,22 @@ import (
"encoding/json"
"errors"
"io/ioutil"
"sync"
"time"
"github.com/google/uuid"
"github.com/stretchr/testify/suite"
"go.uber.org/zap"
gethcommon "github.com/ethereum/go-ethereum/common"
hexutil "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/status-im/status-go/account"
"github.com/status-im/status-go/account/generator"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/multiaccounts"
"github.com/status-im/status-go/multiaccounts/accounts"
"github.com/status-im/status-go/multiaccounts/settings"
"github.com/status-im/status-go/params"
"github.com/status-im/status-go/protocol/common"
@ -25,6 +32,88 @@ import (
"github.com/status-im/status-go/protocol/tt"
)
type AccountManagerMock struct {
AccountsMap map[string]string
}
func (m *AccountManagerMock) GetVerifiedWalletAccount(db *accounts.Database, address, password string) (*account.SelectedExtKey, error) {
return &account.SelectedExtKey{
Address: types.HexToAddress(address),
}, nil
}
func (m *AccountManagerMock) CanRecover(rpcParams account.RecoverParams, revealedAddress types.Address) (bool, error) {
return true, nil
}
func (m *AccountManagerMock) Sign(rpcParams account.SignParams, verifiedAccount *account.SelectedExtKey) (result types.HexBytes, err error) {
return types.HexBytes{}, nil
}
func (m *AccountManagerMock) DeleteAccount(address types.Address) error {
return nil
}
type TokenManagerMock struct {
Balances *map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big
}
func (m *TokenManagerMock) GetAllChainIDs() ([]uint64, error) {
chainIDs := make([]uint64, 0, len(*m.Balances))
for key := range *m.Balances {
chainIDs = append(chainIDs, key)
}
return chainIDs, nil
}
func (m *TokenManagerMock) GetBalancesByChain(ctx context.Context, accounts, tokenAddresses []gethcommon.Address, chainIDs []uint64) (map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big, error) {
time.Sleep(100 * time.Millisecond) // simulate response time
return *m.Balances, nil
}
func newMessenger(s *suite.Suite, shh types.Waku, logger *zap.Logger, password string, walletAddresses []string,
mockedBalances *map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big) *Messenger {
accountsManagerMock := &AccountManagerMock{}
accountsManagerMock.AccountsMap = make(map[string]string)
for _, walletAddress := range walletAddresses {
accountsManagerMock.AccountsMap[walletAddress] = types.EncodeHex(crypto.Keccak256([]byte(password)))
}
tokenManagerMock := &TokenManagerMock{
Balances: mockedBalances,
}
privateKey, err := crypto.GenerateKey()
s.Require().NoError(err)
messenger, err := newCommunitiesTestMessenger(shh, privateKey, logger, accountsManagerMock, tokenManagerMock)
s.Require().NoError(err)
currentDistributorObj, ok := messenger.communitiesKeyDistributor.(*CommunitiesKeyDistributorImpl)
s.Require().True(ok)
messenger.communitiesKeyDistributor = &TestCommunitiesKeyDistributor{
CommunitiesKeyDistributorImpl: *currentDistributorObj,
subscriptions: map[chan *CommunityAndKeyActions]bool{},
mutex: sync.RWMutex{},
}
// add wallet account with keypair
for _, walletAddress := range walletAddresses {
kp := accounts.GetProfileKeypairForTest(false, true, false)
kp.Accounts[0].Address = types.HexToAddress(walletAddress)
err := messenger.settings.SaveOrUpdateKeypair(kp)
s.Require().NoError(err)
}
walletAccounts, err := messenger.settings.GetActiveAccounts()
s.Require().NoError(err)
s.Require().Len(walletAccounts, len(walletAddresses))
for i := range walletAddresses {
s.Require().Equal(walletAccounts[i].Type, accounts.AccountTypeGenerated)
}
return messenger
}
func newCommunitiesTestMessenger(shh types.Waku, privateKey *ecdsa.PrivateKey, logger *zap.Logger, accountsManager account.Manager, tokenManager communities.TokenManager) (*Messenger, error) {
tmpfile, err := ioutil.TempFile("", "accounts-tests-")
if err != nil {

View File

@ -2,7 +2,6 @@ package protocol
import (
"bytes"
"context"
"crypto/ecdsa"
"errors"
"math/big"
@ -15,11 +14,9 @@ import (
gethcommon "github.com/ethereum/go-ethereum/common"
hexutil "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/status-im/status-go/account"
gethbridge "github.com/status-im/status-go/eth-node/bridge/geth"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/multiaccounts/accounts"
"github.com/status-im/status-go/protocol/common"
"github.com/status-im/status-go/protocol/communities"
"github.com/status-im/status-go/protocol/protobuf"
@ -39,45 +36,6 @@ const aliceAddress1 = "0x0200000000000000000000000000000000000000"
const aliceAddress2 = "0x0210000000000000000000000000000000000000"
const bobAddress = "0x0300000000000000000000000000000000000000"
type AccountManagerMock struct {
AccountsMap map[string]string
}
func (m *AccountManagerMock) GetVerifiedWalletAccount(db *accounts.Database, address, password string) (*account.SelectedExtKey, error) {
return &account.SelectedExtKey{
Address: types.HexToAddress(address),
}, nil
}
func (m *AccountManagerMock) CanRecover(rpcParams account.RecoverParams, revealedAddress types.Address) (bool, error) {
return true, nil
}
func (m *AccountManagerMock) Sign(rpcParams account.SignParams, verifiedAccount *account.SelectedExtKey) (result types.HexBytes, err error) {
return types.HexBytes{}, nil
}
func (m *AccountManagerMock) DeleteAccount(address types.Address) error {
return nil
}
type TokenManagerMock struct {
Balances *map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big
}
func (m *TokenManagerMock) GetAllChainIDs() ([]uint64, error) {
chainIDs := make([]uint64, 0, len(*m.Balances))
for key := range *m.Balances {
chainIDs = append(chainIDs, key)
}
return chainIDs, nil
}
func (m *TokenManagerMock) GetBalancesByChain(ctx context.Context, accounts, tokenAddresses []gethcommon.Address, chainIDs []uint64) (map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big, error) {
time.Sleep(100 * time.Millisecond) // simulate response time
return *m.Balances, nil
}
type CommunityAndKeyActions struct {
community *communities.Community
keyActions *communities.EncryptionKeyActions
@ -200,45 +158,7 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) TearDownTest() {
}
func (s *MessengerCommunitiesTokenPermissionsSuite) newMessenger(password string, walletAddresses []string) *Messenger {
accountsManagerMock := &AccountManagerMock{}
accountsManagerMock.AccountsMap = make(map[string]string)
for _, walletAddress := range walletAddresses {
accountsManagerMock.AccountsMap[walletAddress] = types.EncodeHex(crypto.Keccak256([]byte(password)))
}
tokenManagerMock := &TokenManagerMock{
Balances: &s.mockedBalances,
}
privateKey, err := crypto.GenerateKey()
s.Require().NoError(err)
messenger, err := newCommunitiesTestMessenger(s.shh, privateKey, s.logger, accountsManagerMock, tokenManagerMock)
s.Require().NoError(err)
currentDistributorObj, ok := messenger.communitiesKeyDistributor.(*CommunitiesKeyDistributorImpl)
s.Require().True(ok)
messenger.communitiesKeyDistributor = &TestCommunitiesKeyDistributor{
CommunitiesKeyDistributorImpl: *currentDistributorObj,
subscriptions: map[chan *CommunityAndKeyActions]bool{},
mutex: sync.RWMutex{},
}
// add wallet account with keypair
for _, walletAddress := range walletAddresses {
kp := accounts.GetProfileKeypairForTest(false, true, false)
kp.Accounts[0].Address = types.HexToAddress(walletAddress)
err := messenger.settings.SaveOrUpdateKeypair(kp)
s.Require().NoError(err)
}
walletAccounts, err := messenger.settings.GetActiveAccounts()
s.Require().NoError(err)
s.Require().Len(walletAccounts, len(walletAddresses))
for i := range walletAddresses {
s.Require().Equal(walletAccounts[i].Type, accounts.AccountTypeGenerated)
}
return messenger
return newMessenger(&s.Suite, s.shh, s.logger, password, walletAddresses, &s.mockedBalances)
}
func (s *MessengerCommunitiesTokenPermissionsSuite) joinCommunity(community *communities.Community, user *Messenger, password string, addresses []string) {