feat: make any member able to edit group chat properties

closes: #2824
This commit is contained in:
Patryk Osmaczko 2022-08-29 16:07:32 +02:00 committed by osmaczko
parent c01316524c
commit f915fc6df4
3 changed files with 110 additions and 26 deletions

View File

@ -12,6 +12,7 @@ import (
gethbridge "github.com/status-im/status-go/eth-node/bridge/geth" gethbridge "github.com/status-im/status-go/eth-node/bridge/geth"
"github.com/status-im/status-go/eth-node/crypto" "github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/eth-node/types"
userimage "github.com/status-im/status-go/images"
"github.com/status-im/status-go/protocol/common" "github.com/status-im/status-go/protocol/common"
"github.com/status-im/status-go/protocol/tt" "github.com/status-im/status-go/protocol/tt"
"github.com/status-im/status-go/waku" "github.com/status-im/status-go/waku"
@ -105,6 +106,11 @@ func (s *MessengerGroupChatSuite) makeContact(origin *Messenger, toAdd *Messenge
s.Require().NoError(makeMutualContact(origin, &toAdd.identity.PublicKey)) s.Require().NoError(makeMutualContact(origin, &toAdd.identity.PublicKey))
} }
func (s *MessengerGroupChatSuite) makeMutualContacts(lhs *Messenger, rhs *Messenger) {
s.makeContact(lhs, rhs)
s.makeContact(rhs, lhs)
}
func (s *MessengerGroupChatSuite) TestGroupChatCreation() { func (s *MessengerGroupChatSuite) TestGroupChatCreation() {
testCases := []struct { testCases := []struct {
name string name string
@ -163,8 +169,8 @@ func (s *MessengerGroupChatSuite) TestGroupChatCreation() {
s.Require().EqualError(err, "group-chat: can't add members who are not mutual contacts") s.Require().EqualError(err, "group-chat: can't add members who are not mutual contacts")
} }
defer creator.Shutdown() defer s.NoError(creator.Shutdown())
defer member.Shutdown() defer s.NoError(member.Shutdown())
} }
} }
@ -239,12 +245,91 @@ func (s *MessengerGroupChatSuite) TestGroupChatMembersAddition() {
} }
} }
defer admin.Shutdown() defer s.NoError(admin.Shutdown())
defer inviter.Shutdown() defer s.NoError(inviter.Shutdown())
defer member.Shutdown() defer s.NoError(member.Shutdown())
} }
} }
func (s *MessengerGroupChatSuite) TestGroupChatEdit() { func (s *MessengerGroupChatSuite) TestGroupChatMembersRemoval() {
admin := s.startNewMessenger()
memberA := s.startNewMessenger()
memberB := s.startNewMessenger()
members := []string{common.PubkeyToHex(&memberA.identity.PublicKey), common.PubkeyToHex(&memberB.identity.PublicKey)}
s.makeMutualContacts(admin, memberA)
s.makeMutualContacts(admin, memberB)
groupChat := s.createGroupChat(admin, "test_group_chat", members)
s.verifyGroupChatCreated(memberA, true)
s.verifyGroupChatCreated(memberB, true)
_, err := memberA.RemoveMemberFromGroupChat(context.Background(), groupChat.ID, common.PubkeyToHex(&memberB.identity.PublicKey))
s.Require().Error(err)
// only admin can remove members from the group
_, err = admin.RemoveMemberFromGroupChat(context.Background(), groupChat.ID, common.PubkeyToHex(&memberB.identity.PublicKey))
s.Require().NoError(err)
// ensure removal is propagated to other members
response, err := WaitOnMessengerResponse(
memberA,
func(r *MessengerResponse) bool { return len(r.Chats()) > 0 },
"chat invitation not received",
)
s.Require().NoError(err)
s.Require().Len(response.Chats(), 1)
s.Require().True(response.Chats()[0].Active)
s.Require().Len(response.Chats()[0].Members, 2)
defer s.NoError(admin.Shutdown())
defer s.NoError(memberA.Shutdown())
defer s.NoError(memberB.Shutdown())
}
func (s *MessengerGroupChatSuite) TestGroupChatEdit() {
admin := s.startNewMessenger()
member := s.startNewMessenger()
s.makeMutualContacts(admin, member)
groupChat := s.createGroupChat(admin, "test_group_chat", []string{common.PubkeyToHex(&member.identity.PublicKey)})
s.verifyGroupChatCreated(member, true)
response, err := admin.EditGroupChat(context.Background(), groupChat.ID, "test_admin_group", "#FF00FF", userimage.CroppedImage{})
s.Require().NoError(err)
s.Require().Len(response.Chats(), 1)
s.Require().Equal("test_admin_group", response.Chats()[0].Name)
s.Require().Equal("#FF00FF", response.Chats()[0].Color)
// TODO: handle image
// ensure group edit is propagated to other members
response, err = WaitOnMessengerResponse(
member,
func(r *MessengerResponse) bool { return len(r.Chats()) > 0 },
"chat invitation not received",
)
s.Require().NoError(err)
s.Require().Len(response.Chats(), 1)
s.Require().Equal("test_admin_group", response.Chats()[0].Name)
s.Require().Equal("#FF00FF", response.Chats()[0].Color)
response, err = member.EditGroupChat(context.Background(), groupChat.ID, "test_member_group", "#F0F0F0", userimage.CroppedImage{})
s.Require().NoError(err)
s.Require().Len(response.Chats(), 1)
s.Require().Equal("test_member_group", response.Chats()[0].Name)
s.Require().Equal("#F0F0F0", response.Chats()[0].Color)
// ensure group edit is propagated to other members
response, err = WaitOnMessengerResponse(
admin,
func(r *MessengerResponse) bool { return len(r.Chats()) > 0 },
"chat invitation not received",
)
s.Require().NoError(err)
s.Require().Len(response.Chats(), 1)
s.Require().Equal("test_member_group", response.Chats()[0].Name)
s.Require().Equal("#F0F0F0", response.Chats()[0].Color)
defer s.NoError(admin.Shutdown())
defer s.NoError(member.Shutdown())
} }

