Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
39bc5a3
WIP
pcapriotti Sep 30, 2021
661c779
Begin work on remote connection logic
pcapriotti Sep 30, 2021
62754a9
WIP: implement remote connection state machine
pcapriotti Oct 1, 2021
68c795e
Fix compilation
smatting Oct 2, 2021
8810830
fix lookupRelation
smatting Oct 4, 2021
6b49061
factor out transitionTo
smatting Oct 4, 2021
27aa504
fleshed out transitionTo
smatting Oct 4, 2021
8729213
change transitionTo
smatting Oct 4, 2021
68326a2
send connection request RPC WIP
jschaul Sep 29, 2021
8c21cb6
sendConnectionRequest: implement one case
smatting Sep 30, 2021
0bdd046
change api
smatting Oct 4, 2021
1ae7ec2
add checkLimit
smatting Oct 4, 2021
52ad1e7
fixup! add checkLimit
pcapriotti Oct 4, 2021
922d6b1
Send user events when connection state changes
pcapriotti Oct 4, 2021
990dbc8
Update conv when connection state transitions
pcapriotti Oct 4, 2021
af92df6
Hook connection update to public API
pcapriotti Oct 5, 2021
7292b33
Handle remote user not existing
pcapriotti Oct 5, 2021
af8f94d
Add remote connection test and fix a few issues
pcapriotti Oct 5, 2021
7321a4e
Remove warnings
akshaymankar Oct 5, 2021
6ea1e86
Simplify assertion
akshaymankar Oct 5, 2021
0d5680c
Fix comment
akshaymankar Oct 5, 2021
e0ed20c
Add mutual remote connection test
pcapriotti Oct 5, 2021
695f1c2
Add a few tests for connection federation RPC
akshaymankar Oct 5, 2021
dd6aa17
Abstract out some connections test functions
pcapriotti Oct 5, 2021
9be3345
Test connection flows involving the ignored state
pcapriotti Oct 5, 2021
5606f7c
Test connection flows involving the blocked state
pcapriotti Oct 5, 2021
51f4e6f
Test cancelling remote connections
pcapriotti Oct 5, 2021
3432bb8
Test connection limits involving remote users
jschaul Oct 5, 2021
9db46e3
Move connection tests to API.User.Connection
pcapriotti Oct 6, 2021
b9819f3
Add CHANGELOG entry
pcapriotti Oct 6, 2021
4fdf741
Add golden tests for connection RPC types
pcapriotti Oct 6, 2021
aede4c1
Clean up comments and haddocks
pcapriotti Oct 6, 2021
05d3810
Use explicit state names in comment
pcapriotti Oct 6, 2021
491135c
Check max connection limit before making federated call
akshaymankar Oct 7, 2021
1848ba4
Test Sent -> Accepted is allowed when max conn limit is reachced
akshaymankar Oct 7, 2021
c9ce5b4
Replace TODO about pending connections with an explanation
akshaymankar Oct 7, 2021
c827dca
Add test for mutual connect when local connect happens after remote
akshaymankar Oct 7, 2021
56f4c0d
Merge remote-tracking branch 'origin/develop' into pcapriotti/fed-con…
akshaymankar Oct 7, 2021
06375d0
Fix wrongly resolved merge conflict
akshaymankar Oct 7, 2021
a46e01c
Remote unnecessary dos
akshaymankar Oct 7, 2021
9a08017
Fix comment
akshaymankar Oct 7, 2021
5427219
Add comment to clarify what is being tested
akshaymankar Oct 7, 2021
42ec52c
Merge remote-tracking branch 'origin/develop' into pcapriotti/fed-con…
akshaymankar Oct 7, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/6-federation/fed-connections
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Allow connecting to remote users. One to one conversations are not created yet.
53 changes: 51 additions & 2 deletions libs/wire-api-federation/src/Wire/API/Federation/API/Brig.hs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ module Wire.API.Federation.API.Brig where
import Control.Monad.Except (MonadError (..))
import Data.Aeson (FromJSON, ToJSON)
import Data.Handle (Handle)
import Data.Id (ClientId, UserId)
import Data.Id
import Imports
import Servant.API
import Servant.API.Generic
import Servant.Client.Generic (AsClientT, genericClient)
import Test.QuickCheck (Arbitrary)
import Wire.API.Arbitrary (GenericUniform (..))
import Wire.API.Federation.Client (FederationClientFailure, FederatorClient)
import Wire.API.Federation.Domain (OriginDomainHeader)
import qualified Wire.API.Federation.GRPC.Types as Proto
import Wire.API.Message (UserClients)
import Wire.API.User (UserProfile)
Expand Down Expand Up @@ -92,7 +93,14 @@ data Api routes = Api
:- "federation"
:> "get-user-clients"
:> ReqBody '[JSON] GetUserClients
:> Post '[JSON] (UserMap (Set PubClient))
:> Post '[JSON] (UserMap (Set PubClient)),
sendConnectionAction ::
routes
:- "federation"
:> "send-connection-action"
:> OriginDomainHeader
:> ReqBody '[JSON] NewConnectionRequest
:> Post '[JSON] NewConnectionResponse
}
deriving (Generic)

