Skip to content

Commit 20c655b

Browse files
committed
Implement a test for the server side of POST /federation/mls-welcome
1 parent 03d485a commit 20c655b

File tree

2 files changed

+62
-37
lines changed

2 files changed

+62
-37
lines changed

services/galley/test/integration/API/Federation.hs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
-- You should have received a copy of the GNU Affero General Public License along
1616
-- with this program. If not, see <https://www.gnu.org/licenses/>.
1717
{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
18+
{-# LANGUAGE RecordWildCards #-}
1819

1920
-- This file is part of the Wire Server implementation.
2021
--
@@ -35,6 +36,7 @@
3536

3637
module API.Federation where
3738

39+
import API.MLS.Util
3840
import API.Util
3941
import Bilge
4042
import Bilge.Assert
@@ -45,8 +47,8 @@ import qualified Data.Aeson as A
4547
import Data.ByteString.Conversion (toByteString')
4648
import Data.Domain
4749
import Data.Id (ConvId, Id (..), UserId, newClientId, randomId)
48-
import Data.Json.Util (Base64ByteString (..), toBase64Text)
49-
import Data.List.NonEmpty (NonEmpty (..))
50+
import Data.Json.Util hiding ((#))
51+
import Data.List.NonEmpty (NonEmpty(..), head)
5052
import Data.List1
5153
import qualified Data.List1 as List1
5254
import qualified Data.Map as Map
@@ -81,6 +83,7 @@ import Wire.API.Internal.Notification
8183
import Wire.API.Message (ClientMismatchStrategy (..), MessageSendingStatus (mssDeletedClients, mssFailedToSend, mssRedundantClients), mkQualifiedOtrPayload, mssMissingClients)
8284
import Wire.API.User.Client (PubClient (..))
8385
import Wire.API.User.Profile
86+
import Data.Default
8487

8588
tests :: IO TestSetup -> TestTree
8689
tests s =
@@ -106,7 +109,8 @@ tests s =
106109
test s "POST /federation/on-message-sent : Receive a message from another backend" onMessageSent,
107110
test s "POST /federation/send-message : Post a message sent from another backend" sendMessage,
108111
test s "POST /federation/on-user-deleted-conversations : Remove deleted remote user from local conversations" onUserDeleted,
109-
test s "POST /federation/update-conversation : Update local conversation by a remote admin " updateConversationByRemoteAdmin
112+
test s "POST /federation/update-conversation : Update local conversation by a remote admin " updateConversationByRemoteAdmin,
113+
test s "POST /federation/mls-welcome : Post an MLS welcome message received from another backend" sendMLSWelcome
110114
]
111115

112116
getConversationsAllFound :: TestM ()
@@ -1158,6 +1162,31 @@ updateConversationByRemoteAdmin = do
11581162
let convUpdate :: ConversationUpdate = fromRight (error $ "Could not parse ConversationUpdate from " <> show (frBody rpc)) $ A.eitherDecode (frBody rpc)
11591163
pure (rpc, convUpdate)
11601164

1165+
sendMLSWelcome :: TestM ()
1166+
sendMLSWelcome = do
1167+
let aliceDomain = Domain "a.far-away.example.com"
1168+
-- Alice is from the originating domain and Bob is local, i.e., on the receiving domain
1169+
MessagingSetup {..} <- aliceInvitesBob 1 def { creatorOrigin = RemoteCreator aliceDomain }
1170+
let bob = users !! 0
1171+
bobClient = snd . Data.List.NonEmpty.head . pClients $ bob
1172+
1173+
fedGalleyClient <- view tsFedGalleyClient
1174+
cannon <- view tsCannon
1175+
1176+
WS.bracketR cannon (qUnqualified (pUserId bob)) $ \wsB -> do
1177+
-- send welcome message
1178+
EmptyResponse <-
1179+
runFedClient @"mls-welcome" fedGalleyClient aliceDomain $
1180+
MLSWelcomeRequest
1181+
(toBase64ByteString welcome)
1182+
[MLSWelcomeRecipient (qUnqualified . pUserId $ bob, bobClient)]
1183+
1184+
-- check that the corresponding event is received
1185+
void . liftIO $
1186+
WS.assertMatch (5 # WS.Second) wsB $
1187+
wsAssertMLSWelcome (pUserId bob) welcome
1188+
1189+
11611190
getConvAction :: Sing tag -> SomeConversationAction -> Maybe (ConversationAction tag)
11621191
getConvAction tquery (SomeConversationAction tag action) =
11631192
case (tag, tquery) of

services/galley/test/integration/API/MLS/Util.hs

Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,17 @@ data CreateClients = CreateWithoutKey | CreateWithKey | DontCreateClients
5858
data CreateConv = CreateConv | CreateProteusConv | DontCreateConv
5959
deriving (Eq)
6060

61+
data CreatorOrigin = LocalCreator | RemoteCreator Domain
62+
6163
createNewConv :: CreateConv -> Maybe NewConv
6264
createNewConv CreateConv = Just defNewMLSConv
6365
createNewConv CreateProteusConv = Just defNewProteusConv
6466
createNewConv DontCreateConv = Nothing
6567

68+
6669
data SetupOptions = SetupOptions
6770
{ createClients :: CreateClients,
71+
creatorOrigin :: CreatorOrigin,
6872
createConv :: CreateConv,
6973
makeConnections :: Bool
7074
}
@@ -73,6 +77,7 @@ instance Default SetupOptions where
7377
def =
7478
SetupOptions
7579
{ createClients = CreateWithKey,
80+
creatorOrigin = LocalCreator,
7681
createConv = DontCreateConv,
7782
makeConnections = True
7883
}
@@ -152,41 +157,31 @@ setupParticipants ::
152157
[Int] ->
153158
State.StateT [LastPrekey] TestM (Participant, [Participant])
154159
setupParticipants tmp SetupOptions {..} ns = do
155-
creator <- lift randomQualifiedUser >>= setupParticipant tmp DontCreateClients 1
160+
creator <- lift (creatorUserOrId creatorOrigin) >>= setupParticipant tmp DontCreateClients 1
156161
others <- for ns $ \n ->
157162
lift randomQualifiedUser >>= setupParticipant tmp createClients n
158-
lift . when makeConnections $
159-
traverse_
160-
( connectUsers (qUnqualified (pUserId creator))
161-
. List1
162-
. fmap (qUnqualified . pUserId)
163-
)
164-
(nonEmpty others)
163+
lift . when makeConnections $ case creatorOrigin of
164+
LocalCreator ->
165+
traverse_
166+
( connectUsers (qUnqualified (pUserId creator))
167+
. List1
168+
. fmap (qUnqualified . pUserId)
169+
)
170+
(nonEmpty others)
171+
RemoteCreator _ ->
172+
traverse_
173+
( \u ->
174+
connectWithRemoteUser
175+
(qUnqualified . pUserId $ u)
176+
(pUserId creator)
177+
)
178+
others
165179
pure (creator, others)
166-
167-
-- | Just like 'setupParticipants', this function sets up MLS participants. The
168-
-- assumption is that the creator is remote to the local backend, and the rest
169-
-- of participants are local.
170-
setupParticipantsOnServer ::
171-
HasCallStack =>
172-
FilePath ->
173-
Domain ->
174-
SetupOptions ->
175-
[Int] ->
176-
State.StateT [LastPrekey] TestM (Participant, [Participant])
177-
setupParticipantsOnServer tmp originDomain SetupOptions {..} ns = do
178-
creator <- lift (randomQualifiedId originDomain) >>= setupParticipant tmp DontCreateClients 1
179-
locals <- for ns $ \n ->
180-
lift randomQualifiedUser >>= setupParticipant tmp createClients n
181-
lift . when makeConnections $
182-
traverse_
183-
( \u ->
184-
connectWithRemoteUser
185-
(qUnqualified . pUserId $ u)
186-
(pUserId creator)
187-
)
188-
locals
189-
pure (creator, locals)
180+
where
181+
creatorUserOrId :: CreatorOrigin -> TestM (Qualified UserId)
182+
creatorUserOrId = \case
183+
LocalCreator -> randomQualifiedUser
184+
RemoteCreator d -> randomQualifiedId d
190185

191186
withLastPrekeys :: Monad m => State.StateT [LastPrekey] m a -> m a
192187
withLastPrekeys m = State.evalStateT m someLastPrekeys
@@ -242,11 +237,12 @@ takeLastPrekey = do
242237
State.put lpks
243238
pure lpk
244239

245-
-- | Setup: Alice creates a group and invites bob. Return welcome and commit message.
240+
-- | Setup: Alice creates a group and invites Bob that is local or remote to
241+
-- Alice depending on the passed in creator origin. Return welcome and commit
242+
-- message.
246243
aliceInvitesBob :: HasCallStack => Int -> SetupOptions -> TestM MessagingSetup
247244
aliceInvitesBob numBobClients opts@SetupOptions {..} = withSystemTempDirectory "mls" $ \tmp -> do
248245
(alice, [bob]) <- withLastPrekeys $ setupParticipants tmp opts [numBobClients]
249-
250246
-- create a group
251247
conversation <- setupGroup tmp createConv alice "group"
252248

0 commit comments

Comments
 (0)