2023-07-26 12:16:50 +00:00
|
|
|
package protocol
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
2023-08-04 10:28:46 +00:00
|
|
|
"math/big"
|
2023-07-26 12:16:50 +00:00
|
|
|
|
|
|
|
"github.com/stretchr/testify/suite"
|
|
|
|
|
2023-08-08 15:02:56 +00:00
|
|
|
gethcommon "github.com/ethereum/go-ethereum/common"
|
|
|
|
hexutil "github.com/ethereum/go-ethereum/common/hexutil"
|
|
|
|
|
2023-07-26 12:16:50 +00:00
|
|
|
"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"
|
2023-07-07 13:03:37 +00:00
|
|
|
"github.com/status-im/status-go/protocol/communities/token"
|
2023-07-26 12:16:50 +00:00
|
|
|
"github.com/status-im/status-go/protocol/protobuf"
|
|
|
|
"github.com/status-im/status-go/protocol/requests"
|
2023-08-25 15:36:39 +00:00
|
|
|
"github.com/status-im/status-go/services/communitytokens"
|
2023-08-04 10:28:46 +00:00
|
|
|
"github.com/status-im/status-go/services/wallet/bigint"
|
2023-07-26 12:16:50 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type CommunityEventsTestsInterface interface {
|
|
|
|
GetControlNode() *Messenger
|
|
|
|
GetEventSender() *Messenger
|
|
|
|
GetMember() *Messenger
|
|
|
|
GetSuite() *suite.Suite
|
2023-08-22 17:48:42 +00:00
|
|
|
GetCollectiblesServiceMock() *CollectiblesServiceMock
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
2023-08-08 15:02:56 +00:00
|
|
|
const commmunitiesEventsTestTokenAddress = "0x0400000000000000000000000000000000000000"
|
|
|
|
const commmunitiesEventsTestChainID = 1
|
|
|
|
const commmunitiesEventsEventSenderAddress = "0x0200000000000000000000000000000000000000"
|
|
|
|
|
2023-07-26 12:16:50 +00:00
|
|
|
type MessageResponseValidator func(*MessengerResponse) error
|
|
|
|
type WaitResponseValidator func(*MessengerResponse) bool
|
|
|
|
|
|
|
|
func WaitCommunityCondition(r *MessengerResponse) bool {
|
|
|
|
return len(r.Communities()) > 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func WaitMessageCondition(response *MessengerResponse) bool {
|
|
|
|
return len(response.Messages()) > 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func waitOnMessengerResponse(s *suite.Suite, fnWait WaitResponseValidator, fn MessageResponseValidator, user *Messenger) {
|
|
|
|
response, err := WaitOnMessengerResponse(
|
|
|
|
user,
|
|
|
|
fnWait,
|
|
|
|
"MessengerResponse data not received",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NoError(fn(response))
|
|
|
|
}
|
|
|
|
|
|
|
|
func checkClientsReceivedAdminEvent(base CommunityEventsTestsInterface, fnWait WaitResponseValidator, fn MessageResponseValidator) {
|
|
|
|
s := base.GetSuite()
|
|
|
|
// Wait and verify Member received community event
|
|
|
|
waitOnMessengerResponse(s, fnWait, fn, base.GetMember())
|
|
|
|
// Wait and verify event sender received his own event
|
|
|
|
waitOnMessengerResponse(s, fnWait, fn, base.GetEventSender())
|
|
|
|
// Wait and verify ControlNode received community event
|
|
|
|
// ControlNode will publish CommunityDescription update
|
|
|
|
waitOnMessengerResponse(s, fnWait, fn, base.GetControlNode())
|
|
|
|
// Wait and verify Member received the ControlNode CommunityDescription update
|
|
|
|
waitOnMessengerResponse(s, fnWait, fn, base.GetMember())
|
|
|
|
// Wait and verify event sender received the ControlNode CommunityDescription update
|
|
|
|
waitOnMessengerResponse(s, fnWait, fn, base.GetEventSender())
|
|
|
|
// Wait and verify ControlNode received his own CommunityDescription update
|
|
|
|
waitOnMessengerResponse(s, fnWait, fn, base.GetControlNode())
|
|
|
|
}
|
|
|
|
|
|
|
|
func refreshMessengerResponses(base CommunityEventsTestsInterface) {
|
|
|
|
_, err := WaitOnMessengerResponse(base.GetControlNode(), func(response *MessengerResponse) bool {
|
|
|
|
return true
|
|
|
|
}, "community description changed message not received")
|
|
|
|
base.GetSuite().Require().NoError(err)
|
|
|
|
|
|
|
|
_, err = WaitOnMessengerResponse(base.GetEventSender(), func(response *MessengerResponse) bool {
|
|
|
|
return true
|
|
|
|
}, "community description changed message not received")
|
|
|
|
base.GetSuite().Require().NoError(err)
|
|
|
|
|
|
|
|
_, err = WaitOnMessengerResponse(base.GetMember(), func(response *MessengerResponse) bool {
|
|
|
|
return true
|
|
|
|
}, "community description changed message not received")
|
|
|
|
base.GetSuite().Require().NoError(err)
|
|
|
|
}
|
|
|
|
|
2023-08-08 15:02:56 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2023-07-26 12:16:50 +00:00
|
|
|
func setUpCommunityAndRoles(base CommunityEventsTestsInterface, role protobuf.CommunityMember_Roles) *communities.Community {
|
|
|
|
tcs2, err := base.GetControlNode().communitiesManager.All()
|
|
|
|
suite := base.GetSuite()
|
|
|
|
suite.Require().NoError(err, "eventSender.communitiesManager.All")
|
|
|
|
suite.Len(tcs2, 1, "Must have 1 community")
|
|
|
|
|
|
|
|
// ControlNode creates a community and chat
|
|
|
|
community := createTestCommunity(base, protobuf.CommunityPermissions_NO_MEMBERSHIP)
|
|
|
|
refreshMessengerResponses(base)
|
|
|
|
|
|
|
|
// add events sender and member to the community
|
|
|
|
advertiseCommunityTo(suite, community, base.GetControlNode(), base.GetEventSender())
|
|
|
|
advertiseCommunityTo(suite, community, base.GetControlNode(), base.GetMember())
|
|
|
|
|
2023-08-08 15:02:56 +00:00
|
|
|
request := &requests.RequestToJoinCommunity{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
AddressesToReveal: []string{commmunitiesEventsEventSenderAddress},
|
|
|
|
Password: "qwerty1",
|
|
|
|
AirdropAddress: commmunitiesEventsEventSenderAddress,
|
|
|
|
}
|
2023-07-26 12:16:50 +00:00
|
|
|
joinCommunity(suite, community, base.GetControlNode(), base.GetEventSender(), request)
|
2023-07-28 18:18:27 +00:00
|
|
|
refreshMessengerResponses(base)
|
2023-08-08 15:02:56 +00:00
|
|
|
|
|
|
|
request = &requests.RequestToJoinCommunity{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
AddressesToReveal: []string{"0x0300000000000000000000000000000000000000"},
|
|
|
|
Password: "qwerty2",
|
|
|
|
AirdropAddress: "0x0300000000000000000000000000000000000000",
|
|
|
|
}
|
2023-07-26 12:16:50 +00:00
|
|
|
joinCommunity(suite, community, base.GetControlNode(), base.GetMember(), request)
|
|
|
|
refreshMessengerResponses(base)
|
|
|
|
|
|
|
|
// grant permissions to the event sender
|
|
|
|
grantPermission(suite, community, base.GetControlNode(), base.GetEventSender(), role)
|
|
|
|
refreshMessengerResponses(base)
|
|
|
|
|
|
|
|
return community
|
|
|
|
}
|
|
|
|
|
|
|
|
func createTestCommunity(base CommunityEventsTestsInterface, membershipType protobuf.CommunityPermissions_Access) *communities.Community {
|
|
|
|
description := &requests.CreateCommunity{
|
|
|
|
Membership: membershipType,
|
|
|
|
Name: "status",
|
|
|
|
Color: "#ffffff",
|
|
|
|
Description: "status community description",
|
|
|
|
PinMessageAllMembersEnabled: false,
|
|
|
|
}
|
|
|
|
response, err := base.GetControlNode().CreateCommunity(description, true)
|
|
|
|
|
|
|
|
suite := base.GetSuite()
|
|
|
|
suite.Require().NoError(err)
|
|
|
|
suite.Require().NotNil(response)
|
|
|
|
suite.Require().Len(response.Communities(), 1)
|
|
|
|
suite.Require().Len(response.Chats(), 1)
|
|
|
|
|
|
|
|
return response.Communities()[0]
|
|
|
|
}
|
|
|
|
|
|
|
|
func getModifiedCommunity(response *MessengerResponse, communityID string) (*communities.Community, error) {
|
|
|
|
if len(response.Communities()) == 0 {
|
|
|
|
return nil, errors.New("community not received")
|
|
|
|
}
|
|
|
|
|
|
|
|
var modifiedCommmunity *communities.Community = nil
|
|
|
|
for _, c := range response.Communities() {
|
|
|
|
if c.IDString() == communityID {
|
|
|
|
modifiedCommmunity = c
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if modifiedCommmunity == nil {
|
|
|
|
return nil, errors.New("couldn't find community in response")
|
|
|
|
}
|
|
|
|
|
|
|
|
return modifiedCommmunity, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func createCommunityChannel(base CommunityEventsTestsInterface, community *communities.Community, newChannel *protobuf.CommunityChat) string {
|
|
|
|
checkChannelCreated := func(response *MessengerResponse) error {
|
|
|
|
modifiedCommmunity, err := getModifiedCommunity(response, community.IDString())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, chat := range modifiedCommmunity.Chats() {
|
|
|
|
if chat.GetIdentity().GetDisplayName() == newChannel.GetIdentity().GetDisplayName() {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return errors.New("couldn't find created chat in response")
|
|
|
|
}
|
|
|
|
|
|
|
|
response, err := base.GetEventSender().CreateCommunityChat(community.ID(), newChannel)
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NoError(checkChannelCreated(response))
|
|
|
|
s.Require().Len(response.CommunityChanges, 1)
|
|
|
|
s.Require().Len(response.CommunityChanges[0].ChatsAdded, 1)
|
|
|
|
var addedChatID string
|
|
|
|
for addedChatID = range response.CommunityChanges[0].ChatsAdded {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkChannelCreated)
|
|
|
|
|
|
|
|
return addedChatID
|
|
|
|
}
|
|
|
|
|
|
|
|
func editCommunityChannel(base CommunityEventsTestsInterface, community *communities.Community, editChannel *protobuf.CommunityChat, channelID string) {
|
|
|
|
checkChannelEdited := func(response *MessengerResponse) error {
|
|
|
|
modifiedCommmunity, err := getModifiedCommunity(response, community.IDString())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, chat := range modifiedCommmunity.Chats() {
|
|
|
|
if chat.GetIdentity().GetDisplayName() == editChannel.GetIdentity().GetDisplayName() {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return errors.New("couldn't find modified chat in response")
|
|
|
|
}
|
|
|
|
|
|
|
|
response, err := base.GetEventSender().EditCommunityChat(community.ID(), channelID, editChannel)
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NoError(checkChannelEdited(response))
|
|
|
|
|
|
|
|
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkChannelEdited)
|
|
|
|
}
|
|
|
|
|
|
|
|
func deleteCommunityChannel(base CommunityEventsTestsInterface, community *communities.Community, channelID string) {
|
|
|
|
checkChannelDeleted := func(response *MessengerResponse) error {
|
|
|
|
modifiedCommmunity, err := getModifiedCommunity(response, community.IDString())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, exists := modifiedCommmunity.Chats()[channelID]; exists {
|
|
|
|
return errors.New("channel was not deleted")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
response, err := base.GetEventSender().DeleteCommunityChat(community.ID(), channelID)
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NoError(checkChannelDeleted(response))
|
|
|
|
|
|
|
|
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkChannelDeleted)
|
|
|
|
}
|
|
|
|
|
2023-08-08 15:02:56 +00:00
|
|
|
func createTestPermissionRequest(community *communities.Community, pType protobuf.CommunityTokenPermission_Type) *requests.CreateCommunityTokenPermission {
|
2023-07-26 12:16:50 +00:00
|
|
|
return &requests.CreateCommunityTokenPermission{
|
|
|
|
CommunityID: community.ID(),
|
2023-08-08 15:02:56 +00:00
|
|
|
Type: pType,
|
2023-07-26 12:16:50 +00:00
|
|
|
TokenCriteria: []*protobuf.TokenCriteria{
|
|
|
|
{
|
|
|
|
Type: protobuf.CommunityTokenType_ERC20,
|
2023-08-08 15:02:56 +00:00
|
|
|
ContractAddresses: map[uint64]string{uint64(commmunitiesEventsTestChainID): commmunitiesEventsTestTokenAddress},
|
2023-07-26 12:16:50 +00:00
|
|
|
Symbol: "TEST",
|
|
|
|
Amount: "100",
|
|
|
|
Decimals: uint64(18),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func createTokenPermission(base CommunityEventsTestsInterface, community *communities.Community, request *requests.CreateCommunityTokenPermission) (string, *requests.CreateCommunityTokenPermission) {
|
2023-08-17 17:14:23 +00:00
|
|
|
response, err := base.GetEventSender().CreateCommunityTokenPermission(request)
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(response.CommunityChanges, 1)
|
|
|
|
s.Require().Len(response.CommunityChanges[0].TokenPermissionsAdded, 1)
|
2023-07-26 12:16:50 +00:00
|
|
|
|
2023-08-17 17:14:23 +00:00
|
|
|
addedPermission := func() *communities.CommunityTokenPermission {
|
|
|
|
for _, permission := range response.CommunityChanges[0].TokenPermissionsAdded {
|
|
|
|
return permission
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
return nil
|
2023-08-17 17:14:23 +00:00
|
|
|
}()
|
|
|
|
s.Require().NotNil(addedPermission)
|
|
|
|
// Permission added by event must be in pending state
|
|
|
|
s.Require().Equal(communities.TokenPermissionAdditionPending, addedPermission.State)
|
|
|
|
|
|
|
|
responseHasApprovedTokenPermission := func(r *MessengerResponse) bool {
|
|
|
|
if len(r.Communities()) == 0 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
receivedPermission := r.Communities()[0].TokenPermissionByID(addedPermission.Id)
|
|
|
|
return receivedPermission != nil && receivedPermission.State == communities.TokenPermissionApproved
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
2023-08-17 17:14:23 +00:00
|
|
|
// Control node receives community event & approves it
|
|
|
|
_, err = WaitOnMessengerResponse(base.GetControlNode(), responseHasApprovedTokenPermission, "community with approved permission not found")
|
2023-07-26 12:16:50 +00:00
|
|
|
s.Require().NoError(err)
|
|
|
|
|
2023-08-17 17:14:23 +00:00
|
|
|
// Member receives updated community description
|
|
|
|
_, err = WaitOnMessengerResponse(base.GetMember(), responseHasApprovedTokenPermission, "community with approved permission not found")
|
|
|
|
s.Require().NoError(err)
|
2023-07-26 12:16:50 +00:00
|
|
|
|
2023-08-17 17:14:23 +00:00
|
|
|
// EventSender receives updated community description
|
|
|
|
_, err = WaitOnMessengerResponse(base.GetEventSender(), responseHasApprovedTokenPermission, "community with approved permission not found")
|
|
|
|
s.Require().NoError(err)
|
2023-07-26 12:16:50 +00:00
|
|
|
|
2023-08-17 17:14:23 +00:00
|
|
|
return addedPermission.Id, request
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
2023-08-08 15:02:56 +00:00
|
|
|
func createTestTokenPermission(base CommunityEventsTestsInterface, community *communities.Community, pType protobuf.CommunityTokenPermission_Type) (string, *requests.CreateCommunityTokenPermission) {
|
|
|
|
createTokenPermissionRequest := createTestPermissionRequest(community, pType)
|
2023-07-26 12:16:50 +00:00
|
|
|
return createTokenPermission(base, community, createTokenPermissionRequest)
|
|
|
|
}
|
|
|
|
|
|
|
|
func editTokenPermission(base CommunityEventsTestsInterface, community *communities.Community, request *requests.EditCommunityTokenPermission) {
|
|
|
|
s := base.GetSuite()
|
|
|
|
|
2023-08-17 17:14:23 +00:00
|
|
|
response, err := base.GetEventSender().EditCommunityTokenPermission(request)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(response.CommunityChanges, 1)
|
|
|
|
s.Require().Len(response.CommunityChanges[0].TokenPermissionsModified, 1)
|
|
|
|
|
|
|
|
editedPermission := response.CommunityChanges[0].TokenPermissionsModified[request.PermissionID]
|
|
|
|
s.Require().NotNil(editedPermission)
|
|
|
|
// Permission edited by event must be in pending state
|
|
|
|
s.Require().Equal(communities.TokenPermissionUpdatePending, editedPermission.State)
|
|
|
|
|
|
|
|
permissionSatisfyRequest := func(p *communities.CommunityTokenPermission) bool {
|
|
|
|
return request.Type == p.Type &&
|
|
|
|
request.TokenCriteria[0].Symbol == p.TokenCriteria[0].Symbol &&
|
|
|
|
request.TokenCriteria[0].Amount == p.TokenCriteria[0].Amount &&
|
|
|
|
request.TokenCriteria[0].Decimals == p.TokenCriteria[0].Decimals
|
|
|
|
}
|
|
|
|
s.Require().True(permissionSatisfyRequest(editedPermission))
|
2023-07-26 12:16:50 +00:00
|
|
|
|
2023-08-17 17:14:23 +00:00
|
|
|
responseHasApprovedEditedTokenPermission := func(r *MessengerResponse) bool {
|
|
|
|
if len(r.Communities()) == 0 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
receivedPermission := r.Communities()[0].TokenPermissionByID(editedPermission.Id)
|
|
|
|
return receivedPermission != nil && receivedPermission.State == communities.TokenPermissionApproved &&
|
|
|
|
permissionSatisfyRequest(receivedPermission)
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
2023-08-17 17:14:23 +00:00
|
|
|
// Control node receives community event & approves it
|
|
|
|
_, err = WaitOnMessengerResponse(base.GetControlNode(), responseHasApprovedEditedTokenPermission, "community with approved permission not found")
|
2023-07-26 12:16:50 +00:00
|
|
|
s.Require().NoError(err)
|
|
|
|
|
2023-08-17 17:14:23 +00:00
|
|
|
// Member receives updated community description
|
|
|
|
_, err = WaitOnMessengerResponse(base.GetMember(), responseHasApprovedEditedTokenPermission, "community with approved permission not found")
|
|
|
|
s.Require().NoError(err)
|
2023-07-26 12:16:50 +00:00
|
|
|
|
2023-08-17 17:14:23 +00:00
|
|
|
// EventSender receives updated community description
|
|
|
|
_, err = WaitOnMessengerResponse(base.GetEventSender(), responseHasApprovedEditedTokenPermission, "community with approved permission not found")
|
|
|
|
s.Require().NoError(err)
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func deleteTokenPermission(base CommunityEventsTestsInterface, community *communities.Community, request *requests.DeleteCommunityTokenPermission) {
|
2023-08-17 17:14:23 +00:00
|
|
|
response, err := base.GetEventSender().DeleteCommunityTokenPermission(request)
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(response.CommunityChanges, 1)
|
|
|
|
s.Require().Len(response.CommunityChanges[0].TokenPermissionsModified, 1)
|
|
|
|
|
|
|
|
removedPermission := response.CommunityChanges[0].TokenPermissionsModified[request.PermissionID]
|
|
|
|
s.Require().NotNil(removedPermission)
|
|
|
|
// Permission removed by event must be in pending state
|
|
|
|
s.Require().Equal(communities.TokenPermissionRemovalPending, removedPermission.State)
|
2023-07-26 12:16:50 +00:00
|
|
|
|
2023-08-17 17:14:23 +00:00
|
|
|
responseHasNoTokenPermission := func(r *MessengerResponse) bool {
|
|
|
|
if len(r.Communities()) == 0 {
|
|
|
|
return false
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
2023-08-17 17:14:23 +00:00
|
|
|
return r.Communities()[0].TokenPermissionByID(removedPermission.Id) == nil
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
2023-08-17 17:14:23 +00:00
|
|
|
// Control node receives community event & approves it
|
|
|
|
_, err = WaitOnMessengerResponse(base.GetControlNode(), responseHasNoTokenPermission, "community with approved permission not found")
|
2023-07-26 12:16:50 +00:00
|
|
|
s.Require().NoError(err)
|
|
|
|
|
2023-08-17 17:14:23 +00:00
|
|
|
// Member receives updated community description
|
|
|
|
_, err = WaitOnMessengerResponse(base.GetMember(), responseHasNoTokenPermission, "community with approved permission not found")
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// EventSender receives updated community description
|
|
|
|
_, err = WaitOnMessengerResponse(base.GetEventSender(), responseHasNoTokenPermission, "community with approved permission not found")
|
|
|
|
s.Require().NoError(err)
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
2023-08-08 15:02:56 +00:00
|
|
|
func assertCheckTokenPermissionCreated(s *suite.Suite, community *communities.Community, pType protobuf.CommunityTokenPermission_Type) {
|
|
|
|
permissions := community.TokenPermissionsByType(pType)
|
2023-07-26 12:16:50 +00:00
|
|
|
s.Require().Len(permissions, 1)
|
|
|
|
s.Require().Len(permissions[0].TokenCriteria, 1)
|
|
|
|
s.Require().Equal(permissions[0].TokenCriteria[0].Type, protobuf.CommunityTokenType_ERC20)
|
|
|
|
s.Require().Equal(permissions[0].TokenCriteria[0].Symbol, "TEST")
|
|
|
|
s.Require().Equal(permissions[0].TokenCriteria[0].Amount, "100")
|
|
|
|
s.Require().Equal(permissions[0].TokenCriteria[0].Decimals, uint64(18))
|
|
|
|
}
|
|
|
|
|
refactor: EventSenders forward RequestToJoin decision to control node
This is a bigger change in how community membership requests are handled
among admins, token masters, owners, and control nodes.
Prior to this commit, all privileged users, also known as
`EventSenders`, were able to accept and reject community membership
requests and those changes would be applied by all users.
This commit changes this behaviour such that:
1. EventSenders can make a decision (accept, reject), but merely forward
their decision to the control node, which ultimately has to confirm
it
2. EventSenders are no longer removing or adding members to and from
communities
3. When an eventsender signaled a decision, the membership request will
enter a pending state (acceptedPending or rejectedPending)
4. Once a decision was made by one eventsender, no other eventsender can
override that decision
This implementation is covered with a bunch of tests:
- Ensure that decision made by event sender is shared with other event
senders
- `testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- `testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- Ensure memebrship request stays pending, until control node has
confirmed decision by event senders
- `testAcceptMemberRequestToJoinNotConfirmedByControlNode()`
- `testRejectMemberRequestToJoinNotConfirmedByControlNode()`
- Ensure that decision made by event sender cannot be overriden by other
event senders
- `testEventSenderCannotOverrideRequestToJoinState()`
These test cases live in three test suites for different event sender
types respectively
- `OwnerWithoutCommunityKeyCommunityEventsSuite`
- `TokenMasterCommunityEventsSuite`
- `AdminCommunityEventsSuite`
In addition to the changes mentioned above, there's also a smaller
changes that ensures membership requests to *not* attached revealed wallet
addresses when the requests are sent to event senders (in addition to
control nodes).
Requests send to a control node will still include revealed addresses as
the control node needs them to verify token permissions.
This commit does not yet handle the case of event senders attempting to
kick and ban members.
Similar to accepting and rejecting membership requests, kicking and
banning need a new pending state. However, we don't track such state in
local databases yet so those two cases will be handled in future commit
to not have this commit grow larger.
2023-08-02 12:04:47 +00:00
|
|
|
func setUpOnRequestCommunityAndRoles(base CommunityEventsTestsInterface, role protobuf.CommunityMember_Roles, additionalEventSenders []*Messenger) *communities.Community {
|
2023-07-26 12:16:50 +00:00
|
|
|
tcs2, err := base.GetControlNode().communitiesManager.All()
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err, "eventSender.communitiesManager.All")
|
|
|
|
s.Len(tcs2, 1, "Must have 1 community")
|
|
|
|
|
|
|
|
// control node creates a community and chat
|
|
|
|
community := createTestCommunity(base, protobuf.CommunityPermissions_ON_REQUEST)
|
2023-07-28 18:18:27 +00:00
|
|
|
refreshMessengerResponses(base)
|
|
|
|
|
2023-07-26 12:16:50 +00:00
|
|
|
advertiseCommunityTo(s, community, base.GetControlNode(), base.GetEventSender())
|
|
|
|
advertiseCommunityTo(s, community, base.GetControlNode(), base.GetMember())
|
|
|
|
|
|
|
|
joinOnRequestCommunity(s, community, base.GetControlNode(), base.GetEventSender())
|
|
|
|
joinOnRequestCommunity(s, community, base.GetControlNode(), base.GetMember())
|
2023-07-31 15:52:41 +00:00
|
|
|
|
|
|
|
checkMemberJoined := func(response *MessengerResponse) error {
|
|
|
|
return checkMemberJoinedToTheCommunity(response, base.GetMember().IdentityPublicKey())
|
|
|
|
}
|
|
|
|
|
|
|
|
waitOnMessengerResponse(s, WaitCommunityCondition, checkMemberJoined, base.GetEventSender())
|
2023-07-26 12:16:50 +00:00
|
|
|
|
|
|
|
// grant permissions to event sender
|
|
|
|
grantPermission(s, community, base.GetControlNode(), base.GetEventSender(), role)
|
2023-07-31 15:52:41 +00:00
|
|
|
checkPermissionGranted := func(response *MessengerResponse) error {
|
|
|
|
return checkRolePermissionInResponse(response, base.GetEventSender().IdentityPublicKey(), role)
|
|
|
|
}
|
|
|
|
waitOnMessengerResponse(s, WaitCommunityCondition, checkPermissionGranted, base.GetMember())
|
2023-07-26 12:16:50 +00:00
|
|
|
|
refactor: EventSenders forward RequestToJoin decision to control node
This is a bigger change in how community membership requests are handled
among admins, token masters, owners, and control nodes.
Prior to this commit, all privileged users, also known as
`EventSenders`, were able to accept and reject community membership
requests and those changes would be applied by all users.
This commit changes this behaviour such that:
1. EventSenders can make a decision (accept, reject), but merely forward
their decision to the control node, which ultimately has to confirm
it
2. EventSenders are no longer removing or adding members to and from
communities
3. When an eventsender signaled a decision, the membership request will
enter a pending state (acceptedPending or rejectedPending)
4. Once a decision was made by one eventsender, no other eventsender can
override that decision
This implementation is covered with a bunch of tests:
- Ensure that decision made by event sender is shared with other event
senders
- `testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- `testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- Ensure memebrship request stays pending, until control node has
confirmed decision by event senders
- `testAcceptMemberRequestToJoinNotConfirmedByControlNode()`
- `testRejectMemberRequestToJoinNotConfirmedByControlNode()`
- Ensure that decision made by event sender cannot be overriden by other
event senders
- `testEventSenderCannotOverrideRequestToJoinState()`
These test cases live in three test suites for different event sender
types respectively
- `OwnerWithoutCommunityKeyCommunityEventsSuite`
- `TokenMasterCommunityEventsSuite`
- `AdminCommunityEventsSuite`
In addition to the changes mentioned above, there's also a smaller
changes that ensures membership requests to *not* attached revealed wallet
addresses when the requests are sent to event senders (in addition to
control nodes).
Requests send to a control node will still include revealed addresses as
the control node needs them to verify token permissions.
This commit does not yet handle the case of event senders attempting to
kick and ban members.
Similar to accepting and rejecting membership requests, kicking and
banning need a new pending state. However, we don't track such state in
local databases yet so those two cases will be handled in future commit
to not have this commit grow larger.
2023-08-02 12:04:47 +00:00
|
|
|
for _, eventSender := range additionalEventSenders {
|
|
|
|
advertiseCommunityTo(s, community, base.GetControlNode(), eventSender)
|
|
|
|
joinOnRequestCommunity(s, community, base.GetControlNode(), eventSender)
|
|
|
|
|
|
|
|
grantPermission(s, community, base.GetControlNode(), eventSender, role)
|
|
|
|
checkPermissionGranted = func(response *MessengerResponse) error {
|
|
|
|
return checkRolePermissionInResponse(response, eventSender.IdentityPublicKey(), role)
|
|
|
|
}
|
|
|
|
waitOnMessengerResponse(s, WaitCommunityCondition, checkPermissionGranted, base.GetMember())
|
|
|
|
waitOnMessengerResponse(s, WaitCommunityCondition, checkPermissionGranted, base.GetEventSender())
|
|
|
|
}
|
|
|
|
|
2023-07-26 12:16:50 +00:00
|
|
|
return community
|
|
|
|
}
|
|
|
|
|
|
|
|
func createCommunityCategory(base CommunityEventsTestsInterface, community *communities.Community, newCategory *requests.CreateCommunityCategory) string {
|
|
|
|
checkCategoryCreated := func(response *MessengerResponse) error {
|
|
|
|
modifiedCommmunity, err := getModifiedCommunity(response, community.IDString())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, category := range modifiedCommmunity.Categories() {
|
|
|
|
if category.GetName() == newCategory.CategoryName {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return errors.New("couldn't find created Category in the response")
|
|
|
|
}
|
|
|
|
|
|
|
|
response, err := base.GetEventSender().CreateCommunityCategory(newCategory)
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NoError(checkCategoryCreated(response))
|
|
|
|
s.Require().Len(response.Communities(), 1)
|
|
|
|
s.Require().Len(response.CommunityChanges[0].CategoriesAdded, 1)
|
|
|
|
|
|
|
|
var categoryID string
|
|
|
|
for categoryID = range response.CommunityChanges[0].CategoriesAdded {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkCategoryCreated)
|
|
|
|
|
|
|
|
return categoryID
|
|
|
|
}
|
|
|
|
|
|
|
|
func editCommunityCategory(base CommunityEventsTestsInterface, communityID string, editCategory *requests.EditCommunityCategory) {
|
|
|
|
checkCategoryEdited := func(response *MessengerResponse) error {
|
|
|
|
modifiedCommmunity, err := getModifiedCommunity(response, communityID)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, category := range modifiedCommmunity.Categories() {
|
|
|
|
if category.GetName() == editCategory.CategoryName {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return errors.New("couldn't find edited Category in the response")
|
|
|
|
}
|
|
|
|
|
|
|
|
response, err := base.GetEventSender().EditCommunityCategory(editCategory)
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NoError(checkCategoryEdited(response))
|
|
|
|
|
|
|
|
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkCategoryEdited)
|
|
|
|
}
|
|
|
|
|
|
|
|
func deleteCommunityCategory(base CommunityEventsTestsInterface, communityID string, deleteCategory *requests.DeleteCommunityCategory) {
|
|
|
|
checkCategoryDeleted := func(response *MessengerResponse) error {
|
|
|
|
modifiedCommmunity, err := getModifiedCommunity(response, communityID)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, exists := modifiedCommmunity.Chats()[deleteCategory.CategoryID]; exists {
|
|
|
|
return errors.New("community was not deleted")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
response, err := base.GetEventSender().DeleteCommunityCategory(deleteCategory)
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NoError(checkCategoryDeleted(response))
|
|
|
|
|
|
|
|
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkCategoryDeleted)
|
|
|
|
}
|
|
|
|
|
|
|
|
func reorderCategory(base CommunityEventsTestsInterface, reorderRequest *requests.ReorderCommunityCategories) {
|
|
|
|
checkCategoryReorder := func(response *MessengerResponse) error {
|
|
|
|
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(reorderRequest.CommunityID))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
category, exist := modifiedCommmunity.Categories()[reorderRequest.CategoryID]
|
|
|
|
if !exist {
|
|
|
|
return errors.New("couldn't find community category")
|
|
|
|
}
|
|
|
|
|
|
|
|
if int(category.Position) != reorderRequest.Position {
|
|
|
|
return errors.New("category was not reordered")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
response, err := base.GetEventSender().ReorderCommunityCategories(reorderRequest)
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NoError(checkCategoryReorder(response))
|
|
|
|
|
|
|
|
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkCategoryReorder)
|
|
|
|
}
|
|
|
|
|
|
|
|
func reorderChannel(base CommunityEventsTestsInterface, reorderRequest *requests.ReorderCommunityChat) {
|
|
|
|
checkChannelReorder := func(response *MessengerResponse) error {
|
|
|
|
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(reorderRequest.CommunityID))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
chat, exist := modifiedCommmunity.Chats()[reorderRequest.ChatID]
|
|
|
|
if !exist {
|
|
|
|
return errors.New("couldn't find community chat")
|
|
|
|
}
|
|
|
|
|
|
|
|
if int(chat.Position) != reorderRequest.Position {
|
|
|
|
return errors.New("chat position was not reordered")
|
|
|
|
}
|
|
|
|
|
|
|
|
if chat.CategoryId != reorderRequest.CategoryID {
|
|
|
|
return errors.New("chat category was not reordered")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
response, err := base.GetEventSender().ReorderCommunityChat(reorderRequest)
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NoError(checkChannelReorder(response))
|
|
|
|
|
|
|
|
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkChannelReorder)
|
|
|
|
}
|
|
|
|
|
|
|
|
func kickMember(base CommunityEventsTestsInterface, communityID types.HexBytes, pubkey string) {
|
|
|
|
checkKicked := func(response *MessengerResponse) error {
|
|
|
|
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(communityID))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if modifiedCommmunity.HasMember(&base.GetMember().identity.PublicKey) {
|
|
|
|
return errors.New("alice was not kicked")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
response, err := base.GetEventSender().RemoveUserFromCommunity(
|
|
|
|
communityID,
|
|
|
|
pubkey,
|
|
|
|
)
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Nil(checkKicked(response))
|
|
|
|
|
|
|
|
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkKicked)
|
|
|
|
}
|
|
|
|
|
|
|
|
func banMember(base CommunityEventsTestsInterface, banRequest *requests.BanUserFromCommunity) {
|
|
|
|
checkBanned := func(response *MessengerResponse) error {
|
|
|
|
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(banRequest.CommunityID))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if modifiedCommmunity.HasMember(&base.GetMember().identity.PublicKey) {
|
|
|
|
return errors.New("alice was not removed from the member list")
|
|
|
|
}
|
|
|
|
|
|
|
|
if !modifiedCommmunity.IsBanned(&base.GetMember().identity.PublicKey) {
|
|
|
|
return errors.New("alice was not added to the banned list")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
response, err := base.GetEventSender().BanUserFromCommunity(banRequest)
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Nil(checkBanned(response))
|
|
|
|
|
|
|
|
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkBanned)
|
|
|
|
}
|
|
|
|
|
|
|
|
func unbanMember(base CommunityEventsTestsInterface, unbanRequest *requests.UnbanUserFromCommunity) {
|
|
|
|
checkUnbanned := func(response *MessengerResponse) error {
|
|
|
|
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(unbanRequest.CommunityID))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if modifiedCommmunity.IsBanned(&base.GetMember().identity.PublicKey) {
|
|
|
|
return errors.New("alice was not unbanned")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
response, err := base.GetEventSender().UnbanUserFromCommunity(unbanRequest)
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Nil(checkUnbanned(response))
|
|
|
|
|
|
|
|
response, err = WaitOnMessengerResponse(
|
|
|
|
base.GetControlNode(),
|
|
|
|
WaitCommunityCondition,
|
|
|
|
"MessengerResponse data not received",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NoError(checkUnbanned(response))
|
|
|
|
}
|
|
|
|
|
|
|
|
func controlNodeSendMessage(base CommunityEventsTestsInterface, inputMessage *common.Message) string {
|
|
|
|
response, err := base.GetControlNode().SendChatMessage(context.Background(), inputMessage)
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
message := response.Messages()[0]
|
|
|
|
s.Require().Equal(inputMessage.Text, message.Text)
|
|
|
|
messageID := message.ID
|
|
|
|
|
|
|
|
response, err = WaitOnMessengerResponse(base.GetEventSender(), WaitMessageCondition, "messages not received")
|
|
|
|
s.Require().NoError(err)
|
|
|
|
message = response.Messages()[0]
|
|
|
|
s.Require().Equal(inputMessage.Text, message.Text)
|
|
|
|
|
|
|
|
response, err = WaitOnMessengerResponse(base.GetMember(), WaitMessageCondition, "messages not received")
|
|
|
|
s.Require().NoError(err)
|
|
|
|
message = response.Messages()[0]
|
|
|
|
s.Require().Equal(inputMessage.Text, message.Text)
|
|
|
|
|
|
|
|
refreshMessengerResponses(base)
|
|
|
|
|
|
|
|
return messageID
|
|
|
|
}
|
|
|
|
|
|
|
|
func deleteControlNodeMessage(base CommunityEventsTestsInterface, messageID string) {
|
|
|
|
checkMessageDeleted := func(response *MessengerResponse) error {
|
|
|
|
if len(response.RemovedMessages()) > 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return errors.New("message was not deleted")
|
|
|
|
}
|
|
|
|
|
|
|
|
response, err := base.GetEventSender().DeleteMessageAndSend(context.Background(), messageID)
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NoError(checkMessageDeleted(response))
|
|
|
|
|
|
|
|
waitMessageCondition := func(response *MessengerResponse) bool {
|
|
|
|
return len(response.RemovedMessages()) > 0
|
|
|
|
}
|
|
|
|
waitOnMessengerResponse(s, waitMessageCondition, checkMessageDeleted, base.GetMember())
|
|
|
|
waitOnMessengerResponse(s, waitMessageCondition, checkMessageDeleted, base.GetControlNode())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func pinControlNodeMessage(base CommunityEventsTestsInterface, pinnedMessage *common.PinMessage) {
|
|
|
|
checkPinned := func(response *MessengerResponse) error {
|
|
|
|
if len(response.PinMessages()) > 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return errors.New("pin messages was not added")
|
|
|
|
}
|
|
|
|
|
|
|
|
response, err := base.GetEventSender().SendPinMessage(context.Background(), pinnedMessage)
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NoError(checkPinned(response))
|
|
|
|
|
|
|
|
waitOnMessengerResponse(s, WaitMessageCondition, checkPinned, base.GetMember())
|
|
|
|
waitOnMessengerResponse(s, WaitMessageCondition, checkPinned, base.GetControlNode())
|
|
|
|
}
|
|
|
|
|
|
|
|
func editCommunityDescription(base CommunityEventsTestsInterface, community *communities.Community) {
|
|
|
|
expectedName := "edited community name"
|
|
|
|
expectedColor := "#000000"
|
|
|
|
expectedDescr := "edited community description"
|
|
|
|
|
|
|
|
response, err := base.GetEventSender().EditCommunity(&requests.EditCommunity{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
CreateCommunity: requests.CreateCommunity{
|
|
|
|
Membership: protobuf.CommunityPermissions_ON_REQUEST,
|
|
|
|
Name: expectedName,
|
|
|
|
Color: expectedColor,
|
|
|
|
Description: expectedDescr,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
checkCommunityEdit := func(response *MessengerResponse) error {
|
|
|
|
if len(response.Communities()) == 0 {
|
|
|
|
return errors.New("community not received")
|
|
|
|
}
|
|
|
|
|
|
|
|
rCommunities := response.Communities()
|
|
|
|
if expectedName != rCommunities[0].Name() {
|
|
|
|
return errors.New("incorrect community name")
|
|
|
|
}
|
|
|
|
|
|
|
|
if expectedColor != rCommunities[0].Color() {
|
|
|
|
return errors.New("incorrect community color")
|
|
|
|
}
|
|
|
|
|
|
|
|
if expectedDescr != rCommunities[0].DescriptionText() {
|
|
|
|
return errors.New("incorrect community description")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Nil(checkCommunityEdit(response))
|
|
|
|
|
|
|
|
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkCommunityEdit)
|
|
|
|
}
|
|
|
|
|
2023-08-08 15:02:56 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2023-07-26 12:16:50 +00:00
|
|
|
func testCreateEditDeleteChannels(base CommunityEventsTestsInterface, community *communities.Community) {
|
|
|
|
newChat := &protobuf.CommunityChat{
|
|
|
|
Permissions: &protobuf.CommunityPermissions{
|
|
|
|
Access: protobuf.CommunityPermissions_NO_MEMBERSHIP,
|
|
|
|
},
|
|
|
|
Identity: &protobuf.ChatIdentity{
|
|
|
|
DisplayName: "chat from the event sender",
|
|
|
|
Emoji: "",
|
|
|
|
Description: "chat created by an event sender",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
newChatID := createCommunityChannel(base, community, newChat)
|
|
|
|
|
|
|
|
newChat.Identity.DisplayName = "modified chat from event sender"
|
|
|
|
editCommunityChannel(base, community, newChat, newChatID)
|
|
|
|
deleteCommunityChannel(base, community, newChatID)
|
|
|
|
}
|
|
|
|
|
2023-08-08 15:02:56 +00:00
|
|
|
func testCreateEditDeleteBecomeMemberPermission(base CommunityEventsTestsInterface, community *communities.Community, pType protobuf.CommunityTokenPermission_Type) {
|
2023-07-26 12:16:50 +00:00
|
|
|
// first, create token permission
|
2023-08-08 15:02:56 +00:00
|
|
|
tokenPermissionID, createTokenPermission := createTestTokenPermission(base, community, pType)
|
2023-07-26 12:16:50 +00:00
|
|
|
|
|
|
|
createTokenPermission.TokenCriteria[0].Symbol = "UPDATED"
|
|
|
|
createTokenPermission.TokenCriteria[0].Amount = "200"
|
|
|
|
|
|
|
|
editTokenPermissionRequest := &requests.EditCommunityTokenPermission{
|
|
|
|
PermissionID: tokenPermissionID,
|
|
|
|
CreateCommunityTokenPermission: *createTokenPermission,
|
|
|
|
}
|
|
|
|
|
|
|
|
// then, event sender edits the permission
|
|
|
|
editTokenPermission(base, community, editTokenPermissionRequest)
|
|
|
|
|
|
|
|
deleteTokenPermissionRequest := &requests.DeleteCommunityTokenPermission{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
PermissionID: tokenPermissionID,
|
|
|
|
}
|
|
|
|
|
|
|
|
// then, event sender deletes previously created token permission
|
|
|
|
deleteTokenPermission(base, community, deleteTokenPermissionRequest)
|
|
|
|
}
|
|
|
|
|
|
|
|
func testAcceptMemberRequestToJoin(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger) {
|
|
|
|
// set up additional user that will send request to join
|
|
|
|
_, err := user.Start()
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
|
|
|
|
s.Require().NoError(err)
|
|
|
|
defer user.Shutdown() // nolint: errcheck
|
|
|
|
|
|
|
|
advertiseCommunityTo(s, community, base.GetControlNode(), user)
|
|
|
|
|
|
|
|
// user sends request to join
|
|
|
|
requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID()}
|
|
|
|
response, err := user.RequestToJoinCommunity(requestToJoin)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(response)
|
|
|
|
s.Require().Len(response.RequestsToJoinCommunity, 1)
|
refactor: EventSenders forward RequestToJoin decision to control node
This is a bigger change in how community membership requests are handled
among admins, token masters, owners, and control nodes.
Prior to this commit, all privileged users, also known as
`EventSenders`, were able to accept and reject community membership
requests and those changes would be applied by all users.
This commit changes this behaviour such that:
1. EventSenders can make a decision (accept, reject), but merely forward
their decision to the control node, which ultimately has to confirm
it
2. EventSenders are no longer removing or adding members to and from
communities
3. When an eventsender signaled a decision, the membership request will
enter a pending state (acceptedPending or rejectedPending)
4. Once a decision was made by one eventsender, no other eventsender can
override that decision
This implementation is covered with a bunch of tests:
- Ensure that decision made by event sender is shared with other event
senders
- `testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- `testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- Ensure memebrship request stays pending, until control node has
confirmed decision by event senders
- `testAcceptMemberRequestToJoinNotConfirmedByControlNode()`
- `testRejectMemberRequestToJoinNotConfirmedByControlNode()`
- Ensure that decision made by event sender cannot be overriden by other
event senders
- `testEventSenderCannotOverrideRequestToJoinState()`
These test cases live in three test suites for different event sender
types respectively
- `OwnerWithoutCommunityKeyCommunityEventsSuite`
- `TokenMasterCommunityEventsSuite`
- `AdminCommunityEventsSuite`
In addition to the changes mentioned above, there's also a smaller
changes that ensures membership requests to *not* attached revealed wallet
addresses when the requests are sent to event senders (in addition to
control nodes).
Requests send to a control node will still include revealed addresses as
the control node needs them to verify token permissions.
This commit does not yet handle the case of event senders attempting to
kick and ban members.
Similar to accepting and rejecting membership requests, kicking and
banning need a new pending state. However, we don't track such state in
local databases yet so those two cases will be handled in future commit
to not have this commit grow larger.
2023-08-02 12:04:47 +00:00
|
|
|
|
|
|
|
sentRequest := response.RequestsToJoinCommunity[0]
|
2023-07-26 12:16:50 +00:00
|
|
|
|
|
|
|
// event sender receives request to join
|
|
|
|
response, err = WaitOnMessengerResponse(
|
|
|
|
base.GetEventSender(),
|
|
|
|
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)
|
|
|
|
|
2023-08-08 15:02:56 +00:00
|
|
|
// 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)
|
|
|
|
|
2023-07-26 12:16:50 +00:00
|
|
|
// event sender has not accepted request yet
|
|
|
|
eventSenderCommunity, err := base.GetEventSender().GetCommunityByID(community.ID())
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().False(eventSenderCommunity.HasMember(&user.identity.PublicKey))
|
|
|
|
|
refactor: EventSenders forward RequestToJoin decision to control node
This is a bigger change in how community membership requests are handled
among admins, token masters, owners, and control nodes.
Prior to this commit, all privileged users, also known as
`EventSenders`, were able to accept and reject community membership
requests and those changes would be applied by all users.
This commit changes this behaviour such that:
1. EventSenders can make a decision (accept, reject), but merely forward
their decision to the control node, which ultimately has to confirm
it
2. EventSenders are no longer removing or adding members to and from
communities
3. When an eventsender signaled a decision, the membership request will
enter a pending state (acceptedPending or rejectedPending)
4. Once a decision was made by one eventsender, no other eventsender can
override that decision
This implementation is covered with a bunch of tests:
- Ensure that decision made by event sender is shared with other event
senders
- `testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- `testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- Ensure memebrship request stays pending, until control node has
confirmed decision by event senders
- `testAcceptMemberRequestToJoinNotConfirmedByControlNode()`
- `testRejectMemberRequestToJoinNotConfirmedByControlNode()`
- Ensure that decision made by event sender cannot be overriden by other
event senders
- `testEventSenderCannotOverrideRequestToJoinState()`
These test cases live in three test suites for different event sender
types respectively
- `OwnerWithoutCommunityKeyCommunityEventsSuite`
- `TokenMasterCommunityEventsSuite`
- `AdminCommunityEventsSuite`
In addition to the changes mentioned above, there's also a smaller
changes that ensures membership requests to *not* attached revealed wallet
addresses when the requests are sent to event senders (in addition to
control nodes).
Requests send to a control node will still include revealed addresses as
the control node needs them to verify token permissions.
This commit does not yet handle the case of event senders attempting to
kick and ban members.
Similar to accepting and rejecting membership requests, kicking and
banning need a new pending state. However, we don't track such state in
local databases yet so those two cases will be handled in future commit
to not have this commit grow larger.
2023-08-02 12:04:47 +00:00
|
|
|
acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: sentRequest.ID}
|
2023-07-26 12:16:50 +00:00
|
|
|
response, err = base.GetEventSender().AcceptRequestToJoinCommunity(acceptRequestToJoin)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(response)
|
|
|
|
s.Require().Len(response.Communities(), 1)
|
refactor: EventSenders forward RequestToJoin decision to control node
This is a bigger change in how community membership requests are handled
among admins, token masters, owners, and control nodes.
Prior to this commit, all privileged users, also known as
`EventSenders`, were able to accept and reject community membership
requests and those changes would be applied by all users.
This commit changes this behaviour such that:
1. EventSenders can make a decision (accept, reject), but merely forward
their decision to the control node, which ultimately has to confirm
it
2. EventSenders are no longer removing or adding members to and from
communities
3. When an eventsender signaled a decision, the membership request will
enter a pending state (acceptedPending or rejectedPending)
4. Once a decision was made by one eventsender, no other eventsender can
override that decision
This implementation is covered with a bunch of tests:
- Ensure that decision made by event sender is shared with other event
senders
- `testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- `testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- Ensure memebrship request stays pending, until control node has
confirmed decision by event senders
- `testAcceptMemberRequestToJoinNotConfirmedByControlNode()`
- `testRejectMemberRequestToJoinNotConfirmedByControlNode()`
- Ensure that decision made by event sender cannot be overriden by other
event senders
- `testEventSenderCannotOverrideRequestToJoinState()`
These test cases live in three test suites for different event sender
types respectively
- `OwnerWithoutCommunityKeyCommunityEventsSuite`
- `TokenMasterCommunityEventsSuite`
- `AdminCommunityEventsSuite`
In addition to the changes mentioned above, there's also a smaller
changes that ensures membership requests to *not* attached revealed wallet
addresses when the requests are sent to event senders (in addition to
control nodes).
Requests send to a control node will still include revealed addresses as
the control node needs them to verify token permissions.
This commit does not yet handle the case of event senders attempting to
kick and ban members.
Similar to accepting and rejecting membership requests, kicking and
banning need a new pending state. However, we don't track such state in
local databases yet so those two cases will be handled in future commit
to not have this commit grow larger.
2023-08-02 12:04:47 +00:00
|
|
|
// we don't expect `user` to be a member already, because `eventSender` merely
|
|
|
|
// forwards its accept decision to the control node
|
|
|
|
s.Require().False(response.Communities()[0].HasMember(&user.identity.PublicKey))
|
2023-07-26 12:16:50 +00:00
|
|
|
|
2023-08-15 15:27:01 +00:00
|
|
|
// at this point, the request to join is marked as accepted by GetEventSender node
|
|
|
|
acceptedRequestsPending, err := base.GetEventSender().AcceptedPendingRequestsToJoinForCommunity(community.ID())
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(acceptedRequestsPending, 1)
|
|
|
|
s.Require().Equal(acceptedRequestsPending[0].PublicKey, common.PubkeyToHex(&user.identity.PublicKey))
|
|
|
|
|
|
|
|
// user should not receive community admin event without being a member yet
|
|
|
|
_, err = WaitOnMessengerResponse(
|
2023-07-26 12:16:50 +00:00
|
|
|
user,
|
|
|
|
func(r *MessengerResponse) bool { return len(r.Communities()) > 0 },
|
|
|
|
"user did not receive community request to join response",
|
|
|
|
)
|
2023-08-15 15:27:01 +00:00
|
|
|
s.Require().Error(err)
|
2023-07-26 12:16:50 +00:00
|
|
|
|
refactor: EventSenders forward RequestToJoin decision to control node
This is a bigger change in how community membership requests are handled
among admins, token masters, owners, and control nodes.
Prior to this commit, all privileged users, also known as
`EventSenders`, were able to accept and reject community membership
requests and those changes would be applied by all users.
This commit changes this behaviour such that:
1. EventSenders can make a decision (accept, reject), but merely forward
their decision to the control node, which ultimately has to confirm
it
2. EventSenders are no longer removing or adding members to and from
communities
3. When an eventsender signaled a decision, the membership request will
enter a pending state (acceptedPending or rejectedPending)
4. Once a decision was made by one eventsender, no other eventsender can
override that decision
This implementation is covered with a bunch of tests:
- Ensure that decision made by event sender is shared with other event
senders
- `testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- `testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- Ensure memebrship request stays pending, until control node has
confirmed decision by event senders
- `testAcceptMemberRequestToJoinNotConfirmedByControlNode()`
- `testRejectMemberRequestToJoinNotConfirmedByControlNode()`
- Ensure that decision made by event sender cannot be overriden by other
event senders
- `testEventSenderCannotOverrideRequestToJoinState()`
These test cases live in three test suites for different event sender
types respectively
- `OwnerWithoutCommunityKeyCommunityEventsSuite`
- `TokenMasterCommunityEventsSuite`
- `AdminCommunityEventsSuite`
In addition to the changes mentioned above, there's also a smaller
changes that ensures membership requests to *not* attached revealed wallet
addresses when the requests are sent to event senders (in addition to
control nodes).
Requests send to a control node will still include revealed addresses as
the control node needs them to verify token permissions.
This commit does not yet handle the case of event senders attempting to
kick and ban members.
Similar to accepting and rejecting membership requests, kicking and
banning need a new pending state. However, we don't track such state in
local databases yet so those two cases will be handled in future commit
to not have this commit grow larger.
2023-08-02 12:04:47 +00:00
|
|
|
// control node receives community event with accepted membership request
|
2023-08-15 15:27:01 +00:00
|
|
|
_, err = WaitOnMessengerResponse(
|
2023-07-26 12:16:50 +00:00
|
|
|
base.GetControlNode(),
|
2023-08-15 15:27:01 +00:00
|
|
|
func(r *MessengerResponse) bool {
|
|
|
|
return len(r.Communities()) > 0 && r.Communities()[0].HasMember(&user.identity.PublicKey)
|
|
|
|
},
|
2023-07-26 12:16:50 +00:00
|
|
|
"control node did not receive community request to join response",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
refactor: EventSenders forward RequestToJoin decision to control node
This is a bigger change in how community membership requests are handled
among admins, token masters, owners, and control nodes.
Prior to this commit, all privileged users, also known as
`EventSenders`, were able to accept and reject community membership
requests and those changes would be applied by all users.
This commit changes this behaviour such that:
1. EventSenders can make a decision (accept, reject), but merely forward
their decision to the control node, which ultimately has to confirm
it
2. EventSenders are no longer removing or adding members to and from
communities
3. When an eventsender signaled a decision, the membership request will
enter a pending state (acceptedPending or rejectedPending)
4. Once a decision was made by one eventsender, no other eventsender can
override that decision
This implementation is covered with a bunch of tests:
- Ensure that decision made by event sender is shared with other event
senders
- `testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- `testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- Ensure memebrship request stays pending, until control node has
confirmed decision by event senders
- `testAcceptMemberRequestToJoinNotConfirmedByControlNode()`
- `testRejectMemberRequestToJoinNotConfirmedByControlNode()`
- Ensure that decision made by event sender cannot be overriden by other
event senders
- `testEventSenderCannotOverrideRequestToJoinState()`
These test cases live in three test suites for different event sender
types respectively
- `OwnerWithoutCommunityKeyCommunityEventsSuite`
- `TokenMasterCommunityEventsSuite`
- `AdminCommunityEventsSuite`
In addition to the changes mentioned above, there's also a smaller
changes that ensures membership requests to *not* attached revealed wallet
addresses when the requests are sent to event senders (in addition to
control nodes).
Requests send to a control node will still include revealed addresses as
the control node needs them to verify token permissions.
This commit does not yet handle the case of event senders attempting to
kick and ban members.
Similar to accepting and rejecting membership requests, kicking and
banning need a new pending state. However, we don't track such state in
local databases yet so those two cases will be handled in future commit
to not have this commit grow larger.
2023-08-02 12:04:47 +00:00
|
|
|
// at this point, the request to join is marked as accepted by control node
|
|
|
|
acceptedRequests, err := base.GetControlNode().AcceptedRequestsToJoinForCommunity(community.ID())
|
|
|
|
s.Require().NoError(err)
|
|
|
|
// we expect 3 here (1 event senders, 1 member + 1 from user)
|
|
|
|
s.Require().Len(acceptedRequests, 3)
|
|
|
|
s.Require().Equal(acceptedRequests[2].PublicKey, common.PubkeyToHex(&user.identity.PublicKey))
|
|
|
|
|
|
|
|
// user receives updated community
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
user,
|
|
|
|
func(r *MessengerResponse) bool {
|
|
|
|
return len(r.Communities()) > 0 && r.Communities()[0].HasMember(&user.identity.PublicKey)
|
|
|
|
},
|
|
|
|
"alice did not receive community request to join response",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
2023-08-15 15:27:01 +00:00
|
|
|
// event sender receives updated community
|
|
|
|
_, err = WaitOnMessengerResponse(
|
refactor: EventSenders forward RequestToJoin decision to control node
This is a bigger change in how community membership requests are handled
among admins, token masters, owners, and control nodes.
Prior to this commit, all privileged users, also known as
`EventSenders`, were able to accept and reject community membership
requests and those changes would be applied by all users.
This commit changes this behaviour such that:
1. EventSenders can make a decision (accept, reject), but merely forward
their decision to the control node, which ultimately has to confirm
it
2. EventSenders are no longer removing or adding members to and from
communities
3. When an eventsender signaled a decision, the membership request will
enter a pending state (acceptedPending or rejectedPending)
4. Once a decision was made by one eventsender, no other eventsender can
override that decision
This implementation is covered with a bunch of tests:
- Ensure that decision made by event sender is shared with other event
senders
- `testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- `testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- Ensure memebrship request stays pending, until control node has
confirmed decision by event senders
- `testAcceptMemberRequestToJoinNotConfirmedByControlNode()`
- `testRejectMemberRequestToJoinNotConfirmedByControlNode()`
- Ensure that decision made by event sender cannot be overriden by other
event senders
- `testEventSenderCannotOverrideRequestToJoinState()`
These test cases live in three test suites for different event sender
types respectively
- `OwnerWithoutCommunityKeyCommunityEventsSuite`
- `TokenMasterCommunityEventsSuite`
- `AdminCommunityEventsSuite`
In addition to the changes mentioned above, there's also a smaller
changes that ensures membership requests to *not* attached revealed wallet
addresses when the requests are sent to event senders (in addition to
control nodes).
Requests send to a control node will still include revealed addresses as
the control node needs them to verify token permissions.
This commit does not yet handle the case of event senders attempting to
kick and ban members.
Similar to accepting and rejecting membership requests, kicking and
banning need a new pending state. However, we don't track such state in
local databases yet so those two cases will be handled in future commit
to not have this commit grow larger.
2023-08-02 12:04:47 +00:00
|
|
|
base.GetEventSender(),
|
2023-08-15 15:27:01 +00:00
|
|
|
func(r *MessengerResponse) bool {
|
|
|
|
return len(r.Communities()) > 0 && r.Communities()[0].HasMember(&user.identity.PublicKey)
|
|
|
|
},
|
|
|
|
"event sender did not receive community with the new member",
|
refactor: EventSenders forward RequestToJoin decision to control node
This is a bigger change in how community membership requests are handled
among admins, token masters, owners, and control nodes.
Prior to this commit, all privileged users, also known as
`EventSenders`, were able to accept and reject community membership
requests and those changes would be applied by all users.
This commit changes this behaviour such that:
1. EventSenders can make a decision (accept, reject), but merely forward
their decision to the control node, which ultimately has to confirm
it
2. EventSenders are no longer removing or adding members to and from
communities
3. When an eventsender signaled a decision, the membership request will
enter a pending state (acceptedPending or rejectedPending)
4. Once a decision was made by one eventsender, no other eventsender can
override that decision
This implementation is covered with a bunch of tests:
- Ensure that decision made by event sender is shared with other event
senders
- `testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- `testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- Ensure memebrship request stays pending, until control node has
confirmed decision by event senders
- `testAcceptMemberRequestToJoinNotConfirmedByControlNode()`
- `testRejectMemberRequestToJoinNotConfirmedByControlNode()`
- Ensure that decision made by event sender cannot be overriden by other
event senders
- `testEventSenderCannotOverrideRequestToJoinState()`
These test cases live in three test suites for different event sender
types respectively
- `OwnerWithoutCommunityKeyCommunityEventsSuite`
- `TokenMasterCommunityEventsSuite`
- `AdminCommunityEventsSuite`
In addition to the changes mentioned above, there's also a smaller
changes that ensures membership requests to *not* attached revealed wallet
addresses when the requests are sent to event senders (in addition to
control nodes).
Requests send to a control node will still include revealed addresses as
the control node needs them to verify token permissions.
This commit does not yet handle the case of event senders attempting to
kick and ban members.
Similar to accepting and rejecting membership requests, kicking and
banning need a new pending state. However, we don't track such state in
local databases yet so those two cases will be handled in future commit
to not have this commit grow larger.
2023-08-02 12:04:47 +00:00
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
2023-08-15 15:27:01 +00:00
|
|
|
// check control node notify event sender about accepting request to join
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
base.GetEventSender(),
|
|
|
|
func(r *MessengerResponse) bool {
|
|
|
|
acceptedRequests, err := base.GetEventSender().AcceptedRequestsToJoinForCommunity(community.ID())
|
|
|
|
return err == nil && len(acceptedRequests) == 2 && (acceptedRequests[1].PublicKey == common.PubkeyToHex(&user.identity.PublicKey))
|
|
|
|
},
|
|
|
|
"no updates from control node",
|
|
|
|
)
|
refactor: EventSenders forward RequestToJoin decision to control node
This is a bigger change in how community membership requests are handled
among admins, token masters, owners, and control nodes.
Prior to this commit, all privileged users, also known as
`EventSenders`, were able to accept and reject community membership
requests and those changes would be applied by all users.
This commit changes this behaviour such that:
1. EventSenders can make a decision (accept, reject), but merely forward
their decision to the control node, which ultimately has to confirm
it
2. EventSenders are no longer removing or adding members to and from
communities
3. When an eventsender signaled a decision, the membership request will
enter a pending state (acceptedPending or rejectedPending)
4. Once a decision was made by one eventsender, no other eventsender can
override that decision
This implementation is covered with a bunch of tests:
- Ensure that decision made by event sender is shared with other event
senders
- `testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- `testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- Ensure memebrship request stays pending, until control node has
confirmed decision by event senders
- `testAcceptMemberRequestToJoinNotConfirmedByControlNode()`
- `testRejectMemberRequestToJoinNotConfirmedByControlNode()`
- Ensure that decision made by event sender cannot be overriden by other
event senders
- `testEventSenderCannotOverrideRequestToJoinState()`
These test cases live in three test suites for different event sender
types respectively
- `OwnerWithoutCommunityKeyCommunityEventsSuite`
- `TokenMasterCommunityEventsSuite`
- `AdminCommunityEventsSuite`
In addition to the changes mentioned above, there's also a smaller
changes that ensures membership requests to *not* attached revealed wallet
addresses when the requests are sent to event senders (in addition to
control nodes).
Requests send to a control node will still include revealed addresses as
the control node needs them to verify token permissions.
This commit does not yet handle the case of event senders attempting to
kick and ban members.
Similar to accepting and rejecting membership requests, kicking and
banning need a new pending state. However, we don't track such state in
local databases yet so those two cases will be handled in future commit
to not have this commit grow larger.
2023-08-02 12:04:47 +00:00
|
|
|
|
2023-07-26 12:16:50 +00:00
|
|
|
s.Require().NoError(err)
|
|
|
|
|
2023-08-15 15:27:01 +00:00
|
|
|
acceptedRequestsPending, err = base.GetEventSender().AcceptedPendingRequestsToJoinForCommunity(community.ID())
|
2023-07-26 12:16:50 +00:00
|
|
|
s.Require().NoError(err)
|
2023-08-15 15:27:01 +00:00
|
|
|
s.Require().Len(acceptedRequestsPending, 0)
|
refactor: EventSenders forward RequestToJoin decision to control node
This is a bigger change in how community membership requests are handled
among admins, token masters, owners, and control nodes.
Prior to this commit, all privileged users, also known as
`EventSenders`, were able to accept and reject community membership
requests and those changes would be applied by all users.
This commit changes this behaviour such that:
1. EventSenders can make a decision (accept, reject), but merely forward
their decision to the control node, which ultimately has to confirm
it
2. EventSenders are no longer removing or adding members to and from
communities
3. When an eventsender signaled a decision, the membership request will
enter a pending state (acceptedPending or rejectedPending)
4. Once a decision was made by one eventsender, no other eventsender can
override that decision
This implementation is covered with a bunch of tests:
- Ensure that decision made by event sender is shared with other event
senders
- `testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- `testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- Ensure memebrship request stays pending, until control node has
confirmed decision by event senders
- `testAcceptMemberRequestToJoinNotConfirmedByControlNode()`
- `testRejectMemberRequestToJoinNotConfirmedByControlNode()`
- Ensure that decision made by event sender cannot be overriden by other
event senders
- `testEventSenderCannotOverrideRequestToJoinState()`
These test cases live in three test suites for different event sender
types respectively
- `OwnerWithoutCommunityKeyCommunityEventsSuite`
- `TokenMasterCommunityEventsSuite`
- `AdminCommunityEventsSuite`
In addition to the changes mentioned above, there's also a smaller
changes that ensures membership requests to *not* attached revealed wallet
addresses when the requests are sent to event senders (in addition to
control nodes).
Requests send to a control node will still include revealed addresses as
the control node needs them to verify token permissions.
This commit does not yet handle the case of event senders attempting to
kick and ban members.
Similar to accepting and rejecting membership requests, kicking and
banning need a new pending state. However, we don't track such state in
local databases yet so those two cases will be handled in future commit
to not have this commit grow larger.
2023-08-02 12:04:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger, additionalEventSender *Messenger) {
|
|
|
|
// set up additional user that will send request to join
|
|
|
|
_, err := user.Start()
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
|
|
|
|
s.Require().NoError(err)
|
|
|
|
defer user.Shutdown() // nolint: errcheck
|
|
|
|
|
|
|
|
advertiseCommunityTo(s, community, base.GetControlNode(), user)
|
|
|
|
|
|
|
|
// user sends request to join
|
|
|
|
requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID()}
|
|
|
|
response, err := user.RequestToJoinCommunity(requestToJoin)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(response)
|
|
|
|
s.Require().Len(response.RequestsToJoinCommunity, 1)
|
|
|
|
|
|
|
|
sentRequest := response.RequestsToJoinCommunity[0]
|
|
|
|
|
|
|
|
// event sender receives request to join
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
base.GetEventSender(),
|
|
|
|
func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity) > 0 },
|
|
|
|
"event sender did not receive community request to join",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// event sender 2 receives request to join
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
additionalEventSender,
|
|
|
|
func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity) > 0 },
|
|
|
|
"event sender did not receive community request to join",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// event sender 1 accepts request
|
|
|
|
acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: sentRequest.ID}
|
|
|
|
response, err = base.GetEventSender().AcceptRequestToJoinCommunity(acceptRequestToJoin)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(response)
|
|
|
|
s.Require().Len(response.Communities(), 1)
|
|
|
|
|
|
|
|
// event sender 2 receives decision of other event sender
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
additionalEventSender,
|
|
|
|
func(r *MessengerResponse) bool { return len(r.Communities()) > 0 },
|
|
|
|
"event sender did not receive community request to join",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// at this point, the request to join is in accepted/pending state for event sender 2
|
|
|
|
acceptedPendingRequests, err := additionalEventSender.AcceptedPendingRequestsToJoinForCommunity(community.ID())
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(acceptedPendingRequests, 1)
|
|
|
|
s.Require().Equal(acceptedPendingRequests[0].PublicKey, common.PubkeyToHex(&user.identity.PublicKey))
|
|
|
|
}
|
|
|
|
|
|
|
|
func testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger, additionalEventSender *Messenger) {
|
|
|
|
// set up additional user that will send request to join
|
|
|
|
_, err := user.Start()
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
|
|
|
|
s.Require().NoError(err)
|
|
|
|
defer user.Shutdown() // nolint: errcheck
|
|
|
|
|
|
|
|
advertiseCommunityTo(s, community, base.GetControlNode(), user)
|
|
|
|
|
|
|
|
// user sends request to join
|
|
|
|
requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID()}
|
|
|
|
response, err := user.RequestToJoinCommunity(requestToJoin)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(response)
|
|
|
|
s.Require().Len(response.RequestsToJoinCommunity, 1)
|
|
|
|
|
|
|
|
sentRequest := response.RequestsToJoinCommunity[0]
|
|
|
|
|
|
|
|
// event sender receives request to join
|
|
|
|
response, err = WaitOnMessengerResponse(
|
|
|
|
base.GetEventSender(),
|
|
|
|
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 2 receives request to join
|
|
|
|
response, err = WaitOnMessengerResponse(
|
|
|
|
additionalEventSender,
|
|
|
|
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)
|
|
|
|
|
|
|
|
rejectRequestToJoin := &requests.DeclineRequestToJoinCommunity{ID: sentRequest.ID}
|
|
|
|
response, err = base.GetEventSender().DeclineRequestToJoinCommunity(rejectRequestToJoin)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(response)
|
|
|
|
|
|
|
|
// event sender 2 receives decision of other event sender
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
additionalEventSender,
|
|
|
|
func(r *MessengerResponse) bool { return len(r.Communities()) > 0 },
|
|
|
|
"event sender did not receive community request to join",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// at this point, the request to join is in declined/pending state for event sender 2
|
|
|
|
rejectedPendingRequests, err := additionalEventSender.DeclinedPendingRequestsToJoinForCommunity(community.ID())
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(rejectedPendingRequests, 1)
|
|
|
|
s.Require().Equal(rejectedPendingRequests[0].PublicKey, common.PubkeyToHex(&user.identity.PublicKey))
|
|
|
|
}
|
|
|
|
|
2023-07-26 12:16:50 +00:00
|
|
|
func testRejectMemberRequestToJoin(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger) {
|
|
|
|
_, err := user.Start()
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
defer user.Shutdown() // nolint: errcheck
|
|
|
|
|
|
|
|
advertiseCommunityTo(s, community, base.GetControlNode(), user)
|
|
|
|
|
|
|
|
// user sends request to join
|
|
|
|
requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID()}
|
|
|
|
response, err := user.RequestToJoinCommunity(requestToJoin)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(response)
|
|
|
|
s.Require().Len(response.RequestsToJoinCommunity, 1)
|
|
|
|
|
refactor: EventSenders forward RequestToJoin decision to control node
This is a bigger change in how community membership requests are handled
among admins, token masters, owners, and control nodes.
Prior to this commit, all privileged users, also known as
`EventSenders`, were able to accept and reject community membership
requests and those changes would be applied by all users.
This commit changes this behaviour such that:
1. EventSenders can make a decision (accept, reject), but merely forward
their decision to the control node, which ultimately has to confirm
it
2. EventSenders are no longer removing or adding members to and from
communities
3. When an eventsender signaled a decision, the membership request will
enter a pending state (acceptedPending or rejectedPending)
4. Once a decision was made by one eventsender, no other eventsender can
override that decision
This implementation is covered with a bunch of tests:
- Ensure that decision made by event sender is shared with other event
senders
- `testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- `testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- Ensure memebrship request stays pending, until control node has
confirmed decision by event senders
- `testAcceptMemberRequestToJoinNotConfirmedByControlNode()`
- `testRejectMemberRequestToJoinNotConfirmedByControlNode()`
- Ensure that decision made by event sender cannot be overriden by other
event senders
- `testEventSenderCannotOverrideRequestToJoinState()`
These test cases live in three test suites for different event sender
types respectively
- `OwnerWithoutCommunityKeyCommunityEventsSuite`
- `TokenMasterCommunityEventsSuite`
- `AdminCommunityEventsSuite`
In addition to the changes mentioned above, there's also a smaller
changes that ensures membership requests to *not* attached revealed wallet
addresses when the requests are sent to event senders (in addition to
control nodes).
Requests send to a control node will still include revealed addresses as
the control node needs them to verify token permissions.
This commit does not yet handle the case of event senders attempting to
kick and ban members.
Similar to accepting and rejecting membership requests, kicking and
banning need a new pending state. However, we don't track such state in
local databases yet so those two cases will be handled in future commit
to not have this commit grow larger.
2023-08-02 12:04:47 +00:00
|
|
|
sentRequest := response.RequestsToJoinCommunity[0]
|
|
|
|
|
2023-07-26 12:16:50 +00:00
|
|
|
// event sender receives request to join
|
|
|
|
response, err = WaitOnMessengerResponse(
|
|
|
|
base.GetEventSender(),
|
|
|
|
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)
|
|
|
|
|
2023-07-31 15:52:41 +00:00
|
|
|
// control node receives request to join
|
|
|
|
response, err = WaitOnMessengerResponse(
|
|
|
|
base.GetControlNode(),
|
|
|
|
func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity) > 0 },
|
|
|
|
"control node did not receive community request to join",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(response.RequestsToJoinCommunity, 1)
|
|
|
|
|
2023-07-26 12:16:50 +00:00
|
|
|
// event sender has not accepted request yet
|
|
|
|
eventSenderCommunity, err := base.GetEventSender().GetCommunityByID(community.ID())
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().False(eventSenderCommunity.HasMember(&user.identity.PublicKey))
|
|
|
|
|
|
|
|
// event sender rejects request to join
|
refactor: EventSenders forward RequestToJoin decision to control node
This is a bigger change in how community membership requests are handled
among admins, token masters, owners, and control nodes.
Prior to this commit, all privileged users, also known as
`EventSenders`, were able to accept and reject community membership
requests and those changes would be applied by all users.
This commit changes this behaviour such that:
1. EventSenders can make a decision (accept, reject), but merely forward
their decision to the control node, which ultimately has to confirm
it
2. EventSenders are no longer removing or adding members to and from
communities
3. When an eventsender signaled a decision, the membership request will
enter a pending state (acceptedPending or rejectedPending)
4. Once a decision was made by one eventsender, no other eventsender can
override that decision
This implementation is covered with a bunch of tests:
- Ensure that decision made by event sender is shared with other event
senders
- `testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- `testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- Ensure memebrship request stays pending, until control node has
confirmed decision by event senders
- `testAcceptMemberRequestToJoinNotConfirmedByControlNode()`
- `testRejectMemberRequestToJoinNotConfirmedByControlNode()`
- Ensure that decision made by event sender cannot be overriden by other
event senders
- `testEventSenderCannotOverrideRequestToJoinState()`
These test cases live in three test suites for different event sender
types respectively
- `OwnerWithoutCommunityKeyCommunityEventsSuite`
- `TokenMasterCommunityEventsSuite`
- `AdminCommunityEventsSuite`
In addition to the changes mentioned above, there's also a smaller
changes that ensures membership requests to *not* attached revealed wallet
addresses when the requests are sent to event senders (in addition to
control nodes).
Requests send to a control node will still include revealed addresses as
the control node needs them to verify token permissions.
This commit does not yet handle the case of event senders attempting to
kick and ban members.
Similar to accepting and rejecting membership requests, kicking and
banning need a new pending state. However, we don't track such state in
local databases yet so those two cases will be handled in future commit
to not have this commit grow larger.
2023-08-02 12:04:47 +00:00
|
|
|
rejectRequestToJoin := &requests.DeclineRequestToJoinCommunity{ID: sentRequest.ID}
|
2023-07-26 12:16:50 +00:00
|
|
|
_, err = base.GetEventSender().DeclineRequestToJoinCommunity(rejectRequestToJoin)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
eventSenderCommunity, err = base.GetEventSender().GetCommunityByID(community.ID())
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().False(eventSenderCommunity.HasMember(&user.identity.PublicKey))
|
|
|
|
|
2023-08-15 15:27:01 +00:00
|
|
|
requests, err := base.GetEventSender().DeclinedPendingRequestsToJoinForCommunity(community.ID())
|
|
|
|
s.Require().Len(requests, 1)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
2023-07-26 12:16:50 +00:00
|
|
|
// control node receives event sender event and stores rejected request to join
|
|
|
|
response, err = WaitOnMessengerResponse(
|
|
|
|
base.GetControlNode(),
|
2023-08-15 15:27:01 +00:00
|
|
|
func(r *MessengerResponse) bool {
|
|
|
|
return len(r.Communities()) > 0 && !r.Communities()[0].HasMember(&user.identity.PublicKey)
|
|
|
|
},
|
2023-07-26 12:16:50 +00:00
|
|
|
"control node did not receive community request to join update from event sender",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().False(response.Communities()[0].HasMember(&user.identity.PublicKey))
|
|
|
|
|
2023-08-15 15:27:01 +00:00
|
|
|
requests, err = base.GetControlNode().DeclinedRequestsToJoinForCommunity(community.ID())
|
2023-07-26 12:16:50 +00:00
|
|
|
s.Require().Len(requests, 1)
|
|
|
|
s.Require().NoError(err)
|
2023-08-15 15:27:01 +00:00
|
|
|
|
|
|
|
// event sender receives updated community
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
base.GetEventSender(),
|
|
|
|
func(r *MessengerResponse) bool {
|
|
|
|
return len(r.Communities()) > 0 && !r.Communities()[0].HasMember(&user.identity.PublicKey)
|
|
|
|
},
|
|
|
|
"event sender did not receive community update",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// check control node notify event sender about declined request to join
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
base.GetEventSender(),
|
|
|
|
func(r *MessengerResponse) bool {
|
|
|
|
declinedRequests, err := base.GetEventSender().DeclinedRequestsToJoinForCommunity(community.ID())
|
|
|
|
return err == nil && len(declinedRequests) == 1
|
|
|
|
},
|
|
|
|
"no updates from control node",
|
|
|
|
)
|
|
|
|
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
declinedRequestsPending, err := base.GetEventSender().DeclinedPendingRequestsToJoinForCommunity(community.ID())
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(declinedRequestsPending, 0)
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
refactor: EventSenders forward RequestToJoin decision to control node
This is a bigger change in how community membership requests are handled
among admins, token masters, owners, and control nodes.
Prior to this commit, all privileged users, also known as
`EventSenders`, were able to accept and reject community membership
requests and those changes would be applied by all users.
This commit changes this behaviour such that:
1. EventSenders can make a decision (accept, reject), but merely forward
their decision to the control node, which ultimately has to confirm
it
2. EventSenders are no longer removing or adding members to and from
communities
3. When an eventsender signaled a decision, the membership request will
enter a pending state (acceptedPending or rejectedPending)
4. Once a decision was made by one eventsender, no other eventsender can
override that decision
This implementation is covered with a bunch of tests:
- Ensure that decision made by event sender is shared with other event
senders
- `testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- `testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders()`
- Ensure memebrship request stays pending, until control node has
confirmed decision by event senders
- `testAcceptMemberRequestToJoinNotConfirmedByControlNode()`
- `testRejectMemberRequestToJoinNotConfirmedByControlNode()`
- Ensure that decision made by event sender cannot be overriden by other
event senders
- `testEventSenderCannotOverrideRequestToJoinState()`
These test cases live in three test suites for different event sender
types respectively
- `OwnerWithoutCommunityKeyCommunityEventsSuite`
- `TokenMasterCommunityEventsSuite`
- `AdminCommunityEventsSuite`
In addition to the changes mentioned above, there's also a smaller
changes that ensures membership requests to *not* attached revealed wallet
addresses when the requests are sent to event senders (in addition to
control nodes).
Requests send to a control node will still include revealed addresses as
the control node needs them to verify token permissions.
This commit does not yet handle the case of event senders attempting to
kick and ban members.
Similar to accepting and rejecting membership requests, kicking and
banning need a new pending state. However, we don't track such state in
local databases yet so those two cases will be handled in future commit
to not have this commit grow larger.
2023-08-02 12:04:47 +00:00
|
|
|
func testEventSenderCannotOverrideRequestToJoinState(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger, additionalEventSender *Messenger) {
|
|
|
|
_, err := user.Start()
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
defer user.Shutdown() // nolint: errcheck
|
|
|
|
|
|
|
|
advertiseCommunityTo(s, community, base.GetControlNode(), user)
|
|
|
|
|
|
|
|
// user sends request to join
|
|
|
|
requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID()}
|
|
|
|
response, err := user.RequestToJoinCommunity(requestToJoin)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(response)
|
|
|
|
s.Require().Len(response.RequestsToJoinCommunity, 1)
|
|
|
|
|
|
|
|
sentRequest := response.RequestsToJoinCommunity[0]
|
|
|
|
|
|
|
|
// event sender receives request to join
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
base.GetEventSender(),
|
|
|
|
func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity) > 0 },
|
|
|
|
"event sender did not receive community request to join",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// event sender 2 receives request to join
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
additionalEventSender,
|
|
|
|
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)
|
|
|
|
|
|
|
|
// request is pending for event sener 2
|
|
|
|
pendingRequests, err := additionalEventSender.PendingRequestsToJoinForCommunity(community.ID())
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(pendingRequests)
|
|
|
|
s.Require().Len(pendingRequests, 1)
|
|
|
|
|
|
|
|
// event sender 1 rejects request to join
|
|
|
|
rejectRequestToJoin := &requests.DeclineRequestToJoinCommunity{ID: sentRequest.ID}
|
|
|
|
_, err = base.GetEventSender().DeclineRequestToJoinCommunity(rejectRequestToJoin)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// request to join is now marked as rejected pending for event sender 1
|
|
|
|
rejectedPendingRequests, err := base.GetEventSender().DeclinedPendingRequestsToJoinForCommunity(community.ID())
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(rejectedPendingRequests)
|
|
|
|
s.Require().Len(rejectedPendingRequests, 1)
|
|
|
|
|
|
|
|
// event sender 2 receives event sender 1's decision
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
additionalEventSender,
|
|
|
|
func(r *MessengerResponse) bool { return len(r.Communities()) > 0 },
|
|
|
|
"event sender did not receive community request to join",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// request to join is now marked as rejected pending for event sender 2
|
|
|
|
rejectedPendingRequests, err = additionalEventSender.DeclinedPendingRequestsToJoinForCommunity(community.ID())
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(rejectedPendingRequests)
|
|
|
|
s.Require().Len(rejectedPendingRequests, 1)
|
|
|
|
|
|
|
|
// event sender 2 should not be able to override that pending state
|
|
|
|
acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: sentRequest.ID}
|
|
|
|
_, err = additionalEventSender.AcceptRequestToJoinCommunity(acceptRequestToJoin)
|
|
|
|
s.Require().Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func testControlNodeHandlesMultipleEventSenderRequestToJoinDecisions(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger, additionalEventSender *Messenger) {
|
|
|
|
_, err := user.Start()
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
defer user.Shutdown() // nolint: errcheck
|
|
|
|
|
|
|
|
advertiseCommunityTo(s, community, base.GetControlNode(), user)
|
|
|
|
|
|
|
|
// user sends request to join
|
|
|
|
requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID()}
|
|
|
|
response, err := user.RequestToJoinCommunity(requestToJoin)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(response)
|
|
|
|
s.Require().Len(response.RequestsToJoinCommunity, 1)
|
|
|
|
|
|
|
|
sentRequest := response.RequestsToJoinCommunity[0]
|
|
|
|
|
|
|
|
// event sender receives request to join
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
base.GetEventSender(),
|
|
|
|
func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity) > 0 },
|
|
|
|
"event sender did not receive community request to join",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// event sender 2 receives request to join
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
additionalEventSender,
|
|
|
|
func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity) > 0 },
|
|
|
|
"event sender did not receive community request to join",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// control node receives request to join
|
|
|
|
_, 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)
|
|
|
|
|
|
|
|
// event sender 1 rejects request to join
|
|
|
|
rejectRequestToJoin := &requests.DeclineRequestToJoinCommunity{ID: sentRequest.ID}
|
|
|
|
_, err = base.GetEventSender().DeclineRequestToJoinCommunity(rejectRequestToJoin)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
// request to join is now marked as rejected pending for event sender 1
|
|
|
|
rejectedPendingRequests, err := base.GetEventSender().DeclinedPendingRequestsToJoinForCommunity(community.ID())
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(rejectedPendingRequests)
|
|
|
|
s.Require().Len(rejectedPendingRequests, 1)
|
|
|
|
|
|
|
|
// control node receives event sender 1's and 2's decision
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
base.GetControlNode(),
|
|
|
|
func(r *MessengerResponse) bool { return len(r.Communities()) > 0 },
|
|
|
|
"control node did not receive event senders decision",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
// request to join is now marked as rejected
|
|
|
|
rejectedRequests, err := base.GetControlNode().DeclinedRequestsToJoinForCommunity(community.ID())
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(rejectedRequests)
|
|
|
|
s.Require().Len(rejectedRequests, 1)
|
|
|
|
|
|
|
|
// event sender 2 accepts request to join
|
|
|
|
acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: sentRequest.ID}
|
|
|
|
_, err = additionalEventSender.AcceptRequestToJoinCommunity(acceptRequestToJoin)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
// request to join is now marked as accepted pending for event sender 2
|
|
|
|
acceptedPendingRequests, err := additionalEventSender.AcceptedPendingRequestsToJoinForCommunity(community.ID())
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(acceptedPendingRequests)
|
|
|
|
s.Require().Len(acceptedPendingRequests, 1)
|
|
|
|
|
|
|
|
// control node now receives event sender 2's decision
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
base.GetControlNode(),
|
|
|
|
func(r *MessengerResponse) bool { return len(r.Communities()) > 0 },
|
|
|
|
"control node did not receive event senders decision",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
rejectedRequests, err = base.GetControlNode().DeclinedRequestsToJoinForCommunity(community.ID())
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(rejectedRequests)
|
|
|
|
s.Require().Len(rejectedRequests, 1)
|
|
|
|
// we expect user's request to join still to be rejected
|
|
|
|
s.Require().Equal(rejectedRequests[0].PublicKey, common.PubkeyToHex(&user.identity.PublicKey))
|
|
|
|
}
|
|
|
|
|
2023-07-26 12:16:50 +00:00
|
|
|
func testCreateEditDeleteCategories(base CommunityEventsTestsInterface, community *communities.Community) {
|
|
|
|
newCategory := &requests.CreateCommunityCategory{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
CategoryName: "event-sender-category-name",
|
|
|
|
}
|
|
|
|
categoryID := createCommunityCategory(base, community, newCategory)
|
|
|
|
|
|
|
|
editCategory := &requests.EditCommunityCategory{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
CategoryID: categoryID,
|
|
|
|
CategoryName: "edited-event-sender-category-name",
|
|
|
|
}
|
|
|
|
|
|
|
|
editCommunityCategory(base, community.IDString(), editCategory)
|
|
|
|
|
|
|
|
deleteCategory := &requests.DeleteCommunityCategory{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
CategoryID: categoryID,
|
|
|
|
}
|
|
|
|
|
|
|
|
deleteCommunityCategory(base, community.IDString(), deleteCategory)
|
|
|
|
}
|
|
|
|
|
|
|
|
func testReorderChannelsAndCategories(base CommunityEventsTestsInterface, community *communities.Community) {
|
|
|
|
newCategory := &requests.CreateCommunityCategory{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
CategoryName: "event-sender-category-name",
|
|
|
|
}
|
|
|
|
_ = createCommunityCategory(base, community, newCategory)
|
|
|
|
|
|
|
|
newCategory.CategoryName = "event-sender-category-name2"
|
|
|
|
categoryID2 := createCommunityCategory(base, community, newCategory)
|
|
|
|
|
|
|
|
chat := &protobuf.CommunityChat{
|
|
|
|
Permissions: &protobuf.CommunityPermissions{
|
|
|
|
Access: protobuf.CommunityPermissions_NO_MEMBERSHIP,
|
|
|
|
},
|
|
|
|
Identity: &protobuf.ChatIdentity{
|
|
|
|
DisplayName: "chat from event-sender",
|
|
|
|
Emoji: "",
|
|
|
|
Description: "chat created by an event-sender",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
chatID := createCommunityChannel(base, community, chat)
|
|
|
|
|
|
|
|
reorderCommunityRequest := requests.ReorderCommunityCategories{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
CategoryID: categoryID2,
|
|
|
|
Position: 0,
|
|
|
|
}
|
|
|
|
|
|
|
|
reorderCategory(base, &reorderCommunityRequest)
|
|
|
|
|
|
|
|
reorderChatRequest := requests.ReorderCommunityChat{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
CategoryID: categoryID2,
|
|
|
|
ChatID: chatID,
|
|
|
|
Position: 0,
|
|
|
|
}
|
|
|
|
|
|
|
|
reorderChannel(base, &reorderChatRequest)
|
|
|
|
}
|
|
|
|
|
|
|
|
func testEventSenderKickTheSameRole(base CommunityEventsTestsInterface, community *communities.Community) {
|
|
|
|
// event sender tries to kick the member with the same role
|
|
|
|
_, err := base.GetEventSender().RemoveUserFromCommunity(
|
|
|
|
community.ID(),
|
|
|
|
common.PubkeyToHex(&base.GetEventSender().identity.PublicKey),
|
|
|
|
)
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().Error(err)
|
|
|
|
s.Require().EqualError(err, "not allowed to remove admin or owner")
|
|
|
|
}
|
|
|
|
|
|
|
|
func testEventSenderKickControlNode(base CommunityEventsTestsInterface, community *communities.Community) {
|
|
|
|
// event sender tries to kick the control node
|
|
|
|
_, err := base.GetEventSender().RemoveUserFromCommunity(
|
|
|
|
community.ID(),
|
|
|
|
common.PubkeyToHex(&base.GetControlNode().identity.PublicKey),
|
|
|
|
)
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().Error(err)
|
|
|
|
s.Require().EqualError(err, "not allowed to remove admin or owner")
|
|
|
|
}
|
|
|
|
|
|
|
|
func testOwnerBanTheSameRole(base CommunityEventsTestsInterface, community *communities.Community) {
|
|
|
|
_, err := base.GetEventSender().BanUserFromCommunity(
|
|
|
|
&requests.BanUserFromCommunity{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
User: common.PubkeyToHexBytes(&base.GetEventSender().identity.PublicKey),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().Error(err)
|
|
|
|
s.Require().EqualError(err, "not allowed to ban admin or owner")
|
|
|
|
}
|
|
|
|
|
|
|
|
func testOwnerBanControlNode(base CommunityEventsTestsInterface, community *communities.Community) {
|
|
|
|
_, err := base.GetEventSender().BanUserFromCommunity(
|
|
|
|
&requests.BanUserFromCommunity{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
User: common.PubkeyToHexBytes(&base.GetControlNode().identity.PublicKey),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().Error(err)
|
|
|
|
s.Require().EqualError(err, "not allowed to ban admin or owner")
|
|
|
|
}
|
|
|
|
|
|
|
|
func testBanUnbanMember(base CommunityEventsTestsInterface, community *communities.Community) {
|
|
|
|
// verify that event sender can't ban a control node
|
|
|
|
_, err := base.GetEventSender().BanUserFromCommunity(
|
|
|
|
&requests.BanUserFromCommunity{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
User: common.PubkeyToHexBytes(&base.GetControlNode().identity.PublicKey),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().Error(err)
|
|
|
|
|
|
|
|
banRequest := &requests.BanUserFromCommunity{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
User: common.PubkeyToHexBytes(&base.GetMember().identity.PublicKey),
|
|
|
|
}
|
|
|
|
|
|
|
|
banMember(base, banRequest)
|
|
|
|
|
|
|
|
unbanRequest := &requests.UnbanUserFromCommunity{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
User: common.PubkeyToHexBytes(&base.GetMember().identity.PublicKey),
|
|
|
|
}
|
|
|
|
|
|
|
|
unbanMember(base, unbanRequest)
|
|
|
|
}
|
|
|
|
|
|
|
|
func testDeleteAnyMessageInTheCommunity(base CommunityEventsTestsInterface, community *communities.Community) {
|
|
|
|
chatID := community.ChatIDs()[0]
|
|
|
|
|
2023-08-18 11:39:59 +00:00
|
|
|
inputMessage := common.NewMessage()
|
2023-07-26 12:16:50 +00:00
|
|
|
inputMessage.ChatId = chatID
|
|
|
|
inputMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN
|
|
|
|
inputMessage.Text = "control node text"
|
|
|
|
|
2023-08-18 11:39:59 +00:00
|
|
|
messageID := controlNodeSendMessage(base, inputMessage)
|
2023-07-26 12:16:50 +00:00
|
|
|
|
|
|
|
deleteControlNodeMessage(base, messageID)
|
|
|
|
}
|
|
|
|
|
|
|
|
func testEventSenderPinMessage(base CommunityEventsTestsInterface, community *communities.Community) {
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().False(community.AllowsAllMembersToPinMessage())
|
|
|
|
chatID := community.ChatIDs()[0]
|
|
|
|
|
2023-08-18 11:39:59 +00:00
|
|
|
inputMessage := common.NewMessage()
|
2023-07-26 12:16:50 +00:00
|
|
|
inputMessage.ChatId = chatID
|
|
|
|
inputMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN
|
|
|
|
inputMessage.Text = "control node text"
|
|
|
|
|
2023-08-18 11:39:59 +00:00
|
|
|
messageID := controlNodeSendMessage(base, inputMessage)
|
2023-07-26 12:16:50 +00:00
|
|
|
|
2023-08-18 11:39:59 +00:00
|
|
|
pinnedMessage := common.NewPinMessage()
|
2023-07-26 12:16:50 +00:00
|
|
|
pinnedMessage.MessageId = messageID
|
|
|
|
pinnedMessage.ChatId = chatID
|
|
|
|
pinnedMessage.Pinned = true
|
|
|
|
|
2023-08-18 11:39:59 +00:00
|
|
|
pinControlNodeMessage(base, pinnedMessage)
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func testMemberReceiveEventsWhenControlNodeOffline(base CommunityEventsTestsInterface, community *communities.Community) {
|
|
|
|
// To simulate behavior when control node is offline, we will not use control node for listening new events
|
|
|
|
// In this scenario member will reveive list of events
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
member := base.GetMember()
|
|
|
|
eventSender := base.GetEventSender()
|
|
|
|
|
|
|
|
newAdminChat := &protobuf.CommunityChat{
|
|
|
|
Permissions: &protobuf.CommunityPermissions{
|
|
|
|
Access: protobuf.CommunityPermissions_NO_MEMBERSHIP,
|
|
|
|
},
|
|
|
|
Identity: &protobuf.ChatIdentity{
|
|
|
|
DisplayName: "chat from event sender",
|
|
|
|
Emoji: "",
|
|
|
|
Description: "chat created by an event sender",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
checkChannelCreated := func(response *MessengerResponse) error {
|
|
|
|
modifiedCommmunity, err := getModifiedCommunity(response, community.IDString())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, chat := range modifiedCommmunity.Chats() {
|
|
|
|
if chat.GetIdentity().GetDisplayName() == newAdminChat.GetIdentity().GetDisplayName() {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return errors.New("couldn't find created chat in response")
|
|
|
|
}
|
|
|
|
|
|
|
|
response, err := eventSender.CreateCommunityChat(community.ID(), newAdminChat)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NoError(checkChannelCreated(response))
|
|
|
|
s.Require().Len(response.CommunityChanges, 1)
|
|
|
|
s.Require().Len(response.CommunityChanges[0].ChatsAdded, 1)
|
|
|
|
var addedChatID string
|
|
|
|
for addedChatID = range response.CommunityChanges[0].ChatsAdded {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
waitOnMessengerResponse(s, WaitCommunityCondition, checkChannelCreated, member)
|
|
|
|
waitOnMessengerResponse(s, WaitCommunityCondition, checkChannelCreated, eventSender)
|
|
|
|
|
|
|
|
newAdminChat.Identity.DisplayName = "modified chat from event sender"
|
|
|
|
|
|
|
|
checkChannelEdited := func(response *MessengerResponse) error {
|
|
|
|
modifiedCommmunity, err := getModifiedCommunity(response, community.IDString())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, chat := range modifiedCommmunity.Chats() {
|
|
|
|
if chat.GetIdentity().GetDisplayName() == newAdminChat.GetIdentity().GetDisplayName() {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return errors.New("couldn't find modified chat in response")
|
|
|
|
}
|
|
|
|
|
|
|
|
response, err = eventSender.EditCommunityChat(community.ID(), addedChatID, newAdminChat)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NoError(checkChannelEdited(response))
|
|
|
|
|
|
|
|
waitOnMessengerResponse(s, WaitCommunityCondition, checkChannelEdited, member)
|
|
|
|
waitOnMessengerResponse(s, WaitCommunityCondition, checkChannelEdited, eventSender)
|
|
|
|
|
|
|
|
checkChannelDeleted := func(response *MessengerResponse) error {
|
|
|
|
modifiedCommmunity, err := getModifiedCommunity(response, community.IDString())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, exists := modifiedCommmunity.Chats()[addedChatID]; exists {
|
|
|
|
return errors.New("channel was not deleted")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
response, err = eventSender.DeleteCommunityChat(community.ID(), addedChatID)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NoError(checkChannelDeleted(response))
|
|
|
|
|
|
|
|
waitOnMessengerResponse(s, WaitCommunityCondition, checkChannelDeleted, member)
|
|
|
|
waitOnMessengerResponse(s, WaitCommunityCondition, checkChannelDeleted, eventSender)
|
|
|
|
}
|
2023-07-26 16:01:19 +00:00
|
|
|
|
2023-08-08 15:02:56 +00:00
|
|
|
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)
|
2023-07-26 16:01:19 +00:00
|
|
|
}
|
|
|
|
|
2023-08-08 15:02:56 +00:00
|
|
|
permissionRequest := createTestPermissionRequest(community, testPermissionType)
|
|
|
|
tokenPermissionID := controlNodeCreatesCommunityPermission(base, community, permissionRequest)
|
2023-07-26 16:01:19 +00:00
|
|
|
|
|
|
|
deleteTokenPermission := &requests.DeleteCommunityTokenPermission{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
PermissionID: tokenPermissionID,
|
|
|
|
}
|
|
|
|
|
2023-08-08 15:02:56 +00:00
|
|
|
// then event sender tries to delete permission which should fail
|
|
|
|
response, err := base.GetEventSender().DeleteCommunityTokenPermission(deleteTokenPermission)
|
|
|
|
s := base.GetSuite()
|
2023-07-26 16:01:19 +00:00
|
|
|
s.Require().Error(err)
|
|
|
|
s.Require().Nil(response)
|
|
|
|
}
|
|
|
|
|
2023-08-08 15:02:56 +00:00
|
|
|
func testEventSenderCannotEditPrivilegedCommunityPermission(base CommunityEventsTestsInterface, community *communities.Community,
|
|
|
|
testPermissionType protobuf.CommunityTokenPermission_Type, rolePermissionType protobuf.CommunityTokenPermission_Type) {
|
2023-07-26 16:01:19 +00:00
|
|
|
|
2023-08-08 15:02:56 +00:00
|
|
|
// 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)
|
2023-07-26 16:01:19 +00:00
|
|
|
}
|
|
|
|
|
2023-08-08 15:02:56 +00:00
|
|
|
permissionRequest := createTestPermissionRequest(community, testPermissionType)
|
|
|
|
tokenPermissionID := controlNodeCreatesCommunityPermission(base, community, permissionRequest)
|
2023-07-26 16:01:19 +00:00
|
|
|
|
|
|
|
permissionRequest.TokenCriteria[0].Symbol = "UPDATED"
|
|
|
|
permissionRequest.TokenCriteria[0].Amount = "200"
|
|
|
|
|
|
|
|
permissionEditRequest := &requests.EditCommunityTokenPermission{
|
|
|
|
PermissionID: tokenPermissionID,
|
|
|
|
CreateCommunityTokenPermission: *permissionRequest,
|
|
|
|
}
|
|
|
|
|
|
|
|
// then, event sender tries to edit permission
|
2023-08-08 15:02:56 +00:00
|
|
|
response, err := base.GetEventSender().EditCommunityTokenPermission(permissionEditRequest)
|
|
|
|
s := base.GetSuite()
|
2023-07-26 16:01:19 +00:00
|
|
|
s.Require().Error(err)
|
|
|
|
s.Require().Nil(response)
|
|
|
|
}
|
2023-08-04 10:28:46 +00:00
|
|
|
|
2023-08-15 17:42:40 +00:00
|
|
|
func testAddAndSyncTokenFromControlNode(base CommunityEventsTestsInterface, community *communities.Community,
|
2023-08-22 17:48:42 +00:00
|
|
|
privilegesLvl token.PrivilegesLevel) {
|
2023-08-15 17:42:40 +00:00
|
|
|
tokenERC721 := createCommunityToken(community.IDString(), privilegesLvl)
|
2023-08-25 15:36:39 +00:00
|
|
|
addCommunityTokenToCommunityTokensService(base, tokenERC721)
|
2023-08-15 17:42:40 +00:00
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
|
|
|
|
_, err := base.GetControlNode().SaveCommunityToken(tokenERC721, nil)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
err = base.GetControlNode().AddCommunityToken(tokenERC721.CommunityID, tokenERC721.ChainID, tokenERC721.Address)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
tokens, err := base.GetEventSender().communitiesManager.GetAllCommunityTokens()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(tokens, 0)
|
|
|
|
|
|
|
|
checkTokenAdded := func(response *MessengerResponse) error {
|
|
|
|
modifiedCommmunity, err := getModifiedCommunity(response, community.IDString())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-08-22 17:48:42 +00:00
|
|
|
if privilegesLvl != token.CommunityLevel && len(modifiedCommmunity.TokenPermissions()) == 0 {
|
|
|
|
return errors.New("Token permissions was not found")
|
|
|
|
}
|
|
|
|
|
2023-08-15 17:42:40 +00:00
|
|
|
for _, tokenMetadata := range modifiedCommmunity.CommunityTokensMetadata() {
|
|
|
|
if tokenMetadata.Name == tokenERC721.Name {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return errors.New("Token was not found")
|
|
|
|
}
|
|
|
|
|
|
|
|
waitOnMessengerResponse(s, WaitCommunityCondition, checkTokenAdded, base.GetMember())
|
|
|
|
waitOnMessengerResponse(s, WaitCommunityCondition, checkTokenAdded, base.GetEventSender())
|
|
|
|
|
2023-08-22 17:48:42 +00:00
|
|
|
// check CommunityToken was added to the DB
|
|
|
|
syncTokens, err := base.GetEventSender().communitiesManager.GetAllCommunityTokens()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(syncTokens, 1)
|
|
|
|
s.Require().Equal(syncTokens[0].PrivilegesLevel, privilegesLvl)
|
2023-08-15 17:42:40 +00:00
|
|
|
|
2023-08-22 17:48:42 +00:00
|
|
|
// check CommunityToken was not added to the DB
|
|
|
|
syncTokens, err = base.GetMember().communitiesManager.GetAllCommunityTokens()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(syncTokens, 0)
|
2023-08-15 17:42:40 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
|
|
|
func createCommunityToken(communityID string, privilegesLevel token.PrivilegesLevel) *token.CommunityToken {
|
|
|
|
return &token.CommunityToken{
|
|
|
|
CommunityID: communityID,
|
2023-08-04 10:28:46 +00:00
|
|
|
TokenType: protobuf.CommunityTokenType_ERC721,
|
|
|
|
Address: "0x123",
|
|
|
|
Name: "StatusToken",
|
|
|
|
Symbol: "STT",
|
|
|
|
Description: "desc",
|
|
|
|
Supply: &bigint.BigInt{Int: big.NewInt(123)},
|
|
|
|
InfiniteSupply: false,
|
|
|
|
Transferable: true,
|
|
|
|
RemoteSelfDestruct: true,
|
|
|
|
ChainID: 1,
|
2023-07-07 13:03:37 +00:00
|
|
|
DeployState: token.Deployed,
|
2023-08-04 10:28:46 +00:00
|
|
|
Base64Image: "ABCD",
|
2023-08-15 17:42:40 +00:00
|
|
|
PrivilegesLevel: privilegesLevel,
|
2023-08-04 10:28:46 +00:00
|
|
|
}
|
2023-08-15 17:42:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func testAddAndSyncTokenFromEventSenderByControlNode(base CommunityEventsTestsInterface, community *communities.Community,
|
|
|
|
privilegesLvl token.PrivilegesLevel) {
|
|
|
|
tokenERC721 := createCommunityToken(community.IDString(), privilegesLvl)
|
2023-08-25 15:36:39 +00:00
|
|
|
addCommunityTokenToCommunityTokensService(base, tokenERC721)
|
2023-08-04 10:28:46 +00:00
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
|
|
|
|
_, err := base.GetEventSender().SaveCommunityToken(tokenERC721, nil)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
err = base.GetEventSender().AddCommunityToken(tokenERC721.CommunityID, tokenERC721.ChainID, tokenERC721.Address)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
2023-08-15 17:42:40 +00:00
|
|
|
tokens, err := base.GetControlNode().communitiesManager.GetAllCommunityTokens()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(tokens, 0)
|
|
|
|
|
2023-08-04 10:28:46 +00:00
|
|
|
checkTokenAdded := func(response *MessengerResponse) error {
|
|
|
|
modifiedCommmunity, err := getModifiedCommunity(response, community.IDString())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tokenMetadata := range modifiedCommmunity.CommunityTokensMetadata() {
|
|
|
|
if tokenMetadata.Name == tokenERC721.Name {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return errors.New("Token was not found")
|
|
|
|
}
|
|
|
|
|
|
|
|
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkTokenAdded)
|
2023-08-15 17:42:40 +00:00
|
|
|
|
|
|
|
// check event sender sent sync message to the control node
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
base.GetControlNode(),
|
|
|
|
func(r *MessengerResponse) bool {
|
|
|
|
tokens, err := base.GetControlNode().communitiesManager.GetAllCommunityTokens()
|
|
|
|
return err == nil && len(tokens) == 1
|
|
|
|
},
|
|
|
|
"no token sync message from event sender",
|
|
|
|
)
|
|
|
|
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// check member did not receive sync message with the token
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
base.GetMember(),
|
|
|
|
func(r *MessengerResponse) bool {
|
|
|
|
tokens, err := base.GetMember().communitiesManager.GetAllCommunityTokens()
|
|
|
|
return err == nil && len(tokens) == 1
|
|
|
|
},
|
|
|
|
"no token sync message from event sender",
|
|
|
|
)
|
|
|
|
|
|
|
|
s.Require().Error(err)
|
2023-08-04 10:28:46 +00:00
|
|
|
}
|
2023-08-08 15:02:56 +00:00
|
|
|
|
2023-08-15 17:42:40 +00:00
|
|
|
func testEventSenderAddTokenMasterAndOwnerToken(base CommunityEventsTestsInterface, community *communities.Community) {
|
|
|
|
ownerToken := createCommunityToken(community.IDString(), token.OwnerLevel)
|
2023-08-25 15:36:39 +00:00
|
|
|
addCommunityTokenToCommunityTokensService(base, ownerToken)
|
2023-08-08 15:02:56 +00:00
|
|
|
|
|
|
|
s := base.GetSuite()
|
2023-08-15 17:42:40 +00:00
|
|
|
|
|
|
|
_, err := base.GetEventSender().SaveCommunityToken(ownerToken, nil)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
err = base.GetEventSender().AddCommunityToken(ownerToken.CommunityID, ownerToken.ChainID, ownerToken.Address)
|
|
|
|
s.Require().Error(err, communities.ErrInvalidManageTokensPermission)
|
|
|
|
|
|
|
|
tokenMasterToken := ownerToken
|
|
|
|
tokenMasterToken.PrivilegesLevel = token.MasterLevel
|
|
|
|
tokenMasterToken.Address = "0x124"
|
|
|
|
|
|
|
|
_, err = base.GetEventSender().SaveCommunityToken(tokenMasterToken, nil)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
err = base.GetEventSender().AddCommunityToken(ownerToken.CommunityID, ownerToken.ChainID, ownerToken.Address)
|
|
|
|
s.Require().Error(err, communities.ErrInvalidManageTokensPermission)
|
2023-08-08 15:02:56 +00:00
|
|
|
}
|
2023-08-22 17:48:42 +00:00
|
|
|
|
2023-08-25 15:36:39 +00:00
|
|
|
func addCommunityTokenToCommunityTokensService(base CommunityEventsTestsInterface, token *token.CommunityToken) {
|
|
|
|
data := &communitytokens.CollectibleContractData{
|
2023-08-22 17:48:42 +00:00
|
|
|
TotalSupply: token.Supply,
|
|
|
|
Transferable: token.Transferable,
|
|
|
|
RemoteBurnable: token.RemoteSelfDestruct,
|
|
|
|
InfiniteSupply: token.InfiniteSupply,
|
|
|
|
}
|
|
|
|
|
|
|
|
base.GetCollectiblesServiceMock().SetMockCollectibleContractData(uint64(token.ChainID), token.Address, data)
|
|
|
|
}
|