Expand All @@ -102,5 +110,46 @@ newtype GetUserClients = GetUserClients
deriving stock (Eq, Show, Generic)
deriving (ToJSON, FromJSON) via (CustomEncoded GetUserClients)

-- NOTE: ConversationId for remote connections
--
-- The plan is to model the connect/one2one conversationId as deterministically derived from
-- the combination of both userIds and both domains. It may be in the domain
-- of the sending OR the receiving backend (with a 50/50 probability).
-- However at the level of the federation API, we are only concerned about
-- the question of which backend has the authority over the conversationId.
--
-- (Backend A should not prescribe backend B to use a certain UUID for its
-- conversation; as that could lead to a potential malicious override of an
-- existing conversation)
--
-- The deterministic conversation Id should be seen as a 'best effort'
-- attempt only. (we cannot guarantee a backend won't change the code in the
-- future)

data NewConnectionRequest = NewConnectionRequest
{ -- | The 'from' userId is understood to always have the domain of the backend making the connection request
ncrFrom :: UserId,
-- | The 'to' userId is understood to always have the domain of the receiving backend.
ncrTo :: UserId,
ncrAction :: RemoteConnectionAction
}
deriving stock (Eq, Show, Generic)
deriving (Arbitrary) via (GenericUniform NewConnectionRequest)
deriving (FromJSON, ToJSON) via (CustomEncoded NewConnectionRequest)

data RemoteConnectionAction
= RemoteConnect
| RemoteRescind
deriving stock (Eq, Show, Generic)
deriving (Arbitrary) via (GenericUniform RemoteConnectionAction)
deriving (FromJSON, ToJSON) via (CustomEncoded RemoteConnectionAction)

data NewConnectionResponse
= NewConnectionResponseUserNotActivated
| NewConnectionResponseOk (Maybe RemoteConnectionAction)
deriving stock (Eq, Show, Generic)
deriving (Arbitrary) via (GenericUniform NewConnectionResponse)
deriving (FromJSON, ToJSON) via (CustomEncoded NewConnectionResponse)

