Skip to content

Commit

Permalink
Add endpoint to Federator API, cleanup (#1189)
Browse files Browse the repository at this point in the history
* Add endpoint to Federator API, cleanup

* rename API to Api

* remove search endpoint

It being here doesn't give us a lot, still needs some answers and
tweaks. We will need a while to get there anyways.
  • Loading branch information
mheinzel authored Aug 18, 2020
1 parent dcabede commit 8114163
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 141 deletions.
14 changes: 7 additions & 7 deletions services/federator/federator.cabal
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
cabal-version: 1.12

-- This file has been generated from package.yaml by hpack version 0.31.2.
-- This file has been generated from package.yaml by hpack version 0.33.0.
--
-- see: https://github.com/sol/hpack
--
-- hash: 05e45399becaef2bbecfa958ec4d5633900e2e1d8e1c1a2e7ecd2afbdbc2404f
-- hash: 72597caf8878551b0609bfdc790852575f38db429ea5c83935a399c676ee3c2c

name: federator
version: 1.0.0
Expand All @@ -20,10 +20,10 @@ library
exposed-modules:
Federator.API
Federator.App
Federator.Impl
Federator.Options
Federator.Run
Federator.Types
Federator.Util
other-modules:
Paths_federator
hs-source-dirs:
Expand All @@ -35,14 +35,12 @@ library
, aeson
, base
, bilge
, brig-types
, bytestring-conversion
, data-default
, email-validate
, errors
, exceptions
, extended
, galley-types
, imports
, lens
, metrics-core
Expand All @@ -60,6 +58,8 @@ library
, wai
, wai-utilities
, warp
, wire-api
, wire-api-federation
default-language: Haskell2010

executable federator
Expand All @@ -75,15 +75,13 @@ executable federator
, aeson
, base
, bilge
, brig-types
, bytestring-conversion
, data-default
, email-validate
, errors
, exceptions
, extended
, federator
, galley-types
, imports
, lens
, metrics-core
Expand All @@ -101,4 +99,6 @@ executable federator
, wai
, wai-utilities
, warp
, wire-api
, wire-api-federation
default-language: Haskell2010
4 changes: 2 additions & 2 deletions services/federator/package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,12 @@ dependencies:
- aeson
- base
- bilge
- brig-types
- bytestring-conversion
- data-default
- email-validate
- errors
- exceptions
- extended
- galley-types
- imports
- lens
- metrics-core
Expand All @@ -38,6 +36,8 @@ dependencies:
- wai
- wai-utilities
- warp
- wire-api
- wire-api-federation
library:
source-dirs: src
executables:
Expand Down
65 changes: 27 additions & 38 deletions services/federator/src/Federator/API.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,53 +17,42 @@
-- 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 Federator.API where

import Brig.Types.Client.Prekey
import Brig.Types.Test.Arbitrary ()
import Data.Aeson.TH (deriveJSON)
import Data.Handle (Handle (..))
import Data.Id (UserId)
import Data.Qualified
import Federator.Util
module Federator.API
( Api (..),
module Fed,
)
where

import Data.Id (ConvId, UserId)
import Data.Qualified (Qualified)
import Imports
import Servant.API
import Servant.API.Generic
import Test.QuickCheck
import Wire.API.Federation.API.Conversation as Fed hiding (Api)
import Wire.API.Federation.Event as Fed
import Wire.API.User.Client.Prekey (PrekeyBundle)

data API route = API
{ _gapiSearch ::
route
:- "i"
:> "search"
-- QUESTION: what exactly should the query be? text + domain?
:> QueryParam' [Required, Strict] "q" (Qualified Handle)
:> Get '[JSON] FUser,
_gapiPrekeys ::
data Api route = Api
{ _gapiPrekeys ::
route
:- "i"
:> "users"
:> Capture "fqu" (Qualified UserId)
:> Capture "id" (Qualified UserId)
:> "prekeys"
:> Get '[JSON] PrekeyBundle
-- FUTUREWORK(federation):
-- this should return a version of PrekeyBundle with qualified UserId,
-- defined in wire-api-federation
:> Get '[JSON] PrekeyBundle,
_gapiJoinConversationById ::
route
:- "i"
:> "conversations"
:> Capture "cnv" (Qualified ConvId)
:> "join"
:> ReqBody '[JSON] Fed.JoinConversationByIdRequest
:> Post '[JSON] (Fed.ConversationUpdateResult Fed.MemberJoin)
}
deriving (Generic)

-- curl http://localhost:8097/i/[email protected]; curl http://localhost:8097/i/users/`uuid`@example.com/prekeys

----------------------------------------------------------------------
-- TODO: add roundtrip tests for *HttpApiData, *JSON, ...
--
-- TODO: the client ids in the 'PrekeyBundle' aren't really needed here. do we want to make a
-- new type for that, then?

data FUser = FUser
{ _fuGlobalHandle :: !(Qualified Handle),
_fuFQU :: !(Qualified UserId)
}
deriving (Eq, Show, Generic)

deriveJSON (wireJsonOptions "_fu") ''FUser

instance Arbitrary FUser where
arbitrary = FUser <$> arbitrary <*> arbitrary
-- FUTUREWORK: add roundtrip tests for *HttpApiData, *JSON, ...
75 changes: 61 additions & 14 deletions services/federator/src/Federator/App.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE RecordWildCards #-}

-- This file is part of the Wire Server implementation.
--
Expand All @@ -19,19 +19,66 @@
-- with this program. If not, see <https://www.gnu.org/licenses/>.

module Federator.App
( app,
( AppT,
AppIO,
runAppT,
runAppResourceT,
)
where

import Data.Proxy
import qualified Federator.API as API
import Federator.Types
import Network.Wai
import Servant.API.Generic
import Servant.Mock
import Servant.Server

app :: Env -> Application
app _ = serve api (mock api Proxy)
where
api = Proxy @(ToServantApi API.API)
import Bilge (RequestId (unRequestId))
import Bilge.RPC (HasRequestId (..))
import Control.Error (ExceptT)
import Control.Lens (view)
import Control.Monad.Catch (MonadCatch, MonadMask, MonadThrow)
import Control.Monad.Trans.Resource (MonadUnliftIO, ResourceT, runResourceT, transResourceT)
import Federator.Types (Env, applog, requestId)
import Imports
import Servant.API.Generic ()
import Servant.Server ()
import System.Logger.Class as LC
import qualified System.Logger.Extended as Log

-- FUTUREWORK: this code re-occurs in every service. introduce 'MkAppT' in types-common that
-- takes 'Env' as one more argument.
newtype AppT m a = AppT
{ unAppT :: ReaderT Env m a
}
deriving newtype
( Functor,
Applicative,
Monad,
MonadIO,
MonadThrow,
MonadCatch,
MonadMask,
MonadReader Env
)

type AppIO = AppT IO

instance MonadIO m => LC.MonadLogger (AppT m) where
log l m = do
g <- view applog
r <- view requestId
Log.log g l $ field "request" (unRequestId r) ~~ m

instance MonadIO m => LC.MonadLogger (ExceptT err (AppT m)) where
log l m = lift (LC.log l m)

instance Monad m => HasRequestId (AppT m) where
getRequestId = view requestId

instance MonadUnliftIO m => MonadUnliftIO (AppT m) where
withRunInIO inner =
AppT . ReaderT $ \r ->
withRunInIO $ \runner ->
inner (runner . flip runReaderT r . unAppT)

runAppT :: Env -> AppT m a -> m a
runAppT e (AppT ma) = runReaderT ma e

runAppResourceT :: ResourceT AppIO a -> AppIO a
runAppResourceT ma = do
e <- ask
liftIO . runResourceT $ transResourceT (runAppT e) ma
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE RecordWildCards #-}

-- This file is part of the Wire Server implementation.
--
-- Copyright (C) 2020 Wire Swiss GmbH <[email protected]>
Expand All @@ -15,25 +18,20 @@
-- 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 Federator.Util
( wireJsonOptions,
module Federator.Impl
( app,
)
where

import Data.Aeson as Aeson
import Imports

dropPrefix :: String -> String -> Maybe String
dropPrefix pfx str =
if length pfx > length str
then Nothing
else case splitAt (length pfx) str of
(pfx', sfx) ->
if pfx' /= pfx
then Nothing
else Just sfx
import Data.Proxy
import qualified Federator.API as API
import Federator.Types
import Network.Wai
import Servant.API.Generic
import Servant.Mock
import Servant.Server

-- | This is a partial function; totality of all calls must be verified by roundtrip tests on
-- the aeson instances involved.
wireJsonOptions :: String -> Options
wireJsonOptions pfx = defaultOptions {fieldLabelModifier = fromJust . dropPrefix pfx . fmap toLower}
app :: Env -> Application
app _ = serve api (mock api Proxy)
where
api = Proxy @(ToServantApi API.Api)
Loading

0 comments on commit 8114163

Please sign in to comment.