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
|
2024-01-22 14:47:22 +00:00
|
|
|
SetupAdditionalMessengers([]*Messenger)
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
const communitiesEventsTestTokenAddress = "0x0400000000000000000000000000000000000000"
|
|
|
|
const aliceAccountAddress = "0x0777100000000000000000000000000000000000"
|
|
|
|
const bobAccountAddress = "0x0330000000000000000000000000000000000000"
|
|
|
|
const communitiesEventsTestChainID = 1
|
|
|
|
const eventsSenderAccountAddress = "0x0200000000000000000000000000000000000000"
|
|
|
|
const accountPassword = "qwerty"
|
2023-08-08 15:02:56 +00:00
|
|
|
|
2023-07-26 12:16:50 +00:00
|
|
|
type MessageResponseValidator func(*MessengerResponse) error
|
|
|
|
|
|
|
|
func WaitMessageCondition(response *MessengerResponse) bool {
|
|
|
|
return len(response.Messages()) > 0
|
|
|
|
}
|
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
func waitOnMessengerResponse(s *suite.Suite, fnWait MessageResponseValidator, user *Messenger) {
|
|
|
|
_, err := WaitOnMessengerResponse(
|
2023-07-26 12:16:50 +00:00
|
|
|
user,
|
2023-09-20 08:37:46 +00:00
|
|
|
func(r *MessengerResponse) bool {
|
|
|
|
err := fnWait(r)
|
|
|
|
return err == nil
|
|
|
|
},
|
2023-07-26 12:16:50 +00:00
|
|
|
"MessengerResponse data not received",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
}
|
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
func checkClientsReceivedAdminEvent(base CommunityEventsTestsInterface, fn MessageResponseValidator) {
|
2023-07-26 12:16:50 +00:00
|
|
|
s := base.GetSuite()
|
|
|
|
// Wait and verify Member received community event
|
2023-09-20 08:37:46 +00:00
|
|
|
waitOnMessengerResponse(s, fn, base.GetMember())
|
2023-07-26 12:16:50 +00:00
|
|
|
// Wait and verify event sender received his own event
|
2023-09-20 08:37:46 +00:00
|
|
|
waitOnMessengerResponse(s, fn, base.GetEventSender())
|
2023-07-26 12:16:50 +00:00
|
|
|
// Wait and verify ControlNode received community event
|
|
|
|
// ControlNode will publish CommunityDescription update
|
2023-09-20 08:37:46 +00:00
|
|
|
waitOnMessengerResponse(s, fn, base.GetControlNode())
|
2023-07-26 12:16:50 +00:00
|
|
|
// Wait and verify Member received the ControlNode CommunityDescription update
|
2023-09-20 08:37:46 +00:00
|
|
|
waitOnMessengerResponse(s, fn, base.GetMember())
|
2023-07-26 12:16:50 +00:00
|
|
|
// Wait and verify event sender received the ControlNode CommunityDescription update
|
2023-09-20 08:37:46 +00:00
|
|
|
waitOnMessengerResponse(s, fn, base.GetEventSender())
|
2023-07-26 12:16:50 +00:00
|
|
|
// Wait and verify ControlNode received his own CommunityDescription update
|
2023-09-20 08:37:46 +00:00
|
|
|
waitOnMessengerResponse(s, fn, base.GetControlNode())
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
2023-09-20 08:37:46 +00:00
|
|
|
eventSenderAddress := gethcommon.HexToAddress(eventsSenderAccountAddress)
|
2023-08-08 15:02:56 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
// event sender will have token with `communitiesEventsTestTokenAddress``
|
|
|
|
contractAddress := gethcommon.HexToAddress(communitiesEventsTestTokenAddress)
|
2023-08-08 15:02:56 +00:00
|
|
|
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)
|
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
mockedBalances[communitiesEventsTestChainID][eventSenderAddress][contractAddress] = (*hexutil.Big)(balance)
|
2023-08-08 15:02:56 +00:00
|
|
|
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
|
2023-10-25 13:03:26 +00:00
|
|
|
community := createTestCommunity(base, protobuf.CommunityPermissions_AUTO_ACCEPT)
|
2023-07-26 12:16:50 +00:00
|
|
|
refreshMessengerResponses(base)
|
|
|
|
|
|
|
|
// add events sender and member to the community
|
2023-12-15 11:55:32 +00:00
|
|
|
advertiseCommunityToUserOldWay(suite, community, base.GetControlNode(), base.GetEventSender())
|
|
|
|
advertiseCommunityToUserOldWay(suite, community, base.GetControlNode(), base.GetMember())
|
2023-07-26 12:16:50 +00:00
|
|
|
|
2023-08-08 15:02:56 +00:00
|
|
|
request := &requests.RequestToJoinCommunity{
|
|
|
|
CommunityID: community.ID(),
|
2023-09-20 08:37:46 +00:00
|
|
|
AddressesToReveal: []string{eventsSenderAccountAddress},
|
|
|
|
AirdropAddress: eventsSenderAccountAddress,
|
2023-08-08 15:02:56 +00:00
|
|
|
}
|
2023-10-20 06:21:41 +00:00
|
|
|
joinCommunity(suite, community, base.GetControlNode(), base.GetEventSender(), request, accountPassword)
|
2023-07-28 18:18:27 +00:00
|
|
|
refreshMessengerResponses(base)
|
2023-08-08 15:02:56 +00:00
|
|
|
|
|
|
|
request = &requests.RequestToJoinCommunity{
|
|
|
|
CommunityID: community.ID(),
|
2023-09-20 08:37:46 +00:00
|
|
|
AddressesToReveal: []string{aliceAccountAddress},
|
|
|
|
AirdropAddress: aliceAccountAddress,
|
2023-08-08 15:02:56 +00:00
|
|
|
}
|
2023-10-20 06:21:41 +00:00
|
|
|
joinCommunity(suite, community, base.GetControlNode(), base.GetMember(), request, accountPassword)
|
2023-07-26 12:16:50 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
checkClientsReceivedAdminEvent(base, checkChannelCreated)
|
2023-07-26 12:16:50 +00:00
|
|
|
|
|
|
|
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))
|
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
checkClientsReceivedAdminEvent(base, checkChannelEdited)
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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))
|
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
checkClientsReceivedAdminEvent(base, checkChannelDeleted)
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
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-09-20 08:37:46 +00:00
|
|
|
ContractAddresses: map[uint64]string{uint64(communitiesEventsTestChainID): communitiesEventsTestTokenAddress},
|
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 {
|
2024-01-22 14:47:22 +00:00
|
|
|
base.SetupAdditionalMessengers(additionalEventSenders)
|
|
|
|
|
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
|
2023-10-25 13:03:26 +00:00
|
|
|
community := createTestCommunity(base, protobuf.CommunityPermissions_MANUAL_ACCEPT)
|
2023-07-28 18:18:27 +00:00
|
|
|
refreshMessengerResponses(base)
|
|
|
|
|
2023-12-15 11:55:32 +00:00
|
|
|
advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), base.GetEventSender())
|
|
|
|
advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), base.GetMember())
|
2023-07-26 12:16:50 +00:00
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
requestEventSender := &requests.RequestToJoinCommunity{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
AddressesToReveal: []string{eventsSenderAccountAddress},
|
|
|
|
ENSName: "eventSender",
|
|
|
|
AirdropAddress: eventsSenderAccountAddress,
|
|
|
|
}
|
|
|
|
|
|
|
|
joinOnRequestCommunity(s, community, base.GetControlNode(), base.GetEventSender(), requestEventSender)
|
|
|
|
|
|
|
|
requestMember := &requests.RequestToJoinCommunity{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
AddressesToReveal: []string{aliceAccountAddress},
|
|
|
|
ENSName: "alice",
|
|
|
|
AirdropAddress: aliceAccountAddress,
|
|
|
|
}
|
|
|
|
joinOnRequestCommunity(s, community, base.GetControlNode(), base.GetMember(), requestMember)
|
2023-07-31 15:52:41 +00:00
|
|
|
|
|
|
|
checkMemberJoined := func(response *MessengerResponse) error {
|
|
|
|
return checkMemberJoinedToTheCommunity(response, base.GetMember().IdentityPublicKey())
|
|
|
|
}
|
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
waitOnMessengerResponse(s, 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)
|
|
|
|
}
|
2023-09-20 08:37:46 +00:00
|
|
|
waitOnMessengerResponse(s, 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 {
|
2023-12-15 11:55:32 +00:00
|
|
|
advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), eventSender)
|
2023-09-20 08:37:46 +00:00
|
|
|
joinOnRequestCommunity(s, community, base.GetControlNode(), eventSender, requestEventSender)
|
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
|
|
|
|
|
|
|
grantPermission(s, community, base.GetControlNode(), eventSender, role)
|
|
|
|
checkPermissionGranted = func(response *MessengerResponse) error {
|
|
|
|
return checkRolePermissionInResponse(response, eventSender.IdentityPublicKey(), role)
|
|
|
|
}
|
2023-09-20 08:37:46 +00:00
|
|
|
waitOnMessengerResponse(s, checkPermissionGranted, base.GetMember())
|
|
|
|
waitOnMessengerResponse(s, checkPermissionGranted, base.GetEventSender())
|
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
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
checkClientsReceivedAdminEvent(base, checkCategoryCreated)
|
2023-07-26 12:16:50 +00:00
|
|
|
|
|
|
|
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))
|
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
checkClientsReceivedAdminEvent(base, checkCategoryEdited)
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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))
|
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
checkClientsReceivedAdminEvent(base, checkCategoryDeleted)
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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))
|
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
checkClientsReceivedAdminEvent(base, checkCategoryReorder)
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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))
|
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
checkClientsReceivedAdminEvent(base, checkChannelReorder)
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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")
|
|
|
|
}
|
|
|
|
|
2023-10-04 20:47:22 +00:00
|
|
|
if len(modifiedCommmunity.PendingAndBannedMembers()) > 0 {
|
|
|
|
return errors.New("alice was kicked and should not be presented in the pending list")
|
|
|
|
}
|
|
|
|
|
2023-07-26 12:16:50 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
response, err := base.GetEventSender().RemoveUserFromCommunity(
|
|
|
|
communityID,
|
|
|
|
pubkey,
|
|
|
|
)
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
2023-10-04 20:47:22 +00:00
|
|
|
// 1. event sender should get pending state for kicked member
|
|
|
|
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(communityID))
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().True(modifiedCommmunity.HasMember(&base.GetMember().identity.PublicKey))
|
|
|
|
s.Require().Equal(communities.CommunityMemberKickPending, modifiedCommmunity.PendingAndBannedMembers()[pubkey])
|
|
|
|
|
|
|
|
// 2. wait for event as a sender
|
|
|
|
waitOnMessengerResponse(s, 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 should not be not kicked (yet)")
|
|
|
|
}
|
|
|
|
|
|
|
|
if modifiedCommmunity.PendingAndBannedMembers()[pubkey] != communities.CommunityMemberKickPending {
|
|
|
|
return errors.New("alice should be in the pending state")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}, base.GetEventSender())
|
|
|
|
|
|
|
|
// 3. wait for event as the community member and check we are still until control node gets it
|
|
|
|
waitOnMessengerResponse(s, 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 should not be not kicked (yet)")
|
|
|
|
}
|
|
|
|
|
2023-12-19 11:00:29 +00:00
|
|
|
if len(modifiedCommmunity.PendingAndBannedMembers()) == 0 {
|
|
|
|
return errors.New("alice should know about banned and pending members")
|
2023-10-04 20:47:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}, base.GetMember())
|
|
|
|
|
|
|
|
// 4. control node should handle event and actually kick member
|
|
|
|
waitOnMessengerResponse(s, checkKicked, base.GetControlNode())
|
|
|
|
|
|
|
|
// 5. event sender get removed member
|
|
|
|
waitOnMessengerResponse(s, checkKicked, base.GetEventSender())
|
|
|
|
|
|
|
|
// 6. member should be notified about actual removal
|
|
|
|
waitOnMessengerResponse(s, checkKicked, base.GetMember())
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func banMember(base CommunityEventsTestsInterface, banRequest *requests.BanUserFromCommunity) {
|
2023-10-04 20:47:22 +00:00
|
|
|
pubkey := common.PubkeyToHex(&base.GetMember().identity.PublicKey)
|
|
|
|
|
2023-07-26 12:16:50 +00:00
|
|
|
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")
|
|
|
|
}
|
|
|
|
|
2023-10-04 20:47:22 +00:00
|
|
|
if modifiedCommmunity.PendingAndBannedMembers()[pubkey] != communities.CommunityMemberBanned {
|
|
|
|
return errors.New("alice should be in the pending state")
|
|
|
|
}
|
|
|
|
|
2023-07-26 12:16:50 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-10-22 09:41:20 +00:00
|
|
|
response, err := base.GetEventSender().BanUserFromCommunity(context.Background(), banRequest)
|
2023-07-26 12:16:50 +00:00
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
2023-10-04 20:47:22 +00:00
|
|
|
// 1. event sender should get pending state for ban member
|
|
|
|
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(banRequest.CommunityID))
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().True(modifiedCommmunity.HasMember(&base.GetMember().identity.PublicKey))
|
|
|
|
s.Require().Equal(communities.CommunityMemberBanPending, modifiedCommmunity.PendingAndBannedMembers()[pubkey])
|
|
|
|
|
|
|
|
// 2. wait for event as a sender
|
|
|
|
waitOnMessengerResponse(s, 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 should not be not banned (yet)")
|
|
|
|
}
|
|
|
|
|
|
|
|
if modifiedCommmunity.PendingAndBannedMembers()[pubkey] != communities.CommunityMemberBanPending {
|
|
|
|
return errors.New("alice should be in the pending state")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}, base.GetEventSender())
|
|
|
|
|
|
|
|
// 3. wait for event as the community member and check we are still until control node gets it
|
|
|
|
waitOnMessengerResponse(s, 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 should not be not banned (yet)")
|
|
|
|
}
|
|
|
|
|
2023-12-19 11:00:29 +00:00
|
|
|
if len(modifiedCommmunity.PendingAndBannedMembers()) == 0 {
|
|
|
|
return errors.New("alice should know about banned and pending members")
|
2023-10-04 20:47:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}, base.GetMember())
|
|
|
|
|
|
|
|
// 4. control node should handle event and actually ban member
|
|
|
|
waitOnMessengerResponse(s, checkBanned, base.GetControlNode())
|
|
|
|
|
|
|
|
// 5. event sender get banned member
|
|
|
|
waitOnMessengerResponse(s, checkBanned, base.GetEventSender())
|
|
|
|
|
|
|
|
// 6. member should be notified about actual removal
|
|
|
|
waitOnMessengerResponse(s, checkBanned, base.GetMember())
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func unbanMember(base CommunityEventsTestsInterface, unbanRequest *requests.UnbanUserFromCommunity) {
|
2023-10-04 20:47:22 +00:00
|
|
|
pubkey := common.PubkeyToHex(&base.GetMember().identity.PublicKey)
|
|
|
|
|
2023-07-26 12:16:50 +00:00
|
|
|
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")
|
|
|
|
}
|
|
|
|
|
2023-10-04 20:47:22 +00:00
|
|
|
if modifiedCommmunity.PendingAndBannedMembers()[pubkey] != communities.CommunityMemberBanned {
|
|
|
|
return errors.New("alice should be in the pending state")
|
|
|
|
}
|
|
|
|
|
2023-07-26 12:16:50 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
response, err := base.GetEventSender().UnbanUserFromCommunity(unbanRequest)
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
2023-10-04 20:47:22 +00:00
|
|
|
// 1. event sender should get pending state for unban member
|
|
|
|
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(unbanRequest.CommunityID))
|
2023-07-26 12:16:50 +00:00
|
|
|
s.Require().NoError(err)
|
2023-10-04 20:47:22 +00:00
|
|
|
s.Require().Equal(communities.CommunityMemberUnbanPending, modifiedCommmunity.PendingAndBannedMembers()[pubkey])
|
|
|
|
|
|
|
|
// 2. wait for event as a sender
|
|
|
|
waitOnMessengerResponse(s, func(response *MessengerResponse) error {
|
|
|
|
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(unbanRequest.CommunityID))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if modifiedCommmunity.PendingAndBannedMembers()[pubkey] != communities.CommunityMemberUnbanPending {
|
|
|
|
return errors.New("alice should be in the pending state")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}, base.GetEventSender())
|
|
|
|
|
|
|
|
// 3. wait for event as the community member and check we are still until control node gets it
|
|
|
|
waitOnMessengerResponse(s, func(response *MessengerResponse) error {
|
|
|
|
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(unbanRequest.CommunityID))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-12-19 11:00:29 +00:00
|
|
|
if len(modifiedCommmunity.PendingAndBannedMembers()) == 0 {
|
|
|
|
return errors.New("alice should know about banned and pending members")
|
2023-10-04 20:47:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}, base.GetMember())
|
|
|
|
|
|
|
|
// 4. control node should handle event and actually unban member
|
|
|
|
waitOnMessengerResponse(s, checkUnbanned, base.GetControlNode())
|
|
|
|
|
|
|
|
// 5. event sender get removed member
|
|
|
|
waitOnMessengerResponse(s, checkUnbanned, base.GetEventSender())
|
|
|
|
|
|
|
|
// 6. member should be notified about actual removal
|
|
|
|
waitOnMessengerResponse(s, checkUnbanned, base.GetMember())
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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))
|
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
waitOnMessengerResponse(s, checkMessageDeleted, base.GetMember())
|
|
|
|
waitOnMessengerResponse(s, checkMessageDeleted, base.GetControlNode())
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func pinControlNodeMessage(base CommunityEventsTestsInterface, pinnedMessage *common.PinMessage) {
|
|
|
|
checkPinned := func(response *MessengerResponse) error {
|
2023-09-20 08:37:46 +00:00
|
|
|
if len(response.Messages()) == 0 {
|
|
|
|
return errors.New("no messages in the response")
|
|
|
|
}
|
|
|
|
|
2023-07-26 12:16:50 +00:00
|
|
|
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))
|
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
waitOnMessengerResponse(s, checkPinned, base.GetMember())
|
|
|
|
waitOnMessengerResponse(s, checkPinned, base.GetControlNode())
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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{
|
2023-10-25 13:03:26 +00:00
|
|
|
Membership: protobuf.CommunityPermissions_MANUAL_ACCEPT,
|
2023-07-26 12:16:50 +00:00
|
|
|
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))
|
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
checkClientsReceivedAdminEvent(base, checkCommunityEdit)
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
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
|
2023-09-20 08:37:46 +00:00
|
|
|
resp, err := WaitOnMessengerResponse(
|
2023-08-08 15:02:56 +00:00
|
|
|
base.GetEventSender(),
|
|
|
|
func(r *MessengerResponse) bool {
|
|
|
|
return len(r.Communities()) > 0 &&
|
2023-09-20 08:37:46 +00:00
|
|
|
len(r.Communities()[0].TokenPermissionsByType(permissionRequest.Type)) > 0 &&
|
|
|
|
r.Communities()[0].HasPermissionToSendCommunityEvents()
|
2023-08-08 15:02:56 +00:00
|
|
|
},
|
|
|
|
"event sender did not receive community token permission",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
2023-09-20 08:37:46 +00:00
|
|
|
s.Require().NotNil(resp)
|
2023-08-08 15:02:56 +00:00
|
|
|
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{
|
2023-10-25 13:03:26 +00:00
|
|
|
Access: protobuf.CommunityPermissions_AUTO_ACCEPT,
|
2023-07-26 12:16:50 +00:00
|
|
|
},
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2023-12-15 11:55:32 +00:00
|
|
|
// To be removed in https://github.com/status-im/status-go/issues/4437
|
|
|
|
func advertiseCommunityToUserOldWay(s *suite.Suite, community *communities.Community, owner *Messenger, user *Messenger) {
|
|
|
|
|
|
|
|
chat := CreateOneToOneChat(common.PubkeyToHex(&user.identity.PublicKey), &user.identity.PublicKey, user.transport)
|
|
|
|
|
|
|
|
inputMessage := common.NewMessage()
|
|
|
|
inputMessage.ChatId = chat.ID
|
|
|
|
inputMessage.Text = "some text"
|
|
|
|
inputMessage.CommunityID = community.IDString()
|
|
|
|
|
|
|
|
err := owner.SaveChat(chat)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
_, err = owner.SendChatMessage(context.Background(), inputMessage)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// Ensure community is received
|
|
|
|
response, err := WaitOnMessengerResponse(
|
|
|
|
user,
|
|
|
|
func(r *MessengerResponse) bool {
|
|
|
|
return len(r.Communities()) > 0
|
|
|
|
},
|
|
|
|
"event sender did not receive community request to join",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
communityInResponse := response.Communities()[0]
|
|
|
|
s.Require().Equal(community.ID(), communityInResponse.ID())
|
|
|
|
}
|
|
|
|
|
2023-07-26 12:16:50 +00:00
|
|
|
func testAcceptMemberRequestToJoin(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger) {
|
|
|
|
s := base.GetSuite()
|
|
|
|
|
2023-12-15 11:55:32 +00:00
|
|
|
advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), user)
|
2023-07-26 12:16:50 +00:00
|
|
|
|
|
|
|
// user sends request to join
|
2023-09-20 08:37:46 +00:00
|
|
|
requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID(), ENSName: "testName"}
|
2023-07-26 12:16:50 +00:00
|
|
|
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
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
checkRequestToJoin := func(r *MessengerResponse) bool {
|
|
|
|
if len(r.RequestsToJoinCommunity) == 0 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
for _, request := range r.RequestsToJoinCommunity {
|
|
|
|
if request.ENSName == requestToJoin.ENSName {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
2023-07-26 12:16:50 +00:00
|
|
|
// event sender receives request to join
|
|
|
|
response, err = WaitOnMessengerResponse(
|
|
|
|
base.GetEventSender(),
|
2023-09-20 08:37:46 +00:00
|
|
|
checkRequestToJoin,
|
2023-07-26 12:16:50 +00:00
|
|
|
"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
|
2023-09-20 08:37:46 +00:00
|
|
|
_, err = WaitOnMessengerResponse(
|
2023-08-08 15:02:56 +00:00
|
|
|
base.GetControlNode(),
|
2023-09-20 08:37:46 +00:00
|
|
|
checkRequestToJoin,
|
2023-08-08 15:02:56 +00:00
|
|
|
"event sender did not receive community request to join",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
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))
|
|
|
|
|
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) {
|
|
|
|
s := base.GetSuite()
|
|
|
|
|
2023-12-15 11:55:32 +00:00
|
|
|
advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), user)
|
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
|
|
|
|
|
|
|
// 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))
|
2023-10-04 19:02:17 +00:00
|
|
|
|
|
|
|
// event sender 1 changes its mind and rejects the request
|
|
|
|
rejectRequestToJoin := &requests.DeclineRequestToJoinCommunity{ID: sentRequest.ID}
|
|
|
|
response, err = base.GetEventSender().DeclineRequestToJoinCommunity(rejectRequestToJoin)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(response)
|
|
|
|
|
|
|
|
// event sender 2 receives updated 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))
|
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 testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger, additionalEventSender *Messenger) {
|
|
|
|
s := base.GetSuite()
|
|
|
|
|
2023-12-15 11:55:32 +00:00
|
|
|
advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), user)
|
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
|
|
|
|
|
|
|
// 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-10-04 19:02:17 +00:00
|
|
|
|
|
|
|
// event sender 1 changes its mind and accepts the 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 updated 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))
|
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
|
|
|
func testRejectMemberRequestToJoin(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger) {
|
|
|
|
s := base.GetSuite()
|
|
|
|
|
2023-12-15 11:55:32 +00:00
|
|
|
advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), user)
|
2023-07-26 12:16:50 +00:00
|
|
|
|
|
|
|
// 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 {
|
2023-11-01 12:01:51 +00:00
|
|
|
requests, err := base.GetControlNode().DeclinedRequestsToJoinForCommunity(community.ID())
|
|
|
|
s.Require().NoError(err)
|
|
|
|
return len(response.Communities()) == 1 && len(requests) == 1
|
2023-08-15 15:27:01 +00:00
|
|
|
},
|
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
|
|
|
}
|
|
|
|
|
2024-01-16 15:21:02 +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 testControlNodeHandlesMultipleEventSenderRequestToJoinDecisions(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger, additionalEventSender *Messenger) {
|
|
|
|
_, err := user.Start()
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
s.Require().NoError(err)
|
2023-11-27 17:01:13 +00:00
|
|
|
defer TearDownMessenger(s, user)
|
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-12-15 11:55:32 +00:00
|
|
|
advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), user)
|
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
|
|
|
|
|
|
|
// 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(),
|
2023-12-07 16:27:14 +00:00
|
|
|
func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity) > 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
|
|
|
"control node did not receive event senders decision",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
2023-12-15 16:16:18 +00:00
|
|
|
|
|
|
|
err = tt.RetryWithBackOff(func() error {
|
|
|
|
// request to join is now marked as rejected
|
|
|
|
rejectedRequests, err := base.GetControlNode().DeclinedRequestsToJoinForCommunity(community.ID())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if len(rejectedRequests) != 1 {
|
|
|
|
return errors.New("rejected requests should be 1")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
})
|
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)
|
|
|
|
|
|
|
|
// event sender 2 accepts request to join
|
|
|
|
acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: sentRequest.ID}
|
|
|
|
_, err = additionalEventSender.AcceptRequestToJoinCommunity(acceptRequestToJoin)
|
2023-12-15 16:16:18 +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
|
|
|
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)
|
2023-12-15 16:16:18 +00:00
|
|
|
|
|
|
|
err = tt.RetryWithBackOff(func() error {
|
|
|
|
rejectedRequests, err := base.GetControlNode().DeclinedRequestsToJoinForCommunity(community.ID())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if len(rejectedRequests) != 1 {
|
|
|
|
return errors.New("rejected requests should be 1")
|
|
|
|
}
|
|
|
|
// we expect user's request to join still to be rejected
|
|
|
|
if rejectedRequests[0].PublicKey != common.PubkeyToHex(&user.identity.PublicKey) {
|
|
|
|
return errors.New("public key of rejected request not matching")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
|
|
|
|
})
|
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)
|
|
|
|
}
|
2024-01-16 15:21:02 +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
|
|
|
|
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{
|
2023-10-25 13:03:26 +00:00
|
|
|
Access: protobuf.CommunityPermissions_AUTO_ACCEPT,
|
2023-07-26 12:16:50 +00:00
|
|
|
},
|
|
|
|
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(
|
2023-10-22 09:41:20 +00:00
|
|
|
context.Background(),
|
2023-07-26 12:16:50 +00:00
|
|
|
&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(
|
2023-10-22 09:41:20 +00:00
|
|
|
context.Background(),
|
2023-07-26 12:16:50 +00:00
|
|
|
&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(
|
2023-10-22 09:41:20 +00:00
|
|
|
context.Background(),
|
2023-07-26 12:16:50 +00:00
|
|
|
&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{
|
2023-10-25 13:03:26 +00:00
|
|
|
Access: protobuf.CommunityPermissions_AUTO_ACCEPT,
|
2023-07-26 12:16:50 +00:00
|
|
|
},
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
waitOnMessengerResponse(s, checkChannelCreated, member)
|
|
|
|
waitOnMessengerResponse(s, checkChannelCreated, eventSender)
|
2023-07-26 12:16:50 +00:00
|
|
|
|
|
|
|
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))
|
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
waitOnMessengerResponse(s, checkChannelEdited, member)
|
|
|
|
waitOnMessengerResponse(s, checkChannelEdited, eventSender)
|
2023-07-26 12:16:50 +00:00
|
|
|
|
|
|
|
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))
|
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
waitOnMessengerResponse(s, checkChannelDeleted, member)
|
|
|
|
waitOnMessengerResponse(s, checkChannelDeleted, eventSender)
|
2023-07-26 12:16:50 +00:00
|
|
|
}
|
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")
|
|
|
|
}
|
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
waitOnMessengerResponse(s, checkTokenAdded, base.GetMember())
|
|
|
|
waitOnMessengerResponse(s, checkTokenAdded, base.GetEventSender())
|
2023-08-15 17:42:40 +00:00
|
|
|
|
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
|
|
|
|
2024-01-16 08:08:56 +00:00
|
|
|
// check CommunityToken was added to the DB
|
2023-08-22 17:48:42 +00:00
|
|
|
syncTokens, err = base.GetMember().communitiesManager.GetAllCommunityTokens()
|
|
|
|
s.Require().NoError(err)
|
2024-01-16 08:08:56 +00:00
|
|
|
s.Require().Len(syncTokens, 1)
|
2023-07-05 17:35:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func testAddAndSyncOwnerTokenFromControlNode(base CommunityEventsTestsInterface, community *communities.Community,
|
|
|
|
privilegesLvl token.PrivilegesLevel) {
|
|
|
|
tokenERC721 := createCommunityToken(community.IDString(), privilegesLvl)
|
|
|
|
addCommunityTokenToCommunityTokensService(base, tokenERC721)
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
// we only check that the community has been queued for validation
|
|
|
|
checkTokenAdded := func(response *MessengerResponse) error {
|
|
|
|
member := base.GetMember()
|
|
|
|
communitiesToValidate, err := member.communitiesManager.CommunitiesToValidate()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if len(communitiesToValidate) == 0 || communitiesToValidate[community.IDString()] == nil {
|
|
|
|
|
|
|
|
return errors.New("no communities to validate")
|
|
|
|
}
|
2023-08-15 17:42:40 +00:00
|
|
|
|
2023-07-05 17:35:22 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
waitOnMessengerResponse(s, checkTokenAdded, base.GetMember())
|
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")
|
|
|
|
}
|
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
checkClientsReceivedAdminEvent(base, 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)
|
|
|
|
|
2024-01-16 08:08:56 +00:00
|
|
|
// check member received sync message with the token
|
2023-08-15 17:42:40 +00:00
|
|
|
_, 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",
|
|
|
|
)
|
|
|
|
|
2024-01-16 08:08:56 +00:00
|
|
|
s.Require().NoError(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)
|
|
|
|
}
|
2023-09-20 08:37:46 +00:00
|
|
|
|
|
|
|
func testJoinedPrivilegedMemberReceiveRequestsToJoin(base CommunityEventsTestsInterface, community *communities.Community,
|
|
|
|
bob *Messenger, newPrivilegedUser *Messenger, tokenPermissionType protobuf.CommunityTokenPermission_Type) {
|
|
|
|
// create community permission
|
|
|
|
rolePermission := createTestPermissionRequest(community, tokenPermissionType)
|
|
|
|
controlNodeCreatesCommunityPermission(base, community, rolePermission)
|
|
|
|
|
|
|
|
s := base.GetSuite()
|
|
|
|
|
2023-12-15 11:55:32 +00:00
|
|
|
advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), bob)
|
|
|
|
advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), newPrivilegedUser)
|
2023-09-20 08:37:46 +00:00
|
|
|
|
|
|
|
requestNewPrivilegedUser := &requests.RequestToJoinCommunity{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
AddressesToReveal: []string{eventsSenderAccountAddress},
|
|
|
|
ENSName: "newPrivilegedUser",
|
|
|
|
AirdropAddress: eventsSenderAccountAddress,
|
|
|
|
}
|
|
|
|
|
|
|
|
requestToJoinID := requestToJoinCommunity(s, base.GetControlNode(), newPrivilegedUser, requestNewPrivilegedUser)
|
|
|
|
|
|
|
|
// accept join request
|
|
|
|
acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: requestToJoinID}
|
|
|
|
response, err := base.GetControlNode().AcceptRequestToJoinCommunity(acceptRequestToJoin)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(response)
|
|
|
|
|
|
|
|
updatedCommunity := response.Communities()[0]
|
|
|
|
s.Require().NotNil(updatedCommunity)
|
|
|
|
s.Require().True(updatedCommunity.HasMember(&newPrivilegedUser.identity.PublicKey))
|
|
|
|
|
|
|
|
_, err = WaitOnMessengerResponse(
|
2023-12-07 16:27:14 +00:00
|
|
|
base.GetEventSender(),
|
2023-09-20 08:37:46 +00:00
|
|
|
func(r *MessengerResponse) bool {
|
2023-12-07 16:27:14 +00:00
|
|
|
return len(r.Communities()) > 0 &&
|
|
|
|
len(r.Communities()[0].TokenPermissionsByType(tokenPermissionType)) > 0 &&
|
|
|
|
r.Communities()[0].HasPermissionToSendCommunityEvents()
|
2023-09-20 08:37:46 +00:00
|
|
|
},
|
2023-12-07 16:27:14 +00:00
|
|
|
"newPrivilegedUser did not receive privileged role",
|
2023-09-20 08:37:46 +00:00
|
|
|
)
|
2023-12-07 16:27:14 +00:00
|
|
|
|
2023-09-20 08:37:46 +00:00
|
|
|
s.Require().NoError(err)
|
2023-12-07 16:27:14 +00:00
|
|
|
|
|
|
|
expectedLength := 3
|
|
|
|
// newPrivilegedUser user should receive all requests to join with shared addresses from the control node
|
|
|
|
waitAndCheckRequestsToJoin(s, newPrivilegedUser, expectedLength, community.ID(), tokenPermissionType == protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER)
|
|
|
|
|
|
|
|
// bob joins the community
|
|
|
|
requestMember := &requests.RequestToJoinCommunity{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
AddressesToReveal: []string{bobAccountAddress},
|
|
|
|
ENSName: "bob",
|
|
|
|
AirdropAddress: bobAccountAddress,
|
|
|
|
}
|
|
|
|
|
|
|
|
bobRequestToJoinID := requestToJoinCommunity(s, base.GetControlNode(), bob, requestMember)
|
|
|
|
|
|
|
|
// accept join request
|
|
|
|
acceptRequestToJoin = &requests.AcceptRequestToJoinCommunity{ID: bobRequestToJoinID}
|
|
|
|
_, err = base.GetControlNode().AcceptRequestToJoinCommunity(acceptRequestToJoin)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
expectedLength = 4
|
|
|
|
waitAndCheckRequestsToJoin(s, newPrivilegedUser, expectedLength, community.ID(), tokenPermissionType == protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER)
|
2023-09-20 08:37:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func testMemberReceiveRequestsToJoinAfterGettingNewRole(base CommunityEventsTestsInterface, bob *Messenger, tokenPermissionType protobuf.CommunityTokenPermission_Type) {
|
|
|
|
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
|
2023-10-25 13:03:26 +00:00
|
|
|
community := createTestCommunity(base, protobuf.CommunityPermissions_MANUAL_ACCEPT)
|
2023-09-20 08:37:46 +00:00
|
|
|
|
2023-12-15 11:55:32 +00:00
|
|
|
advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), base.GetEventSender())
|
|
|
|
advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), base.GetMember())
|
|
|
|
advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), bob)
|
2023-09-20 08:37:46 +00:00
|
|
|
|
|
|
|
requestAlice := &requests.RequestToJoinCommunity{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
AddressesToReveal: []string{aliceAccountAddress},
|
|
|
|
ENSName: "alice",
|
|
|
|
AirdropAddress: aliceAccountAddress,
|
|
|
|
}
|
|
|
|
|
|
|
|
requestToJoinCommunity(s, base.GetControlNode(), base.GetMember(), requestAlice)
|
|
|
|
|
|
|
|
requestBob := &requests.RequestToJoinCommunity{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
AddressesToReveal: []string{bobAccountAddress},
|
|
|
|
ENSName: "bob",
|
|
|
|
AirdropAddress: bobAccountAddress,
|
|
|
|
}
|
|
|
|
|
|
|
|
requestToJoinCommunity(s, base.GetControlNode(), bob, requestBob)
|
|
|
|
|
|
|
|
requestEventSender := &requests.RequestToJoinCommunity{
|
|
|
|
CommunityID: community.ID(),
|
|
|
|
AddressesToReveal: []string{eventsSenderAccountAddress},
|
|
|
|
ENSName: "eventSender",
|
|
|
|
AirdropAddress: eventsSenderAccountAddress,
|
|
|
|
}
|
|
|
|
|
|
|
|
// event sender joins as simple user
|
|
|
|
joinOnRequestCommunity(s, community, base.GetControlNode(), base.GetEventSender(), requestEventSender)
|
|
|
|
|
|
|
|
// create community permission
|
|
|
|
rolePermission := createTestPermissionRequest(community, tokenPermissionType)
|
|
|
|
|
|
|
|
response, err := base.GetControlNode().CreateCommunityTokenPermission(rolePermission)
|
|
|
|
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, rolePermission.Type)
|
|
|
|
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
base.GetEventSender(),
|
|
|
|
func(r *MessengerResponse) bool {
|
2023-12-07 16:27:14 +00:00
|
|
|
return len(r.Communities()) > 0 &&
|
|
|
|
len(r.Communities()[0].TokenPermissionsByType(tokenPermissionType)) > 0 &&
|
|
|
|
r.Communities()[0].HasPermissionToSendCommunityEvents()
|
2023-09-20 08:37:46 +00:00
|
|
|
},
|
2023-12-07 16:27:14 +00:00
|
|
|
"event sender did not receive privileged role",
|
2023-09-20 08:37:46 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
2023-12-07 16:27:14 +00:00
|
|
|
expectedLength := 3
|
|
|
|
waitAndCheckRequestsToJoin(s, base.GetEventSender(), expectedLength, community.ID(), tokenPermissionType == protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER)
|
|
|
|
}
|
|
|
|
|
|
|
|
func waitAndCheckRequestsToJoin(s *suite.Suite, user *Messenger, expectedLength int, communityID types.HexBytes, checkRevealedAddresses bool) {
|
|
|
|
_, err := WaitOnMessengerResponse(
|
|
|
|
user,
|
|
|
|
func(r *MessengerResponse) bool {
|
|
|
|
requestsToJoin, err := user.communitiesManager.GetCommunityRequestsToJoinWithRevealedAddresses(communityID)
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if len(requestsToJoin) != expectedLength {
|
|
|
|
s.T().Log("invalid requests to join count:", len(requestsToJoin))
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, request := range requestsToJoin {
|
|
|
|
if request.PublicKey == common.PubkeyToHex(&user.identity.PublicKey) {
|
|
|
|
if len(request.RevealedAccounts) != 1 {
|
|
|
|
s.T().Log("our own requests to join must always have accounts revealed")
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
} else if checkRevealedAddresses {
|
|
|
|
if len(request.RevealedAccounts) != 1 {
|
|
|
|
s.T().Log("no accounts revealed")
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if len(request.RevealedAccounts) != 0 {
|
|
|
|
s.T().Log("unexpected accounts revealed")
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
},
|
|
|
|
"user did not receive all requests to join from the control node",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
2023-09-20 08:37:46 +00:00
|
|
|
}
|
2023-12-19 13:45:34 +00:00
|
|
|
|
|
|
|
func testPrivilegedMemberAcceptsRequestToJoinAfterMemberLeave(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger) {
|
|
|
|
s := base.GetSuite()
|
|
|
|
|
|
|
|
advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), user)
|
|
|
|
|
|
|
|
// user sends request to join
|
|
|
|
requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID(), ENSName: "testName"}
|
|
|
|
response, err := user.RequestToJoinCommunity(requestToJoin)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(response)
|
|
|
|
s.Require().Len(response.RequestsToJoinCommunity, 1)
|
|
|
|
|
|
|
|
sentRequest := response.RequestsToJoinCommunity[0]
|
|
|
|
|
|
|
|
checkRequestToJoin := func(r *MessengerResponse) bool {
|
|
|
|
if len(r.RequestsToJoinCommunity) == 0 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
for _, request := range r.RequestsToJoinCommunity {
|
|
|
|
if request.ENSName == requestToJoin.ENSName {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
// event sender receives request to join
|
|
|
|
response, err = WaitOnMessengerResponse(
|
|
|
|
base.GetEventSender(),
|
|
|
|
checkRequestToJoin,
|
|
|
|
"event sender did not receive community request to join",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(response.RequestsToJoinCommunity, 1)
|
|
|
|
|
|
|
|
// control node receives request to join
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
base.GetControlNode(),
|
|
|
|
checkRequestToJoin,
|
|
|
|
"event sender did not receive community request to join",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
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)
|
|
|
|
// 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))
|
|
|
|
|
|
|
|
// 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))
|
|
|
|
|
|
|
|
// control node receives community event with accepted membership request
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
base.GetControlNode(),
|
|
|
|
func(r *MessengerResponse) bool {
|
|
|
|
return len(r.Communities()) > 0 && r.Communities()[0].HasMember(&user.identity.PublicKey)
|
|
|
|
},
|
|
|
|
"control node did not receive community request to join response",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
|
|
|
|
// 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 with the new member",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// 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",
|
|
|
|
)
|
|
|
|
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
acceptedRequestsPending, err = base.GetEventSender().AcceptedPendingRequestsToJoinForCommunity(community.ID())
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(acceptedRequestsPending, 0)
|
|
|
|
|
|
|
|
// user leaves the community
|
|
|
|
response, err = user.LeaveCommunity(community.ID())
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(response.Communities(), 1)
|
|
|
|
s.Require().False(response.Communities()[0].Joined())
|
|
|
|
|
|
|
|
checkMemberLeave := func(r *MessengerResponse) bool {
|
|
|
|
return len(r.Communities()) > 0 && !r.Communities()[0].HasMember(&user.identity.PublicKey)
|
|
|
|
}
|
|
|
|
|
|
|
|
// check control node received member leave msg
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
base.GetControlNode(),
|
|
|
|
checkMemberLeave,
|
|
|
|
"control node did not receive member leave msg",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// check event sender received member leave update from ControlNode
|
|
|
|
_, err = WaitOnMessengerResponse(
|
2023-12-22 16:43:38 +00:00
|
|
|
base.GetEventSender(),
|
2023-12-19 13:45:34 +00:00
|
|
|
checkMemberLeave,
|
|
|
|
"event sender did not receive member leave update",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// user tries to rejoin again
|
|
|
|
response, err = user.RequestToJoinCommunity(requestToJoin)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(response)
|
|
|
|
s.Require().Len(response.RequestsToJoinCommunity, 1)
|
|
|
|
|
|
|
|
// event sender receives request to join
|
|
|
|
response, err = WaitOnMessengerResponse(
|
|
|
|
base.GetEventSender(),
|
|
|
|
checkRequestToJoin,
|
|
|
|
"event sender did not receive community request to join",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(response.RequestsToJoinCommunity, 1)
|
|
|
|
|
|
|
|
// control node receives request to join
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
base.GetControlNode(),
|
|
|
|
checkRequestToJoin,
|
|
|
|
"event sender did not receive community request to join",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
response, err = base.GetEventSender().AcceptRequestToJoinCommunity(acceptRequestToJoin)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(response)
|
|
|
|
s.Require().Len(response.Communities(), 1)
|
|
|
|
// 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))
|
|
|
|
|
|
|
|
// at this point, the request to join is marked as accepted pending 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))
|
|
|
|
|
|
|
|
// control node receives community event with accepted membership request
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
|
|
base.GetControlNode(),
|
|
|
|
func(r *MessengerResponse) bool {
|
|
|
|
return len(r.Communities()) > 0 && r.Communities()[0].HasMember(&user.identity.PublicKey)
|
|
|
|
},
|
|
|
|
"control node did not receive community request to join response",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
},
|
|
|
|
"user did not receive community request to join response",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// 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 with the new member",
|
|
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
// 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",
|
|
|
|
)
|
|
|
|
|
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
|
|
acceptedRequestsPending, err = base.GetEventSender().AcceptedPendingRequestsToJoinForCommunity(community.ID())
|
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(acceptedRequestsPending, 0)
|
|
|
|
}
|