clientRoutes :: (MonadError FederationClientFailure m, MonadIO m) => Api (AsClientT (FederatorClient 'Proto.Brig m))
clientRoutes = genericClient
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import qualified Test.Wire.API.Federation.Golden.ConversationUpdate as Conversat
import qualified Test.Wire.API.Federation.Golden.LeaveConversationRequest as LeaveConversationRequest
import qualified Test.Wire.API.Federation.Golden.LeaveConversationResponse as LeaveConversationResponse
import qualified Test.Wire.API.Federation.Golden.MessageSendResponse as MessageSendResponse
import qualified Test.Wire.API.Federation.Golden.NewConnectionRequest as NewConnectionRequest
import qualified Test.Wire.API.Federation.Golden.NewConnectionResponse as NewConnectionResponse
import Test.Wire.API.Federation.Golden.Runner (testObjects)

spec :: Spec
Expand Down Expand Up @@ -50,3 +52,13 @@ spec =
(LeaveConversationResponse.testObject_LeaveConversationResponse7, "testObject_LeaveConversationResponse7.json"),
(LeaveConversationResponse.testObject_LeaveConversationResponse8, "testObject_LeaveConversationResponse8.json")
]
testObjects
[ (NewConnectionRequest.testObject_NewConnectionRequest1, "testObject_NewConnectionRequest1.json"),
(NewConnectionRequest.testObject_NewConnectionRequest2, "testObject_NewConnectionRequest2.json")
]
testObjects
[ (NewConnectionResponse.testObject_NewConnectionResponse1, "testObject_NewConnectionResponse1.json"),
(NewConnectionResponse.testObject_NewConnectionResponse2, "testObject_NewConnectionResponse2.json"),
(NewConnectionResponse.testObject_NewConnectionResponse3, "testObject_NewConnectionResponse3.json"),
(NewConnectionResponse.testObject_NewConnectionResponse4, "testObject_NewConnectionResponse4.json")
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
-- This file is part of the Wire Server implementation.
--
-- Copyright (C) 2021 Wire Swiss GmbH <[email protected]>
--
-- This program is free software: you can redistribute it and/or modify it under
-- the terms of the GNU Affero General Public License as published by the Free
-- Software Foundation, either version 3 of the License, or (at your option) any
-- later version.
--
-- This program is distributed in the hope that it will be useful, but WITHOUT
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-- details.
--
-- You should have received a copy of the GNU Affero General Public License along
-- with this program. If not, see <https://www.gnu.org/licenses/>.

module Test.Wire.API.Federation.Golden.NewConnectionRequest where

import Data.Id
import qualified Data.UUID as UUID
import Imports
import Wire.API.Federation.API.Brig

testObject_NewConnectionRequest1 :: NewConnectionRequest
testObject_NewConnectionRequest1 =
NewConnectionRequest
{ ncrFrom = Id (fromJust (UUID.fromString "69f66843-6cf1-48fb-8c05-1cf58c23566a")),
ncrTo = Id (fromJust (UUID.fromString "1669240c-c510-43e0-bf1a-33378fa4ba55")),
ncrAction = RemoteConnect
}

testObject_NewConnectionRequest2 :: NewConnectionRequest
testObject_NewConnectionRequest2 =
NewConnectionRequest
{ ncrFrom = Id (fromJust (UUID.fromString "69f66843-6cf1-48fb-8c05-1cf58c23566a")),
ncrTo = Id (fromJust (UUID.fromString "1669240c-c510-43e0-bf1a-33378fa4ba55")),
ncrAction = RemoteRescind
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
-- This file is part of the Wire Server implementation.
--
-- Copyright (C) 2021 Wire Swiss GmbH <[email protected]>
--
-- This program is free software: you can redistribute it and/or modify it under
-- the terms of the GNU Affero General Public License as published by the Free
-- Software Foundation, either version 3 of the License, or (at your option) any
-- later version.
--
-- This program is distributed in the hope that it will be useful, but WITHOUT
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-- details.
--
-- You should have received a copy of the GNU Affero General Public License along
-- with this program. If not, see <https://www.gnu.org/licenses/>.

module Test.Wire.API.Federation.Golden.NewConnectionResponse where

import Imports
import Wire.API.Federation.API.Brig

testObject_NewConnectionResponse1 :: NewConnectionResponse
testObject_NewConnectionResponse1 = NewConnectionResponseOk Nothing

testObject_NewConnectionResponse2 :: NewConnectionResponse
testObject_NewConnectionResponse2 = NewConnectionResponseOk (Just RemoteConnect)

testObject_NewConnectionResponse3 :: NewConnectionResponse
testObject_NewConnectionResponse3 = NewConnectionResponseOk (Just RemoteRescind)

testObject_NewConnectionResponse4 :: NewConnectionResponse
testObject_NewConnectionResponse4 = NewConnectionResponseUserNotActivated
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"to": "1669240c-c510-43e0-bf1a-33378fa4ba55",
"from": "69f66843-6cf1-48fb-8c05-1cf58c23566a",
"action": "RemoteConnect"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"to": "1669240c-c510-43e0-bf1a-33378fa4ba55",
"from": "69f66843-6cf1-48fb-8c05-1cf58c23566a",
"action": "RemoteRescind"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"tag": "NewConnectionResponseOk",
"contents": null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"tag": "NewConnectionResponseOk",
"contents": "RemoteConnect"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"tag": "NewConnectionResponseOk",
"contents": "RemoteRescind"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"tag": "NewConnectionResponseUserNotActivated"
}
4 changes: 3 additions & 1 deletion libs/wire-api-federation/wire-api-federation.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ cabal-version: 1.12
--
-- see: https://github.com/sol/hpack
--
-- hash: 8106f61fbca587df7a82a89effeec838bb9d9326c84bd7af8f615502cedc152f
-- hash: 03f7245b036ccc38819ed5f5654dae8d96b7ec5917b2f898be3305193bc3faf5

name: wire-api-federation
version: 0.1.0
Expand Down Expand Up @@ -82,6 +82,8 @@ test-suite spec
Test.Wire.API.Federation.Golden.LeaveConversationRequest
Test.Wire.API.Federation.Golden.LeaveConversationResponse
Test.Wire.API.Federation.Golden.MessageSendResponse
Test.Wire.API.Federation.Golden.NewConnectionRequest
Test.Wire.API.Federation.Golden.NewConnectionResponse
Test.Wire.API.Federation.Golden.Runner
Test.Wire.API.Federation.GRPC.TypesSpec
Paths_wire_api_federation
Expand Down
1 change: 1 addition & 0 deletions libs/wire-api/package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ library:
- cassandra-util
- cassava >= 0.5
- cereal
- comonad
- cookie
- cryptonite
- currency-codes >=2.0
Expand Down
12 changes: 12 additions & 0 deletions libs/wire-api/src/Wire/API/Connection.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ module Wire.API.Connection
Relation (..),
RelationWithHistory (..),
relationDropHistory,
relationWithHistory,

-- * Requests
ConnectionRequest (..),
Expand Down Expand Up @@ -192,6 +193,17 @@ data RelationWithHistory
deriving stock (Eq, Ord, Show, Generic)
deriving (Arbitrary) via (GenericUniform RelationWithHistory)

-- | Convert a 'Relation' to 'RelationWithHistory'. This is to be used only if
-- the MissingLegalholdConsent case does not need to be supported.
relationWithHistory :: Relation -> RelationWithHistory
relationWithHistory Accepted = AcceptedWithHistory
relationWithHistory Blocked = BlockedWithHistory
relationWithHistory Pending = PendingWithHistory
relationWithHistory Ignored = IgnoredWithHistory
relationWithHistory Sent = SentWithHistory
relationWithHistory Cancelled = CancelledWithHistory
relationWithHistory MissingLegalholdConsent = MissingLegalholdConsentFromCancelled

relationDropHistory :: RelationWithHistory -> Relation
relationDropHistory = \case
AcceptedWithHistory -> Accepted
Expand Down
9 changes: 8 additions & 1 deletion libs/wire-api/src/Wire/API/Routes/Public/Util.hs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@

module Wire.API.Routes.Public.Util where

import Control.Comonad
import Data.SOP (I (..), NS (..))
import Imports
import Servant
import Servant.Swagger.Internal.Orphans ()
import Wire.API.Routes.MultiVerb
Expand All @@ -45,6 +45,13 @@ data ResponseForExistedCreated a
| Created !a
deriving (Functor)

instance Comonad ResponseForExistedCreated where
extract (Existed x) = x
extract (Created x) = x

duplicate r@(Existed _) = Existed r
duplicate r@(Created _) = Created r

type ResponsesForExistedCreated eDesc cDesc a =
'[ Respond 200 eDesc a,
Respond 201 cDesc a
Expand Down
3 changes: 2 additions & 1 deletion libs/wire-api/wire-api.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ cabal-version: 1.12
--
-- see: https://github.com/sol/hpack
--
-- hash: c6591983c73573c4734c452218e0831333768e896f0ab08718ba9f2c6b110567
-- hash: 3acb28729470b6c8562eb847a9eb27f8ba8f9999ecce268b3a5a404e5f4794b6

name: wire-api
version: 0.1.0
Expand Down Expand Up @@ -113,6 +113,7 @@ library
, cassandra-util
, cassava >=0.5
, cereal
, comonad
, containers >=0.5
, cookie
, cryptonite
Expand Down
5 changes: 4 additions & 1 deletion services/brig/brig.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ cabal-version: 1.12
--
-- see: https://github.com/sol/hpack
--
-- hash: 74882d161b7ecee96907491a40139775942d4f15987cbe1aa30d13b30fc79e0e
-- hash: 33acd5be229059e16903857f1923a9afcf55f285461298721a15d8d8c5b88a12

name: brig
version: 1.35.0
Expand All @@ -22,6 +22,8 @@ library
Brig.API
Brig.API.Client
Brig.API.Connection
Brig.API.Connection.Remote
Brig.API.Connection.Util
Brig.API.Error
Brig.API.Federation
Brig.API.Handler
Expand Down Expand Up @@ -137,6 +139,7 @@ library
, bytestring >=0.10
, bytestring-conversion >=0.2
, cassandra-util >=0.16.2
, comonad
, conduit >=1.2.8
, containers >=0.5
, cookie >=0.4
Expand Down
1 change: 1 addition & 0 deletions services/brig/package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ library:
- bytestring >=0.10
- bytestring-conversion >=0.2
- cassandra-util >=0.16.2
- comonad
- conduit >=1.2.8
- containers >=0.5
- cookie >=0.4
Expand Down
Loading