diff --git a/CHANGELOG-draft.md b/CHANGELOG-draft.md index 77c1171514..8239b0c23d 100644 --- a/CHANGELOG-draft.md +++ b/CHANGELOG-draft.md @@ -6,6 +6,7 @@ THIS FILE ACCUMULATES THE RELEASE NOTES FOR THE UPCOMING RELEASE. ## API Changes +* Remove the long-deprecated `message` field in `POST /connections` (#1726) * Add `PUT /conversations/:domain/:cnv/name` (#1737) * Deprecate `PUT /conversations/:cnv/name` (#1737) @@ -17,6 +18,8 @@ THIS FILE ACCUMULATES THE RELEASE NOTES FOR THE UPCOMING RELEASE. ## Internal changes +* Rewrite the `POST /connections` endpoint to Servant (#1726) + ## Federation changes -* Ensure clients only receive messages meant for them in remote convs (#1739) \ No newline at end of file +* Ensure clients only receive messages meant for them in remote convs (#1739) diff --git a/libs/brig-types/src/Brig/Types/Connection.hs b/libs/brig-types/src/Brig/Types/Connection.hs index 3d6b37ff99..a606894f76 100644 --- a/libs/brig-types/src/Brig/Types/Connection.hs +++ b/libs/brig-types/src/Brig/Types/Connection.hs @@ -29,7 +29,6 @@ module Brig.Types.Connection UpdateConnectionsInternal (..), -- * re-exports - Message (..), Relation (..), UserConnection (..), ConnectionRequest (..), diff --git a/libs/wire-api/src/Wire/API/Connection.hs b/libs/wire-api/src/Wire/API/Connection.hs index 46e51e67d0..7b217f31e8 100644 --- a/libs/wire-api/src/Wire/API/Connection.hs +++ b/libs/wire-api/src/Wire/API/Connection.hs @@ -1,5 +1,4 @@ -{-# LANGUAGE GeneralizedNewtypeDeriving #-} -{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE StrictData #-} -- This file is part of the Wire Server implementation. @@ -26,7 +25,6 @@ module Wire.API.Connection ( -- * UserConnection UserConnection (..), UserConnectionList (..), - Message (..), Relation (..), RelationWithHistory (..), relationDropHistory, @@ -38,24 +36,23 @@ module Wire.API.Connection -- * Swagger modelConnectionList, modelConnection, - modelConnectionRequest, modelConnectionUpdate, ) where -import Data.Aeson -import Data.Aeson.Types (Parser) +import Control.Lens ((?~)) +import Data.Aeson as Aeson import Data.Attoparsec.ByteString (takeByteString) import Data.ByteString.Conversion import Data.Id import Data.Json.Util (UTCTimeMillis) import Data.Range +import qualified Data.Schema as P import qualified Data.Swagger.Build.Api as Doc -import Data.Swagger.Schema +import Data.Swagger.Schema as S import Data.Text as Text -import Deriving.Swagger (CamelToKebab, ConstructorTagModifier, CustomSwagger) import Imports -import Wire.API.Arbitrary (Arbitrary (arbitrary), GenericUniform (..)) +import Wire.API.Arbitrary (Arbitrary (..), GenericUniform (..)) -------------------------------------------------------------------------------- -- UserConnectionList @@ -68,6 +65,14 @@ data UserConnectionList = UserConnectionList } deriving stock (Eq, Show, Generic) deriving (Arbitrary) via (GenericUniform UserConnectionList) + deriving (FromJSON, ToJSON, S.ToSchema) via (P.Schema UserConnectionList) + +instance P.ToSchema UserConnectionList where + schema = + P.object "UserConnectionList" $ + UserConnectionList + <$> clConnections P..= P.field "connections" (P.array P.schema) + <*> clHasMore P..= P.fieldWithDocModifier "has_more" (P.description ?~ "Indicator that the server has more connections than returned.") P.schema modelConnectionList :: Doc.Model modelConnectionList = Doc.defineModel "UserConnectionList" $ do @@ -76,19 +81,6 @@ modelConnectionList = Doc.defineModel "UserConnectionList" $ do Doc.property "has_more" Doc.bool' $ Doc.description "Indicator that the server has more connections than returned." -instance ToJSON UserConnectionList where - toJSON (UserConnectionList l m) = - object - [ "connections" .= l, - "has_more" .= m - ] - -instance FromJSON UserConnectionList where - parseJSON = withObject "UserConnectionList" $ \o -> - UserConnectionList - <$> o .: "connections" - <*> o .: "has_more" - -------------------------------------------------------------------------------- -- UserConnection @@ -103,11 +95,21 @@ data UserConnection = UserConnection ucStatus :: Relation, -- | When 'ucStatus' was last changed ucLastUpdate :: UTCTimeMillis, - ucMessage :: Maybe Message, ucConvId :: Maybe ConvId } deriving stock (Eq, Show, Generic) deriving (Arbitrary) via (GenericUniform UserConnection) + deriving (FromJSON, ToJSON, S.ToSchema) via (P.Schema UserConnection) + +instance P.ToSchema UserConnection where + schema = + P.object "UserConnection" $ + UserConnection + <$> ucFrom P..= P.field "from" P.schema + <*> ucTo P..= P.field "to" P.schema + <*> ucStatus P..= P.field "status" P.schema + <*> ucLastUpdate P..= P.field "last_update" P.schema + <*> ucConvId P..= P.optField "conversation" Nothing P.schema modelConnection :: Doc.Model modelConnection = Doc.defineModel "Connection" $ do @@ -127,27 +129,6 @@ modelConnection = Doc.defineModel "Connection" $ do Doc.description "Conversation ID" Doc.optional -instance ToJSON UserConnection where - toJSON uc = - object - [ "from" .= ucFrom uc, - "to" .= ucTo uc, - "status" .= ucStatus uc, - "last_update" .= ucLastUpdate uc, - "message" .= ucMessage uc, - "conversation" .= ucConvId uc - ] - -instance FromJSON UserConnection where - parseJSON = withObject "user-connection" $ \o -> - UserConnection - <$> o .: "from" - <*> o .: "to" - <*> o .: "status" - <*> o .: "last_update" - <*> o .:? "message" - <*> o .:? "conversation" - -------------------------------------------------------------------------------- -- Relation @@ -165,7 +146,7 @@ data Relation MissingLegalholdConsent deriving stock (Eq, Ord, Show, Generic) deriving (Arbitrary) via (GenericUniform Relation) - deriving (ToSchema) via (CustomSwagger '[ConstructorTagModifier CamelToKebab] Relation) + deriving (FromJSON, ToJSON, S.ToSchema) via (P.Schema Relation) -- | 'updateConnectionInternal', requires knowledge of the previous state (before -- 'MissingLegalholdConsent'), but the clients don't need that information. To avoid having @@ -215,29 +196,22 @@ typeRelation = "missing-legalhold-consent" ] -instance ToJSON Relation where - toJSON = \case - Accepted -> "accepted" - Blocked -> "blocked" - Pending -> "pending" - Ignored -> "ignored" - Sent -> "sent" - Cancelled -> "cancelled" - MissingLegalholdConsent -> "missing-legalhold-consent" - -instance FromJSON Relation where - parseJSON (String "accepted") = return Accepted - parseJSON (String "blocked") = return Blocked - parseJSON (String "pending") = return Pending - parseJSON (String "ignored") = return Ignored - parseJSON (String "sent") = return Sent - parseJSON (String "cancelled") = return Cancelled - parseJSON (String "missing-legalhold-consent") = return MissingLegalholdConsent - parseJSON _ = mzero +instance P.ToSchema Relation where + schema = + P.enum @Text "Relation" $ + mconcat + [ P.element "accepted" Accepted, + P.element "blocked" Blocked, + P.element "pending" Pending, + P.element "ignored" Ignored, + P.element "sent" Sent, + P.element "cancelled" Cancelled, + P.element "missing-legalhold-consent" MissingLegalholdConsent + ] instance FromByteString Relation where parser = - takeByteString >>= \b -> case b of + takeByteString >>= \case "accepted" -> return Accepted "blocked" -> return Blocked "pending" -> return Pending @@ -257,21 +231,6 @@ instance ToByteString Relation where Cancelled -> "cancelled" MissingLegalholdConsent -> "missing-legalhold-consent" --------------------------------------------------------------------------------- --- Message - --- | Initial message sent along with a connection request. 1-256 characters. --- --- /Note 2019-03-28:/ some clients send it, but we have hidden it anyway in the UI since it --- works as a nice source of spam. TODO deprecate and remove. -newtype Message = Message {messageText :: Text} - deriving stock (Eq, Ord, Show, Generic) - deriving newtype (ToJSON) - deriving (Arbitrary) via (Ranged 1 256 Text) - -instance FromJSON Message where - parseJSON x = Message . fromRange <$> (parseJSON x :: Parser (Range 1 256 Text)) - -------------------------------------------------------------------------------- -- Requests @@ -280,61 +239,36 @@ data ConnectionRequest = ConnectionRequest { -- | Connection recipient crUser :: UserId, -- | Name of the conversation to be created - crName :: Text, - -- | Initial message - crMessage :: Message + -- FUTUREWORK investigate: shouldn't this name be optional? Do we use this name actually anywhere? + crName :: Range 1 256 Text } deriving stock (Eq, Show, Generic) + deriving (Arbitrary) via (GenericUniform ConnectionRequest) + deriving (FromJSON, ToJSON, S.ToSchema) via (P.Schema ConnectionRequest) -modelConnectionRequest :: Doc.Model -modelConnectionRequest = Doc.defineModel "ConnectionRequest" $ do - Doc.description "Connection request from one user to another" - Doc.property "user" Doc.bytes' $ - Doc.description "User ID of the user to request a connection with" - Doc.property "name" Doc.string' $ - Doc.description "Name of the (pending) conversation being initiated (1 - 256 characters)." - Doc.property "message" Doc.string' $ - Doc.description "The initial message in the request (1 - 256 characters)." - -instance ToJSON ConnectionRequest where - toJSON c = - object - [ "user" .= crUser c, - "name" .= crName c, - "message" .= crMessage c - ] - -instance FromJSON ConnectionRequest where - parseJSON = withObject "connection-request" $ \o -> - ConnectionRequest - <$> o .: "user" - <*> (fromRange <$> ((o .: "name") :: Parser (Range 1 256 Text))) - <*> o .: "message" - --- | TODO: make 'crName :: Range 1 256 Text' and derive this instance. -instance Arbitrary ConnectionRequest where - arbitrary = - ConnectionRequest - <$> arbitrary - <*> (fromRange <$> arbitrary @(Range 1 256 Text)) - <*> arbitrary +instance P.ToSchema ConnectionRequest where + schema = + P.object "ConnectionRequest" $ + ConnectionRequest + <$> crUser P..= P.fieldWithDocModifier "user" (P.description ?~ "user ID of the user to request a connection with") P.schema + <*> crName P..= P.fieldWithDocModifier "name" (P.description ?~ "Name of the (pending) conversation being initiated (1 - 256) characters)") P.schema -- | Payload type for "please change the status of this connection". -data ConnectionUpdate = ConnectionUpdate +newtype ConnectionUpdate = ConnectionUpdate { cuStatus :: Relation } deriving stock (Eq, Show, Generic) deriving (Arbitrary) via (GenericUniform ConnectionUpdate) + deriving (FromJSON, ToJSON, S.ToSchema) via (P.Schema ConnectionUpdate) + +instance P.ToSchema ConnectionUpdate where + schema = + P.object "ConnectionUpdate" $ + ConnectionUpdate + <$> cuStatus P..= P.fieldWithDocModifier "status" (P.description ?~ "New relation status") P.schema modelConnectionUpdate :: Doc.Model modelConnectionUpdate = Doc.defineModel "ConnectionUpdate" $ do Doc.description "Connection update" Doc.property "status" typeRelation $ Doc.description "New relation status" - -instance ToJSON ConnectionUpdate where - toJSON c = object ["status" .= cuStatus c] - -instance FromJSON ConnectionUpdate where - parseJSON = withObject "connection-update" $ \o -> - ConnectionUpdate <$> o .: "status" diff --git a/libs/wire-api/src/Wire/API/ErrorDescription.hs b/libs/wire-api/src/Wire/API/ErrorDescription.hs index f484f73a59..d9c0def1b3 100644 --- a/libs/wire-api/src/Wire/API/ErrorDescription.hs +++ b/libs/wire-api/src/Wire/API/ErrorDescription.hs @@ -221,6 +221,21 @@ type NotConnected = ErrorDescription 403 "not-connected" "Users are not connecte notConnected :: NotConnected notConnected = mkErrorDescription +type ConnectionLimitReached = ErrorDescription 403 "connection-limit" "Too many sent/accepted connections." + +connectionLimitReached :: ConnectionLimitReached +connectionLimitReached = mkErrorDescription + +type InvalidUser = ErrorDescription 400 "invalid-user" "Invalid user." + +invalidUser :: InvalidUser +invalidUser = mkErrorDescription + +type NoIdentity = ErrorDescription 403 "no-identity" "The user has no verified identity (email or phone number)." + +noIdentity :: forall code lbl desc. (NoIdentity ~ ErrorDescription code lbl desc) => Int -> NoIdentity +noIdentity n = ErrorDescription (Text.pack (symbolVal (Proxy @desc)) <> " (code " <> Text.pack (show n) <> ")") + type OperationDenied = ErrorDescription 403 "operation-denied" "Insufficient permissions" operationDenied :: Show perm => perm -> OperationDenied diff --git a/libs/wire-api/src/Wire/API/Event/Conversation.hs b/libs/wire-api/src/Wire/API/Event/Conversation.hs index d9438e4051..e1bfdc9978 100644 --- a/libs/wire-api/src/Wire/API/Event/Conversation.hs +++ b/libs/wire-api/src/Wire/API/Event/Conversation.hs @@ -337,6 +337,9 @@ instance ToSchema SimpleMember where data Connect = Connect { cRecipient :: UserId, + -- FUTUREWORK: As a follow-up from + -- https://github.com/wireapp/wire-server/pull/1726, the message field can + -- be removed from this event. cMessage :: Maybe Text, cName :: Maybe Text, cEmail :: Maybe Text diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs b/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs index 933362d46e..b31097c67a 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs @@ -33,17 +33,11 @@ import Servant hiding (Handler, JSON, addHeader, respond) import Servant.API.Generic import Servant.Swagger (HasSwagger (toSwagger)) import Servant.Swagger.Internal.Orphans () +import Wire.API.Connection import Wire.API.ErrorDescription - ( CanThrow, - EmptyErrorForLegacyReasons, - HandleNotFound, - MalformedPrekeys, - MissingAuth, - TooManyClients, - UserNotFound, - ) import Wire.API.Routes.MultiVerb import Wire.API.Routes.Public (ZConn, ZUser) +import Wire.API.Routes.Public.Util import Wire.API.Routes.QualifiedCapture import Wire.API.User import Wire.API.User.Client @@ -309,6 +303,34 @@ data Api routes = Api :> CaptureClientId "client" :> "prekeys" :> Get '[JSON] [PrekeyId], + -- + -- This endpoint can lead to the following events being sent: + -- - ConnectionUpdated event to self and other, if any side's connection state changes + -- - MemberJoin event to self and other, if joining an existing connect conversation (via galley) + -- - ConvCreate event to self, if creating a connect conversation (via galley) + -- - ConvConnect event to self, in some cases (via galley), + -- for details see 'Galley.API.Create.createConnectConversation' + -- + createConnection :: + routes :- Summary "Create a connection to another user." + :> CanThrow MissingLegalholdConsent + :> CanThrow InvalidUser + :> CanThrow ConnectionLimitReached + :> CanThrow NoIdentity + -- Config value 'setUserMaxConnections' value in production/by default + -- is currently 1000 and has not changed in the last few years. + -- While it would be more correct to use the config value here, that + -- might not be time well spent. + :> Description "You can have no more than 1000 connections in accepted or sent state" + :> ZUser + :> ZConn + :> "connections" + :> ReqBody '[JSON] ConnectionRequest + :> MultiVerb + 'POST + '[JSON] + (ResponsesForExistedCreated "Connection existed" "Connection was created" UserConnection) + (ResponseForExistedCreated UserConnection), searchContacts :: routes :- Summary "Search for users" :> ZUser diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Galley.hs b/libs/wire-api/src/Wire/API/Routes/Public/Galley.hs index 24a1087641..3a12ac4d85 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Galley.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Galley.hs @@ -41,6 +41,7 @@ import Wire.API.Message import Wire.API.Routes.MultiVerb import Wire.API.Routes.Public (ZConn, ZUser) import Wire.API.Routes.Public.Galley.Responses +import Wire.API.Routes.Public.Util import Wire.API.Routes.QualifiedCapture import Wire.API.ServantProto (Proto, RawProto) import Wire.API.Team.Conversation @@ -51,22 +52,7 @@ instance AsHeaders '[Header "Location" ConvId] Conversation Conversation where toHeaders c = Headers c (HCons (Header (qUnqualified (cnvQualifiedId c))) HNil) fromHeaders = getResponse -instance - (ResponseType r1 ~ a, ResponseType r2 ~ a) => - AsUnion '[r1, r2] (ConversationResponseFor a) - where - toUnion (ConversationExisted x) = Z (I x) - toUnion (ConversationCreated x) = S (Z (I x)) - - fromUnion (Z (I x)) = ConversationExisted x - fromUnion (S (Z (I x))) = ConversationCreated x - fromUnion (S (S x)) = case x of - -data ConversationResponseFor a - = ConversationExisted !a - | ConversationCreated !a - -type ConversationResponse = ConversationResponseFor Conversation +type ConversationResponse = ResponseForExistedCreated Conversation type ConversationHeaders = '[DescHeader "Location" "Conversation ID" ConvId] diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Util.hs b/libs/wire-api/src/Wire/API/Routes/Public/Util.hs new file mode 100644 index 0000000000..e3efc84ba1 --- /dev/null +++ b/libs/wire-api/src/Wire/API/Routes/Public/Util.hs @@ -0,0 +1,48 @@ +{-# LANGUAGE DerivingVia #-} +{-# OPTIONS_GHC -Wno-orphans #-} + +-- This file is part of the Wire Server implementation. +-- +-- Copyright (C) 2021 Wire Swiss GmbH +-- +-- 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 . + +module Wire.API.Routes.Public.Util where + +import Data.SOP (I (..), NS (..)) +import Servant.Swagger.Internal.Orphans () +import Wire.API.Routes.MultiVerb + +instance + (ResponseType r1 ~ a, ResponseType r2 ~ a) => + AsUnion '[r1, r2] (ResponseForExistedCreated a) + where + toUnion (Existed x) = Z (I x) + toUnion (Created x) = S (Z (I x)) + + fromUnion (Z (I x)) = Existed x + fromUnion (S (Z (I x))) = Created x + fromUnion (S (S x)) = case x of + +-- Note: order is important here; if you swap Existed with Created, the wrong +-- status codes will be returned. Keep the Order in ResponseForExistedCreated +-- and the corresponding type the same. +data ResponseForExistedCreated a + = Existed !a + | Created !a + +type ResponsesForExistedCreated eDesc cDesc a = + '[ Respond 200 eDesc a, + Respond 201 cDesc a + ] diff --git a/libs/wire-api/src/Wire/API/Swagger.hs b/libs/wire-api/src/Wire/API/Swagger.hs index 2d3989b03a..3777e1d354 100644 --- a/libs/wire-api/src/Wire/API/Swagger.hs +++ b/libs/wire-api/src/Wire/API/Swagger.hs @@ -57,7 +57,6 @@ models = Call.Config.modelRtcIceServer, Connection.modelConnectionList, Connection.modelConnection, - Connection.modelConnectionRequest, Connection.modelConnectionUpdate, Conversation.modelConversation, Conversation.modelConversations, diff --git a/libs/wire-api/test/golden/testObject_ConnectionRequest_user_1.json b/libs/wire-api/test/golden/testObject_ConnectionRequest_user_1.json index 548331fcd6..33ce331c17 100644 --- a/libs/wire-api/test/golden/testObject_ConnectionRequest_user_1.json +++ b/libs/wire-api/test/golden/testObject_ConnectionRequest_user_1.json @@ -1,5 +1,4 @@ { - "message": "X[l\u001d}\u0000c𣈚@\u0004b,{\u0002DSZ7\n\u0013\"V󳇉Wox𝌥*᷈q4IO\u001f\u000b]YJ\u0004!􍳘􃛁瑹\u001a:󿄟*b\u001a+4nByz7uF\u0003셇􀨚$𨴺􊰀<;9\u0015*\u0012&\r'*(^>C􄴦LxZ륬\u001b󲇯𨩹zM\u0016𣟧s􄸩i⌧\u000b𨟑􈄬\u0007dO\u000c\u0015l", "name": "$Sz%e泐9湬NfG a\u001a􍥰士\u0000kF\u000eq𘎖W\u0014K\u0010\u0004F1e\u000b\u0004Q1D󶸏𩞈R󰊠\u0008\u0010QNvP!i󿊤A雷\u0011fE􁱥𗜗􉟫+g~r%'J󱵟s\u00139/'󼆮󲫈𓅢w\u001d\u0006ㅘ􇝅<(o􀦬", "user": "00005686-0000-796a-0000-712b00006414" } diff --git a/libs/wire-api/test/golden/testObject_ConnectionRequest_user_2.json b/libs/wire-api/test/golden/testObject_ConnectionRequest_user_2.json index 20cd8230bc..f65dde6bd7 100644 --- a/libs/wire-api/test/golden/testObject_ConnectionRequest_user_2.json +++ b/libs/wire-api/test/golden/testObject_ConnectionRequest_user_2.json @@ -1,5 +1,4 @@ { - "message": "}k󲊔\u0000𐚺\u0013𣑛T.kjW@󲚕cㅏ􏂲n𝜰0\u0001pH,?^+󷉴8\u0002𤶞b\tF𐊎n\u0003!![\u000b󺐯3󳱌\u0002𝀵\u0015󵸲􅇫I􀻀La𨲸.碅󵰮33a\u0011H󺓶X𡰧𣷖pSyL2\"y\\8ꎴ󿄈@!F\u001cQ\u000c􃜻𦼗\u000e󱘯[!\u000e麪\u0006=uH󴼌㺨\u0003󻋣󰩞B2􃿍𑱃\u0000yy𢝴\u000c\"􌩢鑋!𢓿\u0017󻋟K 舧Z􃄌5.m󰁱n\u001c\u001ds頒JXo[8󸧹􃄙%\u0001}I|>\u00084aG4􍝌􎨳(U􇐍􉿗e4q\u0004\u0006\u0010\"𬺖Q*u|􉸾T}bT\u000ct\u0012UꜮ_Y\u0003􀼶v𗧅􇏆'󲙄.%󿠇v8\u001b;\u000bl>🖋s􂡋􄠈f\"\u0002\u0003𤘍", "name": "垏󿄣a𨪺\u000f$\u001b2&\u0012S<\u0011􊐙o󳜛𑐤U", "user": "00003697-0000-346d-0000-6baf00003034" } diff --git a/libs/wire-api/test/golden/testObject_ConnectionRequest_user_3.json b/libs/wire-api/test/golden/testObject_ConnectionRequest_user_3.json deleted file mode 100644 index 57fafed82e..0000000000 --- a/libs/wire-api/test/golden/testObject_ConnectionRequest_user_3.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "message": "􉈤󲚥\u0002\u0012\u001aj𩰙X\u001ez[r\u0010꼃L]zl𣦂\u0015", - "name": "e\u001cx膂IBV 5􎑇hWeYpU􃣠(\n딾\tn𨐺󲵽𤜅󴈔\u0007MNk 3V\u000c~𭮩XltD'\u0018𤡶􈖘g\u0015L3S\u0018𣂲􈲎煪莧Y\u0005󼲖T󱖃I𪴏E [\t􌝤!􈟌\u0014\u0011􇕊⃪jn'(cw\u0002\u0013󾔴\n\u0010T%\u0018𩓔`󾘜㸈|iGOZ\u0001R8FC\u00087黼\u001dN*dT#𭕙\\<\u0010?𣓃%\tZC+Ht௸;\u000f􃶕(𤀀H𦬊=P\u000e𧉽\u001buO*\\QM\u000c{r)~E\u000b!k􍴫W}1\u0017[𦿡a󿠏7/LM9𪭩隝pk\u0001>m􂳡1z􉝪\\𐇜𤙷\u001c5􈐣𗲿0\u0007\t󲵭a\u001a󴣽`XY\u001d^𐒩!ၘ\u001b냨Z뼽\u001f\u001a[R>\u001a*\u0012=X󴐝/UE\u0016􅙗𨙾>􊆍>\u0015\",\u0014", - "user": "0000302a-0000-1612-0000-459400001b2a" -} diff --git a/libs/wire-api/test/golden/testObject_ConnectionRequest_user_4.json b/libs/wire-api/test/golden/testObject_ConnectionRequest_user_4.json deleted file mode 100644 index e48c0c38ae..0000000000 --- a/libs/wire-api/test/golden/testObject_ConnectionRequest_user_4.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "message": "bJiQ􍌐m_\u0013!\u000bD㩄>京'eᘬ]1i㎛\u000fiy𣘃\t🖼)􎣗\u001aD|_慃\nDP\u0011>𨡰<󵛖\u0013\u0011\u001a0:Z1V\u0015\u0010j󴢀r🜼𪌺𠽊DgC&3┩0~󹄛S\u0018z:L\u001b]󽎺%xM󴇏ᙰ\u0019!64%v\u001bsj\u0014Io3$逖SH:N4𭠈Do䋞;|u跢u{&􃣒󰐲\u0014vX󳿒g\"O􋘆%􁷫ᔣ盍􊙯(\u000e\u0017\u0014-^F\u0010\u0013n𪽯𝘴\u0001whiU󵥙l\n􂾆s󽁛\u0010 􄁌􂲛\nu$*P􀲊R5w`𫁰U𣊻_5𥫎G\u0017\u000c~d\u00104", - "name": ".#Y󻇶\u0004D|<.╭\u0007@v󹬯Nn􂗨k󻺱f=M\u0000쀿彸Pd\u0018&s󿙰􆘎b\u001b󳖤G}󿞇\u0015iE\u000c\n|\u0013\t􆃾\u001d騃\u0002R&>∞\n\u0005􋨧8$󲤺G\u0008\u001eYA8.}!k*􌍀𬭮X󲲔^𘓥𫒞󳏋Z􍭬7X\u0002󵺣\"=&Sr^o􇓉`鼬/\n'𓍿8f\n𡅲{", - "user": "00005bd6-0000-77a4-0000-2a3600001251" -} diff --git a/libs/wire-api/test/golden/testObject_ConnectionRequest_user_8.json b/libs/wire-api/test/golden/testObject_ConnectionRequest_user_8.json deleted file mode 100644 index bd1d8f16df..0000000000 --- a/libs/wire-api/test/golden/testObject_ConnectionRequest_user_8.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "message": "u𗠶:@o\u0005W&\u0004_\u001f{𗗩L󾍽E\u0002䩩&\u0010\u0004󸤴\u0011[\u0007KU_\tC왛G8$doଉ󵹁ZU6\u0000\u001eT{4;mq󰃌󺿘\u001a𒉉\u0012\u0008􀵜|fs7􊢗\u0014\u0018⇊>^,K1l\u0004{t󾟀𩪋W\u00025𞠰rS\u0011i\u001d\u0007\u0004K6𦕔f69lZdw\u000c\n\u0013T𝡭#j\u001ey𥹦7󲱨un𭑯􈚱xa#5D\\\u00114\u0011𮡟􀮵?\u00070>Z𧹓v\u000b", - "name": "󺽑;𣶡W莡%vJ\u0011馶/#\r󵯝mUO𠉙5\u0001È⭝𢐨u\u0008\u0006K4\u0011\u0004`%)3\u0019\u0016\u0010uUqQP-\u0008\u0015╓\u0017\u001d*,1\u0003j󴂰h𩽬:ㇿ𦡀t\u0007\u000cH􋁺\u000b䶌TDxd\u0013\u0000<📅𧬨M7\u0011|C\ttLD􊑌􉐑[\u0007z􃛪y𥄖캹V8󽳄󰟚rRD \u0002𨚚􏙞F\u0010G\u001f{%;\u000buaJ\"\u0010!=D묡\u001b;~w>\u001a_\u0018'𝥶]~􂩛0\u000f󾎥\"\u0016'>\u000f4\u0015㭼\u0017[eFL\u000e%W$𨪓_􃨞]\u00135*>$u𣆅\u0001󶛍\u001d󹂓\u00134\u0008\u000b", - "user": "00001ab1-0000-6eb7-0000-71e900007867" -} diff --git a/libs/wire-api/test/golden/testObject_Message_user_1.json b/libs/wire-api/test/golden/testObject_Message_user_1.json deleted file mode 100644 index 2a7eade9b6..0000000000 --- a/libs/wire-api/test/golden/testObject_Message_user_1.json +++ /dev/null @@ -1 +0,0 @@ -"@󽰧n󰟨𫴗l`d\u00087󲯙ﻘ럢,8\u0004~\u001eA𧎨󸹼𣝦\u0008]\u0003f𡡛3n\u0014펹.99􋢷5\n9OqXR[`𐨯𦂙󲹹舽k\u0018􂐣1PK" diff --git a/libs/wire-api/test/golden/testObject_UserConnectionList_user_1.json b/libs/wire-api/test/golden/testObject_UserConnectionList_user_1.json index db9fd2888d..4d3bf2d37c 100644 --- a/libs/wire-api/test/golden/testObject_UserConnectionList_user_1.json +++ b/libs/wire-api/test/golden/testObject_UserConnectionList_user_1.json @@ -1,10 +1,8 @@ { "connections": [ { - "conversation": null, "from": "00000000-0000-0000-0000-000000000000", "last_update": "1864-05-09T06:44:37.367Z", - "message": "\u00188\u0002󼭔-󵈪z.a&Kho󴱐󺽾}9nF𪒲􁺜l\u0014q}\u001a\u0017󺋍m8#餑A􌡲􀲱}Z췅6r-/D*\u001fL󺄥􏻂D􆗉\u0019󹳬ꂛ%PZ5􅈬\\}퓞\u000fᖑ`󶡛'1xNcFhN|*󰵡\u0010\t瓏󺅎6\u0012/IK\u000e􁑑󸘟s𣽛\u0019BM*a󽈎~j\u000b#\u0011-D𭣺𘅁\u00057{𮓥N\u0017C!~😟EGS=\u0005󴋀\u000f󷙏ଡ଼b󸣚'K1\u0000E\u0002𧹴J1\u0000AI%툼QV&Z`O\u0019~Vu6t\"󸨦_I}a󻶚5󶡸Y#\u0017:U𢐵\u0007󼒭29^2t􆀜쥚dC𗏯\u0005\u0004\u001c,\"5.9;@\u0008`gl\u001dEp5\u0015\u0019.VYE_\u000c\u001a\u0004\u001c\u0005bRb;=􄷬󱰎a\u000en\u00151fF", "status": "pending", "to": "00000000-0000-0001-0000-000100000000" }, @@ -12,7 +10,6 @@ "conversation": "00000000-0000-0000-0000-000100000000", "from": "00000001-0000-0001-0000-000000000000", "last_update": "1864-05-09T00:43:52.049Z", - "message": "位\u0015O \u001ez𠥡\u001d󱼟𢎵\u00188:󺔂bQ(XKw}\u000c\t􏏙0䗼kx\u00070=󵥀;L\u000c*\u0010ko\u0019z^x2(󿛢\\ep뗂w𬸪71\n 3\u001d\u0004\u0004?z𥪟䏡->🛃a,𠟚j;-ﱻ\u0013󲨌(L\u0012󴃱\t{􋓊좙J\EOT!\1105112\1062593\29817\SUB:\1044767*b\SUB+4nByz7uF\62747\ETX\49479\1051162$\167226\1092608<;9\NAK*\DC2&\r'*(^>C\1068326LxZ\47468\ESC\991727\166521zM\SYN\145383s\1068585i\8999\v\165841\1081644\adO\f\NAKl" - } + unsafeRange + "$Sz%e\27856\&9\28268NfG a\SUB\1104240\22763\NULkF\SOq\99222W\DC4K\DLE\EOTF1e\v\EOTQ1D\1011215\169864R\983712\b\DLEQNvP!i\1045156A\63817\DC1f\63319E\1055845\96023\1087467+g~r%'J\990559s\DC39/'\1032622\993992\78178w\GS\ACK\12632\1079109<(o\1051052" } testObject_ConnectionRequest_user_2 :: ConnectionRequest testObject_ConnectionRequest_user_2 = ConnectionRequest - { crUser = Id (fromJust (UUID.fromString "00003697-0000-346d-0000-6baf00003034")), - crName = "\22415\1044771a\166586\SI$\ESC2&\DC2S<\DC1\1090585o\997147\70692U", - crMessage = - Message - { messageText = - "}k\991892\NUL\67258\DC3\144475T.kjW@\992917c\12623\1110194n\120624\&0\SOHpH,?^+\1012340\&8\STX\150942b\tF\66190n\ETX!![\v\1025071\&3\998476\STX\118837\NAK\1007154\1069547I\1052352La\167096.\30853\1006638\&33a\DC1H\1025270X\138279\146902pSyL2\"y\\8\41908\1044744@!F\FSQ\f\1062715\159511\SO\988719[!\60553\SO\40618\ACK=uH\1003276\16040\ETX\1028835\985694B2\1064909\72771\NULyy\141172\f\"\1100386\37963!\140543\ETB\1028831K \33319Z\1061132\&5.m\983153n\FS\GSs\38930JXo[8\1018361\1061145%\SOH}I|>\b4aG4\1103692\1108531(U\1078285\1089495e4q\EOT\62925\ACK\DLE\"\183958Q*u|\1089086T}bT\ft\DC2U\42798_Y\ETX\1052470v\96709\1078214'\992836\61708.%\1046535v8\ESC;\vl>\128395s\1058891\1067016f\"\STX\ETX\149005" - } - } - -testObject_ConnectionRequest_user_3 :: ConnectionRequest -testObject_ConnectionRequest_user_3 = - ConnectionRequest - { crUser = Id (fromJust (UUID.fromString "0000302a-0000-1612-0000-459400001b2a")), - crName = - "e\FSx\33154IBV 5\1107015hWeYpU\1063136(\n\46398\tn\164922\994685\149253\999956\aMNk 3V\f~\187305XltD'\CAN\149622\1082776g\NAKL3S\CAN\143538\1084558\29034\33703Y\ENQ\1035414T\988547I\175375E [\t\1099620!\1083340\DC4\DC1\1078602\8426jn'(cw\STX\DC3\1041716\n\DLET%\CAN\169172`\1041948\15880\58820|iGOZ\SOHR8FC\b7\40700\GSN*dT#\185689\\<\DLE?\144579%\tZC+Ht\3064;\SI\1064341(\147456H\158474=P\SO\160381\ESCuO*\\QM\f{r)~E\v!k\1105195W}1\ETB[\159713a\1046543\&7/LM9\174953\38557pk\SOH>m\1060065\&1z\1087338\\\66012\149111\FS5\1082403\97471\&0\a\t\994669a\SUB\1001725`XY\GS^\66729!\4184\ESC\45288Z\48957\US\SUB[R>\SUB*\DC2=X\1000477/UE\SYN\1070679\165502>\1089933>\NAK\",\DC4", - crMessage = Message {messageText = "\1085988\992933\STX\DC2\SUBj\171033X\RSz[r\DLE\44803L]zl\145794\NAK"} - } - -testObject_ConnectionRequest_user_4 :: ConnectionRequest -testObject_ConnectionRequest_user_4 = - ConnectionRequest - { crUser = Id (fromJust (UUID.fromString "00005bd6-0000-77a4-0000-2a3600001251")), - crName = - ".#Y\1028598\EOTD|<.\9581\a@v\1022767Nn\1058280k\1031857f=M\NUL\49215\24440Pd\CAN&s\1046128\1074702b\ESC\996772G}\1046407\NAKiE\f\n|\DC3\t\1073406\GS\39427\STXR&>\8734\n\ENQ\1096231\&8$\993594G\b\RSYA8.\DEL}!k*\1098560\183150X\59315\994452^\99557\177310\996299Z\1104748\&7X\STX\1007267\"=&Sr^o\1078473`\40748/\n'\78719\&8f\n\135538{", - crMessage = - Message - { messageText = - "bJiQ\1102608m_\DC3!\vD\14916>\20140'e\5676]1i\13211\SIiy\144899\t\128444)\1108183\SUBD|_\24899\nDP\DC1>\166000<\1005270\DC3\DC1\SUB0:Z1V\NAK\DLEj\1001600r\128828\172858\134986DgC&3\9513\&0~\1020187S\CANz:L\ESC]\1037242%xM\999887\5744\EM!64%\65366\ESCsj\DC4Io3$\36886SH:N4\186376Do\63628\17118;|u\36322u{&\1063122\984114\DC4vX\999378g\"O\1095174%\1056235\5411\30413\1091183(\SO\ETB\DC4-^F\DLE\DC3n\175983\120372\SOHwhiU\1005913l\n\1060742s\1036379\DLE \1065036\1059995\nu$*P\1051786R5w`\176240U\144059_5\154318G\ETB\f~d\DLE4" - } - } - -testObject_ConnectionRequest_user_8 :: ConnectionRequest -testObject_ConnectionRequest_user_8 = - ConnectionRequest - { crUser = Id (fromJust (UUID.fromString "00001ab1-0000-6eb7-0000-71e900007867")), - crName = - "\1027921;\146849W\33697%vJ\DC1\39350/#\r\1006557mUO\131673\&5\SOH\200\11101\140328u\b\ACKK4\DC1\EOT`%)3\EM\SYN\DLE\DELuUqQP-\b\NAK\9555\ETB\GS*,1\ETXj\999600h\171884:\12799\157760t\a\fH\1093754\v\19852TDxd\DC3\NUL<\128197\162600M7\DC1|C\ttLD\1090636\1086481[\az\1062634y\151830\DEL\52921V8\1039556\985050rRD \STX\165530\1111646F\DLEG\US{%;\vuaJ\"\DLE!=D\47905\ESC;~w>\SUB_\CAN'\121206]~\1059419\&0\SI\1041317\"\SYN'>\SI4\NAK\15228\ETB[e\DELFL\SO%W$\166547_\1063454\59649]\DC35*>$u\143749\SOH\1009357\GS\1020051\DC34\b\v", - crMessage = - Message - { messageText = - "u\96310:@o\ENQW&\EOT_\US{\95721L\1041277E\STX\19049&\DLE\EOT\1018164\DEL\DC1[\aKU_\tC\50779G8$do\2825\1007169ZU6\NUL\RST{4;mq\983244\62749\1028056\SUB\74313\DC2\b\1051996|fs7\1091735\DC4\CAN\8650>^,K1l\EOT{t\1042368\170635W\STX5\124976r\DELS\DC1i\GS\a\EOTK6\157012f69lZdw\f\n\DC3T\120941#j\RSy\155238\&7\994408un\185455\1083057xa#5\63326D\\\DC14\DC1\190559\1051573?\a0>Z\163411v\v" - } + { crUser = (Id (fromJust (UUID.fromString "00003697-0000-346d-0000-6baf00003034"))), + crName = unsafeRange "\22415\1044771a\166586\SI$\ESC2&\DC2S<\DC1\1090585o\997147\70692U" } diff --git a/libs/wire-api/test/unit/Test/Wire/API/Golden/Generated/Message_user.hs b/libs/wire-api/test/unit/Test/Wire/API/Golden/Generated/Message_user.hs deleted file mode 100644 index 38dc1bac6b..0000000000 --- a/libs/wire-api/test/unit/Test/Wire/API/Golden/Generated/Message_user.hs +++ /dev/null @@ -1,42 +0,0 @@ -{-# LANGUAGE OverloadedLists #-} - --- This file is part of the Wire Server implementation. --- --- Copyright (C) 2021 Wire Swiss GmbH --- --- 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 . -module Test.Wire.API.Golden.Generated.Message_user where - -import Wire.API.Connection (Message (..)) - -testObject_Message_user_1 :: Message -testObject_Message_user_1 = - Message - { messageText = - "@\1039399n\985064\179479l`d\b7\994265\65240\47074,8\EOT~\RSA\160680\1019516\145254\b]\ETXf\137307\&3n\DC4\54201.99\1095863\&5\n9OqXR[`\68143\155801\994937\33341k\CAN\1057827\&1PK" - } diff --git a/libs/wire-api/test/unit/Test/Wire/API/Golden/Generated/UserConnectionList_user.hs b/libs/wire-api/test/unit/Test/Wire/API/Golden/Generated/UserConnectionList_user.hs index 799afb9948..82d7d9fbce 100644 --- a/libs/wire-api/test/unit/Test/Wire/API/Golden/Generated/UserConnectionList_user.hs +++ b/libs/wire-api/test/unit/Test/Wire/API/Golden/Generated/UserConnectionList_user.hs @@ -21,19 +21,10 @@ module Test.Wire.API.Golden.Generated.UserConnectionList_user where import Data.Id (Id (Id)) import Data.Json.Util (readUTCTimeMillis) import qualified Data.UUID as UUID (fromString) -import Imports (Bool (False, True), Maybe (Just, Nothing), fromJust) +import Imports (Bool (..), Maybe (..), fromJust) import Wire.API.Connection - ( Message (Message, messageText), - Relation (Accepted, Pending), - UserConnection - ( UserConnection, - ucConvId, - ucFrom, - ucLastUpdate, - ucMessage, - ucStatus, - ucTo - ), + ( Relation (..), + UserConnection (..), UserConnectionList (..), ) @@ -46,13 +37,6 @@ testObject_UserConnectionList_user_1 = ucTo = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000000")), ucStatus = Pending, ucLastUpdate = fromJust (readUTCTimeMillis "1864-05-09T06:44:37.367Z"), - ucMessage = - Just - ( Message - { messageText = - "\CAN\DEL8\STX\1035092-\1004074z.a&Kho\1002576\1027966}9nF\173234\1056412l\DC4q}\SUB\ETB\1024717m8#\39185A\1099890\1051825}Z\52677\&6r-/D*\USL\1024293\1113794D\1074633\EM\1023212\41115%PZ5\1069612\\}\54494\SI\60922\5521`\1009755'1x\DELNcFhN|*\986465\DLE\t\29903\1024334\&6\DC2/IK\SO\1053777\1017375s\147291\EMBM\60429*a\1036814~j\v#\DC1-D\186618\98625\ENQ7{\189669N\ETBC!~\128543EGS=\ENQ\1000128\SI\1013327\2908b\1018074'K1\NULE\58916\STX\163444J1\NULAI%\53820QV&Z`O\EM~Vu6t\"\1018406_I}a\1031578\&5\1009784Y#\ETB:U\140341\a\1033389\&29^2t\1073180\51546dC\95215\ENQ\EOT\FS,\"5.9;@\b`gl\GSEp5\NAK\EM.VYE_\f\SUB\EOT\FS\ENQbRb;=\1068524\990222a\SOn\NAK1\63452fF" - } - ), ucConvId = Nothing }, UserConnection @@ -60,13 +44,6 @@ testObject_UserConnectionList_user_1 = ucTo = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000000")), ucStatus = Accepted, ucLastUpdate = fromJust (readUTCTimeMillis "1864-05-09T00:43:52.049Z"), - ucMessage = - Just - ( Message - { messageText = - "\20301\NAKO\DEL \RSz\133473\GS\991007\140213\CAN8:\1025282bQ(XKw}\f\t\1111001\&0\17916kx\a0=\1005888;L\f*\DLEko\EMz^x2(\1046242\\ep\46530w\63639\183850\&71\n 3\GS\EOT\EOT?z\154271\17377->\128707a,\133082j;-\64635\DC3\993804(L\DC2\999665\t{\1094858\51353 Routes Doc.ApiBuilder Handler () -sitemap o = do - Public.sitemap o - Public.apiDocs o +sitemap :: Routes Doc.ApiBuilder Handler () +sitemap = do + Public.sitemap + Public.apiDocs Internal.sitemap diff --git a/services/brig/src/Brig/API/Connection.hs b/services/brig/src/Brig/API/Connection.hs index 47144bcad1..be837b42f9 100644 --- a/services/brig/src/Brig/API/Connection.hs +++ b/services/brig/src/Brig/API/Connection.hs @@ -59,12 +59,13 @@ import System.Logger.Message import Wire.API.Connection (RelationWithHistory (..)) import qualified Wire.API.Conversation as Conv import Wire.API.ErrorDescription +import Wire.API.Routes.Public.Util (ResponseForExistedCreated (..)) createConnection :: UserId -> ConnectionRequest -> ConnId -> - ExceptT ConnectionError AppIO ConnectionResult + ExceptT ConnectionError AppIO (ResponseForExistedCreated UserConnection) createConnection self req conn = createConnectionToLocalUser self (crUser req) req conn @@ -73,8 +74,8 @@ createConnectionToLocalUser :: UserId -> ConnectionRequest -> ConnId -> - ExceptT ConnectionError AppIO ConnectionResult -createConnectionToLocalUser self crUser ConnectionRequest {crName, crMessage} conn = do + ExceptT ConnectionError AppIO (ResponseForExistedCreated UserConnection) +createConnectionToLocalUser self crUser ConnectionRequest {crName} conn = do when (self == crUser) $ throwE $ InvalidUser crUser @@ -97,28 +98,28 @@ createConnectionToLocalUser self crUser ConnectionRequest {crName, crMessage} co Just rs -> rs Nothing -> do checkLimit self - ConnectionCreated <$> insert Nothing Nothing + Created <$> insert Nothing Nothing where insert :: Maybe UserConnection -> Maybe UserConnection -> ExceptT ConnectionError AppIO UserConnection insert s2o o2s = lift $ do Log.info $ logConnection self crUser . msg (val "Creating connection") - cnv <- Intra.createConnectConv self crUser (Just crName) (Just crMessage) (Just conn) - s2o' <- Data.insertConnection self crUser SentWithHistory (Just crMessage) cnv - o2s' <- Data.insertConnection crUser self PendingWithHistory (Just crMessage) cnv + cnv <- Intra.createConnectConv self crUser (Just (fromRange crName)) (Just conn) + s2o' <- Data.insertConnection self crUser SentWithHistory cnv + o2s' <- Data.insertConnection crUser self PendingWithHistory cnv e2o <- ConnectionUpdated o2s' (ucStatus <$> o2s) <$> Data.lookupName self let e2s = ConnectionUpdated s2o' (ucStatus <$> s2o) Nothing mapM_ (Intra.onConnectionEvent self (Just conn)) [e2o, e2s] return s2o' - update :: UserConnection -> UserConnection -> ExceptT ConnectionError AppIO ConnectionResult + update :: UserConnection -> UserConnection -> ExceptT ConnectionError AppIO (ResponseForExistedCreated UserConnection) update s2o o2s = case (ucStatus s2o, ucStatus o2s) of (MissingLegalholdConsent, _) -> throwE $ InvalidTransition self Sent (_, MissingLegalholdConsent) -> throwE $ InvalidTransition self Sent - (Accepted, Accepted) -> return $ ConnectionExists s2o - (Accepted, Blocked) -> return $ ConnectionExists s2o - (Sent, Blocked) -> return $ ConnectionExists s2o + (Accepted, Accepted) -> return $ Existed s2o + (Accepted, Blocked) -> return $ Existed s2o + (Sent, Blocked) -> return $ Existed s2o (Blocked, _) -> throwE $ InvalidTransition self Sent (_, Blocked) -> change s2o SentWithHistory (_, Sent) -> accept s2o o2s @@ -127,7 +128,7 @@ createConnectionToLocalUser self crUser ConnectionRequest {crName, crMessage} co (_, Pending) -> resend s2o o2s (_, Cancelled) -> resend s2o o2s - accept :: UserConnection -> UserConnection -> ExceptT ConnectionError AppIO ConnectionResult + accept :: UserConnection -> UserConnection -> ExceptT ConnectionError AppIO (ResponseForExistedCreated UserConnection) accept s2o o2s = do when (ucStatus s2o `notElem` [Sent, Accepted]) $ checkLimit self @@ -144,9 +145,9 @@ createConnectionToLocalUser self crUser ConnectionRequest {crName, crMessage} co e2o <- lift $ ConnectionUpdated o2s' (Just $ ucStatus o2s) <$> Data.lookupName self let e2s = ConnectionUpdated s2o' (Just $ ucStatus s2o) Nothing lift $ mapM_ (Intra.onConnectionEvent self (Just conn)) [e2o, e2s] - return $ ConnectionExists s2o' + return $ Existed s2o' - resend :: UserConnection -> UserConnection -> ExceptT ConnectionError AppIO ConnectionResult + resend :: UserConnection -> UserConnection -> ExceptT ConnectionError AppIO (ResponseForExistedCreated UserConnection) resend s2o o2s = do when (ucStatus s2o `notElem` [Sent, Accepted]) $ checkLimit self @@ -154,10 +155,10 @@ createConnectionToLocalUser self crUser ConnectionRequest {crName, crMessage} co logConnection self (ucTo s2o) . msg (val "Resending connection request") s2o' <- insert (Just s2o) (Just o2s) - return $ ConnectionExists s2o' + return $ Existed s2o' - change :: UserConnection -> RelationWithHistory -> ExceptT ConnectionError AppIO ConnectionResult - change c s = ConnectionExists <$> lift (Data.updateConnection c s) + change :: UserConnection -> RelationWithHistory -> ExceptT ConnectionError AppIO (ResponseForExistedCreated UserConnection) + change c s = Existed <$> lift (Data.updateConnection c s) belongSameTeam :: AppIO Bool belongSameTeam = do diff --git a/services/brig/src/Brig/API/Error.hs b/services/brig/src/Brig/API/Error.hs index af50a8a7f1..6cc031076d 100644 --- a/services/brig/src/Brig/API/Error.hs +++ b/services/brig/src/Brig/API/Error.hs @@ -85,11 +85,11 @@ instance ToJSON Error where -- Error Mapping ---------------------------------------------------------- connError :: ConnectionError -> Error -connError TooManyConnections {} = StdError connectionLimitReached +connError TooManyConnections {} = StdError (errorDescriptionToWai connectionLimitReached) connError InvalidTransition {} = StdError invalidTransition connError NotConnected {} = StdError (errorDescriptionToWai notConnected) -connError InvalidUser {} = StdError invalidUser -connError ConnectNoIdentity {} = StdError (noIdentity 0) +connError InvalidUser {} = StdError (errorDescriptionToWai invalidUser) +connError ConnectNoIdentity {} = StdError (errorDescriptionToWai (noIdentity 0)) connError (ConnectBlacklistedUserKey k) = StdError $ foldKey (const blacklistedEmail) (const blacklistedPhone) k connError (ConnectInvalidEmail _ _) = StdError invalidEmail connError ConnectInvalidPhone {} = StdError invalidPhone @@ -147,11 +147,11 @@ changePhoneError (PhoneExists _) = StdError userKeyExists changePwError :: ChangePasswordError -> Error changePwError InvalidCurrentPassword = StdError badCredentials -changePwError ChangePasswordNoIdentity = StdError (noIdentity 1) +changePwError ChangePasswordNoIdentity = StdError (errorDescriptionToWai (noIdentity 1)) changePwError ChangePasswordMustDiffer = StdError changePasswordMustDiffer changeHandleError :: ChangeHandleError -> Error -changeHandleError ChangeHandleNoIdentity = StdError (noIdentity 2) +changeHandleError ChangeHandleNoIdentity = StdError (errorDescriptionToWai (noIdentity 2)) changeHandleError ChangeHandleExists = StdError handleExists changeHandleError ChangeHandleInvalid = StdError invalidHandle changeHandleError ChangeHandleManagedByScim = StdError $ propertyManagedByScim "handle" @@ -198,7 +198,7 @@ zauthError ZAuth.Unsupported = StdError authTokenUnsupported clientError :: ClientError -> Error clientError ClientNotFound = StdError (errorDescriptionToWai clientNotFound) clientError (ClientDataError e) = clientDataError e -clientError (ClientUserNotFound _) = StdError invalidUser +clientError (ClientUserNotFound _) = StdError (errorDescriptionToWai invalidUser) clientError ClientLegalHoldCannotBeRemoved = StdError can'tDeleteLegalHoldClient clientError ClientLegalHoldCannotBeAdded = StdError can'tAddLegalHoldClient clientError (ClientFederationError e) = fedError e @@ -211,7 +211,7 @@ fedError = StdError . federationErrorToWai idtError :: RemoveIdentityError -> Error idtError LastIdentity = StdError lastIdentity idtError NoPassword = StdError noPassword -idtError NoIdentity = StdError (noIdentity 3) +idtError NoIdentity = StdError (errorDescriptionToWai (noIdentity 3)) propDataError :: PropertiesDataError -> Error propDataError TooManyProperties = StdError tooManyProperties @@ -223,7 +223,7 @@ clientDataError ClientMissingAuth = StdError (errorDescriptionToWai missingAuthE clientDataError MalformedPrekeys = StdError (errorDescriptionToWai malformedPrekeys) deleteUserError :: DeleteUserError -> Error -deleteUserError DeleteUserInvalid = StdError invalidUser +deleteUserError DeleteUserInvalid = StdError (errorDescriptionToWai invalidUser) deleteUserError DeleteUserInvalidCode = StdError invalidCode deleteUserError DeleteUserInvalidPassword = StdError badCredentials deleteUserError DeleteUserMissingPassword = StdError (errorDescriptionToWai missingAuthError) @@ -253,21 +253,12 @@ propertyKeyTooLarge = Wai.mkError status403 "property-key-too-large" "The proper propertyValueTooLarge :: Wai.Error propertyValueTooLarge = Wai.mkError status403 "property-value-too-large" "The property value is too large" -connectionLimitReached :: Wai.Error -connectionLimitReached = Wai.mkError status403 "connection-limit" "Too many sent/accepted connections." - clientCapabilitiesCannotBeRemoved :: Wai.Error clientCapabilitiesCannotBeRemoved = Wai.mkError status409 "client-capabilities-cannot-be-removed" "You can only add capabilities to a client, not remove them." -invalidUser :: Wai.Error -invalidUser = Wai.mkError status400 "invalid-user" "Invalid user." - invalidTransition :: Wai.Error invalidTransition = Wai.mkError status403 "bad-conn-update" "Invalid status transition." -noIdentity :: Int -> Wai.Error -noIdentity i = Wai.mkError status403 "no-identity" ("The user has no verified identity (email or phone number). [code: " <> cs (show i) <> "]") - noEmail :: Wai.Error noEmail = Wai.mkError status403 "no-email" "This operation requires the user to have a verified email address." diff --git a/services/brig/src/Brig/API/Internal.hs b/services/brig/src/Brig/API/Internal.hs index 825c58a712..8bf0022036 100644 --- a/services/brig/src/Brig/API/Internal.hs +++ b/services/brig/src/Brig/API/Internal.hs @@ -72,7 +72,7 @@ import Servant.Swagger (HasSwagger (toSwagger)) import Servant.Swagger.Internal.Orphans () import Servant.Swagger.UI import qualified System.Logger.Class as Log -import Wire.API.ErrorDescription (userNotFound) +import Wire.API.ErrorDescription import Wire.API.User import Wire.API.User.Client (UserClientsFull (..)) import Wire.API.User.RichInfo @@ -589,7 +589,7 @@ updateUserNameH (uid ::: _ ::: body) = empty <$ (updateUserName uid =<< parseJso updateUserName :: UserId -> NameUpdate -> Handler () updateUserName uid (NameUpdate nameUpd) = do - name <- either (const $ throwStd invalidUser) pure $ mkName nameUpd + name <- either (const $ throwStd (errorDescriptionToWai invalidUser)) pure $ mkName nameUpd let uu = UserUpdate { uupName = Just name, @@ -599,7 +599,7 @@ updateUserName uid (NameUpdate nameUpd) = do } lift (Data.lookupUser WithPendingInvitations uid) >>= \case Just _ -> API.updateUser uid Nothing uu API.AllowSCIMUpdates !>> updateProfileError - Nothing -> throwStd invalidUser + Nothing -> throwStd (errorDescriptionToWai invalidUser) checkHandleInternalH :: Text -> Handler Response checkHandleInternalH = diff --git a/services/brig/src/Brig/API/Public.hs b/services/brig/src/Brig/API/Public.hs index 5db00dda25..f8741a7b84 100644 --- a/services/brig/src/Brig/API/Public.hs +++ b/services/brig/src/Brig/API/Public.hs @@ -98,6 +98,7 @@ import qualified Wire.API.Routes.Public.Brig as BrigAPI import qualified Wire.API.Routes.Public.Galley as GalleyAPI import qualified Wire.API.Routes.Public.LegalHold as LegalHoldAPI import qualified Wire.API.Routes.Public.Spar as SparAPI +import qualified Wire.API.Routes.Public.Util as Public import qualified Wire.API.Swagger as Public.Swagger (models) import qualified Wire.API.Team as Public import Wire.API.Team.LegalHold (LegalholdProtectee (..)) @@ -194,6 +195,7 @@ servantSitemap = BrigAPI.getClient = getClient, BrigAPI.getClientCapabilities = getClientCapabilities, BrigAPI.getClientPrekeys = getClientPrekeys, + BrigAPI.createConnection = createConnection, BrigAPI.searchContacts = Search.search } @@ -204,8 +206,8 @@ servantSitemap = -- - UserDeleted event to contacts of the user -- - MemberLeave event to members for all conversations the user was in (via galley) -sitemap :: Opts -> Routes Doc.ApiBuilder Handler () -sitemap o = do +sitemap :: Routes Doc.ApiBuilder Handler () +sitemap = do -- User Handle API ---------------------------------------------------- post "/users/handles" (continue checkHandlesH) $ @@ -296,7 +298,7 @@ sitemap o = do Doc.description "JSON body" Doc.response 200 "Password changed." Doc.end Doc.errorResponse badCredentials - Doc.errorResponse (noIdentity 4) + Doc.errorResponse (errorDescriptionToWai (noIdentity 4)) put "/self/locale" (continue changeLocaleH) $ zauthUserId @@ -389,33 +391,6 @@ sitemap o = do -- Connection API ----------------------------------------------------- - -- This endpoint can lead to the following events being sent: - -- - ConnectionUpdated event to self and other, if any side's connection state changes - -- - MemberJoin event to self and other, if joining an existing connect conversation (via galley) - -- - ConvCreate event to self, if creating a connect conversation (via galley) - -- - ConvConnect event to self, in some cases (via galley), - -- for details see 'Galley.API.Create.createConnectConversation' - post "/connections" (continue createConnectionH) $ - accept "application" "json" - .&. zauthUserId - .&. zauthConnId - .&. jsonRequest @Public.ConnectionRequest - document "POST" "createConnection" $ do - Doc.summary "Create a connection to another user." - Doc.notes $ - "You can have no more than " - <> Text.pack (show (setUserMaxConnections $ optSettings o)) - <> " connections in accepted or sent state." - Doc.body (Doc.ref Public.modelConnectionRequest) $ - Doc.description "JSON body" - Doc.returns (Doc.ref Public.modelConnection) - Doc.response 200 "The connection exists." Doc.end - Doc.response 201 "The connection was created." Doc.end - Doc.response 412 "The connection cannot be created (eg., due to legalhold policy conflict)." Doc.end - Doc.errorResponse connectionLimitReached - Doc.errorResponse invalidUser - Doc.errorResponse (noIdentity 5) - -- This endpoint is used to test /i/metrics, when this is servantified, please -- make sure some other endpoint is used to test that routes defined in this -- function are recorded and reported correctly in /i/metrics. @@ -456,10 +431,10 @@ sitemap o = do Doc.returns (Doc.ref Public.modelConnection) Doc.response 200 "Connection updated." Doc.end Doc.response 204 "No change." Doc.end - Doc.errorResponse connectionLimitReached + Doc.errorResponse (errorDescriptionToWai connectionLimitReached) Doc.errorResponse invalidTransition Doc.errorResponse (errorDescriptionToWai notConnected) - Doc.errorResponse invalidUser + Doc.errorResponse (errorDescriptionToWai invalidUser) get "/connections/:id" (continue getConnectionH) $ accept "application" "json" @@ -667,12 +642,12 @@ sitemap o = do Team.routesPublic Calling.routesPublic -apiDocs :: Opts -> Routes Doc.ApiBuilder Handler () -apiDocs o = +apiDocs :: Routes Doc.ApiBuilder Handler () +apiDocs = get "/users/api-docs" ( \(_ ::: url) k -> - let doc = mkSwaggerApi (decodeLatin1 url) Public.Swagger.models (sitemap o) + let doc = mkSwaggerApi (decodeLatin1 url) Public.Swagger.models sitemap in k $ json doc ) $ accept "application" "json" @@ -1114,13 +1089,9 @@ customerExtensionCheckBlockedDomains email = do when (domain `elem` blockedDomains) $ throwM $ customerExtensionBlockedDomain domain -createConnectionH :: JSON ::: UserId ::: ConnId ::: JsonRequest Public.ConnectionRequest -> Handler Response -createConnectionH (_ ::: self ::: conn ::: req) = do - cr <- parseJsonBody req - rs <- API.createConnection self cr conn !>> connError - return $ case rs of - ConnectionCreated c -> setStatus status201 $ json (c :: Public.UserConnection) - ConnectionExists c -> json (c :: Public.UserConnection) +createConnection :: UserId -> ConnId -> Public.ConnectionRequest -> Handler (Public.ResponseForExistedCreated Public.UserConnection) +createConnection self conn cr = do + API.createConnection self cr conn !>> connError updateConnectionH :: JSON ::: UserId ::: ConnId ::: UserId ::: JsonRequest Public.ConnectionUpdate -> Handler Response updateConnectionH (_ ::: self ::: conn ::: other ::: req) = do diff --git a/services/brig/src/Brig/API/Types.hs b/services/brig/src/Brig/API/Types.hs index 8241149efb..0c9e90e48e 100644 --- a/services/brig/src/Brig/API/Types.hs +++ b/services/brig/src/Brig/API/Types.hs @@ -64,10 +64,6 @@ data CreateUserTeam = CreateUserTeam createdTeamName :: !Text } -data ConnectionResult - = ConnectionCreated !UserConnection - | ConnectionExists !UserConnection - data ActivationResult = -- | The key/code was valid and successfully activated. ActivationSuccess !(Maybe UserIdentity) !Bool diff --git a/services/brig/src/Brig/Data/Connection.hs b/services/brig/src/Brig/Data/Connection.hs index 6f53afde9e..e3d83d5d15 100644 --- a/services/brig/src/Brig/Data/Connection.hs +++ b/services/brig/src/Brig/Data/Connection.hs @@ -55,13 +55,12 @@ insertConnection :: -- | To UserId -> RelationWithHistory -> - Maybe Message -> ConvId -> AppIO UserConnection -insertConnection from to status msg cid = do +insertConnection from to status cid = do now <- toUTCTimeMillis <$> liftIO getCurrentTime - retry x5 . write connectionInsert $ params Quorum (from, to, status, now, msg, cid) - return $ toUserConnection (from, to, status, now, msg, Just cid) + retry x5 . write connectionInsert $ params Quorum (from, to, status, now, cid) + return $ toUserConnection (from, to, status, now, Just cid) updateConnection :: UserConnection -> RelationWithHistory -> AppIO UserConnection updateConnection c@UserConnection {..} status = do @@ -153,14 +152,14 @@ deleteConnections u = do -- Queries -connectionInsert :: PrepQuery W (UserId, UserId, RelationWithHistory, UTCTimeMillis, Maybe Message, ConvId) () -connectionInsert = "INSERT INTO connection (left, right, status, last_update, message, conv) VALUES (?, ?, ?, ?, ?, ?)" +connectionInsert :: PrepQuery W (UserId, UserId, RelationWithHistory, UTCTimeMillis, ConvId) () +connectionInsert = "INSERT INTO connection (left, right, status, last_update, conv) VALUES (?, ?, ?, ?, ?)" connectionUpdate :: PrepQuery W (RelationWithHistory, UTCTimeMillis, UserId, UserId) () connectionUpdate = "UPDATE connection SET status = ?, last_update = ? WHERE left = ? AND right = ?" -connectionSelect :: PrepQuery R (UserId, UserId) (UserId, UserId, RelationWithHistory, UTCTimeMillis, Maybe Message, Maybe ConvId) -connectionSelect = "SELECT left, right, status, last_update, message, conv FROM connection WHERE left = ? AND right = ?" +connectionSelect :: PrepQuery R (UserId, UserId) (UserId, UserId, RelationWithHistory, UTCTimeMillis, Maybe ConvId) +connectionSelect = "SELECT left, right, status, last_update, conv FROM connection WHERE left = ? AND right = ?" relationSelect :: PrepQuery R (UserId, UserId) (Identity RelationWithHistory) relationSelect = "SELECT status FROM connection WHERE left = ? AND right = ?" @@ -174,11 +173,11 @@ connectionStatusSelect' = "SELECT left, right, status FROM connection WHERE left contactsSelect :: PrepQuery R (Identity UserId) (UserId, RelationWithHistory) contactsSelect = "SELECT right, status FROM connection WHERE left = ?" -connectionsSelect :: PrepQuery R (Identity UserId) (UserId, UserId, RelationWithHistory, UTCTimeMillis, Maybe Message, Maybe ConvId) -connectionsSelect = "SELECT left, right, status, last_update, message, conv FROM connection WHERE left = ? ORDER BY right ASC" +connectionsSelect :: PrepQuery R (Identity UserId) (UserId, UserId, RelationWithHistory, UTCTimeMillis, Maybe ConvId) +connectionsSelect = "SELECT left, right, status, last_update, conv FROM connection WHERE left = ? ORDER BY right ASC" -connectionsSelectFrom :: PrepQuery R (UserId, UserId) (UserId, UserId, RelationWithHistory, UTCTimeMillis, Maybe Message, Maybe ConvId) -connectionsSelectFrom = "SELECT left, right, status, last_update, message, conv FROM connection WHERE left = ? AND right > ? ORDER BY right ASC" +connectionsSelectFrom :: PrepQuery R (UserId, UserId) (UserId, UserId, RelationWithHistory, UTCTimeMillis, Maybe ConvId) +connectionsSelectFrom = "SELECT left, right, status, last_update, conv FROM connection WHERE left = ? AND right > ? ORDER BY right ASC" connectionDelete :: PrepQuery W (UserId, UserId) () connectionDelete = "DELETE FROM connection WHERE left = ? AND right = ?" @@ -188,8 +187,8 @@ connectionClear = "DELETE FROM connection WHERE left = ?" -- Conversions -toUserConnection :: (UserId, UserId, RelationWithHistory, UTCTimeMillis, Maybe Message, Maybe ConvId) -> UserConnection -toUserConnection (l, r, relationDropHistory -> rel, time, msg, cid) = UserConnection l r rel time msg cid +toUserConnection :: (UserId, UserId, RelationWithHistory, UTCTimeMillis, Maybe ConvId) -> UserConnection +toUserConnection (l, r, relationDropHistory -> rel, time, cid) = UserConnection l r rel time cid toConnectionStatus :: (UserId, UserId, RelationWithHistory) -> ConnectionStatus toConnectionStatus (l, r, relationDropHistory -> rel) = ConnectionStatus l r rel diff --git a/services/brig/src/Brig/Data/Instances.hs b/services/brig/src/Brig/Data/Instances.hs index b282291623..e6b7254b29 100644 --- a/services/brig/src/Brig/Data/Instances.hs +++ b/services/brig/src/Brig/Data/Instances.hs @@ -48,8 +48,6 @@ deriving instance Cql ColourId deriving instance Cql Phone -deriving instance Cql Message - deriving instance Cql InvitationCode deriving instance Cql PasswordResetKey diff --git a/services/brig/src/Brig/IO/Intra.hs b/services/brig/src/Brig/IO/Intra.hs index 536e7c9a85..951c65c582 100644 --- a/services/brig/src/Brig/IO/Intra.hs +++ b/services/brig/src/Brig/IO/Intra.hs @@ -532,8 +532,8 @@ createSelfConv u = do . expect2xx -- | Calls 'Galley.API.createConnectConversationH'. -createConnectConv :: UserId -> UserId -> Maybe Text -> Maybe Message -> Maybe ConnId -> AppIO ConvId -createConnectConv from to cname mess conn = do +createConnectConv :: UserId -> UserId -> Maybe Text -> Maybe ConnId -> AppIO ConvId +createConnectConv from to cname conn = do debug $ logConnection from to . remote "galley" @@ -548,7 +548,7 @@ createConnectConv from to cname mess conn = do . zUser from . maybe id (header "Z-Connection" . fromConnId) conn . contentJson - . lbytes (encode $ Connect to (messageText <$> mess) cname Nothing) + . lbytes (encode $ Connect to Nothing cname Nothing) . expect2xx -- | Calls 'Galley.API.acceptConvH'. diff --git a/services/brig/src/Brig/Provider/API.hs b/services/brig/src/Brig/Provider/API.hs index 3840df84b2..55ba100025 100644 --- a/services/brig/src/Brig/Provider/API.hs +++ b/services/brig/src/Brig/Provider/API.hs @@ -1086,7 +1086,7 @@ maybeInvalidBot :: Maybe a -> Handler a maybeInvalidBot = maybe (throwStd invalidBot) return maybeInvalidUser :: Maybe a -> Handler a -maybeInvalidUser = maybe (throwStd invalidUser) return +maybeInvalidUser = maybe (throwStd (errorDescriptionToWai invalidUser)) return rangeChecked :: Within a n m => a -> Handler (Range n m a) rangeChecked = either (throwStd . invalidRange . fromString) return . checkedEither diff --git a/services/brig/src/Brig/Run.hs b/services/brig/src/Brig/Run.hs index 652db82c14..7cde35593d 100644 --- a/services/brig/src/Brig/Run.hs +++ b/services/brig/src/Brig/Run.hs @@ -107,11 +107,11 @@ mkApp o = do return (middleware e $ \reqId -> servantApp (e & requestId .~ reqId), e) where rtree :: Tree (App Handler) - rtree = compile (sitemap o) + rtree = compile sitemap middleware :: Env -> (RequestId -> Wai.Application) -> Wai.Application middleware e = - Metrics.servantPlusWAIPrometheusMiddleware (sitemap o) (Proxy @ServantCombinedAPI) + Metrics.servantPlusWAIPrometheusMiddleware sitemap (Proxy @ServantCombinedAPI) . GZip.gunzip . GZip.gzip GZip.def . catchErrors (e ^. applog) [Right $ e ^. metrics] diff --git a/services/brig/src/Brig/Team/API.hs b/services/brig/src/Brig/Team/API.hs index f1583b7cc5..f3a069dfc3 100644 --- a/services/brig/src/Brig/Team/API.hs +++ b/services/brig/src/Brig/Team/API.hs @@ -64,6 +64,7 @@ import qualified Network.Wai.Utilities.Swagger as Doc import System.Logger (Msg) import qualified System.Logger.Class as Log import Util.Logging (logFunction, logTeam) +import Wire.API.ErrorDescription import qualified Wire.API.Team.Invitation as Public import qualified Wire.API.Team.Role as Public import qualified Wire.API.Team.Size as Public @@ -88,7 +89,7 @@ routesPublic = do Doc.returns (Doc.ref Public.modelTeamInvitation) Doc.response 201 "Invitation was created and sent." Doc.end Doc.errorResponse noEmail - Doc.errorResponse (noIdentity 6) + Doc.errorResponse (errorDescriptionToWai (noIdentity 6)) Doc.errorResponse invalidEmail Doc.errorResponse blacklistedEmail Doc.errorResponse tooManyTeamInvitations @@ -256,7 +257,7 @@ createInvitationPublic uid tid body = do let inviteeRole = fromMaybe Team.defaultRole . irRole $ body inviter <- do let inviteePerms = Team.rolePermissions inviteeRole - idt <- maybe (throwStd (noIdentity 7)) return =<< lift (fetchUserIdentity uid) + idt <- maybe (throwStd (errorDescriptionToWai (noIdentity 7))) return =<< lift (fetchUserIdentity uid) from <- maybe (throwStd noEmail) return (emailIdentity idt) ensurePermissionToAddUser uid tid inviteePerms pure $ CreateInvitationInviter uid from diff --git a/services/brig/test/integration/Main.hs b/services/brig/test/integration/Main.hs index 5f11bc49f2..b612166de0 100644 --- a/services/brig/test/integration/Main.hs +++ b/services/brig/test/integration/Main.hs @@ -143,7 +143,7 @@ runTests iConf brigOpts otherArgs = do assertEqual "inconcistent sitemap" mempty - (pathsConsistencyCheck . treeToPaths . compile $ Brig.API.sitemap brigOpts), + (pathsConsistencyCheck . treeToPaths . compile $ Brig.API.sitemap), userApi, providerApi, searchApis, diff --git a/services/brig/test/integration/Util.hs b/services/brig/test/integration/Util.hs index c904204c40..d33c4d61c3 100644 --- a/services/brig/test/integration/Util.hs +++ b/services/brig/test/integration/Util.hs @@ -54,6 +54,7 @@ import Data.List1 (List1) import qualified Data.List1 as List1 import Data.Misc (PlainTextPassword (..)) import Data.Qualified (Qualified (qDomain, qUnqualified)) +import Data.Range import qualified Data.Text as Text import qualified Data.Text.Ascii as Ascii import Data.Text.Encoding (encodeUtf8) @@ -406,7 +407,7 @@ postConnection brig from to = where payload = RequestBodyLBS . encode $ - ConnectionRequest to "some conv name" (Message "some message") + ConnectionRequest to (unsafeRange "some conv name") putConnection :: Brig -> UserId -> UserId -> Relation -> (MonadIO m, MonadHttp m) => m ResponseLBS putConnection brig from to r = diff --git a/services/galley/schema/src/Main.hs b/services/galley/schema/src/Main.hs index cbe7fb2c4b..afb480e02c 100644 --- a/services/galley/schema/src/Main.hs +++ b/services/galley/schema/src/Main.hs @@ -98,6 +98,12 @@ main = do V52_FeatureConferenceCalling.migration -- When adding migrations here, don't forget to update -- 'schemaVersion' in Galley.Data + -- (see also docs/developer/cassandra-interaction.md) + -- + -- FUTUREWORK: once #1726 has made its way to master/production, + -- the 'message' field in connections table can be dropped. + -- See also https://github.com/wireapp/wire-server/pull/1747/files + -- for an explanation ] `finally` Log.close l where diff --git a/services/galley/src/Galley/API/Create.hs b/services/galley/src/Galley/API/Create.hs index 8167c2551e..52921e4e5a 100644 --- a/services/galley/src/Galley/API/Create.hs +++ b/services/galley/src/Galley/API/Create.hs @@ -50,10 +50,8 @@ import Network.Wai.Predicate hiding (setStatus) import Network.Wai.Utilities import qualified Wire.API.Conversation as Public import Wire.API.ErrorDescription (missingLegalholdConsent) -import Wire.API.Routes.Public.Galley - ( ConversationResponse, - ConversationResponseFor (..), - ) +import Wire.API.Routes.Public.Galley (ConversationResponse) +import Wire.API.Routes.Public.Util import Wire.API.Team.LegalHold (LegalholdProtectee (LegalholdPlusFederationNotImplemented)) ---------------------------------------------------------------------------- @@ -305,15 +303,15 @@ createConnectConversation usr conn j = do -- Helpers conversationCreated :: UserId -> Data.Conversation -> Galley ConversationResponse -conversationCreated usr cnv = ConversationCreated <$> conversationView usr cnv +conversationCreated usr cnv = Created <$> conversationView usr cnv conversationExisted :: UserId -> Data.Conversation -> Galley ConversationResponse -conversationExisted usr cnv = ConversationExisted <$> conversationView usr cnv +conversationExisted usr cnv = Existed <$> conversationView usr cnv handleConversationResponse :: ConversationResponse -> Response handleConversationResponse = \case - ConversationCreated cnv -> json cnv & setStatus status201 . location (qUnqualified . cnvQualifiedId $ cnv) - ConversationExisted cnv -> json cnv & setStatus status200 . location (qUnqualified . cnvQualifiedId $ cnv) + Created cnv -> json cnv & setStatus status201 . location (qUnqualified . cnvQualifiedId $ cnv) + Existed cnv -> json cnv & setStatus status200 . location (qUnqualified . cnvQualifiedId $ cnv) notifyCreatedConversation :: Maybe UTCTime -> UserId -> Maybe ConnId -> Data.Conversation -> Galley () notifyCreatedConversation dtime usr conn c = do diff --git a/services/galley/test/integration/API/Util.hs b/services/galley/test/integration/API/Util.hs index 0d516aad89..d98e3ad618 100644 --- a/services/galley/test/integration/API/Util.hs +++ b/services/galley/test/integration/API/Util.hs @@ -1478,7 +1478,7 @@ connectUsersWith fn u = mapM connectTo . zUser u . zConn "conn" . path "/connections" - . json (ConnectionRequest v "chat" (Message "Y")) + . json (ConnectionRequest v (unsafeRange "chat")) . fn ) r2 <- @@ -1506,7 +1506,7 @@ postConnection from to = do where payload = RequestBodyLBS . encode $ - ConnectionRequest to "some conv name" (Message "some message") + ConnectionRequest to (unsafeRange "some conv name") -- | A copy of 'putConnection' from Brig integration tests. putConnection :: UserId -> UserId -> Relation -> TestM ResponseLBS diff --git a/tools/api-simulations/lib/src/Network/Wire/Simulations.hs b/tools/api-simulations/lib/src/Network/Wire/Simulations.hs index ccbf6a6567..eaa8035040 100644 --- a/tools/api-simulations/lib/src/Network/Wire/Simulations.hs +++ b/tools/api-simulations/lib/src/Network/Wire/Simulations.hs @@ -50,6 +50,7 @@ import Data.ByteString.Conversion import Data.Id (ConvId, UserId) import qualified Data.Map.Strict as Map import Data.Qualified (qUnqualified) +import Data.Range import Data.Serialize import qualified Data.Set as Set import qualified Data.Text as Text @@ -98,7 +99,7 @@ connectIfNeeded = go 6 -- six turns should be enough case s of -- If no connection: initiate one Nothing -> do - void $ connectTo (ConnectionRequest (botId b) (fromMaybe "" (botEmail a)) (Message "Hi there!")) + void $ connectTo (ConnectionRequest (botId b) (unsafeRange (fromMaybe "" (botEmail a)))) assertConnectRequested a b return False -- If there's a pending connection to us: accept it diff --git a/tools/api-simulations/smoketest/src/Network/Wire/Simulations/SmokeTest.hs b/tools/api-simulations/smoketest/src/Network/Wire/Simulations/SmokeTest.hs index f4a08202f4..ad421ffe9f 100644 --- a/tools/api-simulations/smoketest/src/Network/Wire/Simulations/SmokeTest.hs +++ b/tools/api-simulations/smoketest/src/Network/Wire/Simulations/SmokeTest.hs @@ -29,6 +29,7 @@ import qualified Data.ByteString.Lazy as LBS import Data.Id (ConvId) import Data.List1 import Data.Qualified (qUnqualified) +import Data.Range import Imports import Network.Wire.Bot import Network.Wire.Bot.Assert @@ -64,8 +65,7 @@ mainBotNet n = do connectTo ConnectionRequest { crUser = botId user, - crName = fromMaybe "" (botEmail ally), - crMessage = Message "Hi there!" + crName = unsafeRange $ fromMaybe "" (botEmail ally) } assertConnectRequested ally user requireMaybe (ucConvId conn) "conv_id not set after connection request"