Dont sent messages to user who have not joined
This commit is contained in:
parent
2d525f9503
commit
28e06daf6d
|
@ -115,6 +115,16 @@ func (c *Chat) MembersAsPublicKeys() ([]*ecdsa.PublicKey, error) {
|
|||
return stringSliceToPublicKeys(publicKeys, true)
|
||||
}
|
||||
|
||||
func (c *Chat) JoinedMembersAsPublicKeys() ([]*ecdsa.PublicKey, error) {
|
||||
var publicKeys []string
|
||||
for _, item := range c.Members {
|
||||
if item.Joined {
|
||||
publicKeys = append(publicKeys, item.ID)
|
||||
}
|
||||
}
|
||||
return stringSliceToPublicKeys(publicKeys, true)
|
||||
}
|
||||
|
||||
func (c *Chat) HasMember(memberID string) bool {
|
||||
for _, member := range c.Members {
|
||||
if memberID == member.ID {
|
||||
|
|
|
@ -1663,11 +1663,20 @@ func (m *Messenger) dispatchMessage(ctx context.Context, spec common.RawMessage)
|
|||
case ChatTypePrivateGroupChat:
|
||||
logger.Debug("sending group message", zap.String("chatName", chat.Name))
|
||||
if spec.Recipients == nil {
|
||||
// Chat messages are only dispatched to users who joined
|
||||
if spec.MessageType == protobuf.ApplicationMetadataMessage_CHAT_MESSAGE {
|
||||
spec.Recipients, err = chat.JoinedMembersAsPublicKeys()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
} else {
|
||||
spec.Recipients, err = chat.MembersAsPublicKeys()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
hasPairedDevices := m.hasPairedDevices()
|
||||
|
||||
if !hasPairedDevices {
|
||||
|
@ -3519,7 +3528,7 @@ func (m *Messenger) pushNotificationOptions() *pushnotificationclient.Registrati
|
|||
var publicChatIDs []string
|
||||
|
||||
for _, contact := range m.allContacts {
|
||||
if contact.IsAdded() {
|
||||
if contact.IsAdded() && !contact.IsBlocked() {
|
||||
pk, err := contact.PublicKey()
|
||||
if err != nil {
|
||||
m.logger.Warn("could not parse contact public key")
|
||||
|
|
|
@ -641,168 +641,6 @@ func (s *MessengerPushNotificationSuite) TestReceivePushNotificationRetries() {
|
|||
s.Require().NoError(server.Shutdown())
|
||||
}
|
||||
|
||||
// Here bob acts as his own server
|
||||
func (s *MessengerPushNotificationSuite) TestActAsYourOwnPushNotificationServer() {
|
||||
bob1 := s.m
|
||||
server := s.newPushNotificationServer(s.shh, s.m.identity)
|
||||
bob2 := server
|
||||
alice := s.newMessenger(s.shh)
|
||||
// start alice and enable sending push notifications
|
||||
s.Require().NoError(alice.Start())
|
||||
s.Require().NoError(alice.EnableSendingPushNotifications())
|
||||
bobInstallationIDs := []string{bob1.installationID, bob2.installationID}
|
||||
|
||||
// Register bob1
|
||||
err := bob1.AddPushNotificationsServer(context.Background(), &server.identity.PublicKey, pushnotificationclient.ServerTypeCustom)
|
||||
s.Require().NoError(err)
|
||||
|
||||
err = bob1.RegisterForPushNotifications(context.Background(), bob1DeviceToken, testAPNTopic, protobuf.PushNotificationRegistration_APN_TOKEN)
|
||||
|
||||
// Pull servers and check we registered
|
||||
err = tt.RetryWithBackOff(func() error {
|
||||
_, err = server.RetrieveAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = bob1.RetrieveAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
registered, err := bob1.RegisteredForPushNotifications()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !registered {
|
||||
return errors.New("not registered")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
// Make sure we receive it
|
||||
s.Require().NoError(err)
|
||||
bob1Servers, err := bob1.GetPushNotificationsServers()
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Register bob2
|
||||
err = bob2.AddPushNotificationsServer(context.Background(), &server.identity.PublicKey, pushnotificationclient.ServerTypeCustom)
|
||||
s.Require().NoError(err)
|
||||
|
||||
err = bob2.RegisterForPushNotifications(context.Background(), bob2DeviceToken, testAPNTopic, protobuf.PushNotificationRegistration_APN_TOKEN)
|
||||
s.Require().NoError(err)
|
||||
|
||||
err = tt.RetryWithBackOff(func() error {
|
||||
_, err = server.RetrieveAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = bob2.RetrieveAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
registered, err := bob2.RegisteredForPushNotifications()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !registered {
|
||||
return errors.New("not registered")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
// Make sure we receive it
|
||||
s.Require().NoError(err)
|
||||
bob2Servers, err := bob2.GetPushNotificationsServers()
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Create one to one chat & send message
|
||||
pkString := hex.EncodeToString(crypto.FromECDSAPub(&s.m.identity.PublicKey))
|
||||
chat := CreateOneToOneChat(pkString, &s.m.identity.PublicKey, alice.transport)
|
||||
s.Require().NoError(alice.SaveChat(&chat))
|
||||
inputMessage := buildTestMessage(chat)
|
||||
response, err := alice.SendChatMessage(context.Background(), inputMessage)
|
||||
s.Require().NoError(err)
|
||||
messageIDString := response.Messages[0].ID
|
||||
messageID, err := hex.DecodeString(messageIDString[2:])
|
||||
s.Require().NoError(err)
|
||||
|
||||
var info []*pushnotificationclient.PushNotificationInfo
|
||||
err = tt.RetryWithBackOff(func() error {
|
||||
_, err = server.RetrieveAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = alice.RetrieveAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
info, err = alice.pushNotificationClient.GetPushNotificationInfo(&bob1.identity.PublicKey, bobInstallationIDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Check we have replies for both bob1 and bob2
|
||||
if len(info) != 2 {
|
||||
return errors.New("info not fetched")
|
||||
}
|
||||
return nil
|
||||
|
||||
})
|
||||
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Check we have replies for both bob1 and bob2
|
||||
var bob1Info, bob2Info *pushnotificationclient.PushNotificationInfo
|
||||
|
||||
if info[0].AccessToken == bob1Servers[0].AccessToken {
|
||||
bob1Info = info[0]
|
||||
bob2Info = info[1]
|
||||
} else {
|
||||
bob2Info = info[0]
|
||||
bob1Info = info[1]
|
||||
}
|
||||
|
||||
s.Require().NotNil(bob1Info)
|
||||
s.Require().Equal(bob1.installationID, bob1Info.InstallationID)
|
||||
s.Require().Equal(bob1Servers[0].AccessToken, bob1Info.AccessToken)
|
||||
s.Require().Equal(&bob1.identity.PublicKey, bob1Info.PublicKey)
|
||||
|
||||
s.Require().NotNil(bob2Info)
|
||||
s.Require().Equal(bob2.installationID, bob2Info.InstallationID)
|
||||
s.Require().Equal(bob2Servers[0].AccessToken, bob2Info.AccessToken)
|
||||
s.Require().Equal(&bob2.identity.PublicKey, bob2Info.PublicKey)
|
||||
|
||||
retrievedNotificationInfo, err := alice.pushNotificationClient.GetPushNotificationInfo(&bob1.identity.PublicKey, bobInstallationIDs)
|
||||
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(retrievedNotificationInfo)
|
||||
s.Require().Len(retrievedNotificationInfo, 2)
|
||||
|
||||
var sentNotification *pushnotificationclient.SentNotification
|
||||
err = tt.RetryWithBackOff(func() error {
|
||||
_, err = server.RetrieveAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = alice.RetrieveAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sentNotification, err = alice.pushNotificationClient.GetSentNotification(common.HashPublicKey(&bob1.identity.PublicKey), bob1.installationID, messageID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if sentNotification == nil {
|
||||
return errors.New("sent notification not found")
|
||||
}
|
||||
if !sentNotification.Success {
|
||||
return errors.New("sent notification not successul")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
s.Require().NoError(bob2.Shutdown())
|
||||
s.Require().NoError(alice.Shutdown())
|
||||
}
|
||||
|
||||
func (s *MessengerPushNotificationSuite) TestContactCode() {
|
||||
|
||||
bob1 := s.m
|
||||
|
|
|
@ -363,12 +363,14 @@ func (s *Server) buildPushNotificationRequestResponse(request *protobuf.PushNoti
|
|||
// collect successful requests & registrations
|
||||
var requestAndRegistrations []*RequestAndRegistration
|
||||
|
||||
// TODO: this logic needs to be extracted and tested
|
||||
for _, pn := range request.Requests {
|
||||
registration, err := s.persistence.GetPushNotificationRegistrationByPublicKeyAndInstallationID(pn.PublicKey, pn.InstallationId)
|
||||
report := &protobuf.PushNotificationReport{
|
||||
PublicKey: pn.PublicKey,
|
||||
InstallationId: pn.InstallationId,
|
||||
}
|
||||
s.config.Logger.Info("registration and request", zap.Any("registration", registration), zap.Any("request", pn))
|
||||
|
||||
if pn.Type == protobuf.PushNotification_UNKNOWN_PUSH_NOTIFICATION_TYPE {
|
||||
s.config.Logger.Warn("unhandled type")
|
||||
|
@ -382,14 +384,17 @@ func (s *Server) buildPushNotificationRequestResponse(request *protobuf.PushNoti
|
|||
s.config.Logger.Warn("empty registration")
|
||||
report.Error = protobuf.PushNotificationReport_NOT_REGISTERED
|
||||
} else if registration.AccessToken != pn.AccessToken {
|
||||
s.config.Logger.Debug("invalid token")
|
||||
report.Error = protobuf.PushNotificationReport_WRONG_TOKEN
|
||||
} else if s.contains(registration.BlockedChatList, pn.ChatId) || !s.isValidMentionNotification(pn, registration) {
|
||||
} else if s.contains(registration.BlockedChatList, pn.ChatId) || (s.isMentionNotification(pn) && !s.isValidMentionNotification(pn, registration)) {
|
||||
// We report as successful but don't send the notification
|
||||
// for privacy reasons, as otherwise we would disclose that
|
||||
// the sending client has been blocked or that the registering
|
||||
// client has not joined a given public chat
|
||||
report.Success = true
|
||||
s.config.Logger.Debug("invalid token", zap.Bool("blocked", s.contains(registration.BlockedChatList, pn.ChatId)), zap.Bool("mention", (s.isMentionNotification(pn) && !s.isValidMentionNotification(pn, registration))))
|
||||
} else {
|
||||
s.config.Logger.Debug("sending push notification")
|
||||
// For now we just assume that the notification will be successful
|
||||
requestAndRegistrations = append(requestAndRegistrations, &RequestAndRegistration{
|
||||
Request: pn,
|
||||
|
@ -474,6 +479,10 @@ func (s *Server) buildPushNotificationRegistrationResponse(publicKey *ecdsa.Publ
|
|||
return response
|
||||
}
|
||||
|
||||
func (s *Server) isValidMentionNotification(pn *protobuf.PushNotification, registration *protobuf.PushNotificationRegistration) bool {
|
||||
return !registration.BlockMentions && pn.Type == protobuf.PushNotification_MENTION && s.contains(registration.AllowedMentionsChatList, pn.ChatId)
|
||||
func (s *Server) isMentionNotification(pn *protobuf.PushNotification) bool {
|
||||
return pn.Type == protobuf.PushNotification_MENTION
|
||||
}
|
||||
|
||||
func (s *Server) isValidMentionNotification(pn *protobuf.PushNotification, registration *protobuf.PushNotificationRegistration) bool {
|
||||
return s.isMentionNotification(pn) && !registration.BlockMentions && s.contains(registration.AllowedMentionsChatList, pn.ChatId)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue