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"`
|
Emoji string `json:"emoji"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CommunityMemberState uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
CommunityMemberBanned CommunityMemberState = iota
|
||||||
|
CommunityMemberBanPending
|
||||||
|
CommunityMemberUnbanPending
|
||||||
|
CommunityMemberKickPending
|
||||||
|
)
|
||||||
|
|
||||||
func (o *Community) MarshalPublicAPIJSON() ([]byte, error) {
|
func (o *Community) MarshalPublicAPIJSON() ([]byte, error) {
|
||||||
if o.config.MemberIdentity == nil {
|
if o.config.MemberIdentity == nil {
|
||||||
return nil, errors.New("member identity not set")
|
return nil, errors.New("member identity not set")
|
||||||
|
@ -127,7 +136,6 @@ func (o *Community) MarshalPublicAPIJSON() ([]byte, error) {
|
||||||
Link string `json:"link"`
|
Link string `json:"link"`
|
||||||
CommunityAdminSettings CommunityAdminSettings `json:"adminSettings"`
|
CommunityAdminSettings CommunityAdminSettings `json:"adminSettings"`
|
||||||
Encrypted bool `json:"encrypted"`
|
Encrypted bool `json:"encrypted"`
|
||||||
BanList []string `json:"banList"`
|
|
||||||
TokenPermissions map[string]*CommunityTokenPermission `json:"tokenPermissions"`
|
TokenPermissions map[string]*CommunityTokenPermission `json:"tokenPermissions"`
|
||||||
CommunityTokensMetadata []*protobuf.CommunityTokenMetadata `json:"communityTokensMetadata"`
|
CommunityTokensMetadata []*protobuf.CommunityTokenMetadata `json:"communityTokensMetadata"`
|
||||||
ActiveMembersCount uint64 `json:"activeMembersCount"`
|
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.Link = fmt.Sprintf("https://join.status.im/c/0x%x", o.ID())
|
||||||
communityItem.IntroMessage = o.config.CommunityDescription.IntroMessage
|
communityItem.IntroMessage = o.config.CommunityDescription.IntroMessage
|
||||||
communityItem.OutroMessage = o.config.CommunityDescription.OutroMessage
|
communityItem.OutroMessage = o.config.CommunityDescription.OutroMessage
|
||||||
communityItem.BanList = o.config.CommunityDescription.BanList
|
|
||||||
communityItem.CommunityTokensMetadata = o.config.CommunityDescription.CommunityTokensMetadata
|
communityItem.CommunityTokensMetadata = o.config.CommunityDescription.CommunityTokensMetadata
|
||||||
communityItem.ActiveMembersCount = o.config.CommunityDescription.ActiveMembersCount
|
communityItem.ActiveMembersCount = o.config.CommunityDescription.ActiveMembersCount
|
||||||
|
|
||||||
|
@ -234,7 +241,7 @@ func (o *Community) MarshalJSON() ([]byte, error) {
|
||||||
MuteTill time.Time `json:"muteTill,omitempty"`
|
MuteTill time.Time `json:"muteTill,omitempty"`
|
||||||
CommunityAdminSettings CommunityAdminSettings `json:"adminSettings"`
|
CommunityAdminSettings CommunityAdminSettings `json:"adminSettings"`
|
||||||
Encrypted bool `json:"encrypted"`
|
Encrypted bool `json:"encrypted"`
|
||||||
BanList []string `json:"banList"`
|
PendingAndBannedMembers map[string]CommunityMemberState `json:"pendingAndBannedMembers"`
|
||||||
TokenPermissions map[string]*CommunityTokenPermission `json:"tokenPermissions"`
|
TokenPermissions map[string]*CommunityTokenPermission `json:"tokenPermissions"`
|
||||||
CommunityTokensMetadata []*protobuf.CommunityTokenMetadata `json:"communityTokensMetadata"`
|
CommunityTokensMetadata []*protobuf.CommunityTokenMetadata `json:"communityTokensMetadata"`
|
||||||
ActiveMembersCount uint64 `json:"activeMembersCount"`
|
ActiveMembersCount uint64 `json:"activeMembersCount"`
|
||||||
|
@ -288,11 +295,11 @@ func (o *Community) MarshalJSON() ([]byte, error) {
|
||||||
communityItem.Chats[id] = chat
|
communityItem.Chats[id] = chat
|
||||||
}
|
}
|
||||||
communityItem.TokenPermissions = o.tokenPermissions()
|
communityItem.TokenPermissions = o.tokenPermissions()
|
||||||
|
communityItem.PendingAndBannedMembers = o.PendingAndBannedMembers()
|
||||||
communityItem.Members = o.config.CommunityDescription.Members
|
communityItem.Members = o.config.CommunityDescription.Members
|
||||||
communityItem.Permissions = o.config.CommunityDescription.Permissions
|
communityItem.Permissions = o.config.CommunityDescription.Permissions
|
||||||
communityItem.IntroMessage = o.config.CommunityDescription.IntroMessage
|
communityItem.IntroMessage = o.config.CommunityDescription.IntroMessage
|
||||||
communityItem.OutroMessage = o.config.CommunityDescription.OutroMessage
|
communityItem.OutroMessage = o.config.CommunityDescription.OutroMessage
|
||||||
communityItem.BanList = o.config.CommunityDescription.BanList
|
|
||||||
communityItem.CommunityTokensMetadata = o.config.CommunityDescription.CommunityTokensMetadata
|
communityItem.CommunityTokensMetadata = o.config.CommunityDescription.CommunityTokensMetadata
|
||||||
communityItem.ActiveMembersCount = o.config.CommunityDescription.ActiveMembersCount
|
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 = make(map[string]images.IdentityImage)
|
||||||
}
|
}
|
||||||
communityItem.Images[t] = images.IdentityImage{Name: t, Payload: i.Payload}
|
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
|
return nil, ErrCannotRemoveOwnerOrAdmin
|
||||||
}
|
}
|
||||||
|
|
||||||
o.removeMemberFromOrg(pk)
|
|
||||||
|
|
||||||
if o.IsControlNode() {
|
if o.IsControlNode() {
|
||||||
|
o.removeMemberFromOrg(pk)
|
||||||
o.increaseClock()
|
o.increaseClock()
|
||||||
} else {
|
} else {
|
||||||
err := o.addNewCommunityEvent(o.ToKickCommunityMemberCommunityEvent(common.PubkeyToHex(pk)))
|
err := o.addNewCommunityEvent(o.ToKickCommunityMemberCommunityEvent(common.PubkeyToHex(pk)))
|
||||||
|
@ -761,9 +766,8 @@ func (o *Community) UnbanUserFromCommunity(pk *ecdsa.PublicKey) (*protobuf.Commu
|
||||||
return nil, ErrNotAuthorized
|
return nil, ErrNotAuthorized
|
||||||
}
|
}
|
||||||
|
|
||||||
o.unbanUserFromCommunity(pk)
|
|
||||||
|
|
||||||
if o.IsControlNode() {
|
if o.IsControlNode() {
|
||||||
|
o.unbanUserFromCommunity(pk)
|
||||||
o.increaseClock()
|
o.increaseClock()
|
||||||
} else {
|
} else {
|
||||||
err := o.addNewCommunityEvent(o.ToUnbanCommunityMemberCommunityEvent(common.PubkeyToHex(pk)))
|
err := o.addNewCommunityEvent(o.ToUnbanCommunityMemberCommunityEvent(common.PubkeyToHex(pk)))
|
||||||
|
@ -787,9 +791,8 @@ func (o *Community) BanUserFromCommunity(pk *ecdsa.PublicKey) (*protobuf.Communi
|
||||||
return nil, ErrCannotBanOwnerOrAdmin
|
return nil, ErrCannotBanOwnerOrAdmin
|
||||||
}
|
}
|
||||||
|
|
||||||
o.banUserFromCommunity(pk)
|
|
||||||
|
|
||||||
if o.IsControlNode() {
|
if o.IsControlNode() {
|
||||||
|
o.banUserFromCommunity(pk)
|
||||||
o.increaseClock()
|
o.increaseClock()
|
||||||
} else {
|
} else {
|
||||||
err := o.addNewCommunityEvent(o.ToBanCommunityMemberCommunityEvent(common.PubkeyToHex(pk)))
|
err := o.addNewCommunityEvent(o.ToBanCommunityMemberCommunityEvent(common.PubkeyToHex(pk)))
|
||||||
|
@ -1440,6 +1443,40 @@ func (o *Community) tokenPermissions() map[string]*CommunityTokenPermission {
|
||||||
return result
|
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 {
|
func (o *Community) TokenPermissions() map[string]*CommunityTokenPermission {
|
||||||
o.mutex.Lock()
|
o.mutex.Lock()
|
||||||
defer o.mutex.Unlock()
|
defer o.mutex.Unlock()
|
||||||
|
@ -2233,12 +2270,21 @@ func (o *Community) ValidateEvent(event *CommunityEvent, signer *ecdsa.PublicKey
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
member := o.getMember(signer)
|
eventSender := o.getMember(signer)
|
||||||
if member == nil {
|
if eventSender == nil {
|
||||||
return ErrMemberNotFound
|
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
|
return ErrNotAuthorized
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -298,35 +298,29 @@ func (o *Community) updateCommunityDescriptionByCommunityEvent(communityEvent Co
|
||||||
}
|
}
|
||||||
|
|
||||||
case protobuf.CommunityEvent_COMMUNITY_MEMBER_KICK:
|
case protobuf.CommunityEvent_COMMUNITY_MEMBER_KICK:
|
||||||
pk, err := common.HexToPubkey(communityEvent.MemberToAction)
|
if o.IsControlNode() {
|
||||||
if err != nil {
|
pk, err := common.HexToPubkey(communityEvent.MemberToAction)
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
o.removeMemberFromOrg(pk)
|
||||||
}
|
}
|
||||||
|
|
||||||
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:
|
case protobuf.CommunityEvent_COMMUNITY_MEMBER_BAN:
|
||||||
pk, err := common.HexToPubkey(communityEvent.MemberToAction)
|
if o.IsControlNode() {
|
||||||
if err != nil {
|
pk, err := common.HexToPubkey(communityEvent.MemberToAction)
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
o.banUserFromCommunity(pk)
|
||||||
}
|
}
|
||||||
|
|
||||||
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:
|
case protobuf.CommunityEvent_COMMUNITY_MEMBER_UNBAN:
|
||||||
pk, err := common.HexToPubkey(communityEvent.MemberToAction)
|
if o.IsControlNode() {
|
||||||
if err != nil {
|
pk, err := common.HexToPubkey(communityEvent.MemberToAction)
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
o.unbanUserFromCommunity(pk)
|
||||||
}
|
}
|
||||||
o.unbanUserFromCommunity(pk)
|
|
||||||
|
|
||||||
case protobuf.CommunityEvent_COMMUNITY_TOKEN_ADD:
|
case protobuf.CommunityEvent_COMMUNITY_TOKEN_ADD:
|
||||||
o.config.CommunityDescription.CommunityTokensMetadata = append(o.config.CommunityDescription.CommunityTokensMetadata, communityEvent.TokenMetadata)
|
o.config.CommunityDescription.CommunityTokensMetadata = append(o.config.CommunityDescription.CommunityTokensMetadata, communityEvent.TokenMetadata)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
package communities
|
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{
|
var adminAuthorizedEventTypes = []protobuf.CommunityEvent_EventType{
|
||||||
protobuf.CommunityEvent_COMMUNITY_EDIT,
|
protobuf.CommunityEvent_COMMUNITY_EDIT,
|
||||||
|
@ -56,11 +60,8 @@ var rolesToAuthorizedPermissionTypes = map[protobuf.CommunityMember_Roles][]prot
|
||||||
|
|
||||||
func canRolesPerformEvent(roles []protobuf.CommunityMember_Roles, eventType protobuf.CommunityEvent_EventType) bool {
|
func canRolesPerformEvent(roles []protobuf.CommunityMember_Roles, eventType protobuf.CommunityEvent_EventType) bool {
|
||||||
for _, role := range roles {
|
for _, role := range roles {
|
||||||
authorizedEventTypes := rolesToAuthorizedEventTypes[role]
|
if slices.Contains(rolesToAuthorizedEventTypes[role], eventType) {
|
||||||
for _, authorizedEventType := range authorizedEventTypes {
|
return true
|
||||||
if authorizedEventType == eventType {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -68,24 +69,51 @@ func canRolesPerformEvent(roles []protobuf.CommunityMember_Roles, eventType prot
|
||||||
|
|
||||||
func canRolesModifyPermission(roles []protobuf.CommunityMember_Roles, permissionType protobuf.CommunityTokenPermission_Type) bool {
|
func canRolesModifyPermission(roles []protobuf.CommunityMember_Roles, permissionType protobuf.CommunityTokenPermission_Type) bool {
|
||||||
for _, role := range roles {
|
for _, role := range roles {
|
||||||
authorizedPermissionTypes := rolesToAuthorizedPermissionTypes[role]
|
if slices.Contains(rolesToAuthorizedPermissionTypes[role], permissionType) {
|
||||||
for _, authorizedPermissionType := range authorizedPermissionTypes {
|
return true
|
||||||
if authorizedPermissionType == permissionType {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func RolesAuthorizedToPerformEvent(roles []protobuf.CommunityMember_Roles, event *CommunityEvent) bool {
|
func canRolesKickOrBanMember(senderRoles []protobuf.CommunityMember_Roles, memberRoles []protobuf.CommunityMember_Roles) bool {
|
||||||
if !canRolesPerformEvent(roles, event.Type) {
|
// 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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if event.Type == protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_CHANGE ||
|
if event.Type == protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_CHANGE ||
|
||||||
event.Type == protobuf.CommunityEvent_COMMUNITY_MEMBER_TOKEN_PERMISSION_DELETE {
|
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
|
return true
|
||||||
|
|
|
@ -624,6 +624,10 @@ func kickMember(base CommunityEventsTestsInterface, communityID types.HexBytes,
|
||||||
return errors.New("alice was not kicked")
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -634,12 +638,62 @@ func kickMember(base CommunityEventsTestsInterface, communityID types.HexBytes,
|
||||||
|
|
||||||
s := base.GetSuite()
|
s := base.GetSuite()
|
||||||
s.Require().NoError(err)
|
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) {
|
func banMember(base CommunityEventsTestsInterface, banRequest *requests.BanUserFromCommunity) {
|
||||||
|
pubkey := common.PubkeyToHex(&base.GetMember().identity.PublicKey)
|
||||||
|
|
||||||
checkBanned := func(response *MessengerResponse) error {
|
checkBanned := func(response *MessengerResponse) error {
|
||||||
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(banRequest.CommunityID))
|
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(banRequest.CommunityID))
|
||||||
if err != nil {
|
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")
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -661,12 +719,62 @@ func banMember(base CommunityEventsTestsInterface, banRequest *requests.BanUserF
|
||||||
|
|
||||||
s := base.GetSuite()
|
s := base.GetSuite()
|
||||||
s.Require().NoError(err)
|
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) {
|
func unbanMember(base CommunityEventsTestsInterface, unbanRequest *requests.UnbanUserFromCommunity) {
|
||||||
|
pubkey := common.PubkeyToHex(&base.GetMember().identity.PublicKey)
|
||||||
|
|
||||||
checkUnbanned := func(response *MessengerResponse) error {
|
checkUnbanned := func(response *MessengerResponse) error {
|
||||||
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(unbanRequest.CommunityID))
|
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(unbanRequest.CommunityID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -677,6 +785,10 @@ func unbanMember(base CommunityEventsTestsInterface, unbanRequest *requests.Unba
|
||||||
return errors.New("alice was not unbanned")
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -684,14 +796,48 @@ func unbanMember(base CommunityEventsTestsInterface, unbanRequest *requests.Unba
|
||||||
|
|
||||||
s := base.GetSuite()
|
s := base.GetSuite()
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().Nil(checkUnbanned(response))
|
|
||||||
|
|
||||||
_, err = WaitOnMessengerResponse(
|
// 1. event sender should get pending state for unban member
|
||||||
base.GetControlNode(),
|
modifiedCommmunity, err := getModifiedCommunity(response, types.EncodeHex(unbanRequest.CommunityID))
|
||||||
func(r *MessengerResponse) bool { return checkUnbanned(r) == nil },
|
|
||||||
"MessengerResponse data not received",
|
|
||||||
)
|
|
||||||
s.Require().NoError(err)
|
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 {
|
func controlNodeSendMessage(base CommunityEventsTestsInterface, inputMessage *common.Message) string {
|
||||||
|
|
Loading…
Reference in New Issue