View File

@ -500,13 +500,12 @@ func (g Group) validateEvent(event MembershipUpdateEvent) bool {
case protobuf.MembershipUpdateEvent_CHAT_CREATED: case protobuf.MembershipUpdateEvent_CHAT_CREATED:
return g.admins.Empty() && g.members.Empty() return g.admins.Empty() && g.members.Empty()
case protobuf.MembershipUpdateEvent_NAME_CHANGED: case protobuf.MembershipUpdateEvent_NAME_CHANGED:
return g.admins.Has(event.From) && len(event.Name) > 0 return (g.admins.Has(event.From) || g.members.Has(event.From)) && len(event.Name) > 0
case protobuf.MembershipUpdateEvent_COLOR_CHANGED: case protobuf.MembershipUpdateEvent_COLOR_CHANGED:
return g.admins.Has(event.From) && len(event.Color) > 0 return (g.admins.Has(event.From) || g.members.Has(event.From)) && len(event.Color) > 0
case protobuf.MembershipUpdateEvent_IMAGE_CHANGED: case protobuf.MembershipUpdateEvent_IMAGE_CHANGED:
return g.admins.Has(event.From) && len(event.Image) > 0 return (g.admins.Has(event.From) || g.members.Has(event.From)) && len(event.Image) > 0
case protobuf.MembershipUpdateEvent_MEMBERS_ADDED: case protobuf.MembershipUpdateEvent_MEMBERS_ADDED:
// Admins and members can add new members
return g.admins.Has(event.From) || g.members.Has(event.From) return g.admins.Has(event.From) || g.members.Has(event.From)
case protobuf.MembershipUpdateEvent_MEMBER_JOINED: case protobuf.MembershipUpdateEvent_MEMBER_JOINED:
return g.members.Has(event.From) return g.members.Has(event.From)

View File

@ -212,11 +212,11 @@ func TestGroupValidateEvent(t *testing.T) {
Result: true, Result: true,
}, },
{ {
Name: "name-changed not allowed for non-admins", Name: "name-changed allowed because from is member",
From: "0xabc", From: "0x123",
Group: createGroup(nil, nil), Group: createGroup([]string{"0xabc"}, []string{"0x123"}),
Event: NewNameChangedEvent("new-name", 0), Event: NewNameChangedEvent("new-name", 0),
Result: false, Result: true,
}, },
{ {
Name: "color-changed allowed because from is admin", Name: "color-changed allowed because from is admin",
@ -226,11 +226,11 @@ func TestGroupValidateEvent(t *testing.T) {
Result: true, Result: true,
}, },
{ {
Name: "color-changed not allowed for non-admins", Name: "color-changed allowed because from is member",
From: "0xabc", From: "0x123",
Group: createGroup(nil, nil), Group: createGroup([]string{"0xabc"}, []string{"0x123"}),
Event: NewColorChangedEvent("#7cda00", 0), Event: NewColorChangedEvent("#7cda00", 0),
Result: false, Result: true,
}, },
{ {
Name: "image-changed allowed because from is admin", Name: "image-changed allowed because from is admin",
@ -254,11 +254,11 @@ func TestGroupValidateEvent(t *testing.T) {
Result: true, Result: true,
}, },
{ {
Name: "members-added not allowed for non-admins", Name: "members-added not allowed because from is member",
From: "0xabc", From: "0x123",
Group: createGroup(nil, nil), Group: createGroup([]string{"0xabc"}, []string{"0x123"}),
Event: NewMembersAddedEvent([]string{"0x123"}, 0), Event: NewMembersAddedEvent([]string{"0x123"}, 0),
Result: false, Result: true,
}, },
{ {
Name: "member-removed allowed because removing themselves", Name: "member-removed allowed because removing themselves",
@ -270,15 +270,15 @@ func TestGroupValidateEvent(t *testing.T) {
{ {
Name: "member-removed allowed because from is admin", Name: "member-removed allowed because from is admin",
From: "0xabc", From: "0xabc",
Group: createGroup([]string{"0xabc"}, nil), Group: createGroup([]string{"0xabc"}, []string{"0x123"}),
Event: NewMemberRemovedEvent("0x123", 0), Event: NewMemberRemovedEvent("0x123", 0),
Result: true, Result: true,
}, },
{ {
Name: "member-removed not allowed for non-admins", Name: "member-removed not allowed for non-admins",
From: "0xabc", From: "0x123",
Group: createGroup(nil, nil), Group: createGroup([]string{"0xabc"}, []string{"0x123", "0x456"}),
Event: NewMemberRemovedEvent("0x123", 0), Event: NewMemberRemovedEvent("0x456", 0),
Result: false, Result: false,
}, },
{ {