feat(search)_: filter out messages from non-viewable channels (#5161)
Fixes https://github.com/status-im/status-desktop/issues/14586
This commit is contained in:
parent
574450289c
commit
ae08ba6ad1
|
@ -514,6 +514,10 @@ func CreateCommunityChat(orgID, chatID string, orgChat *protobuf.CommunityChat,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Chat) CommunityChannelID() string {
|
||||||
|
return strings.TrimPrefix(c.ID, c.CommunityID)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Chat) DeepLink() string {
|
func (c *Chat) DeepLink() string {
|
||||||
if c.OneToOne() {
|
if c.OneToOne() {
|
||||||
return "status-app://p/" + c.ID
|
return "status-app://p/" + c.ID
|
||||||
|
@ -523,7 +527,7 @@ func (c *Chat) DeepLink() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.CommunityChat() {
|
if c.CommunityChat() {
|
||||||
communityChannelID := strings.TrimPrefix(c.ID, c.CommunityID)
|
communityChannelID := c.CommunityChannelID()
|
||||||
pubkey, err := types.DecodeHex(c.CommunityID)
|
pubkey, err := types.DecodeHex(c.CommunityID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
|
|
|
@ -1246,6 +1246,133 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) TestViewChannelPermissions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *MessengerCommunitiesTokenPermissionsSuite) TestSearchMessageinPermissionedChannel() {
|
||||||
|
community, chat := s.createCommunity()
|
||||||
|
|
||||||
|
newChat := protobuf.CommunityChat{
|
||||||
|
Permissions: &protobuf.CommunityPermissions{
|
||||||
|
EnsOnly: false,
|
||||||
|
Private: false,
|
||||||
|
Access: 1,
|
||||||
|
},
|
||||||
|
Identity: &protobuf.ChatIdentity{
|
||||||
|
DisplayName: "new-channel",
|
||||||
|
Description: "description",
|
||||||
|
Emoji: "",
|
||||||
|
Color: "",
|
||||||
|
},
|
||||||
|
CategoryId: "",
|
||||||
|
ViewersCanPostReactions: true,
|
||||||
|
HideIfPermissionsNotMet: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := s.owner.CreateCommunityChat(community.ID(), &newChat)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().NotNil(response)
|
||||||
|
newChatID := response.Chats()[0].ID
|
||||||
|
|
||||||
|
// bob joins the community
|
||||||
|
s.advertiseCommunityTo(community, s.bob)
|
||||||
|
s.joinCommunity(community, s.bob, bobPassword, []string{})
|
||||||
|
|
||||||
|
// send message to the original channel
|
||||||
|
msg := s.sendChatMessage(s.owner, chat.ID, "hello on open community")
|
||||||
|
|
||||||
|
// bob can read the message
|
||||||
|
response, err = WaitOnMessengerResponse(
|
||||||
|
s.bob,
|
||||||
|
func(r *MessengerResponse) bool {
|
||||||
|
_, ok := r.messages[msg.ID]
|
||||||
|
return ok
|
||||||
|
},
|
||||||
|
"no messages",
|
||||||
|
)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().Len(response.Messages(), 1)
|
||||||
|
s.Require().Equal(msg.Text, response.Messages()[0].Text)
|
||||||
|
|
||||||
|
// send message to the new channel
|
||||||
|
msgText := "hello on new chat"
|
||||||
|
msg = s.sendChatMessage(s.owner, newChatID, msgText)
|
||||||
|
|
||||||
|
// bob can read the message
|
||||||
|
response, err = WaitOnMessengerResponse(
|
||||||
|
s.bob,
|
||||||
|
func(r *MessengerResponse) bool {
|
||||||
|
_, ok := r.messages[msg.ID]
|
||||||
|
return ok
|
||||||
|
},
|
||||||
|
"no messages",
|
||||||
|
)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().Len(response.Messages(), 1)
|
||||||
|
s.Require().Equal(msg.Text, response.Messages()[0].Text)
|
||||||
|
|
||||||
|
waitOnBobToBeKickedFromChannel := waitOnCommunitiesEvent(s.owner, func(sub *communities.Subscription) bool {
|
||||||
|
channel, ok := sub.Community.Chats()[chat.CommunityChatID()]
|
||||||
|
return ok && len(channel.Members) == 1
|
||||||
|
})
|
||||||
|
waitOnChannelToBeRekeyedOnceBobIsKicked := s.waitOnKeyDistribution(func(sub *CommunityAndKeyActions) bool {
|
||||||
|
action, ok := sub.keyActions.ChannelKeysActions[chat.CommunityChatID()]
|
||||||
|
return ok && (action.ActionType == communities.EncryptionKeyRekey || action.ActionType == communities.EncryptionKeyAdd)
|
||||||
|
})
|
||||||
|
|
||||||
|
// setup view channel permission
|
||||||
|
channelPermissionRequest := requests.CreateCommunityTokenPermission{
|
||||||
|
CommunityID: community.ID(),
|
||||||
|
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
|
||||||
|
TokenCriteria: []*protobuf.TokenCriteria{
|
||||||
|
&protobuf.TokenCriteria{
|
||||||
|
Type: protobuf.CommunityTokenType_ERC20,
|
||||||
|
ContractAddresses: map[uint64]string{testChainID1: "0x123"},
|
||||||
|
Symbol: "TEST",
|
||||||
|
AmountInWei: "100000000000000000000",
|
||||||
|
Decimals: uint64(18),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ChatIds: []string{chat.ID},
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err = s.owner.CreateCommunityTokenPermission(&channelPermissionRequest)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().Len(response.Communities(), 1)
|
||||||
|
s.Require().True(s.owner.communitiesManager.IsChannelEncrypted(community.IDString(), chat.ID))
|
||||||
|
|
||||||
|
err = <-waitOnBobToBeKickedFromChannel
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
err = <-waitOnChannelToBeRekeyedOnceBobIsKicked
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
// bob receives community changes
|
||||||
|
// channel members should be empty,
|
||||||
|
// this info is available only to channel members
|
||||||
|
_, err = WaitOnMessengerResponse(
|
||||||
|
s.bob,
|
||||||
|
func(r *MessengerResponse) bool {
|
||||||
|
c, err := s.bob.GetCommunityByID(community.ID())
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if c == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
channel := c.Chats()[chat.CommunityChatID()]
|
||||||
|
return channel != nil && len(channel.Members) == 0
|
||||||
|
},
|
||||||
|
"no community that satisfies criteria",
|
||||||
|
)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
// Bob searches for "hello" but only finds it in the new channel
|
||||||
|
communities := make([]string, 1)
|
||||||
|
communities[0] = community.IDString()
|
||||||
|
messages, err := s.bob.AllMessagesFromChatsAndCommunitiesWhichMatchTerm(communities, make([]string, 0), "hello", false)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().Len(messages, 1)
|
||||||
|
s.Require().Equal(msgText, messages[0].Text)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *MessengerCommunitiesTokenPermissionsSuite) TestMemberRoleGetUpdatedWhenChangingPermissions() {
|
func (s *MessengerCommunitiesTokenPermissionsSuite) TestMemberRoleGetUpdatedWhenChangingPermissions() {
|
||||||
community, chat := s.createCommunity()
|
community, chat := s.createCommunity()
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,11 @@ const (
|
||||||
privateChat ChatContext = "private-chat"
|
privateChat ChatContext = "private-chat"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// errors
|
||||||
|
var (
|
||||||
|
ErrChatNotFoundError = errors.New("Chat not found")
|
||||||
|
)
|
||||||
|
|
||||||
var communityAdvertiseIntervalSecond int64 = 60 * 60
|
var communityAdvertiseIntervalSecond int64 = 60 * 60
|
||||||
|
|
||||||
// messageCacheIntervalMs is how long we should keep processed messages in the cache, in ms
|
// messageCacheIntervalMs is how long we should keep processed messages in the cache, in ms
|
||||||
|
@ -2382,7 +2387,7 @@ func (m *Messenger) sendChatMessage(ctx context.Context, message *common.Message
|
||||||
// A valid added chat is required.
|
// A valid added chat is required.
|
||||||
chat, ok := m.allChats.Load(message.ChatId)
|
chat, ok := m.allChats.Load(message.ChatId)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("Chat not found")
|
return nil, ErrChatNotFoundError
|
||||||
}
|
}
|
||||||
|
|
||||||
err = m.handleStandaloneChatIdentity(chat)
|
err = m.handleStandaloneChatIdentity(chat)
|
||||||
|
@ -4343,11 +4348,72 @@ func (m *Messenger) AllMessageByChatIDWhichMatchTerm(chatID string, searchTerm s
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.persistence.AllMessageByChatIDWhichMatchTerm(chatID, searchTerm, caseSensitive)
|
messages, err := m.persistence.AllMessageByChatIDWhichMatchTerm(chatID, searchTerm, caseSensitive)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.filterOutHiddenChatMessages(messages)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Messenger) AllMessagesFromChatsAndCommunitiesWhichMatchTerm(communityIds []string, chatIds []string, searchTerm string, caseSensitive bool) ([]*common.Message, error) {
|
func (m *Messenger) AllMessagesFromChatsAndCommunitiesWhichMatchTerm(communityIds []string, chatIds []string, searchTerm string, caseSensitive bool) ([]*common.Message, error) {
|
||||||
return m.persistence.AllMessagesFromChatsAndCommunitiesWhichMatchTerm(communityIds, chatIds, searchTerm, caseSensitive)
|
messages, err := m.persistence.AllMessagesFromChatsAndCommunitiesWhichMatchTerm(communityIds, chatIds, searchTerm, caseSensitive)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.filterOutHiddenChatMessages(messages)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Messenger) filterOutHiddenChatMessages(messages []*common.Message) ([]*common.Message, error) {
|
||||||
|
communitiesCache := make(map[string]*communities.Community)
|
||||||
|
chatVisibilityCache := make(map[string]bool)
|
||||||
|
var filteredMessages []*common.Message
|
||||||
|
|
||||||
|
for _, message := range messages {
|
||||||
|
chatVisible, ok := chatVisibilityCache[message.ChatId]
|
||||||
|
if ok && chatVisible {
|
||||||
|
filteredMessages = append(filteredMessages, message)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
chat, ok := m.allChats.Load(message.ChatId)
|
||||||
|
if !ok {
|
||||||
|
return nil, ErrChatNotFoundError
|
||||||
|
}
|
||||||
|
|
||||||
|
if chat.CommunityID == "" {
|
||||||
|
filteredMessages = append(filteredMessages, message)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
community, ok := communitiesCache[chat.CommunityID]
|
||||||
|
if !ok {
|
||||||
|
communityID, err := hexutil.Decode(chat.CommunityID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
comm, err := m.communitiesManager.GetByID(communityID)
|
||||||
|
if err != nil {
|
||||||
|
if err == communities.ErrOrgNotFound {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
communitiesCache[chat.CommunityID] = comm
|
||||||
|
community = comm
|
||||||
|
}
|
||||||
|
|
||||||
|
canView := community.CanView(&m.identity.PublicKey, chat.CommunityChannelID())
|
||||||
|
chatVisibilityCache[chat.ID] = canView
|
||||||
|
|
||||||
|
if canView {
|
||||||
|
filteredMessages = append(filteredMessages, message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filteredMessages, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Messenger) SaveMessages(messages []*common.Message) error {
|
func (m *Messenger) SaveMessages(messages []*common.Message) error {
|
||||||
|
@ -4522,7 +4588,7 @@ func (m *Messenger) syncChatMessagesRead(ctx context.Context, chatID string, clo
|
||||||
func (m *Messenger) markAllRead(chatID string, clock uint64, shouldBeSynced bool) error {
|
func (m *Messenger) markAllRead(chatID string, clock uint64, shouldBeSynced bool) error {
|
||||||
chat, ok := m.allChats.Load(chatID)
|
chat, ok := m.allChats.Load(chatID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.New("chat not found")
|
return ErrChatNotFoundError
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _, err := m.persistence.MarkAllRead(chatID, clock)
|
_, _, err := m.persistence.MarkAllRead(chatID, clock)
|
||||||
|
@ -4566,7 +4632,7 @@ func (m *Messenger) MarkAllRead(ctx context.Context, chatID string) (*MessengerR
|
||||||
if clock == 0 {
|
if clock == 0 {
|
||||||
chat, ok := m.allChats.Load(chatID)
|
chat, ok := m.allChats.Load(chatID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("chat not found")
|
return nil, ErrChatNotFoundError
|
||||||
}
|
}
|
||||||
clock, _ = chat.NextClockAndTimestamp(m.getTimesource())
|
clock, _ = chat.NextClockAndTimestamp(m.getTimesource())
|
||||||
}
|
}
|
||||||
|
@ -4709,7 +4775,7 @@ func (m *Messenger) muteChat(chat *Chat, contact *Contact, mutedTill time.Time)
|
||||||
func (m *Messenger) UnmuteChat(chatID string) error {
|
func (m *Messenger) UnmuteChat(chatID string) error {
|
||||||
chat, ok := m.allChats.Load(chatID)
|
chat, ok := m.allChats.Load(chatID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.New("chat not found")
|
return ErrChatNotFoundError
|
||||||
}
|
}
|
||||||
|
|
||||||
var contact *Contact
|
var contact *Contact
|
||||||
|
@ -4772,7 +4838,7 @@ func (m *Messenger) RequestTransaction(ctx context.Context, chatID, value, contr
|
||||||
// A valid added chat is required.
|
// A valid added chat is required.
|
||||||
chat, ok := m.allChats.Load(chatID)
|
chat, ok := m.allChats.Load(chatID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("Chat not found")
|
return nil, ErrChatNotFoundError
|
||||||
}
|
}
|
||||||
if chat.ChatType != ChatTypeOneToOne {
|
if chat.ChatType != ChatTypeOneToOne {
|
||||||
return nil, errors.New("Need to be a one-to-one chat")
|
return nil, errors.New("Need to be a one-to-one chat")
|
||||||
|
@ -4850,7 +4916,7 @@ func (m *Messenger) RequestAddressForTransaction(ctx context.Context, chatID, fr
|
||||||
// A valid added chat is required.
|
// A valid added chat is required.
|
||||||
chat, ok := m.allChats.Load(chatID)
|
chat, ok := m.allChats.Load(chatID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("Chat not found")
|
return nil, ErrChatNotFoundError
|
||||||
}
|
}
|
||||||
if chat.ChatType != ChatTypeOneToOne {
|
if chat.ChatType != ChatTypeOneToOne {
|
||||||
return nil, errors.New("Need to be a one-to-one chat")
|
return nil, errors.New("Need to be a one-to-one chat")
|
||||||
|
@ -4939,7 +5005,7 @@ func (m *Messenger) AcceptRequestAddressForTransaction(ctx context.Context, mess
|
||||||
// A valid added chat is required.
|
// A valid added chat is required.
|
||||||
chat, ok := m.allChats.Load(chatID)
|
chat, ok := m.allChats.Load(chatID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("Chat not found")
|
return nil, ErrChatNotFoundError
|
||||||
}
|
}
|
||||||
if chat.ChatType != ChatTypeOneToOne {
|
if chat.ChatType != ChatTypeOneToOne {
|
||||||
return nil, errors.New("Need to be a one-to-one chat")
|
return nil, errors.New("Need to be a one-to-one chat")
|
||||||
|
@ -5035,7 +5101,7 @@ func (m *Messenger) DeclineRequestTransaction(ctx context.Context, messageID str
|
||||||
// A valid added chat is required.
|
// A valid added chat is required.
|
||||||
chat, ok := m.allChats.Load(chatID)
|
chat, ok := m.allChats.Load(chatID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("Chat not found")
|
return nil, ErrChatNotFoundError
|
||||||
}
|
}
|
||||||
if chat.ChatType != ChatTypeOneToOne {
|
if chat.ChatType != ChatTypeOneToOne {
|
||||||
return nil, errors.New("Need to be a one-to-one chat")
|
return nil, errors.New("Need to be a one-to-one chat")
|
||||||
|
@ -5118,7 +5184,7 @@ func (m *Messenger) DeclineRequestAddressForTransaction(ctx context.Context, mes
|
||||||
// A valid added chat is required.
|
// A valid added chat is required.
|
||||||
chat, ok := m.allChats.Load(chatID)
|
chat, ok := m.allChats.Load(chatID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("Chat not found")
|
return nil, ErrChatNotFoundError
|
||||||
}
|
}
|
||||||
if chat.ChatType != ChatTypeOneToOne {
|
if chat.ChatType != ChatTypeOneToOne {
|
||||||
return nil, errors.New("Need to be a one-to-one chat")
|
return nil, errors.New("Need to be a one-to-one chat")
|
||||||
|
@ -5201,7 +5267,7 @@ func (m *Messenger) AcceptRequestTransaction(ctx context.Context, transactionHas
|
||||||
// A valid added chat is required.
|
// A valid added chat is required.
|
||||||
chat, ok := m.allChats.Load(chatID)
|
chat, ok := m.allChats.Load(chatID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("Chat not found")
|
return nil, ErrChatNotFoundError
|
||||||
}
|
}
|
||||||
if chat.ChatType != ChatTypeOneToOne {
|
if chat.ChatType != ChatTypeOneToOne {
|
||||||
return nil, errors.New("Need to be a one-to-one chat")
|
return nil, errors.New("Need to be a one-to-one chat")
|
||||||
|
@ -5290,7 +5356,7 @@ func (m *Messenger) SendTransaction(ctx context.Context, chatID, value, contract
|
||||||
// A valid added chat is required.
|
// A valid added chat is required.
|
||||||
chat, ok := m.allChats.Load(chatID)
|
chat, ok := m.allChats.Load(chatID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("Chat not found")
|
return nil, ErrChatNotFoundError
|
||||||
}
|
}
|
||||||
if chat.ChatType != ChatTypeOneToOne {
|
if chat.ChatType != ChatTypeOneToOne {
|
||||||
return nil, errors.New("Need to be a one-to-one chat")
|
return nil, errors.New("Need to be a one-to-one chat")
|
||||||
|
|
Loading…
Reference in New Issue