diff --git a/changelog.d/3-bug-fixes/welcome-notifications b/changelog.d/3-bug-fixes/welcome-notifications new file mode 100644 index 0000000000..443c569402 --- /dev/null +++ b/changelog.d/3-bug-fixes/welcome-notifications @@ -0,0 +1 @@ +Fix bug where welcome notifications were generated for each client instead of for each user diff --git a/integration/integration.cabal b/integration/integration.cabal index eac2272713..3b832919be 100644 --- a/integration/integration.cabal +++ b/integration/integration.cabal @@ -128,6 +128,7 @@ library Test.MLS Test.MLS.KeyPackage Test.MLS.Message + Test.MLS.Notifications Test.MLS.One2One Test.MLS.SubConversation Test.MLS.Unreachable diff --git a/integration/test/Test/MLS/Notifications.hs b/integration/test/Test/MLS/Notifications.hs new file mode 100644 index 0000000000..ad0595a48c --- /dev/null +++ b/integration/test/Test/MLS/Notifications.hs @@ -0,0 +1,30 @@ +module Test.MLS.Notifications where + +import API.Gundeck +import MLS.Util +import Notifications +import SetupHelpers +import Testlib.Prelude + +testWelcomeNotification :: HasCallStack => App () +testWelcomeNotification = do + [alice, bob] <- createAndConnectUsers [OwnDomain, OtherDomain] + [alice1, alice2, bob1, bob2] <- traverse (createMLSClient def) [alice, alice, bob, bob] + traverse_ uploadNewKeyPackage [alice2, bob1, bob2] + + void $ createNewGroup alice1 + notif <- withWebSocket bob $ \ws -> do + void $ createAddCommit alice1 [alice, bob] >>= sendAndConsumeCommitBundle + awaitMatch isWelcomeNotif ws + + notifId <- notif %. "id" & asString + + for_ [bob1, bob2] $ \cid -> + getNotifications + bob + def + { since = Just notifId, + client = Just cid.client, + size = Just 10000 + } + >>= getJSON 200 diff --git a/services/galley/src/Galley/API/MLS/Welcome.hs b/services/galley/src/Galley/API/MLS/Welcome.hs index 5ee163ea4f..941d4867fd 100644 --- a/services/galley/src/Galley/API/MLS/Welcome.hs +++ b/services/galley/src/Galley/API/MLS/Welcome.hs @@ -26,13 +26,17 @@ import Data.Aeson qualified as A import Data.Domain import Data.Id import Data.Json.Util +import Data.List1 +import Data.Map qualified as Map import Data.Qualified import Data.Time import Galley.API.Push import Galley.Effects.ExternalAccess import Galley.Effects.FederatorAccess import Galley.Effects.GundeckAccess -import Imports +import Galley.Intra.Push.Internal +import Gundeck.Types.Push.V2 (RecipientClients (..)) +import Imports hiding (cs) import Network.Wai.Utilities.JSONResponse import Polysemy import Polysemy.Input @@ -87,9 +91,17 @@ sendLocalWelcomes :: Local [(UserId, ClientId)] -> Sem r () sendLocalWelcomes qcnv qusr con now welcome lclients = do + -- only create one notification per user + let rcpts = + map (\(u, cs) -> Recipient u (RecipientClientsSome (List1 cs))) + . Map.assocs + . foldr + (\(u, c) -> Map.insertWith (<>) u (pure c)) + mempty + $ tUnqualified lclients let e = Event qcnv Nothing qusr now $ EdMLSWelcome welcome.raw runMessagePush lclients (Just qcnv) $ - newMessagePush mempty con defMessageMetadata (tUnqualified lclients) e + newMessagePush mempty con defMessageMetadata rcpts e sendRemoteWelcomes :: ( Member FederatorAccess r,