feat: Introduce KickedPending and BannedPending states (#3948)
* feat: introduce KickedPending state for community members * feat: tests for ban/unban pending states * fix: remove pending And banned members from public serialization * feat: add check for banning and kicking privileged users * fix: process only first event when obtaining PendingAndBannedMembers * fix: review fixes * fix: proper conditions for kicking and banning checks * Fix: fix tests after rebase
This commit is contained in:
parent
eb6ed5ebae
commit
a17ee052fb
|
@ -106,6 +106,15 @@ type CommunityTag struct {
|
|||
Emoji string `json:"emoji"`
|
||||
}
|
||||
|
||||
type CommunityMemberState uint8
|
||||
|
||||
const (
|
||||
CommunityMemberBanned CommunityMemberState = iota
|
||||
CommunityMemberBanPending
|
||||
CommunityMemberUnbanPending
|
||||
CommunityMemberKickPending
|
||||
)
|
||||
|
||||
func (o *Community) MarshalPublicAPIJSON() ([]byte, error) {
|
||||
if o.config.MemberIdentity == nil {
|
||||
return nil, errors.New("member identity not set")
|
||||
|
@ -127,7 +136,6 @@ func (o *Community) MarshalPublicAPIJSON() ([]byte, error) {
|
|||
Link string `json:"link"`
|
||||
CommunityAdminSettings CommunityAdminSettings `json:"adminSettings"`
|
||||
Encrypted bool `json:"encrypted"`
|
||||
BanList []string `json:"banList"`
|
||||
TokenPermissions map[string]*CommunityTokenPermission `json:"tokenPermissions"`
|
||||
CommunityTokensMetadata []*protobuf.CommunityTokenMetadata `json:"communityTokensMetadata"`
|
||||
ActiveMembersCount uint64 `json:"activeMembersCount"`
|
||||
|
@ -173,7 +181,6 @@ func (o *Community) MarshalPublicAPIJSON() ([]byte, error) {
|
|||
communityItem.Link = fmt.Sprintf("https://join.status.im/c/0x%x", o.ID())
|
||||
communityItem.IntroMessage = o.config.CommunityDescription.IntroMessage
|
||||
communityItem.OutroMessage = o.config.CommunityDescription.OutroMessage
|
||||
communityItem.BanList = o.config.CommunityDescription.BanList
|
||||
communityItem.CommunityTokensMetadata = o.config.CommunityDescription.CommunityTokensMetadata
|
||||
communityItem.ActiveMembersCount = o.config.CommunityDescription.ActiveMembersCount
|
||||
|
||||
|
@ -234,7 +241,7 @@ func (o *Community) MarshalJSON() ([]byte, error) {
|
|||
MuteTill time.Time `json:"muteTill,omitempty"`
|
||||
CommunityAdminSettings CommunityAdminSettings `json:"adminSettings"`
|
||||
Encrypted bool `json:"encrypted"`
|
||||
BanList []string `json:"banList"`
|
||||
PendingAndBannedMembers map[string]CommunityMemberState `json:"pendingAndBannedMembers"`
|
||||
TokenPermissions map[string]*CommunityTokenPermission `json:"tokenPermissions"`
|
||||
CommunityTokensMetadata []*protobuf.CommunityTokenMetadata `json:"communityTokensMetadata"`
|
||||
ActiveMembersCount uint64 `json:"activeMembersCount"`
|
||||
|
@ -288,11 +295,11 @@ func (o *Community) MarshalJSON() ([]byte, error) {
|
|||
communityItem.Chats[id] = chat
|
||||
}
|
||||
communityItem.TokenPermissions = o.tokenPermissions()
|
||||
communityItem.PendingAndBannedMembers = o.PendingAndBannedMembers()
|
||||
communityItem.Members = o.config.CommunityDescription.Members
|
||||
communityItem.Permissions = o.config.CommunityDescription.Permissions
|
||||
communityItem.IntroMessage = o.config.CommunityDescription.IntroMessage
|
||||
communityItem.OutroMessage = o.config.CommunityDescription.OutroMessage
|
||||
communityItem.BanList = o.config.CommunityDescription.BanList
|
||||
communityItem.CommunityTokensMetadata = o.config.CommunityDescription.CommunityTokensMetadata
|
||||
communityItem.ActiveMembersCount = o.config.CommunityDescription.ActiveMembersCount
|
||||
|
||||
|
@ -305,7 +312,6 @@ func (o *Community) MarshalJSON() ([]byte, error) {
|
|||
communityItem.Images = make(map[string]images.IdentityImage)
|
||||
}
|
||||
communityItem.Images[t] = images.IdentityImage{Name: t, Payload: i.Payload}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -717,9 +723,8 @@ func (o *Community) RemoveUserFromOrg(pk *ecdsa.PublicKey) (*protobuf.CommunityD
|
|||
return nil, ErrCannotRemoveOwnerOrAdmin
|
||||
}
|
||||
|
||||
o.removeMemberFromOrg(pk)
|
||||
|
||||
if o.IsControlNode() {
|
||||
o.removeMemberFromOrg(pk)
|
||||
o.increaseClock()
|
||||
} else {
|
||||
err := o.addNewCommunityEvent(o.ToKickCommunityMemberCommunityEvent(common.PubkeyToHex(pk)))
|
||||
|
@ -761,9 +766,8 @@ func (o *Community) UnbanUserFromCommunity(pk *ecdsa.PublicKey) (*protobuf.Commu
|
|||
return nil, ErrNotAuthorized
|
||||
}
|
||||
|
||||
o.unbanUserFromCommunity(pk)
|
||||
|
||||
if o.IsControlNode() {
|
||||
o.unbanUserFromCommunity(pk)
|
||||
o.increaseClock()
|
||||
} else {
|
||||
err := o.addNewCommunityEvent(o.ToUnbanCommunityMemberCommunityEvent(common.PubkeyToHex(pk)))
|
||||
|
@ -787,9 +791,8 @@ func (o *Community) BanUserFromCommunity(pk *ecdsa.PublicKey) (*protobuf.Communi
|
|||
return nil, ErrCannotBanOwnerOrAdmin
|
||||
}
|
||||
|
||||
o.banUserFromCommunity(pk)
|
||||
|
||||
if o.IsControlNode() {
|
||||
o.banUserFromCommunity(pk)
|
||||
o.increaseClock()
|
||||
} else {
|
||||
err := o.addNewCommunityEvent(o.ToBanCommunityMemberCommunityEvent(common.PubkeyToHex(pk)))
|
||||
|
@ -1440,6 +1443,40 @@ func (o *Community) tokenPermissions() map[string]*CommunityTokenPermission {
|
|||
return result
|
||||
}
|
||||
|
||||
func (o *Community) PendingAndBannedMembers() map[string]CommunityMemberState {
|
||||
result := make(map[string]CommunityMemberState)
|
||||
|
||||
// Non-privileged members should not see pending and banned members
|
||||
if o.config.EventsData == nil || !o.IsPrivilegedMember(o.MemberIdentity()) {
|
||||
return result
|
||||
}
|
||||
|
||||
for _, bannedMemberID := range o.config.CommunityDescription.BanList {
|
||||
result[bannedMemberID] = CommunityMemberBanned
|
||||
}
|
||||
|
||||
processedEvents := make(map[string]bool)
|
||||
for _, event := range o.config.EventsData.Events {
|
||||
if processedEvents[event.MemberToAction] {
|
||||
continue
|
||||
}
|
||||
|
||||
switch event.Type {
|
||||
case protobuf.CommunityEvent_COMMUNITY_MEMBER_KICK:
|
||||
result[event.MemberToAction] = CommunityMemberKickPending
|
||||
case protobuf.CommunityEvent_COMMUNITY_MEMBER_BAN:
|
||||
result[event.MemberToAction] = CommunityMemberBanPending
|
||||
case protobuf.CommunityEvent_COMMUNITY_MEMBER_UNBAN:
|
||||
result[event.MemberToAction] = CommunityMemberUnbanPending
|
||||
default:
|
||||
continue
|
||||
}
|
||||
processedEvents[event.MemberToAction] = true
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (o *Community) TokenPermissions() map[string]*CommunityTokenPermission {
|
||||
o.mutex.Lock()
|
||||
defer o.mutex.Unlock()
|
||||
|
@ -2233,12 +2270,21 @@ func (o *Community) ValidateEvent(event *CommunityEvent, signer *ecdsa.PublicKey
|
|||
return err
|
||||
}
|
||||
|
||||
member := o.getMember(signer)
|
||||
if member == nil {
|
||||
eventSender := o.getMember(signer)
|
||||
if eventSender == nil {
|
||||
return ErrMemberNotFound
|
||||
}
|
||||
|
||||
if !RolesAuthorizedToPerformEvent(member.Roles, event) {
|
||||
eventTargetRoles := []protobuf.CommunityMember_Roles{}
|
||||
eventTargetPk, err := common.HexToPubkey(event.MemberToAction)
|
||||
if err == nil {
|
||||
eventTarget := o.getMember(eventTargetPk)
|
||||
if eventTarget != nil {
|
||||
eventTargetRoles = eventTarget.Roles
|
||||
}
|
||||
}
|
||||
|
||||
if !RolesAuthorizedToPerformEvent(eventSender.Roles, eventTargetRoles, event) {
|
||||
return ErrNotAuthorized
|
||||
}
|
||||
|
||||
|
|
|
@ -298,35 +298,29 @@ func (o *Community) updateCommunityDescriptionByCommunityEvent(communityEvent Co
|
|||
}
|
||||
|
||||
case protobuf.CommunityEvent_COMMUNITY_MEMBER_KICK:
|
||||
if o.IsControlNode() {
|
||||
pk, err := common.HexToPubkey(communityEvent.MemberToAction)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !o.IsControlNode() && o.IsPrivilegedMember(pk) {
|
||||
return errors.New("attempt to kick an control node or privileged user from non-control node side")
|
||||
}
|
||||
|
||||
o.removeMemberFromOrg(pk)
|
||||
|
||||
}
|
||||
case protobuf.CommunityEvent_COMMUNITY_MEMBER_BAN:
|
||||
if o.IsControlNode() {
|
||||
pk, err := common.HexToPubkey(communityEvent.MemberToAction)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !o.IsControlNode() && o.IsPrivilegedMember(pk) {
|
||||
return errors.New("attempt to ban an control node or privileged user from non-control node side")
|
||||
}
|
||||
o.banUserFromCommunity(pk)
|
||||
|
||||
}
|
||||
case protobuf.CommunityEvent_COMMUNITY_MEMBER_UNBAN:
|
||||
if o.IsControlNode() {
|
||||
pk, err := common.HexToPubkey(communityEvent.MemberToAction)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.unbanUserFromCommunity(pk)
|
||||
|
||||
}
|
||||
case protobuf.CommunityEvent_COMMUNITY_TOKEN_ADD:
|
||||
o.config.CommunityDescription.CommunityTokensMetadata = append(o.config.CommunityDescription.CommunityTokensMetadata, communityEvent.TokenMetadata)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package communities
|
||||
|
||||
import "github.com/status-im/status-go/protocol/protobuf"
|
||||
import (
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/status-im/status-go/protocol/protobuf"
|
||||
)
|
||||
|
||||
var adminAuthorizedEventTypes = []protobuf.CommunityEvent_EventType{
|
||||
protobuf.CommunityEvent_COMMUNITY_EDIT,
|
||||
|
@ -56,36 +60,60 @@ var rolesToAuthorizedPermissionTypes = map[protobuf.CommunityMember_Roles][]prot
|
|||
|
||||
func canRolesPerformEvent(roles []protobuf.CommunityMember_Roles, eventType protobuf.CommunityEvent_EventType) bool {
|
||||
for _, role := range roles {
|
||||
authorizedEventTypes := rolesToAuthorizedEventTypes[role]
|
||||
for _, authorizedEventType := range authorizedEventTypes {
|
||||
if authorizedEventType == eventType {
|
||||
if slices.Contains(rolesToAuthorizedEventTypes[role], eventType) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func canRolesModifyPermission(roles []protobuf.CommunityMember_Roles, permissionType protobuf.CommunityTokenPermission_Type) bool {
|
||||
for _, role := range roles {
|
||||
authorizedPermissionTypes := rolesToAuthorizedPermissionTypes[role]
|
||||
for _, authorizedPermissionType := range authorizedPermissionTypes {
|
||||
if authorizedPermissionType == permissionType {
|
||||
if slices.Contains(rolesToAuthorizedPermissionTypes[role], permissionType) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func RolesAuthorizedToPerformEvent(roles []protobuf.CommunityMember_Roles, event *CommunityEvent) bool {
|
||||
if !canRolesPerformEvent(roles, event.Type) {
|
||||
func canRolesKickOrBanMember(senderRoles []protobuf.CommunityMember_Roles, memberRoles []protobuf.CommunityMember_Roles) bool {
|
||||
// Owner can kick everyone
|
||||
if slices.Contains(senderRoles, protobuf.CommunityMember_ROLE_OWNER) {
|
||||
return true
|
||||
}
|
||||
|
||||
// TokenMaster can kick normal members and admins
|
||||
if (slices.Contains(senderRoles, protobuf.CommunityMember_ROLE_TOKEN_MASTER)) &&
|
||||
!(slices.Contains(memberRoles, protobuf.CommunityMember_ROLE_TOKEN_MASTER) ||
|
||||
slices.Contains(memberRoles, protobuf.CommunityMember_ROLE_OWNER)) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Admins can kick normal members
|
||||
if (slices.Contains(senderRoles, protobuf.CommunityMember_ROLE_ADMIN)) &&
|
||||
!(slices.Contains(memberRoles, protobuf.CommunityMember_ROLE_ADMIN) ||
|
||||
slices.Contains(memberRoles, protobuf.CommunityMember_ROLE_TOKEN_MASTER) ||
|
||||
slices.Contains(memberRoles, protobuf.CommunityMember_ROLE_OWNER)) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Normal members can't kick anyone
|
||||
return false
|
||||
}
|
||||
|
||||
func RolesAuthorizedToPerformEvent(senderRoles []protobuf.CommunityMember_Roles, memberRoles []protobuf.CommunityMember_Roles, event *CommunityEvent) bool {
|
||||
if !canRolesPerformEvent(senderRoles, event.Type) {
|
||||
return false
|
||||
}
|
||||
|
||||
if event.Type == protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_CHANGE ||
|
||||
event.Type == protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_DELETE {
|
||||
return canRolesModifyPermission(roles, event.TokenPermission.Type)
|
||||
return canRolesModifyPermission(senderRoles, event.TokenPermission.Type)
|
||||
}
|
||||
|
||||
if event.Type == protobuf.CommunityEvent_COMMUNITY_MEMBER_BAN ||
|
||||
event.Type == protobuf.CommunityEvent_COMMUNITY_MEMBER_KICK {
|
||||
return canRolesKickOrBanMember(senderRoles, memberRoles)
|
||||
}
|
||||
|
||||
return true
|
||||
|
|
|
@ -624,6 +624,10 @@ func kickMember(base CommunityEventsTestsInterface, communityID types.HexBytes,
|
|||
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
|
||||
}
|
||||
|
||||
|
@ -634,12 +638,62 @@ func kickMember(base CommunityEventsTestsInterface, communityID types.HexBytes,
|
|||
|
||||
s := base.GetSuite()
|
||||
s.Require().NoError(err)
|
||||
s.Require().Nil(checkKicked(response))
|
||||
|
||||
checkClientsReceivedAdminEvent(base, checkKicked)
|
||||
// 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 not 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) {
|
||||
pubkey := common.PubkeyToHex(&base.GetMember().identity.PublicKey)
|
||||
|
||||
checkBanned := func(response *MessengerResponse) error {
|
||||
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(banRequest.CommunityID))
|
||||
if err != nil {
|
||||
|
@ -654,6 +708,10 @@ func banMember(base CommunityEventsTestsInterface, banRequest *requests.BanUserF
|
|||
return errors.New("alice was not added to the banned list")
|
||||
}
|
||||
|
||||
if modifiedCommmunity.PendingAndBannedMembers()[pubkey] != communities.CommunityMemberBanned {
|
||||
return errors.New("alice should be in the pending state")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -661,12 +719,62 @@ func banMember(base CommunityEventsTestsInterface, banRequest *requests.BanUserF
|
|||
|
||||
s := base.GetSuite()
|
||||
s.Require().NoError(err)
|
||||
s.Require().Nil(checkBanned(response))
|
||||
|
||||
checkClientsReceivedAdminEvent(base, checkBanned)
|
||||
// 1. event sender should get pending state for ban member
|
||||
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(banRequest.CommunityID))
|
||||
s.Require().NoError(err)
|
||||
s.Require().True(modifiedCommmunity.HasMember(&base.GetMember().identity.PublicKey))
|
||||
s.Require().Equal(communities.CommunityMemberBanPending, modifiedCommmunity.PendingAndBannedMembers()[pubkey])
|
||||
|
||||
// 2. wait for event as a sender
|
||||
waitOnMessengerResponse(s, func(response *MessengerResponse) error {
|
||||
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(banRequest.CommunityID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !modifiedCommmunity.HasMember(&base.GetMember().identity.PublicKey) {
|
||||
return errors.New("alice should not be not banned (yet)")
|
||||
}
|
||||
|
||||
if modifiedCommmunity.PendingAndBannedMembers()[pubkey] != communities.CommunityMemberBanPending {
|
||||
return errors.New("alice should be in the pending state")
|
||||
}
|
||||
|
||||
return nil
|
||||
}, base.GetEventSender())
|
||||
|
||||
// 3. wait for event as the community member and check we are still until control node gets it
|
||||
waitOnMessengerResponse(s, func(response *MessengerResponse) error {
|
||||
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(banRequest.CommunityID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !modifiedCommmunity.HasMember(&base.GetMember().identity.PublicKey) {
|
||||
return errors.New("alice should not be not banned (yet)")
|
||||
}
|
||||
|
||||
if len(modifiedCommmunity.PendingAndBannedMembers()) > 0 {
|
||||
return errors.New("alice should not know about banned and pending members")
|
||||
}
|
||||
|
||||
return nil
|
||||
}, base.GetMember())
|
||||
|
||||
// 4. control node should handle event and actually ban member
|
||||
waitOnMessengerResponse(s, checkBanned, base.GetControlNode())
|
||||
|
||||
// 5. event sender get banned member
|
||||
waitOnMessengerResponse(s, checkBanned, base.GetEventSender())
|
||||
|
||||
// 6. member should be notified about actual removal
|
||||
waitOnMessengerResponse(s, checkBanned, base.GetMember())
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -677,6 +785,10 @@ func unbanMember(base CommunityEventsTestsInterface, unbanRequest *requests.Unba
|
|||
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
|
||||
}
|
||||
|
||||
|
@ -684,14 +796,48 @@ func unbanMember(base CommunityEventsTestsInterface, unbanRequest *requests.Unba
|
|||
|
||||
s := base.GetSuite()
|
||||
s.Require().NoError(err)
|
||||
s.Require().Nil(checkUnbanned(response))
|
||||
|
||||
_, err = WaitOnMessengerResponse(
|
||||
base.GetControlNode(),
|
||||
func(r *MessengerResponse) bool { return checkUnbanned(r) == nil },
|
||||
"MessengerResponse data not received",
|
||||
)
|
||||
// 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 not 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 {
|
||||
|
|
Loading…
Reference in New Issue