status-go/protocol/communities_events_utils_te...

1846 lines
68 KiB
Go

package protocol
import (
"context"
"errors"
"math/big"
"github.com/stretchr/testify/suite"
gethcommon "github.com/ethereum/go-ethereum/common"
hexutil "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/protocol/common"
"github.com/status-im/status-go/protocol/communities"
"github.com/status-im/status-go/protocol/communities/token"
"github.com/status-im/status-go/protocol/protobuf"
"github.com/status-im/status-go/protocol/requests"
"github.com/status-im/status-go/services/communitytokens"
"github.com/status-im/status-go/services/wallet/bigint"
)
type CommunityEventsTestsInterface interface {
GetControlNode() *Messenger
GetEventSender() *Messenger
GetMember() *Messenger
GetSuite() *suite.Suite
GetCollectiblesServiceMock() *CollectiblesServiceMock
}
const commmunitiesEventsTestTokenAddress = "0x0400000000000000000000000000000000000000"
const commmunitiesEventsTestChainID = 1
const commmunitiesEventsEventSenderAddress = "0x0200000000000000000000000000000000000000"
type MessageResponseValidator func(*MessengerResponse) error
type WaitResponseValidator func(*MessengerResponse) bool
func WaitCommunityCondition(r *MessengerResponse) bool {
return len(r.Communities()) > 0
}
func WaitMessageCondition(response *MessengerResponse) bool {
return len(response.Messages()) > 0
}
func waitOnMessengerResponse(s *suite.Suite, fnWait WaitResponseValidator, fn MessageResponseValidator, user *Messenger) {
response, err := WaitOnMessengerResponse(
user,
fnWait,
"MessengerResponse data not received",
)
s.Require().NoError(err)
s.Require().NoError(fn(response))
}
func checkClientsReceivedAdminEvent(base CommunityEventsTestsInterface, fnWait WaitResponseValidator, fn MessageResponseValidator) {
s := base.GetSuite()
// Wait and verify Member received community event
waitOnMessengerResponse(s, fnWait, fn, base.GetMember())
// Wait and verify event sender received his own event
waitOnMessengerResponse(s, fnWait, fn, base.GetEventSender())
// Wait and verify ControlNode received community event
// ControlNode will publish CommunityDescription update
waitOnMessengerResponse(s, fnWait, fn, base.GetControlNode())
// Wait and verify Member received the ControlNode CommunityDescription update
waitOnMessengerResponse(s, fnWait, fn, base.GetMember())
// Wait and verify event sender received the ControlNode CommunityDescription update
waitOnMessengerResponse(s, fnWait, fn, base.GetEventSender())
// Wait and verify ControlNode received his own CommunityDescription update
waitOnMessengerResponse(s, fnWait, fn, base.GetControlNode())
}
func refreshMessengerResponses(base CommunityEventsTestsInterface) {
_, err := WaitOnMessengerResponse(base.GetControlNode(), func(response *MessengerResponse) bool {
return true
}, "community description changed message not received")
base.GetSuite().Require().NoError(err)
_, err = WaitOnMessengerResponse(base.GetEventSender(), func(response *MessengerResponse) bool {
return true
}, "community description changed message not received")
base.GetSuite().Require().NoError(err)
_, err = WaitOnMessengerResponse(base.GetMember(), func(response *MessengerResponse) bool {
return true
}, "community description changed message not received")
base.GetSuite().Require().NoError(err)
}
func createMockedWalletBalance(s *suite.Suite) map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big {
eventSenderAddress := gethcommon.HexToAddress(commmunitiesEventsEventSenderAddress)
mockedBalances := make(map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big)
mockedBalances[testChainID1] = make(map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big)
mockedBalances[testChainID1][eventSenderAddress] = make(map[gethcommon.Address]*hexutil.Big)
// event sender will have token with `commmunitiesEventsTestTokenAddress``
contractAddress := gethcommon.HexToAddress(commmunitiesEventsTestTokenAddress)
balance, ok := new(big.Int).SetString("200", 10)
s.Require().True(ok)
decimalsFactor := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(18)), nil)
balance.Mul(balance, decimalsFactor)
mockedBalances[commmunitiesEventsTestChainID][eventSenderAddress][contractAddress] = (*hexutil.Big)(balance)
return mockedBalances
}
func setUpCommunityAndRoles(base CommunityEventsTestsInterface, role protobuf.CommunityMember_Roles) *communities.Community {
tcs2, err := base.GetControlNode().communitiesManager.All()
suite := base.GetSuite()
suite.Require().NoError(err, "eventSender.communitiesManager.All")
suite.Len(tcs2, 1, "Must have 1 community")
// ControlNode creates a community and chat
community := createTestCommunity(base, protobuf.CommunityPermissions_NO_MEMBERSHIP)
refreshMessengerResponses(base)
// add events sender and member to the community
advertiseCommunityTo(suite, community, base.GetControlNode(), base.GetEventSender())
advertiseCommunityTo(suite, community, base.GetControlNode(), base.GetMember())
request := &requests.RequestToJoinCommunity{
CommunityID: community.ID(),
AddressesToReveal: []string{commmunitiesEventsEventSenderAddress},
Password: "qwerty1",
AirdropAddress: commmunitiesEventsEventSenderAddress,
}
joinCommunity(suite, community, base.GetControlNode(), base.GetEventSender(), request)
refreshMessengerResponses(base)
request = &requests.RequestToJoinCommunity{
CommunityID: community.ID(),
AddressesToReveal: []string{"0x0300000000000000000000000000000000000000"},
Password: "qwerty2",
AirdropAddress: "0x0300000000000000000000000000000000000000",
}
joinCommunity(suite, community, base.GetControlNode(), base.GetMember(), request)
refreshMessengerResponses(base)
// grant permissions to the event sender
grantPermission(suite, community, base.GetControlNode(), base.GetEventSender(), role)
refreshMessengerResponses(base)
return community
}
func createTestCommunity(base CommunityEventsTestsInterface, membershipType protobuf.CommunityPermissions_Access) *communities.Community {
description := &requests.CreateCommunity{
Membership: membershipType,
Name: "status",
Color: "#ffffff",
Description: "status community description",
PinMessageAllMembersEnabled: false,
}
response, err := base.GetControlNode().CreateCommunity(description, true)
suite := base.GetSuite()
suite.Require().NoError(err)
suite.Require().NotNil(response)
suite.Require().Len(response.Communities(), 1)
suite.Require().Len(response.Chats(), 1)
return response.Communities()[0]
}
func getModifiedCommunity(response *MessengerResponse, communityID string) (*communities.Community, error) {
if len(response.Communities()) == 0 {
return nil, errors.New("community not received")
}
var modifiedCommmunity *communities.Community = nil
for _, c := range response.Communities() {
if c.IDString() == communityID {
modifiedCommmunity = c
}
}
if modifiedCommmunity == nil {
return nil, errors.New("couldn't find community in response")
}
return modifiedCommmunity, nil
}
func createCommunityChannel(base CommunityEventsTestsInterface, community *communities.Community, newChannel *protobuf.CommunityChat) string {
checkChannelCreated := func(response *MessengerResponse) error {
modifiedCommmunity, err := getModifiedCommunity(response, community.IDString())
if err != nil {
return err
}
for _, chat := range modifiedCommmunity.Chats() {
if chat.GetIdentity().GetDisplayName() == newChannel.GetIdentity().GetDisplayName() {
return nil
}
}
return errors.New("couldn't find created chat in response")
}
response, err := base.GetEventSender().CreateCommunityChat(community.ID(), newChannel)
s := base.GetSuite()
s.Require().NoError(err)
s.Require().NoError(checkChannelCreated(response))
s.Require().Len(response.CommunityChanges, 1)
s.Require().Len(response.CommunityChanges[0].ChatsAdded, 1)
var addedChatID string
for addedChatID = range response.CommunityChanges[0].ChatsAdded {
break
}
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkChannelCreated)
return addedChatID
}
func editCommunityChannel(base CommunityEventsTestsInterface, community *communities.Community, editChannel *protobuf.CommunityChat, channelID string) {
checkChannelEdited := func(response *MessengerResponse) error {
modifiedCommmunity, err := getModifiedCommunity(response, community.IDString())
if err != nil {
return err
}
for _, chat := range modifiedCommmunity.Chats() {
if chat.GetIdentity().GetDisplayName() == editChannel.GetIdentity().GetDisplayName() {
return nil
}
}
return errors.New("couldn't find modified chat in response")
}
response, err := base.GetEventSender().EditCommunityChat(community.ID(), channelID, editChannel)
s := base.GetSuite()
s.Require().NoError(err)
s.Require().NoError(checkChannelEdited(response))
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkChannelEdited)
}
func deleteCommunityChannel(base CommunityEventsTestsInterface, community *communities.Community, channelID string) {
checkChannelDeleted := func(response *MessengerResponse) error {
modifiedCommmunity, err := getModifiedCommunity(response, community.IDString())
if err != nil {
return err
}
if _, exists := modifiedCommmunity.Chats()[channelID]; exists {
return errors.New("channel was not deleted")
}
return nil
}
response, err := base.GetEventSender().DeleteCommunityChat(community.ID(), channelID)
s := base.GetSuite()
s.Require().NoError(err)
s.Require().NoError(checkChannelDeleted(response))
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkChannelDeleted)
}
func createTestPermissionRequest(community *communities.Community, pType protobuf.CommunityTokenPermission_Type) *requests.CreateCommunityTokenPermission {
return &requests.CreateCommunityTokenPermission{
CommunityID: community.ID(),
Type: pType,
TokenCriteria: []*protobuf.TokenCriteria{
{
Type: protobuf.CommunityTokenType_ERC20,
ContractAddresses: map[uint64]string{uint64(commmunitiesEventsTestChainID): commmunitiesEventsTestTokenAddress},
Symbol: "TEST",
Amount: "100",
Decimals: uint64(18),
},
},
}
}
func createTokenPermission(base CommunityEventsTestsInterface, community *communities.Community, request *requests.CreateCommunityTokenPermission) (string, *requests.CreateCommunityTokenPermission) {
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)
addedPermission := func() *communities.CommunityTokenPermission {
for _, permission := range response.CommunityChanges[0].TokenPermissionsAdded {
return permission
}
return nil
}()
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
}
// Control node receives community event & approves it
_, err = WaitOnMessengerResponse(base.GetControlNode(), responseHasApprovedTokenPermission, "community with approved permission not found")
s.Require().NoError(err)
// Member receives updated community description
_, err = WaitOnMessengerResponse(base.GetMember(), responseHasApprovedTokenPermission, "community with approved permission not found")
s.Require().NoError(err)
// EventSender receives updated community description
_, err = WaitOnMessengerResponse(base.GetEventSender(), responseHasApprovedTokenPermission, "community with approved permission not found")
s.Require().NoError(err)
return addedPermission.Id, request
}
func createTestTokenPermission(base CommunityEventsTestsInterface, community *communities.Community, pType protobuf.CommunityTokenPermission_Type) (string, *requests.CreateCommunityTokenPermission) {
createTokenPermissionRequest := createTestPermissionRequest(community, pType)
return createTokenPermission(base, community, createTokenPermissionRequest)
}
func editTokenPermission(base CommunityEventsTestsInterface, community *communities.Community, request *requests.EditCommunityTokenPermission) {
s := base.GetSuite()
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))
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)
}
// Control node receives community event & approves it
_, err = WaitOnMessengerResponse(base.GetControlNode(), responseHasApprovedEditedTokenPermission, "community with approved permission not found")
s.Require().NoError(err)
// Member receives updated community description
_, err = WaitOnMessengerResponse(base.GetMember(), responseHasApprovedEditedTokenPermission, "community with approved permission not found")
s.Require().NoError(err)
// EventSender receives updated community description
_, err = WaitOnMessengerResponse(base.GetEventSender(), responseHasApprovedEditedTokenPermission, "community with approved permission not found")
s.Require().NoError(err)
}
func deleteTokenPermission(base CommunityEventsTestsInterface, community *communities.Community, request *requests.DeleteCommunityTokenPermission) {
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)
responseHasNoTokenPermission := func(r *MessengerResponse) bool {
if len(r.Communities()) == 0 {
return false
}
return r.Communities()[0].TokenPermissionByID(removedPermission.Id) == nil
}
// Control node receives community event & approves it
_, err = WaitOnMessengerResponse(base.GetControlNode(), responseHasNoTokenPermission, "community with approved permission not found")
s.Require().NoError(err)
// 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)
}
func assertCheckTokenPermissionCreated(s *suite.Suite, community *communities.Community, pType protobuf.CommunityTokenPermission_Type) {
permissions := community.TokenPermissionsByType(pType)
s.Require().Len(permissions, 1)
s.Require().Len(permissions[0].TokenCriteria, 1)
s.Require().Equal(permissions[0].TokenCriteria[0].Type, protobuf.CommunityTokenType_ERC20)
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))
}
func setUpOnRequestCommunityAndRoles(base CommunityEventsTestsInterface, role protobuf.CommunityMember_Roles, additionalEventSenders []*Messenger) *communities.Community {
tcs2, err := base.GetControlNode().communitiesManager.All()
s := base.GetSuite()
s.Require().NoError(err, "eventSender.communitiesManager.All")
s.Len(tcs2, 1, "Must have 1 community")
// control node creates a community and chat
community := createTestCommunity(base, protobuf.CommunityPermissions_ON_REQUEST)
refreshMessengerResponses(base)
advertiseCommunityTo(s, community, base.GetControlNode(), base.GetEventSender())
advertiseCommunityTo(s, community, base.GetControlNode(), base.GetMember())
joinOnRequestCommunity(s, community, base.GetControlNode(), base.GetEventSender())
joinOnRequestCommunity(s, community, base.GetControlNode(), base.GetMember())
checkMemberJoined := func(response *MessengerResponse) error {
return checkMemberJoinedToTheCommunity(response, base.GetMember().IdentityPublicKey())
}
waitOnMessengerResponse(s, WaitCommunityCondition, checkMemberJoined, base.GetEventSender())
// grant permissions to event sender
grantPermission(s, community, base.GetControlNode(), base.GetEventSender(), role)
checkPermissionGranted := func(response *MessengerResponse) error {
return checkRolePermissionInResponse(response, base.GetEventSender().IdentityPublicKey(), role)
}
waitOnMessengerResponse(s, WaitCommunityCondition, checkPermissionGranted, base.GetMember())
for _, eventSender := range additionalEventSenders {
advertiseCommunityTo(s, community, base.GetControlNode(), eventSender)
joinOnRequestCommunity(s, community, base.GetControlNode(), eventSender)
grantPermission(s, community, base.GetControlNode(), eventSender, role)
checkPermissionGranted = func(response *MessengerResponse) error {
return checkRolePermissionInResponse(response, eventSender.IdentityPublicKey(), role)
}
waitOnMessengerResponse(s, WaitCommunityCondition, checkPermissionGranted, base.GetMember())
waitOnMessengerResponse(s, WaitCommunityCondition, checkPermissionGranted, base.GetEventSender())
}
return community
}
func createCommunityCategory(base CommunityEventsTestsInterface, community *communities.Community, newCategory *requests.CreateCommunityCategory) string {
checkCategoryCreated := func(response *MessengerResponse) error {
modifiedCommmunity, err := getModifiedCommunity(response, community.IDString())
if err != nil {
return err
}
for _, category := range modifiedCommmunity.Categories() {
if category.GetName() == newCategory.CategoryName {
return nil
}
}
return errors.New("couldn't find created Category in the response")
}
response, err := base.GetEventSender().CreateCommunityCategory(newCategory)
s := base.GetSuite()
s.Require().NoError(err)
s.Require().NoError(checkCategoryCreated(response))
s.Require().Len(response.Communities(), 1)
s.Require().Len(response.CommunityChanges[0].CategoriesAdded, 1)
var categoryID string
for categoryID = range response.CommunityChanges[0].CategoriesAdded {
break
}
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkCategoryCreated)
return categoryID
}
func editCommunityCategory(base CommunityEventsTestsInterface, communityID string, editCategory *requests.EditCommunityCategory) {
checkCategoryEdited := func(response *MessengerResponse) error {
modifiedCommmunity, err := getModifiedCommunity(response, communityID)
if err != nil {
return err
}
for _, category := range modifiedCommmunity.Categories() {
if category.GetName() == editCategory.CategoryName {
return nil
}
}
return errors.New("couldn't find edited Category in the response")
}
response, err := base.GetEventSender().EditCommunityCategory(editCategory)
s := base.GetSuite()
s.Require().NoError(err)
s.Require().NoError(checkCategoryEdited(response))
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkCategoryEdited)
}
func deleteCommunityCategory(base CommunityEventsTestsInterface, communityID string, deleteCategory *requests.DeleteCommunityCategory) {
checkCategoryDeleted := func(response *MessengerResponse) error {
modifiedCommmunity, err := getModifiedCommunity(response, communityID)
if err != nil {
return err
}
if _, exists := modifiedCommmunity.Chats()[deleteCategory.CategoryID]; exists {
return errors.New("community was not deleted")
}
return nil
}
response, err := base.GetEventSender().DeleteCommunityCategory(deleteCategory)
s := base.GetSuite()
s.Require().NoError(err)
s.Require().NoError(checkCategoryDeleted(response))
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkCategoryDeleted)
}
func reorderCategory(base CommunityEventsTestsInterface, reorderRequest *requests.ReorderCommunityCategories) {
checkCategoryReorder := func(response *MessengerResponse) error {
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(reorderRequest.CommunityID))
if err != nil {
return err
}
category, exist := modifiedCommmunity.Categories()[reorderRequest.CategoryID]
if !exist {
return errors.New("couldn't find community category")
}
if int(category.Position) != reorderRequest.Position {
return errors.New("category was not reordered")
}
return nil
}
response, err := base.GetEventSender().ReorderCommunityCategories(reorderRequest)
s := base.GetSuite()
s.Require().NoError(err)
s.Require().NoError(checkCategoryReorder(response))
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkCategoryReorder)
}
func reorderChannel(base CommunityEventsTestsInterface, reorderRequest *requests.ReorderCommunityChat) {
checkChannelReorder := func(response *MessengerResponse) error {
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(reorderRequest.CommunityID))
if err != nil {
return err
}
chat, exist := modifiedCommmunity.Chats()[reorderRequest.ChatID]
if !exist {
return errors.New("couldn't find community chat")
}
if int(chat.Position) != reorderRequest.Position {
return errors.New("chat position was not reordered")
}
if chat.CategoryId != reorderRequest.CategoryID {
return errors.New("chat category was not reordered")
}
return nil
}
response, err := base.GetEventSender().ReorderCommunityChat(reorderRequest)
s := base.GetSuite()
s.Require().NoError(err)
s.Require().NoError(checkChannelReorder(response))
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkChannelReorder)
}
func kickMember(base CommunityEventsTestsInterface, communityID types.HexBytes, pubkey string) {
checkKicked := func(response *MessengerResponse) error {
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(communityID))
if err != nil {
return err
}
if modifiedCommmunity.HasMember(&base.GetMember().identity.PublicKey) {
return errors.New("alice was not kicked")
}
return nil
}
response, err := base.GetEventSender().RemoveUserFromCommunity(
communityID,
pubkey,
)
s := base.GetSuite()
s.Require().NoError(err)
s.Require().Nil(checkKicked(response))
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkKicked)
}
func banMember(base CommunityEventsTestsInterface, banRequest *requests.BanUserFromCommunity) {
checkBanned := func(response *MessengerResponse) error {
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(banRequest.CommunityID))
if err != nil {
return err
}
if modifiedCommmunity.HasMember(&base.GetMember().identity.PublicKey) {
return errors.New("alice was not removed from the member list")
}
if !modifiedCommmunity.IsBanned(&base.GetMember().identity.PublicKey) {
return errors.New("alice was not added to the banned list")
}
return nil
}
response, err := base.GetEventSender().BanUserFromCommunity(banRequest)
s := base.GetSuite()
s.Require().NoError(err)
s.Require().Nil(checkBanned(response))
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkBanned)
}
func unbanMember(base CommunityEventsTestsInterface, unbanRequest *requests.UnbanUserFromCommunity) {
checkUnbanned := func(response *MessengerResponse) error {
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(unbanRequest.CommunityID))
if err != nil {
return err
}
if modifiedCommmunity.IsBanned(&base.GetMember().identity.PublicKey) {
return errors.New("alice was not unbanned")
}
return nil
}
response, err := base.GetEventSender().UnbanUserFromCommunity(unbanRequest)
s := base.GetSuite()
s.Require().NoError(err)
s.Require().Nil(checkUnbanned(response))
response, err = WaitOnMessengerResponse(
base.GetControlNode(),
WaitCommunityCondition,
"MessengerResponse data not received",
)
s.Require().NoError(err)
s.Require().NoError(checkUnbanned(response))
}
func controlNodeSendMessage(base CommunityEventsTestsInterface, inputMessage *common.Message) string {
response, err := base.GetControlNode().SendChatMessage(context.Background(), inputMessage)
s := base.GetSuite()
s.Require().NoError(err)
message := response.Messages()[0]
s.Require().Equal(inputMessage.Text, message.Text)
messageID := message.ID
response, err = WaitOnMessengerResponse(base.GetEventSender(), WaitMessageCondition, "messages not received")
s.Require().NoError(err)
message = response.Messages()[0]
s.Require().Equal(inputMessage.Text, message.Text)
response, err = WaitOnMessengerResponse(base.GetMember(), WaitMessageCondition, "messages not received")
s.Require().NoError(err)
message = response.Messages()[0]
s.Require().Equal(inputMessage.Text, message.Text)
refreshMessengerResponses(base)
return messageID
}
func deleteControlNodeMessage(base CommunityEventsTestsInterface, messageID string) {
checkMessageDeleted := func(response *MessengerResponse) error {
if len(response.RemovedMessages()) > 0 {
return nil
}
return errors.New("message was not deleted")
}
response, err := base.GetEventSender().DeleteMessageAndSend(context.Background(), messageID)
s := base.GetSuite()
s.Require().NoError(err)
s.Require().NoError(checkMessageDeleted(response))
waitMessageCondition := func(response *MessengerResponse) bool {
return len(response.RemovedMessages()) > 0
}
waitOnMessengerResponse(s, waitMessageCondition, checkMessageDeleted, base.GetMember())
waitOnMessengerResponse(s, waitMessageCondition, checkMessageDeleted, base.GetControlNode())
}
func pinControlNodeMessage(base CommunityEventsTestsInterface, pinnedMessage *common.PinMessage) {
checkPinned := func(response *MessengerResponse) error {
if len(response.PinMessages()) > 0 {
return nil
}
return errors.New("pin messages was not added")
}
response, err := base.GetEventSender().SendPinMessage(context.Background(), pinnedMessage)
s := base.GetSuite()
s.Require().NoError(err)
s.Require().NoError(checkPinned(response))
waitOnMessengerResponse(s, WaitMessageCondition, checkPinned, base.GetMember())
waitOnMessengerResponse(s, WaitMessageCondition, checkPinned, base.GetControlNode())
}
func editCommunityDescription(base CommunityEventsTestsInterface, community *communities.Community) {
expectedName := "edited community name"
expectedColor := "#000000"
expectedDescr := "edited community description"
response, err := base.GetEventSender().EditCommunity(&requests.EditCommunity{
CommunityID: community.ID(),
CreateCommunity: requests.CreateCommunity{
Membership: protobuf.CommunityPermissions_ON_REQUEST,
Name: expectedName,
Color: expectedColor,
Description: expectedDescr,
},
})
checkCommunityEdit := func(response *MessengerResponse) error {
if len(response.Communities()) == 0 {
return errors.New("community not received")
}
rCommunities := response.Communities()
if expectedName != rCommunities[0].Name() {
return errors.New("incorrect community name")
}
if expectedColor != rCommunities[0].Color() {
return errors.New("incorrect community color")
}
if expectedDescr != rCommunities[0].DescriptionText() {
return errors.New("incorrect community description")
}
return nil
}
s := base.GetSuite()
s.Require().NoError(err)
s.Require().Nil(checkCommunityEdit(response))
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkCommunityEdit)
}
func controlNodeCreatesCommunityPermission(base CommunityEventsTestsInterface, community *communities.Community, permissionRequest *requests.CreateCommunityTokenPermission) string {
// control node creates permission
response, err := base.GetControlNode().CreateCommunityTokenPermission(permissionRequest)
s := base.GetSuite()
s.Require().NoError(err)
var tokenPermissionID string
for id := range response.CommunityChanges[0].TokenPermissionsAdded {
tokenPermissionID = id
}
s.Require().NotEqual(tokenPermissionID, "")
ownerCommunity, err := base.GetControlNode().communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
assertCheckTokenPermissionCreated(s, ownerCommunity, permissionRequest.Type)
// then, ensure event sender receives updated community
_, err = WaitOnMessengerResponse(
base.GetEventSender(),
func(r *MessengerResponse) bool {
return len(r.Communities()) > 0 &&
len(r.Communities()[0].TokenPermissionsByType(permissionRequest.Type)) > 0
},
"event sender did not receive community token permission",
)
s.Require().NoError(err)
eventSenderCommunity, err := base.GetEventSender().communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
assertCheckTokenPermissionCreated(s, eventSenderCommunity, permissionRequest.Type)
s.Require().True(eventSenderCommunity.HasPermissionToSendCommunityEvents())
return tokenPermissionID
}
func testCreateEditDeleteChannels(base CommunityEventsTestsInterface, community *communities.Community) {
newChat := &protobuf.CommunityChat{
Permissions: &protobuf.CommunityPermissions{
Access: protobuf.CommunityPermissions_NO_MEMBERSHIP,
},
Identity: &protobuf.ChatIdentity{
DisplayName: "chat from the event sender",
Emoji: "",
Description: "chat created by an event sender",
},
}
newChatID := createCommunityChannel(base, community, newChat)
newChat.Identity.DisplayName = "modified chat from event sender"
editCommunityChannel(base, community, newChat, newChatID)
deleteCommunityChannel(base, community, newChatID)
}
func testCreateEditDeleteBecomeMemberPermission(base CommunityEventsTestsInterface, community *communities.Community, pType protobuf.CommunityTokenPermission_Type) {
// first, create token permission
tokenPermissionID, createTokenPermission := createTestTokenPermission(base, community, pType)
createTokenPermission.TokenCriteria[0].Symbol = "UPDATED"
createTokenPermission.TokenCriteria[0].Amount = "200"
editTokenPermissionRequest := &requests.EditCommunityTokenPermission{
PermissionID: tokenPermissionID,
CreateCommunityTokenPermission: *createTokenPermission,
}
// then, event sender edits the permission
editTokenPermission(base, community, editTokenPermissionRequest)
deleteTokenPermissionRequest := &requests.DeleteCommunityTokenPermission{
CommunityID: community.ID(),
PermissionID: tokenPermissionID,
}
// then, event sender deletes previously created token permission
deleteTokenPermission(base, community, deleteTokenPermissionRequest)
}
func testAcceptMemberRequestToJoin(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger) {
// set up additional user that will send request to join
_, err := user.Start()
s := base.GetSuite()
s.Require().NoError(err)
defer user.Shutdown() // nolint: errcheck
advertiseCommunityTo(s, community, base.GetControlNode(), user)
// user sends request to join
requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID()}
response, err := user.RequestToJoinCommunity(requestToJoin)
s.Require().NoError(err)
s.Require().NotNil(response)
s.Require().Len(response.RequestsToJoinCommunity, 1)
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)
// control node receives request to join
response, err = WaitOnMessengerResponse(
base.GetControlNode(),
func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity) > 0 },
"event sender did not receive community request to join",
)
s.Require().NoError(err)
s.Require().Len(response.RequestsToJoinCommunity, 1)
// event sender has not accepted request yet
eventSenderCommunity, err := base.GetEventSender().GetCommunityByID(community.ID())
s.Require().NoError(err)
s.Require().False(eventSenderCommunity.HasMember(&user.identity.PublicKey))
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))
// user should not receive community admin event without being a member yet
_, err = WaitOnMessengerResponse(
user,
func(r *MessengerResponse) bool { return len(r.Communities()) > 0 },
"user did not receive community request to join response",
)
s.Require().Error(err)
// 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)
}
func testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger, additionalEventSender *Messenger) {
// set up additional user that will send request to join
_, err := user.Start()
s := base.GetSuite()
s.Require().NoError(err)
defer user.Shutdown() // nolint: errcheck
advertiseCommunityTo(s, community, base.GetControlNode(), user)
// user sends request to join
requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID()}
response, err := user.RequestToJoinCommunity(requestToJoin)
s.Require().NoError(err)
s.Require().NotNil(response)
s.Require().Len(response.RequestsToJoinCommunity, 1)
sentRequest := response.RequestsToJoinCommunity[0]
// event sender receives request to join
_, err = WaitOnMessengerResponse(
base.GetEventSender(),
func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity) > 0 },
"event sender did not receive community request to join",
)
s.Require().NoError(err)
// event sender 2 receives request to join
_, err = WaitOnMessengerResponse(
additionalEventSender,
func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity) > 0 },
"event sender did not receive community request to join",
)
s.Require().NoError(err)
// event sender 1 accepts request
acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: sentRequest.ID}
response, err = base.GetEventSender().AcceptRequestToJoinCommunity(acceptRequestToJoin)
s.Require().NoError(err)
s.Require().NotNil(response)
s.Require().Len(response.Communities(), 1)
// event sender 2 receives decision of other event sender
_, err = WaitOnMessengerResponse(
additionalEventSender,
func(r *MessengerResponse) bool { return len(r.Communities()) > 0 },
"event sender did not receive community request to join",
)
s.Require().NoError(err)
// at this point, the request to join is in accepted/pending state for event sender 2
acceptedPendingRequests, err := additionalEventSender.AcceptedPendingRequestsToJoinForCommunity(community.ID())
s.Require().NoError(err)
s.Require().Len(acceptedPendingRequests, 1)
s.Require().Equal(acceptedPendingRequests[0].PublicKey, common.PubkeyToHex(&user.identity.PublicKey))
}
func testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger, additionalEventSender *Messenger) {
// set up additional user that will send request to join
_, err := user.Start()
s := base.GetSuite()
s.Require().NoError(err)
defer user.Shutdown() // nolint: errcheck
advertiseCommunityTo(s, community, base.GetControlNode(), user)
// user sends request to join
requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID()}
response, err := user.RequestToJoinCommunity(requestToJoin)
s.Require().NoError(err)
s.Require().NotNil(response)
s.Require().Len(response.RequestsToJoinCommunity, 1)
sentRequest := response.RequestsToJoinCommunity[0]
// event sender receives request to join
response, err = WaitOnMessengerResponse(
base.GetEventSender(),
func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity) > 0 },
"event sender did not receive community request to join",
)
s.Require().NoError(err)
s.Require().Len(response.RequestsToJoinCommunity, 1)
// event sender 2 receives request to join
response, err = WaitOnMessengerResponse(
additionalEventSender,
func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity) > 0 },
"event sender did not receive community request to join",
)
s.Require().NoError(err)
s.Require().Len(response.RequestsToJoinCommunity, 1)
rejectRequestToJoin := &requests.DeclineRequestToJoinCommunity{ID: sentRequest.ID}
response, err = base.GetEventSender().DeclineRequestToJoinCommunity(rejectRequestToJoin)
s.Require().NoError(err)
s.Require().NotNil(response)
// event sender 2 receives decision of other event sender
_, err = WaitOnMessengerResponse(
additionalEventSender,
func(r *MessengerResponse) bool { return len(r.Communities()) > 0 },
"event sender did not receive community request to join",
)
s.Require().NoError(err)
// at this point, the request to join is in declined/pending state for event sender 2
rejectedPendingRequests, err := additionalEventSender.DeclinedPendingRequestsToJoinForCommunity(community.ID())
s.Require().NoError(err)
s.Require().Len(rejectedPendingRequests, 1)
s.Require().Equal(rejectedPendingRequests[0].PublicKey, common.PubkeyToHex(&user.identity.PublicKey))
}
func testRejectMemberRequestToJoin(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger) {
_, err := user.Start()
s := base.GetSuite()
s.Require().NoError(err)
defer user.Shutdown() // nolint: errcheck
advertiseCommunityTo(s, community, base.GetControlNode(), user)
// user sends request to join
requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID()}
response, err := user.RequestToJoinCommunity(requestToJoin)
s.Require().NoError(err)
s.Require().NotNil(response)
s.Require().Len(response.RequestsToJoinCommunity, 1)
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)
// 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)
// 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
rejectRequestToJoin := &requests.DeclineRequestToJoinCommunity{ID: sentRequest.ID}
_, 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))
requests, err := base.GetEventSender().DeclinedPendingRequestsToJoinForCommunity(community.ID())
s.Require().Len(requests, 1)
s.Require().NoError(err)
// control node receives event sender event and stores rejected request to join
response, 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 update from event sender",
)
s.Require().NoError(err)
s.Require().False(response.Communities()[0].HasMember(&user.identity.PublicKey))
requests, err = base.GetControlNode().DeclinedRequestsToJoinForCommunity(community.ID())
s.Require().Len(requests, 1)
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 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)
}
func testEventSenderCannotOverrideRequestToJoinState(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger, additionalEventSender *Messenger) {
_, err := user.Start()
s := base.GetSuite()
s.Require().NoError(err)
defer user.Shutdown() // nolint: errcheck
advertiseCommunityTo(s, community, base.GetControlNode(), user)
// user sends request to join
requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID()}
response, err := user.RequestToJoinCommunity(requestToJoin)
s.Require().NoError(err)
s.Require().NotNil(response)
s.Require().Len(response.RequestsToJoinCommunity, 1)
sentRequest := response.RequestsToJoinCommunity[0]
// event sender receives request to join
_, err = WaitOnMessengerResponse(
base.GetEventSender(),
func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity) > 0 },
"event sender did not receive community request to join",
)
s.Require().NoError(err)
// event sender 2 receives request to join
_, err = WaitOnMessengerResponse(
additionalEventSender,
func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity) > 0 },
"event sender did not receive community request to join",
)
s.Require().NoError(err)
s.Require().Len(response.RequestsToJoinCommunity, 1)
// request is pending for event sener 2
pendingRequests, err := additionalEventSender.PendingRequestsToJoinForCommunity(community.ID())
s.Require().NoError(err)
s.Require().NotNil(pendingRequests)
s.Require().Len(pendingRequests, 1)
// event sender 1 rejects request to join
rejectRequestToJoin := &requests.DeclineRequestToJoinCommunity{ID: sentRequest.ID}
_, err = base.GetEventSender().DeclineRequestToJoinCommunity(rejectRequestToJoin)
s.Require().NoError(err)
// request to join is now marked as rejected pending for event sender 1
rejectedPendingRequests, err := base.GetEventSender().DeclinedPendingRequestsToJoinForCommunity(community.ID())
s.Require().NoError(err)
s.Require().NotNil(rejectedPendingRequests)
s.Require().Len(rejectedPendingRequests, 1)
// event sender 2 receives event sender 1's decision
_, err = WaitOnMessengerResponse(
additionalEventSender,
func(r *MessengerResponse) bool { return len(r.Communities()) > 0 },
"event sender did not receive community request to join",
)
s.Require().NoError(err)
// request to join is now marked as rejected pending for event sender 2
rejectedPendingRequests, err = additionalEventSender.DeclinedPendingRequestsToJoinForCommunity(community.ID())
s.Require().NoError(err)
s.Require().NotNil(rejectedPendingRequests)
s.Require().Len(rejectedPendingRequests, 1)
// event sender 2 should not be able to override that pending state
acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: sentRequest.ID}
_, err = additionalEventSender.AcceptRequestToJoinCommunity(acceptRequestToJoin)
s.Require().Error(err)
}
func testControlNodeHandlesMultipleEventSenderRequestToJoinDecisions(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger, additionalEventSender *Messenger) {
_, err := user.Start()
s := base.GetSuite()
s.Require().NoError(err)
defer user.Shutdown() // nolint: errcheck
advertiseCommunityTo(s, community, base.GetControlNode(), user)
// user sends request to join
requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID()}
response, err := user.RequestToJoinCommunity(requestToJoin)
s.Require().NoError(err)
s.Require().NotNil(response)
s.Require().Len(response.RequestsToJoinCommunity, 1)
sentRequest := response.RequestsToJoinCommunity[0]
// event sender receives request to join
_, err = WaitOnMessengerResponse(
base.GetEventSender(),
func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity) > 0 },
"event sender did not receive community request to join",
)
s.Require().NoError(err)
// event sender 2 receives request to join
_, err = WaitOnMessengerResponse(
additionalEventSender,
func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity) > 0 },
"event sender did not receive community request to join",
)
s.Require().NoError(err)
// control node receives request to join
_, err = WaitOnMessengerResponse(
base.GetControlNode(),
func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity) > 0 },
"event sender did not receive community request to join",
)
s.Require().NoError(err)
// event sender 1 rejects request to join
rejectRequestToJoin := &requests.DeclineRequestToJoinCommunity{ID: sentRequest.ID}
_, err = base.GetEventSender().DeclineRequestToJoinCommunity(rejectRequestToJoin)
s.Require().NoError(err)
// request to join is now marked as rejected pending for event sender 1
rejectedPendingRequests, err := base.GetEventSender().DeclinedPendingRequestsToJoinForCommunity(community.ID())
s.Require().NoError(err)
s.Require().NotNil(rejectedPendingRequests)
s.Require().Len(rejectedPendingRequests, 1)
// control node receives event sender 1's and 2's decision
_, err = WaitOnMessengerResponse(
base.GetControlNode(),
func(r *MessengerResponse) bool { return len(r.Communities()) > 0 },
"control node did not receive event senders decision",
)
s.Require().NoError(err)
// request to join is now marked as rejected
rejectedRequests, err := base.GetControlNode().DeclinedRequestsToJoinForCommunity(community.ID())
s.Require().NoError(err)
s.Require().NotNil(rejectedRequests)
s.Require().Len(rejectedRequests, 1)
// event sender 2 accepts request to join
acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: sentRequest.ID}
_, err = additionalEventSender.AcceptRequestToJoinCommunity(acceptRequestToJoin)
s.Require().NoError(err)
// request to join is now marked as accepted pending for event sender 2
acceptedPendingRequests, err := additionalEventSender.AcceptedPendingRequestsToJoinForCommunity(community.ID())
s.Require().NoError(err)
s.Require().NotNil(acceptedPendingRequests)
s.Require().Len(acceptedPendingRequests, 1)
// control node now receives event sender 2's decision
_, err = WaitOnMessengerResponse(
base.GetControlNode(),
func(r *MessengerResponse) bool { return len(r.Communities()) > 0 },
"control node did not receive event senders decision",
)
s.Require().NoError(err)
rejectedRequests, err = base.GetControlNode().DeclinedRequestsToJoinForCommunity(community.ID())
s.Require().NoError(err)
s.Require().NotNil(rejectedRequests)
s.Require().Len(rejectedRequests, 1)
// we expect user's request to join still to be rejected
s.Require().Equal(rejectedRequests[0].PublicKey, common.PubkeyToHex(&user.identity.PublicKey))
}
func testCreateEditDeleteCategories(base CommunityEventsTestsInterface, community *communities.Community) {
newCategory := &requests.CreateCommunityCategory{
CommunityID: community.ID(),
CategoryName: "event-sender-category-name",
}
categoryID := createCommunityCategory(base, community, newCategory)
editCategory := &requests.EditCommunityCategory{
CommunityID: community.ID(),
CategoryID: categoryID,
CategoryName: "edited-event-sender-category-name",
}
editCommunityCategory(base, community.IDString(), editCategory)
deleteCategory := &requests.DeleteCommunityCategory{
CommunityID: community.ID(),
CategoryID: categoryID,
}
deleteCommunityCategory(base, community.IDString(), deleteCategory)
}
func testReorderChannelsAndCategories(base CommunityEventsTestsInterface, community *communities.Community) {
newCategory := &requests.CreateCommunityCategory{
CommunityID: community.ID(),
CategoryName: "event-sender-category-name",
}
_ = createCommunityCategory(base, community, newCategory)
newCategory.CategoryName = "event-sender-category-name2"
categoryID2 := createCommunityCategory(base, community, newCategory)
chat := &protobuf.CommunityChat{
Permissions: &protobuf.CommunityPermissions{
Access: protobuf.CommunityPermissions_NO_MEMBERSHIP,
},
Identity: &protobuf.ChatIdentity{
DisplayName: "chat from event-sender",
Emoji: "",
Description: "chat created by an event-sender",
},
}
chatID := createCommunityChannel(base, community, chat)
reorderCommunityRequest := requests.ReorderCommunityCategories{
CommunityID: community.ID(),
CategoryID: categoryID2,
Position: 0,
}
reorderCategory(base, &reorderCommunityRequest)
reorderChatRequest := requests.ReorderCommunityChat{
CommunityID: community.ID(),
CategoryID: categoryID2,
ChatID: chatID,
Position: 0,
}
reorderChannel(base, &reorderChatRequest)
}
func testEventSenderKickTheSameRole(base CommunityEventsTestsInterface, community *communities.Community) {
// event sender tries to kick the member with the same role
_, err := base.GetEventSender().RemoveUserFromCommunity(
community.ID(),
common.PubkeyToHex(&base.GetEventSender().identity.PublicKey),
)
s := base.GetSuite()
s.Require().Error(err)
s.Require().EqualError(err, "not allowed to remove admin or owner")
}
func testEventSenderKickControlNode(base CommunityEventsTestsInterface, community *communities.Community) {
// event sender tries to kick the control node
_, err := base.GetEventSender().RemoveUserFromCommunity(
community.ID(),
common.PubkeyToHex(&base.GetControlNode().identity.PublicKey),
)
s := base.GetSuite()
s.Require().Error(err)
s.Require().EqualError(err, "not allowed to remove admin or owner")
}
func testOwnerBanTheSameRole(base CommunityEventsTestsInterface, community *communities.Community) {
_, err := base.GetEventSender().BanUserFromCommunity(
&requests.BanUserFromCommunity{
CommunityID: community.ID(),
User: common.PubkeyToHexBytes(&base.GetEventSender().identity.PublicKey),
},
)
s := base.GetSuite()
s.Require().Error(err)
s.Require().EqualError(err, "not allowed to ban admin or owner")
}
func testOwnerBanControlNode(base CommunityEventsTestsInterface, community *communities.Community) {
_, err := base.GetEventSender().BanUserFromCommunity(
&requests.BanUserFromCommunity{
CommunityID: community.ID(),
User: common.PubkeyToHexBytes(&base.GetControlNode().identity.PublicKey),
},
)
s := base.GetSuite()
s.Require().Error(err)
s.Require().EqualError(err, "not allowed to ban admin or owner")
}
func testBanUnbanMember(base CommunityEventsTestsInterface, community *communities.Community) {
// verify that event sender can't ban a control node
_, err := base.GetEventSender().BanUserFromCommunity(
&requests.BanUserFromCommunity{
CommunityID: community.ID(),
User: common.PubkeyToHexBytes(&base.GetControlNode().identity.PublicKey),
},
)
s := base.GetSuite()
s.Require().Error(err)
banRequest := &requests.BanUserFromCommunity{
CommunityID: community.ID(),
User: common.PubkeyToHexBytes(&base.GetMember().identity.PublicKey),
}
banMember(base, banRequest)
unbanRequest := &requests.UnbanUserFromCommunity{
CommunityID: community.ID(),
User: common.PubkeyToHexBytes(&base.GetMember().identity.PublicKey),
}
unbanMember(base, unbanRequest)
}
func testDeleteAnyMessageInTheCommunity(base CommunityEventsTestsInterface, community *communities.Community) {
chatID := community.ChatIDs()[0]
inputMessage := common.NewMessage()
inputMessage.ChatId = chatID
inputMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN
inputMessage.Text = "control node text"
messageID := controlNodeSendMessage(base, inputMessage)
deleteControlNodeMessage(base, messageID)
}
func testEventSenderPinMessage(base CommunityEventsTestsInterface, community *communities.Community) {
s := base.GetSuite()
s.Require().False(community.AllowsAllMembersToPinMessage())
chatID := community.ChatIDs()[0]
inputMessage := common.NewMessage()
inputMessage.ChatId = chatID
inputMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN
inputMessage.Text = "control node text"
messageID := controlNodeSendMessage(base, inputMessage)
pinnedMessage := common.NewPinMessage()
pinnedMessage.MessageId = messageID
pinnedMessage.ChatId = chatID
pinnedMessage.Pinned = true
pinControlNodeMessage(base, pinnedMessage)
}
func testMemberReceiveEventsWhenControlNodeOffline(base CommunityEventsTestsInterface, community *communities.Community) {
// To simulate behavior when control node is offline, we will not use control node for listening new events
// In this scenario member will reveive list of events
s := base.GetSuite()
member := base.GetMember()
eventSender := base.GetEventSender()
newAdminChat := &protobuf.CommunityChat{
Permissions: &protobuf.CommunityPermissions{
Access: protobuf.CommunityPermissions_NO_MEMBERSHIP,
},
Identity: &protobuf.ChatIdentity{
DisplayName: "chat from event sender",
Emoji: "",
Description: "chat created by an event sender",
},
}
checkChannelCreated := func(response *MessengerResponse) error {
modifiedCommmunity, err := getModifiedCommunity(response, community.IDString())
if err != nil {
return err
}
for _, chat := range modifiedCommmunity.Chats() {
if chat.GetIdentity().GetDisplayName() == newAdminChat.GetIdentity().GetDisplayName() {
return nil
}
}
return errors.New("couldn't find created chat in response")
}
response, err := eventSender.CreateCommunityChat(community.ID(), newAdminChat)
s.Require().NoError(err)
s.Require().NoError(checkChannelCreated(response))
s.Require().Len(response.CommunityChanges, 1)
s.Require().Len(response.CommunityChanges[0].ChatsAdded, 1)
var addedChatID string
for addedChatID = range response.CommunityChanges[0].ChatsAdded {
break
}
waitOnMessengerResponse(s, WaitCommunityCondition, checkChannelCreated, member)
waitOnMessengerResponse(s, WaitCommunityCondition, checkChannelCreated, eventSender)
newAdminChat.Identity.DisplayName = "modified chat from event sender"
checkChannelEdited := func(response *MessengerResponse) error {
modifiedCommmunity, err := getModifiedCommunity(response, community.IDString())
if err != nil {
return err
}
for _, chat := range modifiedCommmunity.Chats() {
if chat.GetIdentity().GetDisplayName() == newAdminChat.GetIdentity().GetDisplayName() {
return nil
}
}
return errors.New("couldn't find modified chat in response")
}
response, err = eventSender.EditCommunityChat(community.ID(), addedChatID, newAdminChat)
s.Require().NoError(err)
s.Require().NoError(checkChannelEdited(response))
waitOnMessengerResponse(s, WaitCommunityCondition, checkChannelEdited, member)
waitOnMessengerResponse(s, WaitCommunityCondition, checkChannelEdited, eventSender)
checkChannelDeleted := func(response *MessengerResponse) error {
modifiedCommmunity, err := getModifiedCommunity(response, community.IDString())
if err != nil {
return err
}
if _, exists := modifiedCommmunity.Chats()[addedChatID]; exists {
return errors.New("channel was not deleted")
}
return nil
}
response, err = eventSender.DeleteCommunityChat(community.ID(), addedChatID)
s.Require().NoError(err)
s.Require().NoError(checkChannelDeleted(response))
waitOnMessengerResponse(s, WaitCommunityCondition, checkChannelDeleted, member)
waitOnMessengerResponse(s, WaitCommunityCondition, checkChannelDeleted, eventSender)
}
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)
}
permissionRequest := createTestPermissionRequest(community, testPermissionType)
tokenPermissionID := controlNodeCreatesCommunityPermission(base, community, permissionRequest)
deleteTokenPermission := &requests.DeleteCommunityTokenPermission{
CommunityID: community.ID(),
PermissionID: tokenPermissionID,
}
// then event sender tries to delete permission which should fail
response, err := base.GetEventSender().DeleteCommunityTokenPermission(deleteTokenPermission)
s := base.GetSuite()
s.Require().Error(err)
s.Require().Nil(response)
}
func testEventSenderCannotEditPrivilegedCommunityPermission(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)
}
permissionRequest := createTestPermissionRequest(community, testPermissionType)
tokenPermissionID := controlNodeCreatesCommunityPermission(base, community, permissionRequest)
permissionRequest.TokenCriteria[0].Symbol = "UPDATED"
permissionRequest.TokenCriteria[0].Amount = "200"
permissionEditRequest := &requests.EditCommunityTokenPermission{
PermissionID: tokenPermissionID,
CreateCommunityTokenPermission: *permissionRequest,
}
// then, event sender tries to edit permission
response, err := base.GetEventSender().EditCommunityTokenPermission(permissionEditRequest)
s := base.GetSuite()
s.Require().Error(err)
s.Require().Nil(response)
}
func testAddAndSyncTokenFromControlNode(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)
checkTokenAdded := func(response *MessengerResponse) error {
modifiedCommmunity, err := getModifiedCommunity(response, community.IDString())
if err != nil {
return err
}
if privilegesLvl != token.CommunityLevel && len(modifiedCommmunity.TokenPermissions()) == 0 {
return errors.New("Token permissions was not found")
}
for _, tokenMetadata := range modifiedCommmunity.CommunityTokensMetadata() {
if tokenMetadata.Name == tokenERC721.Name {
return nil
}
}
return errors.New("Token was not found")
}
waitOnMessengerResponse(s, WaitCommunityCondition, checkTokenAdded, base.GetMember())
waitOnMessengerResponse(s, WaitCommunityCondition, checkTokenAdded, base.GetEventSender())
// 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)
// check CommunityToken was not added to the DB
syncTokens, err = base.GetMember().communitiesManager.GetAllCommunityTokens()
s.Require().NoError(err)
s.Require().Len(syncTokens, 0)
}
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,
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,
DeployState: token.Deployed,
Base64Image: "ABCD",
PrivilegesLevel: privilegesLevel,
}
}
func testAddAndSyncTokenFromEventSenderByControlNode(base CommunityEventsTestsInterface, community *communities.Community,
privilegesLvl token.PrivilegesLevel) {
tokenERC721 := createCommunityToken(community.IDString(), privilegesLvl)
addCommunityTokenToCommunityTokensService(base, tokenERC721)
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)
tokens, err := base.GetControlNode().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
}
for _, tokenMetadata := range modifiedCommmunity.CommunityTokensMetadata() {
if tokenMetadata.Name == tokenERC721.Name {
return nil
}
}
return errors.New("Token was not found")
}
checkClientsReceivedAdminEvent(base, WaitCommunityCondition, checkTokenAdded)
// check event sender sent sync message to the control node
_, err = WaitOnMessengerResponse(
base.GetControlNode(),
func(r *MessengerResponse) bool {
tokens, err := base.GetControlNode().communitiesManager.GetAllCommunityTokens()
return err == nil && len(tokens) == 1
},
"no token sync message from event sender",
)
s.Require().NoError(err)
// check member did not receive sync message with the token
_, err = WaitOnMessengerResponse(
base.GetMember(),
func(r *MessengerResponse) bool {
tokens, err := base.GetMember().communitiesManager.GetAllCommunityTokens()
return err == nil && len(tokens) == 1
},
"no token sync message from event sender",
)
s.Require().Error(err)
}
func testEventSenderAddTokenMasterAndOwnerToken(base CommunityEventsTestsInterface, community *communities.Community) {
ownerToken := createCommunityToken(community.IDString(), token.OwnerLevel)
addCommunityTokenToCommunityTokensService(base, ownerToken)
s := base.GetSuite()
_, 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)
}
func addCommunityTokenToCommunityTokensService(base CommunityEventsTestsInterface, token *token.CommunityToken) {
data := &communitytokens.CollectibleContractData{
TotalSupply: token.Supply,
Transferable: token.Transferable,
RemoteBurnable: token.RemoteSelfDestruct,
InfiniteSupply: token.InfiniteSupply,
}
base.GetCollectiblesServiceMock().SetMockCollectibleContractData(uint64(token.ChainID), token.Address, data)
}