2526 lines
92 KiB
Go
2526 lines
92 KiB
Go
package protocol
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"math/big"
|
|
|
|
"github.com/stretchr/testify/suite"
|
|
"go.uber.org/zap"
|
|
|
|
gethcommon "github.com/ethereum/go-ethereum/common"
|
|
hexutil "github.com/ethereum/go-ethereum/common/hexutil"
|
|
|
|
"github.com/status-im/status-go/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/protocol/tt"
|
|
"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
|
|
SetupAdditionalMessengers([]*Messenger)
|
|
}
|
|
|
|
const communitiesEventsTestTokenAddress = "0x0400000000000000000000000000000000000000"
|
|
const aliceAccountAddress = "0x0777100000000000000000000000000000000000"
|
|
const bobAccountAddress = "0x0330000000000000000000000000000000000000"
|
|
const communitiesEventsTestChainID = 1
|
|
const eventsSenderAccountAddress = "0x0200000000000000000000000000000000000000"
|
|
const accountPassword = "qwerty"
|
|
|
|
type MessageResponseValidator func(*MessengerResponse) error
|
|
|
|
func WaitMessageCondition(response *MessengerResponse) bool {
|
|
return len(response.Messages()) > 0
|
|
}
|
|
|
|
func waitOnMessengerResponse(s *suite.Suite, fnWait MessageResponseValidator, user *Messenger) {
|
|
_, err := WaitOnMessengerResponse(
|
|
user,
|
|
func(r *MessengerResponse) bool {
|
|
err := fnWait(r)
|
|
if err != nil {
|
|
user.logger.Error("response error: ", zap.Error(err))
|
|
}
|
|
return err == nil
|
|
},
|
|
"MessengerResponse data not received",
|
|
)
|
|
s.Require().NoError(err)
|
|
}
|
|
|
|
func checkClientsReceivedAdminEvent(base CommunityEventsTestsInterface, fn MessageResponseValidator) {
|
|
s := base.GetSuite()
|
|
// Wait and verify Member received community event
|
|
waitOnMessengerResponse(s, fn, base.GetMember())
|
|
// Wait and verify event sender received his own event
|
|
waitOnMessengerResponse(s, fn, base.GetEventSender())
|
|
// Wait and verify ControlNode received community event
|
|
// ControlNode will publish CommunityDescription update
|
|
waitOnMessengerResponse(s, fn, base.GetControlNode())
|
|
// Wait and verify Member received the ControlNode CommunityDescription update
|
|
waitOnMessengerResponse(s, fn, base.GetMember())
|
|
// Wait and verify event sender received the ControlNode CommunityDescription update
|
|
waitOnMessengerResponse(s, fn, base.GetEventSender())
|
|
// Wait and verify ControlNode received his own CommunityDescription update
|
|
waitOnMessengerResponse(s, 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(eventsSenderAccountAddress)
|
|
|
|
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 `communitiesEventsTestTokenAddress``
|
|
contractAddress := gethcommon.HexToAddress(communitiesEventsTestTokenAddress)
|
|
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[communitiesEventsTestChainID][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_AUTO_ACCEPT)
|
|
refreshMessengerResponses(base)
|
|
|
|
// add events sender and member to the community
|
|
advertiseCommunityToUserOldWay(suite, community, base.GetControlNode(), base.GetEventSender())
|
|
advertiseCommunityToUserOldWay(suite, community, base.GetControlNode(), base.GetMember())
|
|
|
|
request := &requests.RequestToJoinCommunity{
|
|
CommunityID: community.ID(),
|
|
AddressesToReveal: []string{eventsSenderAccountAddress},
|
|
AirdropAddress: eventsSenderAccountAddress,
|
|
}
|
|
joinCommunity(suite, community, base.GetControlNode(), base.GetEventSender(), request, accountPassword)
|
|
refreshMessengerResponses(base)
|
|
|
|
request = &requests.RequestToJoinCommunity{
|
|
CommunityID: community.ID(),
|
|
AddressesToReveal: []string{aliceAccountAddress},
|
|
AirdropAddress: aliceAccountAddress,
|
|
}
|
|
joinCommunity(suite, community, base.GetControlNode(), base.GetMember(), request, accountPassword)
|
|
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, 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, 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, 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(communitiesEventsTestChainID): communitiesEventsTestTokenAddress},
|
|
Symbol: "TEST",
|
|
AmountInWei: "100000000000000000000",
|
|
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].AmountInWei == p.TokenCriteria[0].AmountInWei &&
|
|
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 {
|
|
base.SetupAdditionalMessengers(additionalEventSenders)
|
|
|
|
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_MANUAL_ACCEPT)
|
|
refreshMessengerResponses(base)
|
|
|
|
advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), base.GetEventSender())
|
|
advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), base.GetMember())
|
|
|
|
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)
|
|
|
|
checkMemberJoined := func(response *MessengerResponse) error {
|
|
return checkMemberJoinedToTheCommunity(response, base.GetMember().IdentityPublicKey())
|
|
}
|
|
|
|
waitOnMessengerResponse(s, 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, checkPermissionGranted, base.GetMember())
|
|
|
|
for _, eventSender := range additionalEventSenders {
|
|
advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), eventSender)
|
|
joinOnRequestCommunity(s, community, base.GetControlNode(), eventSender, requestEventSender)
|
|
|
|
grantPermission(s, community, base.GetControlNode(), eventSender, role)
|
|
checkPermissionGranted = func(response *MessengerResponse) error {
|
|
return checkRolePermissionInResponse(response, eventSender.IdentityPublicKey(), role)
|
|
}
|
|
waitOnMessengerResponse(s, checkPermissionGranted, base.GetMember())
|
|
waitOnMessengerResponse(s, 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, 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, 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, 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, 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, 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")
|
|
}
|
|
|
|
if len(modifiedCommmunity.PendingAndBannedMembers()) > 0 {
|
|
return errors.New("alice was kicked and should not be presented in the pending list")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
response, err := base.GetEventSender().RemoveUserFromCommunity(
|
|
communityID,
|
|
pubkey,
|
|
)
|
|
|
|
s := base.GetSuite()
|
|
s.Require().NoError(err)
|
|
|
|
// 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)")
|
|
}
|
|
|
|
if len(modifiedCommmunity.PendingAndBannedMembers()) == 0 {
|
|
return errors.New("alice should know about banned and pending members")
|
|
}
|
|
|
|
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())
|
|
}
|
|
|
|
func banMember(base CommunityEventsTestsInterface, banRequest *requests.BanUserFromCommunity) {
|
|
bannedPK := banRequest.User.String()
|
|
communityStr := banRequest.CommunityID.String()
|
|
|
|
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")
|
|
}
|
|
|
|
expectedState := communities.CommunityMemberBanned
|
|
if banRequest.DeleteAllMessages {
|
|
expectedState = communities.CommunityMemberBanWithAllMessagesDelete
|
|
}
|
|
|
|
if modifiedCommmunity.PendingAndBannedMembers()[bannedPK] != expectedState {
|
|
return errors.New("alice should be in the pending state")
|
|
}
|
|
|
|
if banRequest.DeleteAllMessages {
|
|
if len(response.DeletedMessages()) == 0 {
|
|
return errors.New("alice message must be deleted")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
response, err := base.GetEventSender().BanUserFromCommunity(context.Background(), banRequest)
|
|
|
|
s := base.GetSuite()
|
|
s.Require().NoError(err)
|
|
|
|
// 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()[bannedPK])
|
|
|
|
verifier := "event sender"
|
|
verifyPendingState := 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(verifier + ": alice should not be not banned (yet)")
|
|
}
|
|
|
|
state, exists := modifiedCommmunity.PendingAndBannedMembers()[bannedPK]
|
|
if !exists {
|
|
return errors.New(verifier + ": alice is not in the pending and banned members list")
|
|
}
|
|
|
|
if state != communities.CommunityMemberBanPending {
|
|
return errors.New("event sender: alice has invalid state: " + string(state))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// 2. wait for event as a sender
|
|
waitOnMessengerResponse(s, verifyPendingState, base.GetEventSender())
|
|
|
|
// 3. wait for event as the community member and check we are still until control node gets it
|
|
verifier = "alice"
|
|
waitOnMessengerResponse(s, verifyPendingState, base.GetMember())
|
|
|
|
checkMsgDeletion := func(messenger *Messenger, expectedMsgsCount int) {
|
|
msgs, err := messenger.persistence.GetCommunityMemberAllMessagesID(bannedPK, communityStr)
|
|
s.Require().NoError(err)
|
|
s.Require().Len(msgs, expectedMsgsCount)
|
|
}
|
|
|
|
if banRequest.DeleteAllMessages {
|
|
checkMsgDeletion(base.GetEventSender(), 1)
|
|
checkMsgDeletion(base.GetMember(), 1)
|
|
}
|
|
|
|
// 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())
|
|
|
|
if banRequest.DeleteAllMessages {
|
|
checkMsgDeletion(base.GetEventSender(), 0)
|
|
checkMsgDeletion(base.GetMember(), 0)
|
|
checkMsgDeletion(base.GetControlNode(), 0)
|
|
}
|
|
}
|
|
|
|
func unbanMember(base CommunityEventsTestsInterface, unbanRequest *requests.UnbanUserFromCommunity) {
|
|
pubkey := common.PubkeyToHex(&base.GetMember().identity.PublicKey)
|
|
|
|
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")
|
|
}
|
|
|
|
if modifiedCommmunity.PendingAndBannedMembers()[pubkey] != communities.CommunityMemberBanned {
|
|
return errors.New("alice should be in the pending state")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
response, err := base.GetEventSender().UnbanUserFromCommunity(unbanRequest)
|
|
|
|
s := base.GetSuite()
|
|
s.Require().NoError(err)
|
|
|
|
// 1. event sender should get pending state for unban member
|
|
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(unbanRequest.CommunityID))
|
|
s.Require().NoError(err)
|
|
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
|
|
}
|
|
|
|
if len(modifiedCommmunity.PendingAndBannedMembers()) == 0 {
|
|
return errors.New("alice should know about banned and pending members")
|
|
}
|
|
|
|
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())
|
|
}
|
|
|
|
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))
|
|
|
|
waitOnMessengerResponse(s, checkMessageDeleted, base.GetMember())
|
|
waitOnMessengerResponse(s, checkMessageDeleted, base.GetControlNode())
|
|
}
|
|
|
|
func pinControlNodeMessage(base CommunityEventsTestsInterface, pinnedMessage *common.PinMessage) {
|
|
checkPinned := func(response *MessengerResponse) error {
|
|
if len(response.Messages()) == 0 {
|
|
return errors.New("no messages in the response")
|
|
}
|
|
|
|
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, checkPinned, base.GetMember())
|
|
waitOnMessengerResponse(s, 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_MANUAL_ACCEPT,
|
|
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, 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
|
|
resp, err := WaitOnMessengerResponse(
|
|
base.GetEventSender(),
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Communities()) > 0 &&
|
|
len(r.Communities()[0].TokenPermissionsByType(permissionRequest.Type)) > 0 &&
|
|
r.Communities()[0].HasPermissionToSendCommunityEvents()
|
|
},
|
|
"event sender did not receive community token permission",
|
|
)
|
|
s.Require().NoError(err)
|
|
s.Require().NotNil(resp)
|
|
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_AUTO_ACCEPT,
|
|
},
|
|
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].AmountInWei = "200000000000000000000"
|
|
|
|
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)
|
|
}
|
|
|
|
// 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())
|
|
}
|
|
|
|
func testAcceptMemberRequestToJoin(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)
|
|
|
|
// 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))
|
|
|
|
// 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) {
|
|
s := base.GetSuite()
|
|
|
|
advertiseCommunityToUserOldWay(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))
|
|
|
|
// 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))
|
|
}
|
|
|
|
func testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger, additionalEventSender *Messenger) {
|
|
s := base.GetSuite()
|
|
|
|
advertiseCommunityToUserOldWay(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))
|
|
|
|
// 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))
|
|
}
|
|
|
|
func testRejectMemberRequestToJoin(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()}
|
|
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 {
|
|
requests, err := base.GetControlNode().DeclinedRequestsToJoinForCommunity(community.ID())
|
|
s.Require().NoError(err)
|
|
return len(response.Communities()) == 1 && len(requests) == 1
|
|
},
|
|
"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 testControlNodeHandlesMultipleEventSenderRequestToJoinDecisions(base CommunityEventsTestsInterface, community *communities.Community, user *Messenger, additionalEventSender *Messenger) {
|
|
_, err := user.Start()
|
|
|
|
s := base.GetSuite()
|
|
s.Require().NoError(err)
|
|
defer TearDownMessenger(s, user)
|
|
|
|
advertiseCommunityToUserOldWay(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.RequestsToJoinCommunity()) > 0 },
|
|
"control node did not receive event senders decision",
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
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
|
|
})
|
|
s.Require().NoError(err)
|
|
|
|
// 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)
|
|
|
|
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
|
|
|
|
})
|
|
s.Require().NoError(err)
|
|
}
|
|
|
|
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_AUTO_ACCEPT,
|
|
},
|
|
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(
|
|
context.Background(),
|
|
&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(
|
|
context.Background(),
|
|
&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(
|
|
context.Background(),
|
|
&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_AUTO_ACCEPT,
|
|
},
|
|
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, checkChannelCreated, member)
|
|
waitOnMessengerResponse(s, 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, checkChannelEdited, member)
|
|
waitOnMessengerResponse(s, 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, checkChannelDeleted, member)
|
|
waitOnMessengerResponse(s, 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].AmountInWei = "200000000000000000000"
|
|
|
|
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, checkTokenAdded, base.GetMember())
|
|
waitOnMessengerResponse(s, 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 added to the DB
|
|
syncTokens, err = base.GetMember().communitiesManager.GetAllCommunityTokens()
|
|
s.Require().NoError(err)
|
|
s.Require().Len(syncTokens, 1)
|
|
}
|
|
|
|
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")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
waitOnMessengerResponse(s, checkTokenAdded, base.GetMember())
|
|
}
|
|
|
|
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, 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 received 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().NoError(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)
|
|
}
|
|
|
|
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()
|
|
|
|
advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), bob)
|
|
advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), newPrivilegedUser)
|
|
|
|
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(
|
|
base.GetEventSender(),
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Communities()) > 0 &&
|
|
len(r.Communities()[0].TokenPermissionsByType(tokenPermissionType)) > 0 &&
|
|
r.Communities()[0].HasPermissionToSendCommunityEvents()
|
|
},
|
|
"newPrivilegedUser did not receive privileged role",
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
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)
|
|
}
|
|
|
|
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
|
|
community := createTestCommunity(base, protobuf.CommunityPermissions_MANUAL_ACCEPT)
|
|
|
|
advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), base.GetEventSender())
|
|
advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), base.GetMember())
|
|
advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), bob)
|
|
|
|
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 {
|
|
return len(r.Communities()) > 0 &&
|
|
len(r.Communities()[0].TokenPermissionsByType(tokenPermissionType)) > 0 &&
|
|
r.Communities()[0].HasPermissionToSendCommunityEvents()
|
|
},
|
|
"event sender did not receive privileged role",
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
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)
|
|
}
|
|
|
|
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(
|
|
base.GetEventSender(),
|
|
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)
|
|
}
|
|
|
|
func testBanMemberWithDeletingAllMessages(base CommunityEventsTestsInterface, community *communities.Community) {
|
|
// verify that event sender can't ban a control node and delete his messages
|
|
banRequest := &requests.BanUserFromCommunity{
|
|
CommunityID: community.ID(),
|
|
User: common.PubkeyToHexBytes(&base.GetControlNode().identity.PublicKey),
|
|
DeleteAllMessages: true,
|
|
}
|
|
|
|
_, err := base.GetEventSender().BanUserFromCommunity(
|
|
context.Background(),
|
|
banRequest,
|
|
)
|
|
s := base.GetSuite()
|
|
s.Require().Error(err)
|
|
|
|
chatIds := community.ChatIDs()
|
|
s.Require().Len(chatIds, 1)
|
|
chat := base.GetEventSender().Chat(chatIds[0])
|
|
s.Require().NotNil(chat)
|
|
|
|
inputMessage := buildTestMessage(*chat)
|
|
|
|
sendResponse, err := base.GetMember().SendChatMessage(context.Background(), inputMessage)
|
|
s.NoError(err)
|
|
s.Require().NotNil(sendResponse)
|
|
s.Require().Len(sendResponse.Messages(), 1)
|
|
messageID := sendResponse.Messages()[0].ID
|
|
|
|
checkMsgDelivered := func(response *MessengerResponse) error {
|
|
if len(response.Messages()) == 0 {
|
|
return errors.New("response does not contain message")
|
|
}
|
|
|
|
for _, message := range response.Messages() {
|
|
if message.ID == messageID {
|
|
return nil
|
|
}
|
|
}
|
|
return errors.New("messages was not found in the response")
|
|
}
|
|
|
|
waitOnMessengerResponse(s, checkMsgDelivered, base.GetControlNode())
|
|
|
|
waitOnMessengerResponse(s, checkMsgDelivered, base.GetEventSender())
|
|
|
|
banRequest.User = common.PubkeyToHexBytes(&base.GetMember().identity.PublicKey)
|
|
|
|
banMember(base, banRequest)
|
|
}
|