fix(messenger_communities): block messages and reactions to token gated or spectated communities (#4064)
Which specifies that if a user is not a community member & a chat member, he can't post, react or pin messages in that chat. Notes: - also fix&cleanup associated failing tests. - refactor Community.CanPost() to reflect the new requirement. - grant code is not fully implemented and is to be removed later. Fixes https://github.com/status-im/status-desktop/issues/11915
This commit is contained in:
parent
9d59d889f6
commit
3805662a18
|
@ -1722,72 +1722,54 @@ func (o *Community) VerifyGrantSignature(data []byte) (*protobuf.Grant, error) {
|
||||||
|
|
||||||
func (o *Community) CanPost(pk *ecdsa.PublicKey, chatID string, grantBytes []byte) (bool, error) {
|
func (o *Community) CanPost(pk *ecdsa.PublicKey, chatID string, grantBytes []byte) (bool, error) {
|
||||||
if o.config.CommunityDescription.Chats == nil {
|
if o.config.CommunityDescription.Chats == nil {
|
||||||
o.config.Logger.Debug("canPost, no-chats")
|
o.config.Logger.Debug("Community.CanPost: no-chats")
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
chat, ok := o.config.CommunityDescription.Chats[chatID]
|
chat, ok := o.config.CommunityDescription.Chats[chatID]
|
||||||
if !ok {
|
if !ok {
|
||||||
o.config.Logger.Debug("canPost, no chat with id", zap.String("chat-id", chatID))
|
o.config.Logger.Debug("Community.CanPost: no chat with id", zap.String("chat-id", chatID))
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// creator can always post
|
// community creator can always post, return immediately
|
||||||
if common.IsPubKeyEqual(pk, o.config.ID) {
|
if common.IsPubKeyEqual(pk, o.config.ID) {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// if banned cannot post
|
|
||||||
if o.isBanned(pk) {
|
if o.isBanned(pk) {
|
||||||
|
o.config.Logger.Debug("Community.CanPost: user is banned", zap.String("chat-id", chatID))
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// If both the chat & the org have no permissions, the user is allowed to post
|
if o.config.CommunityDescription.Members == nil {
|
||||||
if o.config.CommunityDescription.Permissions.Access == protobuf.CommunityPermissions_NO_MEMBERSHIP && chat.Permissions.Access == protobuf.CommunityPermissions_NO_MEMBERSHIP {
|
o.config.Logger.Debug("Community.CanPost: no members in org", zap.String("chat-id", chatID))
|
||||||
return true, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if chat.Permissions.Access != protobuf.CommunityPermissions_NO_MEMBERSHIP {
|
// If community member, also check chat membership next
|
||||||
if chat.Members == nil {
|
_, ok = o.config.CommunityDescription.Members[common.PubkeyToHex(pk)]
|
||||||
o.config.Logger.Debug("canPost, no members in chat", zap.String("chat-id", chatID))
|
if !ok {
|
||||||
|
o.config.Logger.Debug("Community.CanPost: not a community member", zap.String("chat-id", chatID))
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if chat.Members == nil {
|
||||||
|
o.config.Logger.Debug("Community.CanPost: no members in chat", zap.String("chat-id", chatID))
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need to also be a chat member to post
|
||||||
|
if !o.IsMemberInChat(pk, chatID) {
|
||||||
|
if grantBytes == nil {
|
||||||
|
o.config.Logger.Debug("Community.CanPost: not a chat member:", zap.String("chat-id", chatID))
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
_, ok := chat.Members[common.PubkeyToHex(pk)]
|
|
||||||
// If member, we stop here
|
|
||||||
if ok {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// If not a member, and not grant, we return
|
|
||||||
if !ok && grantBytes == nil {
|
|
||||||
o.config.Logger.Debug("canPost, not a member in chat", zap.String("chat-id", chatID))
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise we verify the grant
|
|
||||||
return o.canPostWithGrant(pk, chatID, grantBytes)
|
return o.canPostWithGrant(pk, chatID, grantBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chat has no membership, check org permissions
|
// all conditions satisfied, user can post after all
|
||||||
if o.config.CommunityDescription.Members == nil {
|
return true, nil
|
||||||
o.config.Logger.Debug("canPost, no members in org", zap.String("chat-id", chatID))
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// If member, they can post
|
|
||||||
_, ok = o.config.CommunityDescription.Members[common.PubkeyToHex(pk)]
|
|
||||||
if ok {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not a member and no grant, can't post
|
|
||||||
if !ok && grantBytes == nil {
|
|
||||||
o.config.Logger.Debug("canPost, not a member in org", zap.String("chat-id", chatID), zap.String("pubkey", common.PubkeyToHex(pk)))
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return o.canPostWithGrant(pk, chatID, grantBytes)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Community) canPostWithGrant(pk *ecdsa.PublicKey, chatID string, grantBytes []byte) (bool, error) {
|
func (o *Community) canPostWithGrant(pk *ecdsa.PublicKey, chatID string, grantBytes []byte) (bool, error) {
|
||||||
|
|
|
@ -511,7 +511,7 @@ func (s *CommunitySuite) TestCanPost() {
|
||||||
name: "no-membership org with no-membeship chat",
|
name: "no-membership org with no-membeship chat",
|
||||||
config: s.configNoMembershipOrgNoMembershipChat(),
|
config: s.configNoMembershipOrgNoMembershipChat(),
|
||||||
member: notMember,
|
member: notMember,
|
||||||
canPost: true,
|
canPost: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no-membership org with invitation only chat-not-a-member",
|
name: "no-membership org with invitation only chat-not-a-member",
|
||||||
|
@ -529,7 +529,7 @@ func (s *CommunitySuite) TestCanPost() {
|
||||||
name: "no-membership org with invitation only chat-not-a-member valid grant",
|
name: "no-membership org with invitation only chat-not-a-member valid grant",
|
||||||
config: s.configNoMembershipOrgInvitationOnlyChat(),
|
config: s.configNoMembershipOrgInvitationOnlyChat(),
|
||||||
member: notMember,
|
member: notMember,
|
||||||
canPost: true,
|
canPost: false,
|
||||||
grant: validGrant,
|
grant: validGrant,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -555,7 +555,7 @@ func (s *CommunitySuite) TestCanPost() {
|
||||||
name: "membership org with no-membership chat not-a-member valid grant",
|
name: "membership org with no-membership chat not-a-member valid grant",
|
||||||
config: s.configOnRequestOrgNoMembershipChat(),
|
config: s.configOnRequestOrgNoMembershipChat(),
|
||||||
member: notMember,
|
member: notMember,
|
||||||
canPost: true,
|
canPost: false,
|
||||||
grant: validGrant,
|
grant: validGrant,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -442,18 +442,29 @@ func (s *MessengerCommunitiesSuite) TestCommunityContactCodeAdvertisement() {
|
||||||
func (s *MessengerCommunitiesSuite) TestPostToCommunityChat() {
|
func (s *MessengerCommunitiesSuite) TestPostToCommunityChat() {
|
||||||
community, chat := s.createCommunity()
|
community, chat := s.createCommunity()
|
||||||
|
|
||||||
s.advertiseCommunityTo(community, s.owner, s.alice)
|
|
||||||
s.joinCommunity(community, s.owner, s.alice)
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
chatID := chat.ID
|
chatID := chat.ID
|
||||||
inputMessage := common.NewMessage()
|
inputMessage := common.NewMessage()
|
||||||
inputMessage.ChatId = chatID
|
inputMessage.ChatId = chatID
|
||||||
inputMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN
|
inputMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN
|
||||||
inputMessage.Text = "some text"
|
inputMessage.Text = "some text"
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
s.advertiseCommunityTo(community, s.owner, s.alice)
|
||||||
|
|
||||||
|
// Send message without even spectating fails
|
||||||
_, err := s.alice.SendChatMessage(ctx, inputMessage)
|
_, err := s.alice.SendChatMessage(ctx, inputMessage)
|
||||||
|
s.Require().Error(err)
|
||||||
|
|
||||||
|
// Sending a message without joining fails
|
||||||
|
_, err = s.alice.SpectateCommunity(community.ID())
|
||||||
|
s.Require().NoError(err)
|
||||||
|
_, err = s.alice.SendChatMessage(ctx, inputMessage)
|
||||||
|
s.Require().Error(err)
|
||||||
|
|
||||||
|
// Sending should work now
|
||||||
|
s.joinCommunity(community, s.owner, s.alice)
|
||||||
|
_, err = s.alice.SendChatMessage(ctx, inputMessage)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
var response *MessengerResponse
|
var response *MessengerResponse
|
||||||
|
|
|
@ -2137,10 +2137,8 @@ func (m *Messenger) dispatchMessage(ctx context.Context, rawMessage common.RawMe
|
||||||
return rawMessage, err
|
return rawMessage, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// We allow emoji reactions by anyone
|
if !canPost {
|
||||||
if rawMessage.MessageType != protobuf.ApplicationMetadataMessage_EMOJI_REACTION && !canPost {
|
|
||||||
m.logger.Error("can't post on chat", zap.String("chat-id", chat.ID), zap.String("chat-name", chat.Name))
|
m.logger.Error("can't post on chat", zap.String("chat-id", chat.ID), zap.String("chat-name", chat.Name))
|
||||||
|
|
||||||
return rawMessage, errors.New("can't post on chat")
|
return rawMessage, errors.New("can't post on chat")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"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"
|
||||||
"github.com/status-im/status-go/protocol/common"
|
"github.com/status-im/status-go/protocol/common"
|
||||||
|
"github.com/status-im/status-go/protocol/communities"
|
||||||
"github.com/status-im/status-go/protocol/protobuf"
|
"github.com/status-im/status-go/protocol/protobuf"
|
||||||
"github.com/status-im/status-go/protocol/requests"
|
"github.com/status-im/status-go/protocol/requests"
|
||||||
"github.com/status-im/status-go/protocol/tt"
|
"github.com/status-im/status-go/protocol/tt"
|
||||||
|
@ -23,6 +24,19 @@ func TestMessengerActivityCenterMessageSuite(t *testing.T) {
|
||||||
suite.Run(t, new(MessengerActivityCenterMessageSuite))
|
suite.Run(t, new(MessengerActivityCenterMessageSuite))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *MessengerActivityCenterMessageSuite) createCommunity(owner *Messenger) (*communities.Community, *Chat) {
|
||||||
|
return createCommunity(&s.Suite, owner)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MessengerActivityCenterMessageSuite) advertiseCommunityTo(community *communities.Community, owner *Messenger, user *Messenger) {
|
||||||
|
advertiseCommunityTo(&s.Suite, community, owner, user)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MessengerActivityCenterMessageSuite) joinCommunity(community *communities.Community, owner *Messenger, user *Messenger) {
|
||||||
|
request := &requests.RequestToJoinCommunity{CommunityID: community.ID()}
|
||||||
|
joinCommunity(&s.Suite, community, owner, user, request)
|
||||||
|
}
|
||||||
|
|
||||||
type MessengerActivityCenterMessageSuite struct {
|
type MessengerActivityCenterMessageSuite struct {
|
||||||
suite.Suite
|
suite.Suite
|
||||||
m *Messenger // main instance of Messenger
|
m *Messenger // main instance of Messenger
|
||||||
|
@ -117,75 +131,35 @@ func (s *MessengerActivityCenterMessageSuite) TestDeleteOneToOneChat() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MessengerActivityCenterMessageSuite) TestEveryoneMentionTag() {
|
func (s *MessengerActivityCenterMessageSuite) TestEveryoneMentionTag() {
|
||||||
|
|
||||||
description := &requests.CreateCommunity{
|
|
||||||
Membership: protobuf.CommunityPermissions_NO_MEMBERSHIP,
|
|
||||||
Name: "status",
|
|
||||||
Color: "#ffffff",
|
|
||||||
Description: "status community description",
|
|
||||||
}
|
|
||||||
|
|
||||||
alice := s.m
|
alice := s.m
|
||||||
bob := s.newMessenger()
|
bob := s.newMessenger()
|
||||||
_, err := bob.Start()
|
_, err := bob.Start()
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
defer bob.Shutdown() // nolint: errcheck
|
defer bob.Shutdown() // nolint: errcheck
|
||||||
|
|
||||||
// Create an community chat
|
// Create a community
|
||||||
response, err := bob.CreateCommunity(description, true)
|
community, chat := s.createCommunity(bob)
|
||||||
s.Require().NoError(err)
|
|
||||||
s.Require().Len(response.Communities(), 1)
|
|
||||||
|
|
||||||
community := response.Communities()[0]
|
|
||||||
s.Require().NotNil(community)
|
s.Require().NotNil(community)
|
||||||
|
s.Require().NotNil(chat)
|
||||||
chat := CreateOneToOneChat(common.PubkeyToHex(&alice.identity.PublicKey), &alice.identity.PublicKey, bob.transport)
|
|
||||||
|
|
||||||
// bob sends a community message
|
|
||||||
inputMessage := common.NewMessage()
|
|
||||||
inputMessage.ChatId = chat.ID
|
|
||||||
inputMessage.Text = "some text"
|
|
||||||
inputMessage.CommunityID = community.IDString()
|
|
||||||
|
|
||||||
err = bob.SaveChat(chat)
|
|
||||||
s.Require().NoError(err)
|
|
||||||
_, err = bob.SendChatMessage(context.Background(), inputMessage)
|
|
||||||
s.Require().NoError(err)
|
|
||||||
|
|
||||||
_, err = WaitOnMessengerResponse(
|
|
||||||
alice,
|
|
||||||
func(r *MessengerResponse) bool { return len(r.Communities()) == 1 },
|
|
||||||
"no messages",
|
|
||||||
)
|
|
||||||
|
|
||||||
s.Require().NoError(err)
|
|
||||||
|
|
||||||
// Alice joins the community
|
// Alice joins the community
|
||||||
response, err = alice.JoinCommunity(context.Background(), community.ID(), false)
|
s.advertiseCommunityTo(community, bob, alice)
|
||||||
s.Require().NoError(err)
|
s.joinCommunity(community, bob, alice)
|
||||||
s.Require().NotNil(response)
|
|
||||||
s.Require().Len(response.Communities(), 1)
|
|
||||||
s.Require().True(response.Communities()[0].Joined())
|
|
||||||
s.Require().Len(response.Chats(), 1)
|
|
||||||
|
|
||||||
defaultCommunityChatID := response.Chats()[0].ID
|
// alice sends a community message
|
||||||
|
inputMessage := common.NewMessage()
|
||||||
// bob sends a community message
|
inputMessage.ChatId = chat.ID
|
||||||
inputMessage = common.NewMessage()
|
inputMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN
|
||||||
inputMessage.ChatId = defaultCommunityChatID
|
|
||||||
inputMessage.Text = "Good news, @" + common.EveryoneMentionTag + " !"
|
inputMessage.Text = "Good news, @" + common.EveryoneMentionTag + " !"
|
||||||
inputMessage.CommunityID = community.IDString()
|
|
||||||
|
|
||||||
response, err = alice.SendChatMessage(context.Background(), inputMessage)
|
response, err := alice.SendChatMessage(context.Background(), inputMessage)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
s.Require().Len(response.Messages(), 1)
|
s.Require().Len(response.Messages(), 1)
|
||||||
|
|
||||||
s.Require().True(response.Messages()[0].Mentioned)
|
s.Require().True(response.Messages()[0].Mentioned)
|
||||||
|
|
||||||
response, err = WaitOnMessengerResponse(
|
response, err = WaitOnMessengerResponse(
|
||||||
bob,
|
bob,
|
||||||
func(r *MessengerResponse) bool { return len(r.Messages()) == 1 },
|
func(r *MessengerResponse) bool { return len(r.Messages()) >= 1 },
|
||||||
"no messages",
|
"no messages",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -199,14 +173,6 @@ func (s *MessengerActivityCenterMessageSuite) TestEveryoneMentionTag() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MessengerActivityCenterMessageSuite) TestReplyWithImage() {
|
func (s *MessengerActivityCenterMessageSuite) TestReplyWithImage() {
|
||||||
|
|
||||||
description := &requests.CreateCommunity{
|
|
||||||
Membership: protobuf.CommunityPermissions_NO_MEMBERSHIP,
|
|
||||||
Name: "status",
|
|
||||||
Color: "#ffffff",
|
|
||||||
Description: "status community description",
|
|
||||||
}
|
|
||||||
|
|
||||||
alice := s.m
|
alice := s.m
|
||||||
bob := s.newMessenger()
|
bob := s.newMessenger()
|
||||||
_, err := bob.Start()
|
_, err := bob.Start()
|
||||||
|
@ -218,73 +184,36 @@ func (s *MessengerActivityCenterMessageSuite) TestReplyWithImage() {
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().NotNil(mediaServer)
|
s.Require().NotNil(mediaServer)
|
||||||
s.Require().NoError(mediaServer.Start())
|
s.Require().NoError(mediaServer.Start())
|
||||||
|
|
||||||
alice.httpServer = mediaServer
|
alice.httpServer = mediaServer
|
||||||
|
|
||||||
// Create an community chat
|
// Create a community
|
||||||
response, err := bob.CreateCommunity(description, true)
|
community, chat := s.createCommunity(bob)
|
||||||
s.Require().NoError(err)
|
|
||||||
s.Require().Len(response.Communities(), 1)
|
|
||||||
|
|
||||||
community := response.Communities()[0]
|
|
||||||
s.Require().NotNil(community)
|
s.Require().NotNil(community)
|
||||||
|
s.Require().NotNil(chat)
|
||||||
chat := CreateOneToOneChat(common.PubkeyToHex(&alice.identity.PublicKey), &alice.identity.PublicKey, bob.transport)
|
|
||||||
|
|
||||||
// bob sends a community message
|
|
||||||
inputMessage := common.NewMessage()
|
|
||||||
inputMessage.ChatId = chat.ID
|
|
||||||
inputMessage.Text = "some text"
|
|
||||||
inputMessage.CommunityID = community.IDString()
|
|
||||||
|
|
||||||
err = bob.SaveChat(chat)
|
|
||||||
s.Require().NoError(err)
|
|
||||||
_, err = bob.SendChatMessage(context.Background(), inputMessage)
|
|
||||||
s.Require().NoError(err)
|
|
||||||
|
|
||||||
_, err = WaitOnMessengerResponse(
|
|
||||||
alice,
|
|
||||||
func(r *MessengerResponse) bool { return len(r.Communities()) == 1 },
|
|
||||||
"no messages",
|
|
||||||
)
|
|
||||||
|
|
||||||
s.Require().NoError(err)
|
|
||||||
|
|
||||||
// Alice joins the community
|
// Alice joins the community
|
||||||
response, err = alice.JoinCommunity(context.Background(), community.ID(), false)
|
s.advertiseCommunityTo(community, bob, alice)
|
||||||
s.Require().NoError(err)
|
s.joinCommunity(community, bob, alice)
|
||||||
s.Require().NotNil(response)
|
|
||||||
s.Require().Len(response.Communities(), 1)
|
|
||||||
s.Require().True(response.Communities()[0].Joined())
|
|
||||||
s.Require().Len(response.Chats(), 1)
|
|
||||||
|
|
||||||
defaultCommunityChat := response.Chats()[0]
|
// Alice sends a community message
|
||||||
|
inputMessage := common.NewMessage()
|
||||||
defaultCommunityChatID := defaultCommunityChat.ID
|
inputMessage.ChatId = chat.ID
|
||||||
|
inputMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN
|
||||||
// bob sends a community message
|
|
||||||
inputMessage = common.NewMessage()
|
|
||||||
inputMessage.ChatId = defaultCommunityChatID
|
|
||||||
inputMessage.Text = "test message"
|
inputMessage.Text = "test message"
|
||||||
inputMessage.CommunityID = community.IDString()
|
|
||||||
|
|
||||||
response, err = alice.SendChatMessage(context.Background(), inputMessage)
|
response, err := alice.SendChatMessage(context.Background(), inputMessage)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
s.Require().Len(response.Messages(), 1)
|
s.Require().Len(response.Messages(), 1)
|
||||||
|
|
||||||
response, err = WaitOnMessengerResponse(
|
response, err = WaitOnMessengerResponse(
|
||||||
bob,
|
bob,
|
||||||
func(r *MessengerResponse) bool { return len(r.Messages()) == 1 },
|
func(r *MessengerResponse) bool { return len(r.Messages()) == 1 },
|
||||||
"no messages",
|
"no messages",
|
||||||
)
|
)
|
||||||
|
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
s.Require().Len(response.Messages(), 1)
|
s.Require().Len(response.Messages(), 1)
|
||||||
|
|
||||||
// bob sends a community message
|
// bob sends a reply with an image
|
||||||
inputMessage, err = buildImageWithAlbumIDMessage(*defaultCommunityChat, "0x34")
|
inputMessage, err = buildImageWithAlbumIDMessage(*chat, "0x34")
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
inputMessage.Text = "test message reply"
|
inputMessage.Text = "test message reply"
|
||||||
|
@ -292,25 +221,22 @@ func (s *MessengerActivityCenterMessageSuite) TestReplyWithImage() {
|
||||||
|
|
||||||
response, err = bob.SendChatMessage(context.Background(), inputMessage)
|
response, err = bob.SendChatMessage(context.Background(), inputMessage)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
s.Require().Len(response.Messages(), 2)
|
s.Require().Len(response.Messages(), 2)
|
||||||
|
|
||||||
response, err = WaitOnMessengerResponse(
|
response, err = WaitOnMessengerResponse(
|
||||||
alice,
|
alice,
|
||||||
func(r *MessengerResponse) bool { return len(r.Messages()) == 2 },
|
func(r *MessengerResponse) bool { return len(r.Messages()) == 2 },
|
||||||
"no messages",
|
"no messages",
|
||||||
)
|
)
|
||||||
|
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().Len(response.ActivityCenterNotifications(), 1)
|
s.Require().Len(response.ActivityCenterNotifications(), 1)
|
||||||
|
|
||||||
|
// verify the new message
|
||||||
var newMessage *common.Message
|
var newMessage *common.Message
|
||||||
for _, m := range response.Messages() {
|
for _, m := range response.Messages() {
|
||||||
if m.Text == "test message reply" {
|
if m.Text == "test message reply" {
|
||||||
newMessage = m
|
newMessage = m
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Require().NotNil(newMessage)
|
s.Require().NotNil(newMessage)
|
||||||
s.Require().Equal(protobuf.ChatMessage_IMAGE, newMessage.ContentType)
|
s.Require().Equal(protobuf.ChatMessage_IMAGE, newMessage.ContentType)
|
||||||
s.Require().NotEmpty(newMessage.ImageLocalURL)
|
s.Require().NotEmpty(newMessage.ImageLocalURL)
|
||||||
|
@ -331,57 +257,19 @@ func (s *MessengerActivityCenterMessageSuite) TestReplyWithImage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MessengerActivityCenterMessageSuite) TestMuteCommunityActivityCenterNotifications() {
|
func (s *MessengerActivityCenterMessageSuite) TestMuteCommunityActivityCenterNotifications() {
|
||||||
|
|
||||||
description := &requests.CreateCommunity{
|
|
||||||
Membership: protobuf.CommunityPermissions_NO_MEMBERSHIP,
|
|
||||||
Name: "status",
|
|
||||||
Color: "#ffffff",
|
|
||||||
Description: "status community description",
|
|
||||||
}
|
|
||||||
|
|
||||||
alice := s.m
|
alice := s.m
|
||||||
bob := s.newMessenger()
|
bob := s.newMessenger()
|
||||||
_, err := bob.Start()
|
_, err := bob.Start()
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
// Create an community chat
|
// Create a community
|
||||||
response, err := bob.CreateCommunity(description, true)
|
community, chat := s.createCommunity(bob)
|
||||||
s.Require().NoError(err)
|
|
||||||
s.Require().Len(response.Communities(), 1)
|
|
||||||
|
|
||||||
community := response.Communities()[0]
|
|
||||||
s.Require().NotNil(community)
|
s.Require().NotNil(community)
|
||||||
|
s.Require().NotNil(chat)
|
||||||
chat := CreateOneToOneChat(common.PubkeyToHex(&alice.identity.PublicKey), &alice.identity.PublicKey, bob.transport)
|
|
||||||
|
|
||||||
// bob sends a community message
|
|
||||||
inputMessage := common.NewMessage()
|
|
||||||
inputMessage.ChatId = chat.ID
|
|
||||||
inputMessage.Text = "some text"
|
|
||||||
inputMessage.CommunityID = community.IDString()
|
|
||||||
|
|
||||||
err = bob.SaveChat(chat)
|
|
||||||
s.Require().NoError(err)
|
|
||||||
_, err = bob.SendChatMessage(context.Background(), inputMessage)
|
|
||||||
s.Require().NoError(err)
|
|
||||||
|
|
||||||
_, err = WaitOnMessengerResponse(
|
|
||||||
alice,
|
|
||||||
func(r *MessengerResponse) bool { return len(r.Communities()) == 1 },
|
|
||||||
"no messages",
|
|
||||||
)
|
|
||||||
|
|
||||||
s.Require().NoError(err)
|
|
||||||
|
|
||||||
// Alice joins the community
|
// Alice joins the community
|
||||||
response, err = alice.JoinCommunity(context.Background(), community.ID(), true)
|
s.advertiseCommunityTo(community, bob, alice)
|
||||||
s.Require().NoError(err)
|
s.joinCommunity(community, bob, alice)
|
||||||
s.Require().NotNil(response)
|
|
||||||
s.Require().Len(response.Communities(), 1)
|
|
||||||
s.Require().True(response.Communities()[0].Joined())
|
|
||||||
s.Require().Len(response.Chats(), 1)
|
|
||||||
|
|
||||||
defaultCommunityChatID := response.Chats()[0].ID
|
|
||||||
|
|
||||||
// Bob mutes the community
|
// Bob mutes the community
|
||||||
time, err := bob.MuteAllCommunityChats(&requests.MuteCommunity{
|
time, err := bob.MuteAllCommunityChats(&requests.MuteCommunity{
|
||||||
|
@ -396,16 +284,14 @@ func (s *MessengerActivityCenterMessageSuite) TestMuteCommunityActivityCenterNot
|
||||||
s.Require().True(bobCommunity.Muted())
|
s.Require().True(bobCommunity.Muted())
|
||||||
|
|
||||||
// alice sends a community message
|
// alice sends a community message
|
||||||
inputMessage = common.NewMessage()
|
inputMessage := common.NewMessage()
|
||||||
inputMessage.ChatId = defaultCommunityChatID
|
inputMessage.ChatId = chat.ID
|
||||||
|
inputMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN
|
||||||
inputMessage.Text = "Good news, @" + common.EveryoneMentionTag + " !"
|
inputMessage.Text = "Good news, @" + common.EveryoneMentionTag + " !"
|
||||||
inputMessage.CommunityID = community.IDString()
|
|
||||||
|
|
||||||
response, err = alice.SendChatMessage(context.Background(), inputMessage)
|
response, err := alice.SendChatMessage(context.Background(), inputMessage)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
s.Require().Len(response.Messages(), 1)
|
s.Require().Len(response.Messages(), 1)
|
||||||
|
|
||||||
s.Require().True(response.Messages()[0].Mentioned)
|
s.Require().True(response.Messages()[0].Mentioned)
|
||||||
|
|
||||||
response, err = WaitOnMessengerResponse(
|
response, err = WaitOnMessengerResponse(
|
||||||
|
@ -414,10 +300,9 @@ func (s *MessengerActivityCenterMessageSuite) TestMuteCommunityActivityCenterNot
|
||||||
"no messages",
|
"no messages",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Bob still receives it, but no AC notif
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
s.Require().Len(response.Messages(), 1)
|
s.Require().Len(response.Messages(), 1)
|
||||||
|
|
||||||
s.Require().True(response.Messages()[0].Mentioned)
|
s.Require().True(response.Messages()[0].Mentioned)
|
||||||
s.Require().Len(response.ActivityCenterNotifications(), 0)
|
s.Require().Len(response.ActivityCenterNotifications(), 0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2625,31 +2625,27 @@ func (m *Messenger) matchChatEntity(chatEntity common.ChatEntity) (*Chat, error)
|
||||||
return nil, errors.New("not an community chat")
|
return nil, errors.New("not an community chat")
|
||||||
}
|
}
|
||||||
|
|
||||||
var emojiReaction bool
|
|
||||||
var pinMessage bool
|
|
||||||
// We allow emoji reactions from anyone
|
|
||||||
switch chatEntity.(type) {
|
|
||||||
case *EmojiReaction:
|
|
||||||
emojiReaction = true
|
|
||||||
case *common.PinMessage:
|
|
||||||
pinMessage = true
|
|
||||||
}
|
|
||||||
|
|
||||||
canPost, err := m.communitiesManager.CanPost(chatEntity.GetSigPubKey(), chat.CommunityID, chat.CommunityChatID(), chatEntity.GetGrant())
|
canPost, err := m.communitiesManager.CanPost(chatEntity.GetSigPubKey(), chat.CommunityID, chat.CommunityChatID(), chatEntity.GetGrant())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
community, err := m.communitiesManager.GetByIDString(chat.CommunityID)
|
if !canPost {
|
||||||
if err != nil {
|
return nil, errors.New("user can't post in community")
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hasPermission := community.IsPrivilegedMember(chatEntity.GetSigPubKey())
|
_, isPinMessage := chatEntity.(*common.PinMessage)
|
||||||
pinMessageAllowed := community.AllowsAllMembersToPinMessage()
|
if isPinMessage {
|
||||||
|
community, err := m.communitiesManager.GetByIDString(chat.CommunityID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
if (pinMessage && !hasPermission && !pinMessageAllowed) || (!emojiReaction && !canPost) {
|
hasPermission := community.IsPrivilegedMember(chatEntity.GetSigPubKey())
|
||||||
return nil, errors.New("user can't post")
|
pinMessageAllowed := community.AllowsAllMembersToPinMessage()
|
||||||
|
if !hasPermission && !pinMessageAllowed {
|
||||||
|
return nil, errors.New("user can't pin message")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return chat, nil
|
return chat, nil
|
||||||
|
|
Loading…
Reference in New Issue