Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Federation: Convert prekeys endpoints #1372

Merged
merged 31 commits into from
Mar 2, 2021
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c00e318
wip
smatting Feb 9, 2021
651aacb
Make compile
smatting Feb 9, 2021
d8c5b5f
add routing
smatting Feb 9, 2021
094a576
Move duplicated instances from galley to wire-api
smatting Feb 17, 2021
f39354e
errors to exceptions
smatting Feb 18, 2021
eb8d273
Add (deprecated) to swagger docs
smatting Feb 18, 2021
2559cbb
clean up
smatting Feb 18, 2021
22bf1bd
nginz: Remove extraneous routing rules
smatting Feb 22, 2021
bd492e3
PrekeyId: use newtype ToSchema instance
smatting Feb 22, 2021
f424c3d
Remove extraneous routes from services-demo
smatting Feb 22, 2021
18fc922
galley(partial): refactor OpaqueUserId -> UserId
smatting Feb 22, 2021
44fd44a
Fix: Z-Auth mistakingly added to endpoints
smatting Feb 22, 2021
2bdf27e
keep modelOtrClientMap because used by NewOtrMessage
smatting Feb 22, 2021
ff8571f
Remove TODO
smatting Feb 22, 2021
c0b0bca
Remove TODO
smatting Feb 22, 2021
c10c51b
Remove unused modelPrekeyBundle
smatting Feb 22, 2021
8da75da
remove unused modelCientPrekey
smatting Feb 22, 2021
2f9df6a
hi ci
smatting Feb 22, 2021
03c1768
fix api-bot
smatting Feb 23, 2021
e0f075c
fix api-simulations
smatting Feb 23, 2021
1288598
Add test for /users/<localdomain>/:uid/prekeys
smatting Feb 23, 2021
c6dea20
Add test for /users/<localdomain>/:uid/prekeys/:client
smatting Feb 23, 2021
4ff518c
factor out helper generateClients
smatting Feb 23, 2021
e2c2812
Add test for old /users/prekey endpoint
smatting Feb 23, 2021
2a158a0
Add test for post /list-keys
smatting Feb 23, 2021
fcfa202
Add clarification TODOs
smatting Feb 23, 2021
b816ea0
Make swagger examples nice
smatting Feb 23, 2021
9d57293
Revert "Add clarification TODOs"
smatting Feb 23, 2021
45deea5
Move /list-prekeys to /users/list-prekeys
smatting Feb 23, 2021
c2ac6b4
hi ci
smatting Feb 23, 2021
ba42ab4
Apply suggestions from code review
smatting Mar 2, 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
3 changes: 3 additions & 0 deletions charts/nginz/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,9 @@ nginx_conf:
- path: ~* ^/teams/([^/]*)/search$
envs:
- all
- path: /list-prekeys
envs:
- all
galley:
- path: /conversations/code-check
disable_zauth: true
Expand Down
6 changes: 6 additions & 0 deletions deploy/services-demo/conf/nginz/nginx-docker.conf
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ http {

sendfile on;
tcp_nopush on;

tcp_nodelay on;

#
Expand Down Expand Up @@ -213,6 +214,11 @@ http {
proxy_pass http://brig;
}

location /list-prekeys {
include common_response_with_zauth.conf;
proxy_pass http://brig;
}

# Cargohold Endpoints

rewrite ^/api-docs/assets /assets/api-docs?base_url=http://127.0.0.1:8080/ break;
Expand Down
5 changes: 5 additions & 0 deletions deploy/services-demo/conf/nginz/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,11 @@ http {
proxy_pass http://brig;
}

location /list-prekeys {
include common_response_with_zauth.conf;
proxy_pass http://brig;
}

# Cargohold Endpoints

rewrite ^/api-docs/assets /assets/api-docs?base_url=http://127.0.0.1:8080/ break;
Expand Down
4 changes: 2 additions & 2 deletions libs/galley-types/src/Galley/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ module Galley.Types
where

import Data.Aeson
import Data.Id (ClientId, ConvId, OpaqueUserId, TeamId, UserId)
import Data.Id (ClientId, ConvId, TeamId, UserId)
import Data.Json.Util ((#))
import qualified Data.Map.Strict as Map
import Data.Misc (Milliseconds)
Expand Down Expand Up @@ -151,7 +151,7 @@ instance FromJSON Accept where
--------------------------------------------------------------------------------
-- utility functions

foldrOtrRecipients :: (OpaqueUserId -> ClientId -> Text -> a -> a) -> a -> OtrRecipients -> a
foldrOtrRecipients :: (UserId -> ClientId -> Text -> a -> a) -> a -> OtrRecipients -> a
foldrOtrRecipients f a =
Map.foldrWithKey go a
. userClientMap
Expand Down
2 changes: 1 addition & 1 deletion libs/types-common/src/Data/Id.hs
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ newtype ClientId = ClientId
{ client :: Text
}
deriving (Eq, Ord, Show, ToByteString, Hashable, NFData, ToJSON, ToJSONKey, Generic)
deriving newtype (ToSchema)
deriving newtype (ToSchema, ToParamSchema, FromHttpApiData)

newClientId :: Word64 -> ClientId
newClientId = ClientId . toStrict . toLazyText . hexadecimal
Expand Down
9 changes: 5 additions & 4 deletions libs/wire-api/src/Wire/API/Message.hs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ data NewOtrMessage = NewOtrMessage
newOtrTransient :: Bool,
newOtrNativePriority :: Maybe Priority,
newOtrData :: Maybe Text,
newOtrReportMissing :: Maybe [OpaqueUserId]
newOtrReportMissing :: Maybe [UserId]
-- FUTUREWORK: if (and only if) clients can promise this uid list will always exactly
-- be the list of uids we could also extract from the messages' recipients field, we
-- should do the latter, for two reasons: (1) no need for an artificial limit on the
Expand Down Expand Up @@ -157,16 +157,17 @@ instance FromJSON Priority where
--------------------------------------------------------------------------------
-- Recipients

-- FUTUREWORK: Add ToSchema when 'NewOtrMessage' has ToSchema
newtype OtrRecipients = OtrRecipients
{ otrRecipientsMap :: UserClientMap Text
}
deriving stock (Eq, Show)
deriving newtype (ToJSON, FromJSON, Semigroup, Monoid, Arbitrary)

-- FUTUREWORK: Remove when 'NewOtrMessage' has ToSchema
modelOtrRecipients :: Doc.Model
modelOtrRecipients = Doc.defineModel "OtrRecipients" $ do
Doc.description "Recipients of OTR content."
-- FUTUREWORK: is this right?
Doc.property "" (Doc.ref modelOtrClientMap) $
Doc.description "Mapping of user IDs to 'OtrClientMap's."

Expand All @@ -182,10 +183,10 @@ data OtrFilterMissing
OtrReportAllMissing
| -- | Complain only about missing
-- recipients who are /not/ on this list
OtrIgnoreMissing (Set OpaqueUserId)
OtrIgnoreMissing (Set UserId)
| -- | Complain only about missing
-- recipients who /are/ on this list
OtrReportMissing (Set OpaqueUserId)
OtrReportMissing (Set UserId)
deriving stock (Eq, Show, Generic)
deriving (Arbitrary) via (GenericUniform OtrFilterMissing)

Expand Down
9 changes: 5 additions & 4 deletions libs/wire-api/src/Wire/API/Message/Proto.hs
Original file line number Diff line number Diff line change
Expand Up @@ -69,18 +69,18 @@ import qualified Wire.API.User.Client as Client
-- UserId

newtype UserId = UserId
{ _user :: Required 1 (Value Id.OpaqueUserId)
{ _user :: Required 1 (Value Id.UserId)
}
deriving stock (Eq, Show, Generic)

instance Encode UserId

instance Decode UserId

fromUserId :: Id.OpaqueUserId -> UserId
fromUserId :: Id.UserId -> UserId
fromUserId u = UserId {_user = putField u}

userId :: Functor f => (Id.OpaqueUserId -> f Id.OpaqueUserId) -> UserId -> f UserId
userId :: Functor f => (Id.UserId -> f Id.UserId) -> UserId -> f UserId
userId f c = (\x -> c {_user = x}) <$> field f (_user c)

--------------------------------------------------------------------------------
Expand Down Expand Up @@ -168,6 +168,7 @@ toOtrRecipients =
Msg.OtrRecipients . Client.UserClientMap
. foldl' userEntries mempty
where
-- userEntries :: Map UserId (Map ClientId Text) -> UserEntry -> Map UserId (Map ClientId Text)
smatting marked this conversation as resolved.
Show resolved Hide resolved
userEntries acc x =
let u = view userEntryId x
c = view userEntryClients x
Expand Down Expand Up @@ -285,7 +286,7 @@ toNewOtrMessage msg =
Msg.newOtrReportMissing = toReportMissing $ view newOtrMessageReportMissing msg
}

toReportMissing :: [UserId] -> Maybe [Id.OpaqueUserId]
toReportMissing :: [UserId] -> Maybe [Id.UserId]
toReportMissing [] = Nothing
toReportMissing us = Just $ view userId <$> us

Expand Down
2 changes: 0 additions & 2 deletions libs/wire-api/src/Wire/API/Swagger.hs
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,6 @@ models =
User.Client.modelSigkeys,
User.Client.modelLocation, -- re-export from types-common
User.Client.modelPubClient,
User.Client.Prekey.modelPrekeyBundle,
User.Client.Prekey.modelClientPrekey,
User.Client.Prekey.modelPrekey,
User.Handle.modelUserHandleInfo,
User.Handle.modelCheckHandles,
Expand Down
82 changes: 77 additions & 5 deletions libs/wire-api/src/Wire/API/User/Client.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
module Wire.API.User.Client
( -- * UserClients
UserClientMap (..),
QualifiedUserClientMap (..),
UserClients (..),
QualifiedUserClients (..),
filterClients,

-- * Client
Expand Down Expand Up @@ -58,31 +60,39 @@ module Wire.API.User.Client
)
where

import Control.Lens ((?~), (^.))
import Data.Aeson
import Data.Domain (Domain)
import qualified Data.HashMap.Strict as HashMap
import Data.Id
import Data.Json.Util
import qualified Data.Map.Strict as Map
import Data.Misc (Latitude (..), Location, Longitude (..), PlainTextPassword (..), latitude, location, longitude, modelLocation)
import Data.Swagger (ToSchema)
import Data.Proxy (Proxy (..))
import Data.Swagger (HasExample (example), NamedSchema (..), ToSchema (..), declareSchema)
import qualified Data.Swagger as Swagger
import qualified Data.Swagger.Build.Api as Doc
import Data.Swagger.Schema (toSchema)
import qualified Data.Text as Text
import qualified Data.Text.Encoding as Text.E
import Data.Typeable (typeRep)
import Data.UUID (toASCIIBytes)
import Deriving.Swagger (CamelToSnake, ConstructorTagModifier, CustomSwagger, FieldLabelModifier, LabelMapping ((:->)), LabelMappings, LowerCase, StripPrefix, StripSuffix)
import Imports
import Wire.API.Arbitrary (Arbitrary (arbitrary), GenericUniform (..), mapOf', setOf')
import Wire.API.Arbitrary (Arbitrary (arbitrary), GenericUniform (..), generateExample, mapOf', setOf')
import Wire.API.User.Auth (CookieLabel)
import Wire.API.User.Client.Prekey as Prekey

--------------------------------------------------------------------------------
-- UserClientMap

newtype UserClientMap a = UserClientMap
{ userClientMap :: Map OpaqueUserId (Map ClientId a)
{ userClientMap :: Map UserId (Map ClientId a)
}
deriving stock (Eq, Show, Functor, Foldable, Traversable)
deriving newtype (Semigroup, Monoid)

-- FUTUREWORK: Remove when 'NewOtrMessage' has ToSchema
modelOtrClientMap :: Doc.Model
modelOtrClientMap = Doc.defineModel "OtrClientMap" $ do
Doc.description "Map of client IDs to OTR content."
Expand Down Expand Up @@ -115,15 +125,56 @@ instance FromJSON a => FromJSON (UserClientMap a) where
instance Arbitrary a => Arbitrary (UserClientMap a) where
arbitrary = UserClientMap <$> mapOf' arbitrary (mapOf' arbitrary arbitrary)

instance forall a. (Typeable a, ToSchema a, Arbitrary a, ToJSON a) => ToSchema (UserClientMap a) where
declareNamedSchema _ = do
mapSch <- declareSchema (Proxy @(Map UserId (Map ClientId a)))
let valueTypeName = Text.pack $ show $ typeRep $ Proxy @a
return $
NamedSchema (Just $ "UserClientMap (" <> valueTypeName <> ")") $
mapSch
& example
?~ toJSON
( Map.singleton
(generateExample @UserId)
( Map.singleton
(newClientId 4940483633899001999)
(generateExample @a)
)
)

newtype QualifiedUserClientMap a = QualifiedUserClientMap
{ qualifiedUserClientMap :: Map Domain (UserClientMap a)
}
deriving stock (Eq, Show)
deriving newtype (Semigroup, Monoid, ToJSON, FromJSON)

instance Arbitrary a => Arbitrary (QualifiedUserClientMap a) where
arbitrary = QualifiedUserClientMap <$> mapOf' arbitrary arbitrary

instance (Typeable a, ToSchema (UserClientMap a)) => ToSchema (QualifiedUserClientMap a) where
declareNamedSchema _ = do
mapSch <- declareSchema (Proxy @(Map Domain (UserClientMap a)))
let userMapSchema = toSchema (Proxy @(UserClientMap a))
let valueTypeName = Text.pack $ show $ typeRep $ Proxy @a
return $
NamedSchema (Just $ "QualifiedUserClientMap (" <> valueTypeName <> ")") $
mapSch
& Swagger.description ?~ "Map of Domain to (UserMap (" <> valueTypeName <> "))."
& example
?~ toJSON
(Map.singleton ("domain1.example.com" :: Text) (userMapSchema ^. example))

--------------------------------------------------------------------------------
-- UserClients

-- TODO: check if example generated by swagger look okay (probably not)
newtype UserClients = UserClients
{ userClients :: Map OpaqueUserId (Set ClientId)
{ userClients :: Map UserId (Set ClientId)
}
deriving stock (Eq, Show, Generic)
deriving newtype (Semigroup, Monoid)
deriving newtype (Semigroup, Monoid, ToSchema)

-- FUTUREWORK: Remove when 'NewOtrMessage' has ToSchema
modelUserClients :: Doc.Model
modelUserClients =
Doc.defineModel "UserClients" $
Expand All @@ -150,6 +201,27 @@ instance Arbitrary UserClients where
filterClients :: (Set ClientId -> Bool) -> UserClients -> UserClients
filterClients p (UserClients c) = UserClients $ Map.filter p c

newtype QualifiedUserClients = QualifiedUserClients
{ qualifiedUserClients :: Map Domain UserClients
}
deriving stock (Eq, Show, Generic)
deriving newtype (Semigroup, Monoid, FromJSON, ToJSON)

instance Arbitrary QualifiedUserClients where
arbitrary = QualifiedUserClients <$> mapOf' arbitrary arbitrary

instance ToSchema QualifiedUserClients where
declareNamedSchema _ = do
schema <- declareSchema (Proxy @(Map Domain UserClients))
userClientsSchema <- declareSchema (Proxy @UserClients)
return $
NamedSchema (Just "QualifiedUserClients") $
schema
& Swagger.description ?~ "Map of Domain to UserClients"
& example
?~ toJSON
(Map.singleton ("domain1.example.com" :: Text) (userClientsSchema ^. example))

--------------------------------------------------------------------------------
-- Client

Expand Down
43 changes: 23 additions & 20 deletions libs/wire-api/src/Wire/API/User/Client/Prekey.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,23 @@ module Wire.API.User.Client.Prekey
ClientPrekey (..),

-- * Swagger
modelPrekeyBundle,
modelClientPrekey,
modelPrekey,
)
where

import Data.Aeson
import Data.Data (Proxy (Proxy))
import Data.Hashable (hash)
import Data.Id
import Data.Swagger (ToSchema (..))
import qualified Data.Swagger.Build.Api as Doc
import Deriving.Swagger (CustomSwagger (..), FieldLabelModifier, LabelMapping ((:->)), LabelMappings, LowerCase, StripPrefix)
import Imports
import Wire.API.Arbitrary (Arbitrary (arbitrary), GenericUniform (..))

newtype PrekeyId = PrekeyId {keyId :: Word16}
deriving stock (Eq, Ord, Show, Generic)
deriving newtype (ToJSON, FromJSON, Arbitrary)
deriving newtype (ToJSON, FromJSON, Arbitrary, ToSchema)

--------------------------------------------------------------------------------
-- Prekey
Expand All @@ -57,7 +58,9 @@ data Prekey = Prekey
}
deriving stock (Eq, Show, Generic)
deriving (Arbitrary) via (GenericUniform Prekey)
deriving (ToSchema) via (CustomSwagger '[FieldLabelModifier (StripPrefix "prekey", LowerCase)] Prekey)

-- FUTUREWORK: Remove when 'NewClient' has ToSchema
modelPrekey :: Doc.Model
modelPrekey = Doc.defineModel "Prekey" $ do
Doc.description "Prekey"
Expand Down Expand Up @@ -88,6 +91,9 @@ newtype LastPrekey = LastPrekey
{unpackLastPrekey :: Prekey}
deriving stock (Eq, Show, Generic)

instance ToSchema LastPrekey where
declareNamedSchema _ = declareNamedSchema (Proxy @Prekey)

instance ToJSON LastPrekey where
toJSON = toJSON . unpackLastPrekey

Expand All @@ -113,19 +119,12 @@ lastPrekey = LastPrekey . Prekey lastPrekeyId
-- PrekeyBundle

data PrekeyBundle = PrekeyBundle
{ prekeyUser :: OpaqueUserId,
{ prekeyUser :: UserId,
prekeyClients :: [ClientPrekey]
}
deriving stock (Eq, Show, Generic)
deriving (Arbitrary) via (GenericUniform PrekeyBundle)

modelPrekeyBundle :: Doc.Model
modelPrekeyBundle = Doc.defineModel "PrekeyBundle" $ do
Doc.description "Prekeys of all clients of a single user"
Doc.property "user" Doc.bytes' $
Doc.description "User ID"
Doc.property "clients" (Doc.array (Doc.ref modelClientPrekey)) $
Doc.description "Prekeys of all clients"
deriving (ToSchema) via (CustomSwagger '[FieldLabelModifier (StripPrefix "prekey", LowerCase)] PrekeyBundle)

instance ToJSON PrekeyBundle where
toJSON k =
Expand All @@ -147,14 +146,18 @@ data ClientPrekey = ClientPrekey
}
deriving stock (Eq, Show, Generic)
deriving (Arbitrary) via (GenericUniform ClientPrekey)

modelClientPrekey :: Doc.Model
modelClientPrekey = Doc.defineModel "ClientPrekey" $ do
Doc.description "Prekey of a single client"
Doc.property "client" Doc.bytes' $
Doc.description "Client Id"
Doc.property "prekey" (Doc.ref modelPrekey) $
Doc.description "Prekey"
deriving
(ToSchema)
via ( CustomSwagger
'[ FieldLabelModifier
( LabelMappings
'[ "prekeyClient" ':-> "client",
"prekeyData" ':-> "prekey"
]
)
]
ClientPrekey
)

instance ToJSON ClientPrekey where
toJSON k =
Expand Down
Loading