From 7034a6c04715eff57c8edae6bf47ea3827666446 Mon Sep 17 00:00:00 2001 From: Paolo Capriotti Date: Thu, 17 Oct 2024 10:43:48 +0200 Subject: [PATCH 01/19] Fix simple openapi spec violations --- libs/types-common/src/Data/Range.hs | 12 ++++++------ libs/wire-api/src/Wire/API/Call/Config.hs | 4 ++-- libs/wire-api/src/Wire/API/Conversation/Protocol.hs | 2 +- libs/wire-api/src/Wire/API/Event/Conversation.hs | 2 +- libs/wire-api/src/Wire/API/Provider/Service/Tag.hs | 2 +- libs/wire-api/src/Wire/API/Team/Invitation.hs | 2 +- libs/wire-api/src/Wire/API/User/Orphans.hs | 6 +++++- 7 files changed, 17 insertions(+), 13 deletions(-) diff --git a/libs/types-common/src/Data/Range.hs b/libs/types-common/src/Data/Range.hs index c4401541756..b2dd1b60332 100644 --- a/libs/types-common/src/Data/Range.hs +++ b/libs/types-common/src/Data/Range.hs @@ -225,20 +225,20 @@ instance (ToParamSchema a, KnownNat n, KnownNat m) => ToParamSchema (Range n m [ instance (KnownNat n, KnownNat m) => ToParamSchema (Range n m String) where toParamSchema _ = toParamSchema (Proxy @String) - & S.maxLength ?~ fromKnownNat (Proxy @n) - & S.minLength ?~ fromKnownNat (Proxy @m) + & S.minLength ?~ fromKnownNat (Proxy @n) + & S.maxLength ?~ fromKnownNat (Proxy @m) instance (KnownNat n, KnownNat m) => ToParamSchema (Range n m T.Text) where toParamSchema _ = toParamSchema (Proxy @T.Text) - & S.maxLength ?~ fromKnownNat (Proxy @n) - & S.minLength ?~ fromKnownNat (Proxy @m) + & S.minLength ?~ fromKnownNat (Proxy @n) + & S.maxLength ?~ fromKnownNat (Proxy @m) instance (KnownNat n, KnownNat m) => ToParamSchema (Range n m TL.Text) where toParamSchema _ = toParamSchema (Proxy @TL.Text) - & S.maxLength ?~ fromKnownNat (Proxy @n) - & S.minLength ?~ fromKnownNat (Proxy @m) + & S.minLength ?~ fromKnownNat (Proxy @n) + & S.maxLength ?~ fromKnownNat (Proxy @m) instance (KnownNat n, S.ToSchema a, KnownNat m) => S.ToSchema (Range n m a) where declareNamedSchema _ = diff --git a/libs/wire-api/src/Wire/API/Call/Config.hs b/libs/wire-api/src/Wire/API/Call/Config.hs index 889b8ffd1bf..e0fafcf1f6f 100644 --- a/libs/wire-api/src/Wire/API/Call/Config.hs +++ b/libs/wire-api/src/Wire/API/Call/Config.hs @@ -466,7 +466,7 @@ mkSFTUsername shared expires rnd = } instance ToSchema SFTUsername where - schema = toText .= parsedText "" fromText + schema = toText .= parsedText "SFTUsername" fromText where fromText :: Text -> Either String SFTUsername fromText = parseOnly (parseSFTUsername <* endOfInput) @@ -543,7 +543,7 @@ turnUsername expires rnd = } instance ToSchema TurnUsername where - schema = toText .= parsedText "" fromText + schema = toText .= parsedText "TurnUsername" fromText where fromText :: Text -> Either String TurnUsername fromText = parseOnly (parseTurnUsername <* endOfInput) diff --git a/libs/wire-api/src/Wire/API/Conversation/Protocol.hs b/libs/wire-api/src/Wire/API/Conversation/Protocol.hs index 17870c6a249..ef4be957f28 100644 --- a/libs/wire-api/src/Wire/API/Conversation/Protocol.hs +++ b/libs/wire-api/src/Wire/API/Conversation/Protocol.hs @@ -108,7 +108,7 @@ optionalActiveMLSConversationDataSchema (Just v) (description ?~ "The epoch number of the corresponding MLS group") schema <*> fmap (.epochTimestamp) - .= field "epoch_timestamp" (named "Epoch Timestamp" . nullable . unnamed $ utcTimeSchema) + .= field "epoch_timestamp" (named "EpochTimestamp" . nullable . unnamed $ utcTimeSchema) <*> maybe MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519 (.ciphersuite) .= fieldWithDocModifier "cipher_suite" diff --git a/libs/wire-api/src/Wire/API/Event/Conversation.hs b/libs/wire-api/src/Wire/API/Event/Conversation.hs index f06e8d62973..74d537136a4 100644 --- a/libs/wire-api/src/Wire/API/Event/Conversation.hs +++ b/libs/wire-api/src/Wire/API/Event/Conversation.hs @@ -409,7 +409,7 @@ taggedEventDataSchema = memberLeaveSchema :: ValueSchema NamedSwaggerDoc (EdMemberLeftReason, QualifiedUserIdList) memberLeaveSchema = - object "QualifiedUserIdList with EdMemberLeftReason" $ + object "QualifiedUserIdList_with_EdMemberLeftReason" $ (,) <$> fst .= field "reason" schema <*> snd .= qualifiedUserIdListObjectSchema instance ToSchema Event where diff --git a/libs/wire-api/src/Wire/API/Provider/Service/Tag.hs b/libs/wire-api/src/Wire/API/Provider/Service/Tag.hs index 4b0d8e1c848..95aaaebab1d 100644 --- a/libs/wire-api/src/Wire/API/Provider/Service/Tag.hs +++ b/libs/wire-api/src/Wire/API/Provider/Service/Tag.hs @@ -180,7 +180,7 @@ instance ToByteString ServiceTag where builder WeatherTag = "weather" instance ToSchema ServiceTag where - schema = enum @Text "" . mconcat $ (\a -> element (decodeUtf8With lenientDecode $ toStrict $ toByteString a) a) <$> [minBound ..] + schema = enum @Text "ServiceTag" . mconcat $ (\a -> element (decodeUtf8With lenientDecode $ toStrict $ toByteString a) a) <$> [minBound ..] instance S.ToParamSchema ServiceTag where toParamSchema _ = diff --git a/libs/wire-api/src/Wire/API/Team/Invitation.hs b/libs/wire-api/src/Wire/API/Team/Invitation.hs index f195b4072ce..49fe051705a 100644 --- a/libs/wire-api/src/Wire/API/Team/Invitation.hs +++ b/libs/wire-api/src/Wire/API/Team/Invitation.hs @@ -118,7 +118,7 @@ instance ToSchema Invitation where <*> (fmap (TE.decodeUtf8 . serializeURIRef') . inviteeUrl) .= optFieldWithDocModifier "url" (description ?~ "URL of the invitation link to be sent to the invitee") (maybeWithDefault A.Null urlSchema) where - urlSchema = parsedText "URIRef Absolute" (runParser (uriParser strictURIParserOptions) . TE.encodeUtf8) + urlSchema = parsedText "URIRef_Absolute" (runParser (uriParser strictURIParserOptions) . TE.encodeUtf8) newtype InvitationLocation = InvitationLocation { unInvitationLocation :: ByteString diff --git a/libs/wire-api/src/Wire/API/User/Orphans.hs b/libs/wire-api/src/Wire/API/User/Orphans.hs index 0f019fdc1f9..316889c115a 100644 --- a/libs/wire-api/src/Wire/API/User/Orphans.hs +++ b/libs/wire-api/src/Wire/API/User/Orphans.hs @@ -103,7 +103,11 @@ instance ToSchema (SAML.FormRedirect SAML.AuthnRequest) where & properties . at "xml" ?~ authnReqSchema instance ToSchema (SAML.ID SAML.AuthnRequest) where - declareNamedSchema = genericDeclareNamedSchema samlSchemaOptions + declareNamedSchema = + genericDeclareNamedSchema + samlSchemaOptions + { datatypeNameModifier = const "Id_AuthnRequest" + } instance ToSchema SAML.Time where declareNamedSchema = genericDeclareNamedSchema samlSchemaOptions From ceb8ff2ce2af152694237a9571393dba9780a457 Mon Sep 17 00:00:00 2001 From: Paolo Capriotti Date: Mon, 21 Oct 2024 11:11:10 +0200 Subject: [PATCH 02/19] Add operation IDs to swagger --- .../src/Wire/API/Federation/Endpoint.hs | 1 + libs/wire-api/src/Wire/API/Routes/Named.hs | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/libs/wire-api-federation/src/Wire/API/Federation/Endpoint.hs b/libs/wire-api-federation/src/Wire/API/Federation/Endpoint.hs index 910a6c2d4b1..cc565259e44 100644 --- a/libs/wire-api-federation/src/Wire/API/Federation/Endpoint.hs +++ b/libs/wire-api-federation/src/Wire/API/Federation/Endpoint.hs @@ -35,6 +35,7 @@ data Versioned v name instance {-# OVERLAPPING #-} (RenderableSymbol a) => RenderableSymbol (Versioned v a) where renderSymbol = renderSymbol @a + renderOperationId = renderOperationId @a type family FedPath (name :: k) :: Symbol diff --git a/libs/wire-api/src/Wire/API/Routes/Named.hs b/libs/wire-api/src/Wire/API/Routes/Named.hs index 91f702dd412..e80dd5979ac 100644 --- a/libs/wire-api/src/Wire/API/Routes/Named.hs +++ b/libs/wire-api/src/Wire/API/Routes/Named.hs @@ -19,7 +19,7 @@ module Wire.API.Routes.Named where -import Control.Lens ((%~)) +import Control.Lens ((%~), (?~)) import Data.Kind import Data.Metrics.Servant import Data.OpenApi.Lens hiding (HasServer) @@ -42,17 +42,21 @@ newtype Named name x = Named {unnamed :: x} -- types other than string literals in some places. class RenderableSymbol a where renderSymbol :: Text + renderOperationId :: Text instance (KnownSymbol a) => RenderableSymbol a where renderSymbol = T.pack . show $ symbolVal (Proxy @a) + renderOperationId = T.pack $ symbolVal (Proxy @a) instance (RenderableSymbol a, RenderableSymbol b) => RenderableSymbol '(a, b) where renderSymbol = "(" <> (renderSymbol @a) <> ", " <> (renderSymbol @b) <> ")" + renderOperationId = renderSymbol @a <> "_" <> renderSymbol @b newtype RenderableTypeName a = RenderableTypeName a instance (GRenderableSymbol (Rep a)) => RenderableSymbol (RenderableTypeName a) where renderSymbol = grenderSymbol @(Rep a) + renderOperationId = grenderSymbol @(Rep a) class GRenderableSymbol f where grenderSymbol :: Text @@ -64,6 +68,7 @@ instance (HasOpenApi api, RenderableSymbol name) => HasOpenApi (Named name api) toOpenApi _ = toOpenApi (Proxy @api) & allOperations . description %~ (Just (dscr <> "\n\n") <>) + & allOperations . operationId ?~ renderOperationId @name where dscr :: Text dscr = From cf27c3b043486ae4af083fd8e3decf34c9998cfa Mon Sep 17 00:00:00 2001 From: Paolo Capriotti Date: Mon, 21 Oct 2024 16:22:26 +0200 Subject: [PATCH 03/19] Add names to cargohold API --- libs/wire-api/src/Wire/API/Routes/Named.hs | 3 +- .../src/Wire/API/Routes/Public/Cargohold.hs | 84 +++++++++++-------- .../cargohold/src/CargoHold/API/Public.hs | 15 +++- 3 files changed, 64 insertions(+), 38 deletions(-) diff --git a/libs/wire-api/src/Wire/API/Routes/Named.hs b/libs/wire-api/src/Wire/API/Routes/Named.hs index e80dd5979ac..5978774da2a 100644 --- a/libs/wire-api/src/Wire/API/Routes/Named.hs +++ b/libs/wire-api/src/Wire/API/Routes/Named.hs @@ -43,6 +43,7 @@ newtype Named name x = Named {unnamed :: x} class RenderableSymbol a where renderSymbol :: Text renderOperationId :: Text + renderOperationId = renderSymbol @a instance (KnownSymbol a) => RenderableSymbol a where renderSymbol = T.pack . show $ symbolVal (Proxy @a) @@ -50,7 +51,7 @@ instance (KnownSymbol a) => RenderableSymbol a where instance (RenderableSymbol a, RenderableSymbol b) => RenderableSymbol '(a, b) where renderSymbol = "(" <> (renderSymbol @a) <> ", " <> (renderSymbol @b) <> ")" - renderOperationId = renderSymbol @a <> "_" <> renderSymbol @b + renderOperationId = renderOperationId @a <> "_" <> renderOperationId @b newtype RenderableTypeName a = RenderableTypeName a diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Cargohold.hs b/libs/wire-api/src/Wire/API/Routes/Public/Cargohold.hs index d9c7ca0ed3e..7f09ea5e2d0 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Cargohold.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Cargohold.hs @@ -33,6 +33,7 @@ import Wire.API.MakesFederatedCall import Wire.API.Routes.API import Wire.API.Routes.AssetBody import Wire.API.Routes.MultiVerb +import Wire.API.Routes.Named import Wire.API.Routes.Public import Wire.API.Routes.QualifiedCapture import Wire.API.Routes.Version @@ -40,6 +41,15 @@ import Wire.API.Routes.Version data PrincipalTag = UserPrincipalTag | BotPrincipalTag | ProviderPrincipalTag deriving (Eq, Show) +instance RenderableSymbol UserPrincipalTag where + renderSymbol = "user" + +instance RenderableSymbol BotPrincipalTag where + renderSymbol = "bot" + +instance RenderableSymbol ProviderPrincipalTag where + renderSymbol = "provider" + type family PrincipalId (tag :: PrincipalTag) = (id :: Type) | id -> tag where PrincipalId 'UserPrincipalTag = Local UserId PrincipalId 'BotPrincipalTag = BotId @@ -128,40 +138,46 @@ type CargoholdAPI = -- This was introduced before API versioning, and the user endpoints contain a -- v3 suffix, which is removed starting from API V2. type BaseAPIv3 (tag :: PrincipalTag) = - ( Summary "Upload an asset" - :> CanThrow 'AssetTooLarge - :> CanThrow 'InvalidLength - :> tag - :> AssetBody - :> MultiVerb - 'POST - '[JSON] - '[ WithHeaders - (AssetLocationHeader Relative) - (Asset, AssetLocation Relative) - (Respond 201 "Asset posted" Asset) - ] - (Asset, AssetLocation Relative) - ) - :<|> ( Summary "Download an asset" - :> tag - :> Capture "key" AssetKey - :> Header "Asset-Token" AssetToken - :> QueryParam "asset_token" AssetToken - :> ZHostOpt - :> GetAsset - ) - :<|> ( Summary "Delete an asset" - :> CanThrow 'AssetNotFound - :> CanThrow 'Unauthorised - :> tag - :> Capture "key" AssetKey - :> MultiVerb - 'DELETE - '[JSON] - '[RespondEmpty 200 "Asset deleted"] - () - ) + Named + '("upload-asset", tag) + ( Summary "Upload an asset" + :> CanThrow 'AssetTooLarge + :> CanThrow 'InvalidLength + :> tag + :> AssetBody + :> MultiVerb + 'POST + '[JSON] + '[ WithHeaders + (AssetLocationHeader Relative) + (Asset, AssetLocation Relative) + (Respond 201 "Asset posted" Asset) + ] + (Asset, AssetLocation Relative) + ) + :<|> Named + '("download-asset", tag) + ( Summary "Download an asset" + :> tag + :> Capture "key" AssetKey + :> Header "Asset-Token" AssetToken + :> QueryParam "asset_token" AssetToken + :> ZHostOpt + :> GetAsset + ) + :<|> Named + '("delete-asset", tag) + ( Summary "Delete an asset" + :> CanThrow 'AssetNotFound + :> CanThrow 'Unauthorised + :> tag + :> Capture "key" AssetKey + :> MultiVerb + 'DELETE + '[JSON] + '[RespondEmpty 200 "Asset deleted"] + () + ) -- | Qualified asset API. Only download and delete endpoints are supported, as -- upload has stayed unqualified. These endpoints also predate API versioning, diff --git a/services/cargohold/src/CargoHold/API/Public.hs b/services/cargohold/src/CargoHold/API/Public.hs index 607e8947087..009f5f1f281 100644 --- a/services/cargohold/src/CargoHold/API/Public.hs +++ b/services/cargohold/src/CargoHold/API/Public.hs @@ -61,11 +61,20 @@ servantSitemap = :<|> mainAPI where userAPI :: forall tag. (tag ~ 'UserPrincipalTag) => ServerT (BaseAPIv3 tag) Handler - userAPI = uploadAssetV3 @tag :<|> downloadAssetV3 @tag :<|> deleteAssetV3 @tag + userAPI = + Named @'("upload-asset", tag) uploadAssetV3 + :<|> Named @'("download-asset", tag) downloadAssetV3 + :<|> Named @'("delete-asset", tag) deleteAssetV3 botAPI :: forall tag. (tag ~ 'BotPrincipalTag) => ServerT (BaseAPIv3 tag) Handler - botAPI = uploadAssetV3 @tag :<|> downloadAssetV3 @tag :<|> deleteAssetV3 @tag + botAPI = + Named @'("upload-asset", tag) uploadAssetV3 + :<|> Named @'("download-asset", tag) downloadAssetV3 + :<|> Named @'("delete-asset", tag) deleteAssetV3 providerAPI :: forall tag. (tag ~ 'ProviderPrincipalTag) => ServerT (BaseAPIv3 tag) Handler - providerAPI = uploadAssetV3 @tag :<|> downloadAssetV3 @tag :<|> deleteAssetV3 @tag + providerAPI = + Named @'("upload-asset", tag) uploadAssetV3 + :<|> Named @'("download-asset", tag) downloadAssetV3 + :<|> Named @'("delete-asset", tag) deleteAssetV3 legacyAPI = legacyDownloadPlain :<|> legacyDownloadPlain :<|> legacyDownloadOtr qualifiedAPI :: ServerT QualifiedAPI Handler qualifiedAPI = callsFed (exposeAnnotations downloadAssetV4) :<|> deleteAssetV4 From 07a8e22bee54b0ab37e08438887f193e23608e8f Mon Sep 17 00:00:00 2001 From: Paolo Capriotti Date: Tue, 22 Oct 2024 09:35:58 +0200 Subject: [PATCH 04/19] Add IDs to more endpoints --- .../src/Wire/API/Routes/Public/Cargohold.hs | 304 ++++++++++-------- .../src/Wire/API/Routes/Public/Spar.hs | 71 ++-- .../cargohold/src/CargoHold/API/Public.hs | 38 ++- services/spar/src/Spar/API.hs | 11 +- services/spar/src/Spar/Scim.hs | 3 +- 5 files changed, 237 insertions(+), 190 deletions(-) diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Cargohold.hs b/libs/wire-api/src/Wire/API/Routes/Public/Cargohold.hs index 7f09ea5e2d0..203304dd548 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Cargohold.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Cargohold.hs @@ -139,7 +139,7 @@ type CargoholdAPI = -- v3 suffix, which is removed starting from API V2. type BaseAPIv3 (tag :: PrincipalTag) = Named - '("upload-asset", tag) + '("assets-upload-v3", tag) ( Summary "Upload an asset" :> CanThrow 'AssetTooLarge :> CanThrow 'InvalidLength @@ -156,7 +156,7 @@ type BaseAPIv3 (tag :: PrincipalTag) = (Asset, AssetLocation Relative) ) :<|> Named - '("download-asset", tag) + '("assets-download-v3", tag) ( Summary "Download an asset" :> tag :> Capture "key" AssetKey @@ -166,7 +166,7 @@ type BaseAPIv3 (tag :: PrincipalTag) = :> GetAsset ) :<|> Named - '("delete-asset", tag) + '("assets-delete-v3", tag) ( Summary "Delete an asset" :> CanThrow 'AssetNotFound :> CanThrow 'Unauthorised @@ -183,153 +183,173 @@ type BaseAPIv3 (tag :: PrincipalTag) = -- upload has stayed unqualified. These endpoints also predate API versioning, -- and contain a v4 suffix. type QualifiedAPI = - ( Summary "Download an asset" - :> Until 'V2 - :> Description - "**Note**: local assets result in a redirect, \ - \while remote assets are streamed directly." - :> MakesFederatedCall 'Cargohold "get-asset" - :> MakesFederatedCall 'Cargohold "stream-asset" - :> ZLocalUser - :> "assets" - :> "v4" - :> QualifiedCapture "key" AssetKey - :> Header "Asset-Token" AssetToken - :> QueryParam "asset_token" AssetToken - :> ZHostOpt - :> MultiVerb - 'GET - '() - '[ ErrorResponse 'AssetNotFound, - AssetRedirect, - AssetStreaming - ] - (Maybe LocalOrRemoteAsset) - ) - :<|> ( Summary "Delete an asset" - :> Until 'V2 - :> Description "**Note**: only local assets can be deleted." - :> CanThrow 'AssetNotFound - :> CanThrow 'Unauthorised - :> ZLocalUser - :> "assets" - :> "v4" - :> QualifiedCapture "key" AssetKey - :> MultiVerb - 'DELETE - '[JSON] - '[RespondEmpty 200 "Asset deleted"] - () - ) + Named + "assets-download-v4" + ( Summary "Download an asset" + :> Until 'V2 + :> Description + "**Note**: local assets result in a redirect, \ + \while remote assets are streamed directly." + :> MakesFederatedCall 'Cargohold "get-asset" + :> MakesFederatedCall 'Cargohold "stream-asset" + :> ZLocalUser + :> "assets" + :> "v4" + :> QualifiedCapture "key" AssetKey + :> Header "Asset-Token" AssetToken + :> QueryParam "asset_token" AssetToken + :> ZHostOpt + :> MultiVerb + 'GET + '() + '[ ErrorResponse 'AssetNotFound, + AssetRedirect, + AssetStreaming + ] + (Maybe LocalOrRemoteAsset) + ) + :<|> Named + "assets-delete-v4" + ( Summary "Delete an asset" + :> Until 'V2 + :> Description "**Note**: only local assets can be deleted." + :> CanThrow 'AssetNotFound + :> CanThrow 'Unauthorised + :> ZLocalUser + :> "assets" + :> "v4" + :> QualifiedCapture "key" AssetKey + :> MultiVerb + 'DELETE + '[JSON] + '[RespondEmpty 200 "Asset deleted"] + () + ) -- Old endpoints, predating BaseAPIv3, and therefore API versioning. type LegacyAPI = - ( ZLocalUser - :> Until 'V2 - :> "assets" - :> QueryParam' [Required, Strict] "conv_id" ConvId - :> Capture "id" AssetId - :> GetAsset - ) - :<|> ( ZLocalUser - :> Until 'V2 - :> "conversations" - :> Capture "cnv" ConvId - :> "assets" - :> Capture "id" AssetId - :> GetAsset - ) - :<|> ( ZLocalUser - :> Until 'V2 - :> "conversations" - :> Capture "cnv" ConvId - :> "otr" - :> "assets" - :> Capture "id" AssetId - :> GetAsset - ) + Named + "assets-download-legacy" + ( ZLocalUser + :> Until 'V2 + :> "assets" + :> QueryParam' [Required, Strict] "conv_id" ConvId + :> Capture "id" AssetId + :> GetAsset + ) + :<|> Named + "assets-conv-download-legacy" + ( ZLocalUser + :> Until 'V2 + :> "conversations" + :> Capture "cnv" ConvId + :> "assets" + :> Capture "id" AssetId + :> GetAsset + ) + :<|> Named + "assets-conv-otr-download-legacy" + ( ZLocalUser + :> Until 'V2 + :> "conversations" + :> Capture "cnv" ConvId + :> "otr" + :> "assets" + :> Capture "id" AssetId + :> GetAsset + ) -- | With API versioning, the previous ad-hoc v3/v4 versioning is abandoned, and -- asset endpoints are versioned normally as part of the public API, without any -- explicit prefix. type MainAPI = - ( Summary "Renew an asset token" - :> From 'V2 - :> CanThrow 'AssetNotFound - :> CanThrow 'Unauthorised - :> ZLocalUser - :> "assets" - :> Capture "key" AssetKey - :> "token" - :> Post '[JSON] NewAssetToken - ) - :<|> ( Summary "Delete an asset token" - :> From 'V2 - :> Description "**Note**: deleting the token makes the asset public." - :> ZLocalUser - :> "assets" - :> Capture "key" AssetKey - :> "token" - :> MultiVerb - 'DELETE - '[JSON] - '[RespondEmpty 200 "Asset token deleted"] - () - ) - :<|> ( Summary "Upload an asset" - :> From 'V2 - :> CanThrow 'AssetTooLarge - :> CanThrow 'InvalidLength - :> ZLocalUser - :> "assets" - :> AssetBody - :> MultiVerb - 'POST - '[JSON] - '[ WithHeaders - (AssetLocationHeader Relative) - (Asset, AssetLocation Relative) - (Respond 201 "Asset posted" Asset) - ] - (Asset, AssetLocation Relative) - ) - :<|> ( Summary "Download an asset" - :> From 'V2 - :> Description - "**Note**: local assets result in a redirect, \ - \while remote assets are streamed directly." - :> MakesFederatedCall 'Cargohold "get-asset" - :> MakesFederatedCall 'Cargohold "stream-asset" - :> CanThrow 'NoMatchingAssetEndpoint - :> ZLocalUser - :> "assets" - :> QualifiedCapture "key" AssetKey - :> Header "Asset-Token" AssetToken - :> QueryParam "asset_token" AssetToken - :> ZHostOpt - :> MultiVerb - 'GET - '() - '[ ErrorResponse 'AssetNotFound, - AssetRedirect, - AssetStreaming - ] - (Maybe LocalOrRemoteAsset) - ) - :<|> ( Summary "Delete an asset" - :> From 'V2 - :> Description "**Note**: only local assets can be deleted." - :> CanThrow 'AssetNotFound - :> CanThrow 'Unauthorised - :> ZLocalUser - :> "assets" - :> QualifiedCapture "key" AssetKey - :> MultiVerb - 'DELETE - '[JSON] - '[RespondEmpty 200 "Asset deleted"] - () - ) + Named + "tokens-renew" + ( Summary "Renew an asset token" + :> From 'V2 + :> CanThrow 'AssetNotFound + :> CanThrow 'Unauthorised + :> ZLocalUser + :> "assets" + :> Capture "key" AssetKey + :> "token" + :> Post '[JSON] NewAssetToken + ) + :<|> Named + "tokens-delete" + ( Summary "Delete an asset token" + :> From 'V2 + :> Description "**Note**: deleting the token makes the asset public." + :> ZLocalUser + :> "assets" + :> Capture "key" AssetKey + :> "token" + :> MultiVerb + 'DELETE + '[JSON] + '[RespondEmpty 200 "Asset token deleted"] + () + ) + :<|> Named + "assets-upload" + ( Summary "Upload an asset" + :> From 'V2 + :> CanThrow 'AssetTooLarge + :> CanThrow 'InvalidLength + :> ZLocalUser + :> "assets" + :> AssetBody + :> MultiVerb + 'POST + '[JSON] + '[ WithHeaders + (AssetLocationHeader Relative) + (Asset, AssetLocation Relative) + (Respond 201 "Asset posted" Asset) + ] + (Asset, AssetLocation Relative) + ) + :<|> Named + "assets-download" + ( Summary "Download an asset" + :> From 'V2 + :> Description + "**Note**: local assets result in a redirect, \ + \while remote assets are streamed directly." + :> MakesFederatedCall 'Cargohold "get-asset" + :> MakesFederatedCall 'Cargohold "stream-asset" + :> CanThrow 'NoMatchingAssetEndpoint + :> ZLocalUser + :> "assets" + :> QualifiedCapture "key" AssetKey + :> Header "Asset-Token" AssetToken + :> QueryParam "asset_token" AssetToken + :> ZHostOpt + :> MultiVerb + 'GET + '() + '[ ErrorResponse 'AssetNotFound, + AssetRedirect, + AssetStreaming + ] + (Maybe LocalOrRemoteAsset) + ) + :<|> Named + "assets-delete" + ( Summary "Delete an asset" + :> From 'V2 + :> Description "**Note**: only local assets can be deleted." + :> CanThrow 'AssetNotFound + :> CanThrow 'Unauthorised + :> ZLocalUser + :> "assets" + :> QualifiedCapture "key" AssetKey + :> MultiVerb + 'DELETE + '[JSON] + '[RespondEmpty 200 "Asset deleted"] + () + ) data CargoholdAPITag diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Spar.hs b/libs/wire-api/src/Wire/API/Routes/Public/Spar.hs index e1f92b07998..da6c15c871a 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Spar.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Spar.hs @@ -35,6 +35,7 @@ import Wire.API.Error import Wire.API.Error.Brig import Wire.API.Routes.API import Wire.API.Routes.Internal.Spar +import Wire.API.Routes.Named import Wire.API.Routes.Public import Wire.API.SwaggerServant import Wire.API.User.IdentityProvider @@ -69,32 +70,44 @@ type APISSO = type CheckOK = Verb 'HEAD 200 type APIAuthReqPrecheck = - QueryParam "success_redirect" URI.URI - :> QueryParam "error_redirect" URI.URI - :> Capture "idp" SAML.IdPId - :> CheckOK '[PlainText] NoContent + Named + "auth-req-precheck" + ( QueryParam "success_redirect" URI.URI + :> QueryParam "error_redirect" URI.URI + :> Capture "idp" SAML.IdPId + :> CheckOK '[PlainText] NoContent + ) type APIAuthReq = - QueryParam "success_redirect" URI.URI - :> QueryParam "error_redirect" URI.URI - -- (SAML.APIAuthReq from here on, except for the cookies) - :> Capture "idp" SAML.IdPId - :> Get '[SAML.HTML] (SAML.FormRedirect SAML.AuthnRequest) + Named + "auth-req" + ( QueryParam "success_redirect" URI.URI + :> QueryParam "error_redirect" URI.URI + -- (SAML.APIAuthReq from here on, except for the cookies) + :> Capture "idp" SAML.IdPId + :> Get '[SAML.HTML] (SAML.FormRedirect SAML.AuthnRequest) + ) type APIAuthRespLegacy = - DeprecateSSOAPIV1 - :> Deprecated - :> "finalize-login" - -- (SAML.APIAuthResp from here on, except for response) - :> MultipartForm Mem SAML.AuthnResponseBody - :> Post '[PlainText] Void + Named + "auth-resp-legacy" + ( DeprecateSSOAPIV1 + :> Deprecated + :> "finalize-login" + -- (SAML.APIAuthResp from here on, except for response) + :> MultipartForm Mem SAML.AuthnResponseBody + :> Post '[PlainText] Void + ) type APIAuthResp = - "finalize-login" - :> Capture "team" TeamId - -- (SAML.APIAuthResp from here on, except for response) - :> MultipartForm Mem SAML.AuthnResponseBody - :> Post '[PlainText] Void + Named + "auth-resp" + ( "finalize-login" + :> Capture "team" TeamId + -- (SAML.APIAuthResp from here on, except for response) + :> MultipartForm Mem SAML.AuthnResponseBody + :> Post '[PlainText] Void + ) type APIIDP = ZOptUser :> IdpGet @@ -132,7 +145,10 @@ type IdpDelete = :> DeleteNoContent type SsoSettingsGet = - Get '[JSON] SsoSettings + Named + "sso-settings" + ( Get '[JSON] SsoSettings + ) sparSPIssuer :: (Functor m, SAML.HasConfig m) => Maybe TeamId -> m SAML.Issuer sparSPIssuer Nothing = @@ -150,11 +166,14 @@ sparResponseURI (Just tid) = type APIScim = OmitDocs :> "v2" :> ScimSiteAPI SparTag - :<|> "auth-tokens" - :> CanThrow 'PasswordAuthenticationFailed - :> CanThrow 'CodeAuthenticationFailed - :> CanThrow 'CodeAuthenticationRequired - :> APIScimToken + :<|> Named + "auth-tokens" + ( "auth-tokens" + :> CanThrow 'PasswordAuthenticationFailed + :> CanThrow 'CodeAuthenticationFailed + :> CanThrow 'CodeAuthenticationRequired + :> APIScimToken + ) type ScimSiteAPI tag = ToServantApi (ScimSite tag) diff --git a/services/cargohold/src/CargoHold/API/Public.hs b/services/cargohold/src/CargoHold/API/Public.hs index 009f5f1f281..6f0a09d9ed4 100644 --- a/services/cargohold/src/CargoHold/API/Public.hs +++ b/services/cargohold/src/CargoHold/API/Public.hs @@ -62,29 +62,35 @@ servantSitemap = where userAPI :: forall tag. (tag ~ 'UserPrincipalTag) => ServerT (BaseAPIv3 tag) Handler userAPI = - Named @'("upload-asset", tag) uploadAssetV3 - :<|> Named @'("download-asset", tag) downloadAssetV3 - :<|> Named @'("delete-asset", tag) deleteAssetV3 + Named @'("assets-upload-v3", tag) uploadAssetV3 + :<|> Named @'("assets-download-v3", tag) downloadAssetV3 + :<|> Named @'("assets-delete-v3", tag) deleteAssetV3 botAPI :: forall tag. (tag ~ 'BotPrincipalTag) => ServerT (BaseAPIv3 tag) Handler botAPI = - Named @'("upload-asset", tag) uploadAssetV3 - :<|> Named @'("download-asset", tag) downloadAssetV3 - :<|> Named @'("delete-asset", tag) deleteAssetV3 + Named @'("assets-upload-v3", tag) uploadAssetV3 + :<|> Named @'("assets-download-v3", tag) downloadAssetV3 + :<|> Named @'("assets-delete-v3", tag) deleteAssetV3 providerAPI :: forall tag. (tag ~ 'ProviderPrincipalTag) => ServerT (BaseAPIv3 tag) Handler providerAPI = - Named @'("upload-asset", tag) uploadAssetV3 - :<|> Named @'("download-asset", tag) downloadAssetV3 - :<|> Named @'("delete-asset", tag) deleteAssetV3 - legacyAPI = legacyDownloadPlain :<|> legacyDownloadPlain :<|> legacyDownloadOtr + Named @'("assets-upload-v3", tag) uploadAssetV3 + :<|> Named @'("assets-download-v3", tag) downloadAssetV3 + :<|> Named @'("assets-delete-v3", tag) deleteAssetV3 + legacyAPI = + Named @"assets-download-legacy" legacyDownloadPlain + :<|> Named @"assets-conv-download-legacy" legacyDownloadPlain + :<|> Named @"assets-conv-otr-download-legacy" legacyDownloadOtr qualifiedAPI :: ServerT QualifiedAPI Handler - qualifiedAPI = callsFed (exposeAnnotations downloadAssetV4) :<|> deleteAssetV4 + qualifiedAPI = + Named @"assets-download-v4" + (callsFed (exposeAnnotations downloadAssetV4)) + :<|> Named @"assets-delete-v4" deleteAssetV4 mainAPI :: ServerT MainAPI Handler mainAPI = - renewTokenV3 - :<|> deleteTokenV3 - :<|> uploadAssetV3 @'UserPrincipalTag - :<|> callsFed (exposeAnnotations downloadAssetV4) - :<|> deleteAssetV4 + Named @"tokens-renew" renewTokenV3 + :<|> Named @"tokens-delete" deleteTokenV3 + :<|> Named @"assets-upload" (uploadAssetV3 @'UserPrincipalTag) + :<|> Named @"assets-download" (callsFed (exposeAnnotations downloadAssetV4)) + :<|> Named @"assets-delete" deleteAssetV4 internalSitemap :: ServerT InternalAPI Handler internalSitemap = diff --git a/services/spar/src/Spar/API.hs b/services/spar/src/Spar/API.hs index 3d9eca78560..c025ecdca7c 100644 --- a/services/spar/src/Spar/API.hs +++ b/services/spar/src/Spar/API.hs @@ -104,6 +104,7 @@ import qualified Spar.Sem.VerdictFormatStore as VerdictFormatStore import System.Logger (Msg) import qualified URI.ByteString as URI import Wire.API.Routes.Internal.Spar +import Wire.API.Routes.Named import Wire.API.Routes.Public.Spar import Wire.API.Team.Member (HiddenPerm (CreateUpdateDeleteIdp, ReadIdp)) import Wire.API.User @@ -186,11 +187,11 @@ apiSSO :: apiSSO opts = SAML2.meta appName (SamlProtocolSettings.spIssuer Nothing) (SamlProtocolSettings.responseURI Nothing) :<|> (\tid -> SAML2.meta appName (SamlProtocolSettings.spIssuer (Just tid)) (SamlProtocolSettings.responseURI (Just tid))) - :<|> authreqPrecheck - :<|> authreq (maxttlAuthreqDiffTime opts) - :<|> authresp Nothing - :<|> authresp . Just - :<|> ssoSettings + :<|> Named @"auth-req-precheck" authreqPrecheck + :<|> Named @"auth-req" (authreq (maxttlAuthreqDiffTime opts)) + :<|> Named @"auth-resp-legacy" (authresp Nothing) + :<|> Named @"auth-resp" (authresp . Just) + :<|> Named @"sso-settings" ssoSettings apiIDP :: ( Member Random r, diff --git a/services/spar/src/Spar/Scim.hs b/services/spar/src/Spar/Scim.hs index 0d66908bbe7..8cacedfa987 100644 --- a/services/spar/src/Spar/Scim.hs +++ b/services/spar/src/Spar/Scim.hs @@ -97,6 +97,7 @@ import qualified Web.Scim.Handler as Scim import qualified Web.Scim.Schema.Error as Scim import qualified Web.Scim.Schema.Schema as Scim.Schema import qualified Web.Scim.Server as Scim +import Wire.API.Routes.Named import Wire.API.Routes.Public.Spar import Wire.API.User.Scim import Wire.Sem.Logger (Logger) @@ -135,7 +136,7 @@ apiScim :: ServerT APIScim (Sem r) apiScim = hoistScim (toServant (server configuration)) - :<|> apiScimToken + :<|> Named @"auth-tokens" apiScimToken where hoistScim = hoistServer From b4907346c01f600a2f8dc54c00cbaac92b105552 Mon Sep 17 00:00:00 2001 From: Paolo Capriotti Date: Tue, 22 Oct 2024 09:57:42 +0200 Subject: [PATCH 05/19] fixup! Add IDs to more endpoints --- .../src/Wire/API/Routes/Public/Spar.hs | 35 +++++++++---------- services/spar/src/Spar/API.hs | 16 ++++----- services/spar/src/Spar/Scim.hs | 3 +- services/spar/src/Spar/Scim/Auth.hs | 7 ++-- 4 files changed, 29 insertions(+), 32 deletions(-) diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Spar.hs b/libs/wire-api/src/Wire/API/Routes/Public/Spar.hs index da6c15c871a..8b5b37cc6dd 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Spar.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Spar.hs @@ -59,8 +59,8 @@ type DeprecateSSOAPIV1 = \Details: https://docs.wire.com/understand/single-sign-on/trouble-shooting.html#can-i-use-the-same-sso-login-code-for-multiple-teams" type APISSO = - DeprecateSSOAPIV1 :> Deprecated :> "metadata" :> SAML.APIMeta - :<|> "metadata" :> Capture "team" TeamId :> SAML.APIMeta + Named "sso-metadata" (DeprecateSSOAPIV1 :> Deprecated :> "metadata" :> SAML.APIMeta) + :<|> Named "sso-team-metadata" ("metadata" :> Capture "team" TeamId :> SAML.APIMeta) :<|> "initiate-login" :> APIAuthReqPrecheck :<|> "initiate-login" :> APIAuthReq :<|> APIAuthRespLegacy @@ -110,12 +110,12 @@ type APIAuthResp = ) type APIIDP = - ZOptUser :> IdpGet - :<|> ZOptUser :> IdpGetRaw - :<|> ZOptUser :> IdpGetAll - :<|> ZOptUser :> IdpCreate - :<|> ZOptUser :> IdpUpdate - :<|> ZOptUser :> IdpDelete + Named "idp-get" (ZOptUser :> IdpGet) + :<|> Named "idp-get-raw" (ZOptUser :> IdpGetRaw) + :<|> Named "idp-get-all" (ZOptUser :> IdpGetAll) + :<|> Named "idp-create" (ZOptUser :> IdpCreate) + :<|> Named "idp-update" (ZOptUser :> IdpUpdate) + :<|> Named "idp-delete" (ZOptUser :> IdpDelete) type IdpGetRaw = Capture "id" SAML.IdPId :> "raw" :> Get '[RawXML] RawIdPMetadata @@ -166,14 +166,11 @@ sparResponseURI (Just tid) = type APIScim = OmitDocs :> "v2" :> ScimSiteAPI SparTag - :<|> Named - "auth-tokens" - ( "auth-tokens" - :> CanThrow 'PasswordAuthenticationFailed - :> CanThrow 'CodeAuthenticationFailed - :> CanThrow 'CodeAuthenticationRequired - :> APIScimToken - ) + :<|> "auth-tokens" + :> CanThrow 'PasswordAuthenticationFailed + :> CanThrow 'CodeAuthenticationFailed + :> CanThrow 'CodeAuthenticationRequired + :> APIScimToken type ScimSiteAPI tag = ToServantApi (ScimSite tag) @@ -192,9 +189,9 @@ data ScimSite tag route = ScimSite deriving (Generic) type APIScimToken = - ZOptUser :> APIScimTokenCreate - :<|> ZOptUser :> APIScimTokenDelete - :<|> ZOptUser :> APIScimTokenList + Named "auth-tokens-create" (ZOptUser :> APIScimTokenCreate) + :<|> Named "auth-tokens-delete" (ZOptUser :> APIScimTokenDelete) + :<|> Named "auth-tokens-list" (ZOptUser :> APIScimTokenList) type APIScimTokenCreate = ReqBody '[JSON] CreateScimToken diff --git a/services/spar/src/Spar/API.hs b/services/spar/src/Spar/API.hs index c025ecdca7c..a79ac7b21fb 100644 --- a/services/spar/src/Spar/API.hs +++ b/services/spar/src/Spar/API.hs @@ -185,8 +185,8 @@ apiSSO :: Opts -> ServerT APISSO (Sem r) apiSSO opts = - SAML2.meta appName (SamlProtocolSettings.spIssuer Nothing) (SamlProtocolSettings.responseURI Nothing) - :<|> (\tid -> SAML2.meta appName (SamlProtocolSettings.spIssuer (Just tid)) (SamlProtocolSettings.responseURI (Just tid))) + Named @"sso-metadata" (SAML2.meta appName (SamlProtocolSettings.spIssuer Nothing) (SamlProtocolSettings.responseURI Nothing)) + :<|> Named @"sso-team-metadata" (\tid -> SAML2.meta appName (SamlProtocolSettings.spIssuer (Just tid)) (SamlProtocolSettings.responseURI (Just tid))) :<|> Named @"auth-req-precheck" authreqPrecheck :<|> Named @"auth-req" (authreq (maxttlAuthreqDiffTime opts)) :<|> Named @"auth-resp-legacy" (authresp Nothing) @@ -206,12 +206,12 @@ apiIDP :: ) => ServerT APIIDP (Sem r) apiIDP = - idpGet -- get, json, captures idp id - :<|> idpGetRaw -- get, raw xml, capture idp id - :<|> idpGetAll -- get, json - :<|> idpCreate -- post, created - :<|> idpUpdate -- put, okay - :<|> idpDelete -- delete, no content + Named @"idp-get" idpGet -- get, json, captures idp id + :<|> Named @"idp-get-raw" idpGetRaw -- get, raw xml, capture idp id + :<|> Named @"idp-get-all" idpGetAll -- get, json + :<|> Named @"idp-create" idpCreate -- post, created + :<|> Named @"idp-update" idpUpdate -- put, okay + :<|> Named @"idp-delete" idpDelete -- delete, no content apiINTERNAL :: ( Member ScimTokenStore r, diff --git a/services/spar/src/Spar/Scim.hs b/services/spar/src/Spar/Scim.hs index 8cacedfa987..0d66908bbe7 100644 --- a/services/spar/src/Spar/Scim.hs +++ b/services/spar/src/Spar/Scim.hs @@ -97,7 +97,6 @@ import qualified Web.Scim.Handler as Scim import qualified Web.Scim.Schema.Error as Scim import qualified Web.Scim.Schema.Schema as Scim.Schema import qualified Web.Scim.Server as Scim -import Wire.API.Routes.Named import Wire.API.Routes.Public.Spar import Wire.API.User.Scim import Wire.Sem.Logger (Logger) @@ -136,7 +135,7 @@ apiScim :: ServerT APIScim (Sem r) apiScim = hoistScim (toServant (server configuration)) - :<|> Named @"auth-tokens" apiScimToken + :<|> apiScimToken where hoistScim = hoistServer diff --git a/services/spar/src/Spar/Scim/Auth.hs b/services/spar/src/Spar/Scim/Auth.hs index 35e2b6a394f..45d34e667af 100644 --- a/services/spar/src/Spar/Scim/Auth.hs +++ b/services/spar/src/Spar/Scim/Auth.hs @@ -60,6 +60,7 @@ import qualified Spar.Sem.ScimTokenStore as ScimTokenStore import qualified Web.Scim.Class.Auth as Scim.Class.Auth import qualified Web.Scim.Handler as Scim import qualified Web.Scim.Schema.Error as Scim +import Wire.API.Routes.Named import Wire.API.Routes.Public.Spar (APIScimToken) import Wire.API.User as User import Wire.API.User.Scim as Api @@ -97,9 +98,9 @@ apiScimToken :: ) => ServerT APIScimToken (Sem r) apiScimToken = - createScimToken - :<|> deleteScimToken - :<|> listScimTokens + Named @"auth-tokens-create" createScimToken + :<|> Named @"auth-tokens-delete" deleteScimToken + :<|> Named @"auth-tokens-list" listScimTokens -- | > docs/reference/provisioning/scim-token.md {#RefScimTokenCreate} -- From 42a53fb96ac3df3346562b7c162360ba3054d046 Mon Sep 17 00:00:00 2001 From: Paolo Capriotti Date: Tue, 22 Oct 2024 10:32:14 +0200 Subject: [PATCH 06/19] Fix more swagger validation errors --- libs/wire-api/src/Wire/API/Provider/Service.hs | 2 +- libs/wire-api/src/Wire/API/Routes/Public/Brig/Bot.hs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/wire-api/src/Wire/API/Provider/Service.hs b/libs/wire-api/src/Wire/API/Provider/Service.hs index 7b181183e1e..4589dc8dc69 100644 --- a/libs/wire-api/src/Wire/API/Provider/Service.hs +++ b/libs/wire-api/src/Wire/API/Provider/Service.hs @@ -282,7 +282,7 @@ data ServiceProfilePage = ServiceProfilePage instance ToSchema ServiceProfilePage where schema = - object "ServiceProfile" $ + object "ServiceProfilePage" $ ServiceProfilePage <$> serviceProfilePageHasMore .= field "has_more" schema <*> serviceProfilePageResults .= field "services" (array schema) diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Brig/Bot.hs b/libs/wire-api/src/Wire/API/Routes/Public/Brig/Bot.hs index 8f5719ad2d4..782e29fbb59 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Brig/Bot.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Brig/Bot.hs @@ -52,7 +52,7 @@ type BotAPI = :> ZAccess :> ZConn :> "conversations" - :> Capture "Conversation ID" ConvId + :> Capture "conv" ConvId :> "bots" :> ReqBody '[JSON] AddBot :> MultiVerb1 'POST '[JSON] (Respond 201 "" AddBotResponse) @@ -65,9 +65,9 @@ type BotAPI = :> ZAccess :> ZConn :> "conversations" - :> Capture "Conversation ID" ConvId + :> Capture "conv" ConvId :> "bots" - :> Capture "Bot ID" BotId + :> Capture "bot" BotId :> MultiVerb 'DELETE '[JSON] DeleteResponses (Maybe RemoveBotResponse) ) :<|> Named @@ -178,7 +178,7 @@ type BotAPI = :> ZBot :> "bot" :> "users" - :> Capture "User ID" UserId + :> Capture "user" UserId :> "clients" :> Get '[JSON] [PubClient] ) From 204ea5926217d60fd70665dfe7b99fdaf6e98f32 Mon Sep 17 00:00:00 2001 From: Paolo Capriotti Date: Tue, 22 Oct 2024 10:36:16 +0200 Subject: [PATCH 07/19] Add CHANGELOG entry --- changelog.d/4-docs/openapi-validation | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/4-docs/openapi-validation diff --git a/changelog.d/4-docs/openapi-validation b/changelog.d/4-docs/openapi-validation new file mode 100644 index 00000000000..a70ca12d5e5 --- /dev/null +++ b/changelog.d/4-docs/openapi-validation @@ -0,0 +1 @@ +Fix openapi validation errors From c60a3e7a62f4de0fd8474e015e124cca1b63fc36 Mon Sep 17 00:00:00 2001 From: Paolo Capriotti Date: Tue, 22 Oct 2024 10:50:27 +0200 Subject: [PATCH 08/19] Add make rule to run openapi validator --- Makefile | 5 +++++ tools/openapi-validate | 12 ++++++++++++ 2 files changed, 17 insertions(+) create mode 100755 tools/openapi-validate diff --git a/Makefile b/Makefile index 1413ff10e82..612f312a91e 100644 --- a/Makefile +++ b/Makefile @@ -599,3 +599,8 @@ upload-bombon: --project-version $(HELM_SEMVER) \ --api-key $(DEPENDENCY_TRACK_API_KEY) \ --auto-create + +.PHONY: openapi-validate +openapi-validate: + @echo -e "Make sure you are running the backend in another terminal (make cr)\n" + ./tools/openapi-validate diff --git a/tools/openapi-validate b/tools/openapi-validate new file mode 100755 index 00000000000..f5369ee515a --- /dev/null +++ b/tools/openapi-validate @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -euo pipefail + +TEMP=$(mktemp --tmpdir swagger-XXX.json) + +trap cleanup EXIT +cleanup() { + rm -f $TEMP +} + +curl http://localhost:8082/v7/api/swagger.json > $TEMP +docker run --rm -v $(dirname $TEMP):/work:ro dshanley/vacuum:v0.9.8 lint -a -e -d $(basename $TEMP) From 93cf9ae9fb45e85ba2d6d105b14947cc6c2ec6d2 Mon Sep 17 00:00:00 2001 From: Paolo Capriotti Date: Tue, 22 Oct 2024 10:53:24 +0200 Subject: [PATCH 09/19] Add openapi-validate to linters --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 612f312a91e..86a28a0b6ce 100644 --- a/Makefile +++ b/Makefile @@ -159,7 +159,7 @@ ghcid: # Used by CI .PHONY: lint-all -lint-all: formatc hlint-check-all lint-common +lint-all: formatc hlint-check-all lint-common openapi-validate # For use by local devs. # From a40a0716102b947f8210716410ba0e6b385619bd Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Tue, 22 Oct 2024 11:25:27 +0200 Subject: [PATCH 10/19] Use nix derivation instead of docker file. --- nix/wire-server.nix | 1 + tools/openapi-validate | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/nix/wire-server.nix b/nix/wire-server.nix index bf1593940f4..9a0877936d5 100644 --- a/nix/wire-server.nix +++ b/nix/wire-server.nix @@ -414,6 +414,7 @@ let pkgs.nixpkgs-fmt pkgs.openssl pkgs.ormolu + pkgs.vacuum-go pkgs.shellcheck pkgs.treefmt pkgs.gawk diff --git a/tools/openapi-validate b/tools/openapi-validate index f5369ee515a..f66a8bbf997 100755 --- a/tools/openapi-validate +++ b/tools/openapi-validate @@ -9,4 +9,4 @@ cleanup() { } curl http://localhost:8082/v7/api/swagger.json > $TEMP -docker run --rm -v $(dirname $TEMP):/work:ro dshanley/vacuum:v0.9.8 lint -a -e -d $(basename $TEMP) +vacuum lint $TEMP -a -d -w From 0e2e6085e2bc62559cf9f53d5ecf979df2f25779 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Tue, 22 Oct 2024 11:30:10 +0200 Subject: [PATCH 11/19] Don't run openapi-validate in CI (yet). --- Makefile | 4 ++-- tools/openapi-validate | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 86a28a0b6ce..1e7170315a8 100644 --- a/Makefile +++ b/Makefile @@ -159,7 +159,7 @@ ghcid: # Used by CI .PHONY: lint-all -lint-all: formatc hlint-check-all lint-common openapi-validate +lint-all: formatc hlint-check-all lint-common # For use by local devs. # @@ -603,4 +603,4 @@ upload-bombon: .PHONY: openapi-validate openapi-validate: @echo -e "Make sure you are running the backend in another terminal (make cr)\n" - ./tools/openapi-validate + VACUUM_ARGS="-a -d -w" ./tools/openapi-validate diff --git a/tools/openapi-validate b/tools/openapi-validate index f66a8bbf997..1dc308f176a 100755 --- a/tools/openapi-validate +++ b/tools/openapi-validate @@ -9,4 +9,4 @@ cleanup() { } curl http://localhost:8082/v7/api/swagger.json > $TEMP -vacuum lint $TEMP -a -d -w +vacuum lint $TEMP ${VACUUM_ARGS} From dc80ede1bc5df0b4a4a25a7162bbe001d4c95419 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Tue, 22 Oct 2024 11:59:18 +0200 Subject: [PATCH 12/19] rm trailing whitespace. --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 1e7170315a8..dc06a533cfc 100644 --- a/Makefile +++ b/Makefile @@ -85,7 +85,7 @@ cabal.project.local: c: treefmt c-fast .PHONY: c -c-fast: +c-fast: cabal build $(WIRE_CABAL_BUILD_OPTIONS) $(package) || ( make clean-hint; false ) ifeq ($(test), 1) ./hack/bin/cabal-run-tests.sh $(package) $(testargs) @@ -134,7 +134,7 @@ devtest: ghcid --command 'cabal repl integration' --test='Testlib.Run.mainI []' .PHONY: sanitize-pr -sanitize-pr: +sanitize-pr: make lint-all-shallow make git-add-cassandra-schema @git diff-files --quiet -- || ( echo "There are unstaged changes, please take a look, consider committing them, and try again."; exit 1 ) @@ -170,7 +170,7 @@ lint-all: formatc hlint-check-all lint-common # The extra 'hlint-check-pr' has been witnessed to be necessary due to # some bu in `hlint-inplace-pr`. Details got lost in history. .PHONY: lint-all-shallow -lint-all-shallow: lint-common formatf hlint-inplace-pr hlint-check-pr +lint-all-shallow: lint-common formatf hlint-inplace-pr hlint-check-pr .PHONY: lint-common lint-common: check-local-nix-derivations treefmt-check # weeder (does not work on CI yet) From 113e241f1a7886e3c5e310cceeb9146fcd509374 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Tue, 22 Oct 2024 12:02:07 +0200 Subject: [PATCH 13/19] simplify! --- Makefile | 2 +- tools/openapi-validate | 12 ------------ 2 files changed, 1 insertion(+), 13 deletions(-) delete mode 100755 tools/openapi-validate diff --git a/Makefile b/Makefile index dc06a533cfc..9c6d68be5f2 100644 --- a/Makefile +++ b/Makefile @@ -603,4 +603,4 @@ upload-bombon: .PHONY: openapi-validate openapi-validate: @echo -e "Make sure you are running the backend in another terminal (make cr)\n" - VACUUM_ARGS="-a -d -w" ./tools/openapi-validate + vacuum lint -a -d -w <(curl http://localhost:8082/v7/api/swagger.json) diff --git a/tools/openapi-validate b/tools/openapi-validate deleted file mode 100755 index 1dc308f176a..00000000000 --- a/tools/openapi-validate +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -TEMP=$(mktemp --tmpdir swagger-XXX.json) - -trap cleanup EXIT -cleanup() { - rm -f $TEMP -} - -curl http://localhost:8082/v7/api/swagger.json > $TEMP -vacuum lint $TEMP ${VACUUM_ARGS} From 9ca9d70e2054ae430c1e575b6924824b07cfc1dc Mon Sep 17 00:00:00 2001 From: Paolo Capriotti Date: Tue, 22 Oct 2024 14:55:01 +0200 Subject: [PATCH 14/19] Fix overlapping paths in API v7 --- .../src/Wire/API/Routes/Public/Brig.hs | 34 ++++++++++++++++-- .../src/Wire/API/Routes/Public/Brig/Bot.hs | 36 +++++++++++++++++-- .../API/Routes/Public/Galley/Conversation.hs | 28 +++++++++++++-- services/brig/src/Brig/API/Public.hs | 4 ++- services/brig/src/Brig/Provider/API.hs | 4 ++- .../src/Galley/API/Public/Conversation.hs | 1 + 6 files changed, 98 insertions(+), 9 deletions(-) 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 53ebe332541..802eaf88b38 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs @@ -442,8 +442,9 @@ type SelfAPI = type UserHandleAPI = Named - "check-user-handles" + "check-user-handles@v6" ( Summary "Check availability of user handles" + :> Until V7 :> ZUser :> "users" :> "handles" @@ -455,8 +456,22 @@ type UserHandleAPI = [Handle] ) :<|> Named - "check-user-handle" + "check-user-handles" + ( Summary "Check availability of user handles" + :> From V7 + :> ZUser + :> "handles" + :> ReqBody '[JSON] CheckHandles + :> MultiVerb + 'POST + '[JSON] + '[Respond 200 "List of free handles" [Handle]] + [Handle] + ) + :<|> Named + "check-user-handle@v6" ( Summary "Check whether a user handle can be taken" + :> Until V7 :> CanThrow 'InvalidHandle :> CanThrow 'HandleNotFound :> ZUser @@ -469,6 +484,21 @@ type UserHandleAPI = '[Respond 200 "Handle is taken" ()] () ) + :<|> Named + "check-user-handle" + ( Summary "Check whether a user handle can be taken" + :> From V7 + :> CanThrow 'InvalidHandle + :> CanThrow 'HandleNotFound + :> ZUser + :> "handles" + :> Capture "handle" Text + :> MultiVerb + 'HEAD + '[JSON] + '[Respond 200 "Handle is taken" ()] + () + ) type AccountAPI = Named diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Brig/Bot.hs b/libs/wire-api/src/Wire/API/Routes/Public/Brig/Bot.hs index 782e29fbb59..b81f765a261 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Brig/Bot.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Brig/Bot.hs @@ -43,8 +43,9 @@ type DeleteResponses = type BotAPI = Named - "add-bot" + "add-bot@v6" ( Summary "Add bot" + :> Until V7 :> CanThrow 'AccessDenied :> CanThrow 'InvalidConversation :> CanThrow 'TooManyConversationMembers @@ -58,8 +59,25 @@ type BotAPI = :> MultiVerb1 'POST '[JSON] (Respond 201 "" AddBotResponse) ) :<|> Named - "remove-bot" + "add-bot" + ( Summary "Add bot" + :> From V7 + :> CanThrow 'AccessDenied + :> CanThrow 'InvalidConversation + :> CanThrow 'TooManyConversationMembers + :> CanThrow 'ServiceDisabled + :> ZAccess + :> ZConn + :> "bots" + :> "conversations" + :> Capture "conv" ConvId + :> ReqBody '[JSON] AddBot + :> MultiVerb1 'POST '[JSON] (Respond 201 "" AddBotResponse) + ) + :<|> Named + "remove-bot@v6" ( Summary "Remove bot" + :> Until V7 :> CanThrow 'AccessDenied :> CanThrow 'InvalidConversation :> ZAccess @@ -70,6 +88,20 @@ type BotAPI = :> Capture "bot" BotId :> MultiVerb 'DELETE '[JSON] DeleteResponses (Maybe RemoveBotResponse) ) + :<|> Named + "remove-bot" + ( Summary "Remove bot" + :> From V7 + :> CanThrow 'AccessDenied + :> CanThrow 'InvalidConversation + :> ZAccess + :> ZConn + :> "bots" + :> "conversations" + :> Capture "conv" ConvId + :> Capture "bot" BotId + :> MultiVerb 'DELETE '[JSON] DeleteResponses (Maybe RemoveBotResponse) + ) :<|> Named "bot-get-self" ( Summary "Get self" diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Galley/Conversation.hs b/libs/wire-api/src/Wire/API/Routes/Public/Galley/Conversation.hs index a6d377331dc..cdb0d810d00 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Galley/Conversation.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Galley/Conversation.hs @@ -651,10 +651,11 @@ type ConversationAPI = :> ConversationVerb 'V2 Conversation ) :<|> Named - "create-one-to-one-conversation" + "create-one-to-one-conversation@v6" ( Summary "Create a 1:1 conversation" :> MakesFederatedCall 'Galley "on-conversation-created" :> From 'V3 + :> Until 'V7 :> CanThrow 'ConvAccessDenied :> CanThrow 'InvalidOperation :> CanThrow 'NoBindingTeamMembers @@ -672,6 +673,27 @@ type ConversationAPI = :> ReqBody '[JSON] NewConv :> ConversationVerb 'V3 Conversation ) + :<|> Named + "create-one-to-one-conversation" + ( Summary "Create a 1:1 conversation" + :> MakesFederatedCall 'Galley "on-conversation-created" + :> From 'V7 + :> CanThrow 'ConvAccessDenied + :> CanThrow 'InvalidOperation + :> CanThrow 'NoBindingTeamMembers + :> CanThrow 'NonBindingTeam + :> CanThrow 'NotATeamMember + :> CanThrow 'NotConnected + :> CanThrow OperationDenied + :> CanThrow 'TeamNotFound + :> CanThrow 'MissingLegalholdConsent + :> CanThrow UnreachableBackendsLegacy + :> ZLocalUser + :> ZConn + :> "one2one-conversations" + :> ReqBody '[JSON] NewConv + :> ConversationVerb 'V3 Conversation + ) :<|> Named "get-one-to-one-mls-conversation@v5" ( Summary "Get an MLS 1:1 conversation" @@ -706,8 +728,7 @@ type ConversationAPI = :> ZLocalUser :> CanThrow 'MLSNotEnabled :> CanThrow 'NotConnected - :> "conversations" - :> "one2one" + :> "one2one-conversations" :> QualifiedCapture "usr" UserId :> QueryParam "format" MLSPublicKeyFormat :> MultiVerb1 'GET '[JSON] (Respond 200 "MLS 1-1 conversation" (MLSOne2OneConversation SomeKey)) @@ -1015,6 +1036,7 @@ type ConversationAPI = :<|> Named "update-other-member-unqualified" ( Summary "Update membership of the specified user (deprecated)" + :> Until V7 :> Deprecated :> Description "Use `PUT /conversations/:cnv_domain/:cnv/members/:usr_domain/:usr` instead" :> MakesFederatedCall 'Galley "on-conversation-updated" diff --git a/services/brig/src/Brig/API/Public.hs b/services/brig/src/Brig/API/Public.hs index 017f225a190..799983ec59a 100644 --- a/services/brig/src/Brig/API/Public.hs +++ b/services/brig/src/Brig/API/Public.hs @@ -436,7 +436,9 @@ servantSitemap = userHandleAPI :: ServerT UserHandleAPI (Handler r) userHandleAPI = - Named @"check-user-handles" checkHandles + Named @"check-user-handles@v6" checkHandles + :<|> Named @"check-user-handles" checkHandles + :<|> Named @"check-user-handle@v6" checkHandle :<|> Named @"check-user-handle" checkHandle searchAPI :: ServerT SearchAPI (Handler r) diff --git a/services/brig/src/Brig/Provider/API.hs b/services/brig/src/Brig/Provider/API.hs index 65070d3b420..839652bb59c 100644 --- a/services/brig/src/Brig/Provider/API.hs +++ b/services/brig/src/Brig/Provider/API.hs @@ -143,7 +143,9 @@ botAPI :: ) => ServerT BotAPI (Handler r) botAPI = - Named @"add-bot" addBot + Named @"add-bot@v6" addBot + :<|> Named @"add-bot" addBot + :<|> Named @"remove-bot@v6" removeBot :<|> Named @"remove-bot" removeBot :<|> Named @"bot-get-self" botGetSelf :<|> Named @"bot-delete-self" botDeleteSelf diff --git a/services/galley/src/Galley/API/Public/Conversation.hs b/services/galley/src/Galley/API/Public/Conversation.hs index d254ff6c9c8..aa9ba9d4a80 100644 --- a/services/galley/src/Galley/API/Public/Conversation.hs +++ b/services/galley/src/Galley/API/Public/Conversation.hs @@ -61,6 +61,7 @@ conversationAPI = <@> mkNamedAPI @"delete-subconversation" (callsFed deleteSubConversation) <@> mkNamedAPI @"get-subconversation-group-info" (callsFed getSubConversationGroupInfo) <@> mkNamedAPI @"create-one-to-one-conversation@v2" (callsFed createOne2OneConversation) + <@> mkNamedAPI @"create-one-to-one-conversation@v6" (callsFed createOne2OneConversation) <@> mkNamedAPI @"create-one-to-one-conversation" (callsFed createOne2OneConversation) <@> mkNamedAPI @"get-one-to-one-mls-conversation@v5" getMLSOne2OneConversationV5 <@> mkNamedAPI @"get-one-to-one-mls-conversation@v6" getMLSOne2OneConversationV6 From 6031e27630c1f1e113ec5fd3218df8d77b94a6c0 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Tue, 22 Oct 2024 15:24:51 +0200 Subject: [PATCH 15/19] Revert "Fix overlapping paths in API v7" This reverts commit 9ca9d70e2054ae430c1e575b6924824b07cfc1dc. This is not done and can be finished in a separate PR. --- .../src/Wire/API/Routes/Public/Brig.hs | 34 ++---------------- .../src/Wire/API/Routes/Public/Brig/Bot.hs | 36 ++----------------- .../API/Routes/Public/Galley/Conversation.hs | 28 ++------------- services/brig/src/Brig/API/Public.hs | 4 +-- services/brig/src/Brig/Provider/API.hs | 4 +-- .../src/Galley/API/Public/Conversation.hs | 1 - 6 files changed, 9 insertions(+), 98 deletions(-) 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 802eaf88b38..53ebe332541 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs @@ -442,9 +442,8 @@ type SelfAPI = type UserHandleAPI = Named - "check-user-handles@v6" + "check-user-handles" ( Summary "Check availability of user handles" - :> Until V7 :> ZUser :> "users" :> "handles" @@ -455,42 +454,13 @@ type UserHandleAPI = '[Respond 200 "List of free handles" [Handle]] [Handle] ) - :<|> Named - "check-user-handles" - ( Summary "Check availability of user handles" - :> From V7 - :> ZUser - :> "handles" - :> ReqBody '[JSON] CheckHandles - :> MultiVerb - 'POST - '[JSON] - '[Respond 200 "List of free handles" [Handle]] - [Handle] - ) - :<|> Named - "check-user-handle@v6" - ( Summary "Check whether a user handle can be taken" - :> Until V7 - :> CanThrow 'InvalidHandle - :> CanThrow 'HandleNotFound - :> ZUser - :> "users" - :> "handles" - :> Capture "handle" Text - :> MultiVerb - 'HEAD - '[JSON] - '[Respond 200 "Handle is taken" ()] - () - ) :<|> Named "check-user-handle" ( Summary "Check whether a user handle can be taken" - :> From V7 :> CanThrow 'InvalidHandle :> CanThrow 'HandleNotFound :> ZUser + :> "users" :> "handles" :> Capture "handle" Text :> MultiVerb diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Brig/Bot.hs b/libs/wire-api/src/Wire/API/Routes/Public/Brig/Bot.hs index b81f765a261..782e29fbb59 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Brig/Bot.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Brig/Bot.hs @@ -43,9 +43,8 @@ type DeleteResponses = type BotAPI = Named - "add-bot@v6" + "add-bot" ( Summary "Add bot" - :> Until V7 :> CanThrow 'AccessDenied :> CanThrow 'InvalidConversation :> CanThrow 'TooManyConversationMembers @@ -58,47 +57,16 @@ type BotAPI = :> ReqBody '[JSON] AddBot :> MultiVerb1 'POST '[JSON] (Respond 201 "" AddBotResponse) ) - :<|> Named - "add-bot" - ( Summary "Add bot" - :> From V7 - :> CanThrow 'AccessDenied - :> CanThrow 'InvalidConversation - :> CanThrow 'TooManyConversationMembers - :> CanThrow 'ServiceDisabled - :> ZAccess - :> ZConn - :> "bots" - :> "conversations" - :> Capture "conv" ConvId - :> ReqBody '[JSON] AddBot - :> MultiVerb1 'POST '[JSON] (Respond 201 "" AddBotResponse) - ) - :<|> Named - "remove-bot@v6" - ( Summary "Remove bot" - :> Until V7 - :> CanThrow 'AccessDenied - :> CanThrow 'InvalidConversation - :> ZAccess - :> ZConn - :> "conversations" - :> Capture "conv" ConvId - :> "bots" - :> Capture "bot" BotId - :> MultiVerb 'DELETE '[JSON] DeleteResponses (Maybe RemoveBotResponse) - ) :<|> Named "remove-bot" ( Summary "Remove bot" - :> From V7 :> CanThrow 'AccessDenied :> CanThrow 'InvalidConversation :> ZAccess :> ZConn - :> "bots" :> "conversations" :> Capture "conv" ConvId + :> "bots" :> Capture "bot" BotId :> MultiVerb 'DELETE '[JSON] DeleteResponses (Maybe RemoveBotResponse) ) diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Galley/Conversation.hs b/libs/wire-api/src/Wire/API/Routes/Public/Galley/Conversation.hs index cdb0d810d00..a6d377331dc 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Galley/Conversation.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Galley/Conversation.hs @@ -651,11 +651,10 @@ type ConversationAPI = :> ConversationVerb 'V2 Conversation ) :<|> Named - "create-one-to-one-conversation@v6" + "create-one-to-one-conversation" ( Summary "Create a 1:1 conversation" :> MakesFederatedCall 'Galley "on-conversation-created" :> From 'V3 - :> Until 'V7 :> CanThrow 'ConvAccessDenied :> CanThrow 'InvalidOperation :> CanThrow 'NoBindingTeamMembers @@ -673,27 +672,6 @@ type ConversationAPI = :> ReqBody '[JSON] NewConv :> ConversationVerb 'V3 Conversation ) - :<|> Named - "create-one-to-one-conversation" - ( Summary "Create a 1:1 conversation" - :> MakesFederatedCall 'Galley "on-conversation-created" - :> From 'V7 - :> CanThrow 'ConvAccessDenied - :> CanThrow 'InvalidOperation - :> CanThrow 'NoBindingTeamMembers - :> CanThrow 'NonBindingTeam - :> CanThrow 'NotATeamMember - :> CanThrow 'NotConnected - :> CanThrow OperationDenied - :> CanThrow 'TeamNotFound - :> CanThrow 'MissingLegalholdConsent - :> CanThrow UnreachableBackendsLegacy - :> ZLocalUser - :> ZConn - :> "one2one-conversations" - :> ReqBody '[JSON] NewConv - :> ConversationVerb 'V3 Conversation - ) :<|> Named "get-one-to-one-mls-conversation@v5" ( Summary "Get an MLS 1:1 conversation" @@ -728,7 +706,8 @@ type ConversationAPI = :> ZLocalUser :> CanThrow 'MLSNotEnabled :> CanThrow 'NotConnected - :> "one2one-conversations" + :> "conversations" + :> "one2one" :> QualifiedCapture "usr" UserId :> QueryParam "format" MLSPublicKeyFormat :> MultiVerb1 'GET '[JSON] (Respond 200 "MLS 1-1 conversation" (MLSOne2OneConversation SomeKey)) @@ -1036,7 +1015,6 @@ type ConversationAPI = :<|> Named "update-other-member-unqualified" ( Summary "Update membership of the specified user (deprecated)" - :> Until V7 :> Deprecated :> Description "Use `PUT /conversations/:cnv_domain/:cnv/members/:usr_domain/:usr` instead" :> MakesFederatedCall 'Galley "on-conversation-updated" diff --git a/services/brig/src/Brig/API/Public.hs b/services/brig/src/Brig/API/Public.hs index 799983ec59a..017f225a190 100644 --- a/services/brig/src/Brig/API/Public.hs +++ b/services/brig/src/Brig/API/Public.hs @@ -436,9 +436,7 @@ servantSitemap = userHandleAPI :: ServerT UserHandleAPI (Handler r) userHandleAPI = - Named @"check-user-handles@v6" checkHandles - :<|> Named @"check-user-handles" checkHandles - :<|> Named @"check-user-handle@v6" checkHandle + Named @"check-user-handles" checkHandles :<|> Named @"check-user-handle" checkHandle searchAPI :: ServerT SearchAPI (Handler r) diff --git a/services/brig/src/Brig/Provider/API.hs b/services/brig/src/Brig/Provider/API.hs index 839652bb59c..65070d3b420 100644 --- a/services/brig/src/Brig/Provider/API.hs +++ b/services/brig/src/Brig/Provider/API.hs @@ -143,9 +143,7 @@ botAPI :: ) => ServerT BotAPI (Handler r) botAPI = - Named @"add-bot@v6" addBot - :<|> Named @"add-bot" addBot - :<|> Named @"remove-bot@v6" removeBot + Named @"add-bot" addBot :<|> Named @"remove-bot" removeBot :<|> Named @"bot-get-self" botGetSelf :<|> Named @"bot-delete-self" botDeleteSelf diff --git a/services/galley/src/Galley/API/Public/Conversation.hs b/services/galley/src/Galley/API/Public/Conversation.hs index aa9ba9d4a80..d254ff6c9c8 100644 --- a/services/galley/src/Galley/API/Public/Conversation.hs +++ b/services/galley/src/Galley/API/Public/Conversation.hs @@ -61,7 +61,6 @@ conversationAPI = <@> mkNamedAPI @"delete-subconversation" (callsFed deleteSubConversation) <@> mkNamedAPI @"get-subconversation-group-info" (callsFed getSubConversationGroupInfo) <@> mkNamedAPI @"create-one-to-one-conversation@v2" (callsFed createOne2OneConversation) - <@> mkNamedAPI @"create-one-to-one-conversation@v6" (callsFed createOne2OneConversation) <@> mkNamedAPI @"create-one-to-one-conversation" (callsFed createOne2OneConversation) <@> mkNamedAPI @"get-one-to-one-mls-conversation@v5" getMLSOne2OneConversationV5 <@> mkNamedAPI @"get-one-to-one-mls-conversation@v6" getMLSOne2OneConversationV6 From 39837415b0ccb225be8652a238fd22c9bf5b9b2f Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Tue, 22 Oct 2024 16:37:15 +0200 Subject: [PATCH 16/19] Add integration test for vacuum (swagger linter). --- integration/test/Test/Swagger.hs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/integration/test/Test/Swagger.hs b/integration/test/Test/Swagger.hs index b7f7618092c..e68b4d6cfdd 100644 --- a/integration/test/Test/Swagger.hs +++ b/integration/test/Test/Swagger.hs @@ -4,8 +4,12 @@ import qualified API.Brig as BrigP import qualified Data.Set as Set import Data.String.Conversions import GHC.Stack +import System.Exit +import System.Process import Testlib.Assertions import Testlib.Prelude +import UnliftIO.Directory +import UnliftIO.Temporary existingVersions :: Set Int existingVersions = Set.fromList [0, 1, 2, 3, 4, 5, 6, 7] @@ -80,3 +84,17 @@ testSwaggerToc = do html :: String html = "

please pick an api version

/v0/api/swagger-ui/
/v1/api/swagger-ui/
/v2/api/swagger-ui/
/v3/api/swagger-ui/
/v4/api/swagger-ui/
/v5/api/swagger-ui/
/v6/api/swagger-ui/
/v7/api/swagger-ui/
" + +-- | This runs the swagger linter [vacuum](https://quobix.com/vacuum/). There is also a make +-- rule that does this, for convenience in your develop flow. In order to run vacuum on CI, we need a running brig (or at least but running this this test case +-- makes it easier to do this in the integration test job on our CI. vacuum +testSwaggerLint :: (HasCallStack) => App () +testSwaggerLint = do + withSystemTempDirectory "testSwaggerLint-XXX.swagger.json" $ \swaggerFile -> + withCurrentDirectory swaggerFile $ do + let url = "http://localhost:8082/v" <> show (maximum existingVersions) <> "/api/swagger.json" + cmd = shell ("curl " <> url <> " > swagger.json && vacuum lint swagger.json 2>&1") + outcome@(exitCode, _out, _err) <- liftIO $ readCreateProcessWithExitCode cmd "" + case exitCode of + ExitSuccess -> pure () + _ -> error (show outcome) From 7b52d8b6994d82fde19eb32bbe2b9feb2fc8ecf8 Mon Sep 17 00:00:00 2001 From: Paolo Capriotti Date: Tue, 22 Oct 2024 14:55:01 +0200 Subject: [PATCH 17/19] Fix overlapping paths in API v7 --- .../src/Wire/API/Routes/Public/Brig.hs | 34 ++++++++++++++++-- .../src/Wire/API/Routes/Public/Brig/Bot.hs | 36 +++++++++++++++++-- .../API/Routes/Public/Galley/Conversation.hs | 28 +++++++++++++-- services/brig/src/Brig/API/Public.hs | 4 ++- services/brig/src/Brig/Provider/API.hs | 4 ++- .../src/Galley/API/Public/Conversation.hs | 1 + 6 files changed, 98 insertions(+), 9 deletions(-) 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 424ac403d81..d377fc79835 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs @@ -425,8 +425,9 @@ type SelfAPI = type UserHandleAPI = Named - "check-user-handles" + "check-user-handles@v6" ( Summary "Check availability of user handles" + :> Until V7 :> ZUser :> "users" :> "handles" @@ -438,8 +439,22 @@ type UserHandleAPI = [Handle] ) :<|> Named - "check-user-handle" + "check-user-handles" + ( Summary "Check availability of user handles" + :> From V7 + :> ZUser + :> "handles" + :> ReqBody '[JSON] CheckHandles + :> MultiVerb + 'POST + '[JSON] + '[Respond 200 "List of free handles" [Handle]] + [Handle] + ) + :<|> Named + "check-user-handle@v6" ( Summary "Check whether a user handle can be taken" + :> Until V7 :> CanThrow 'InvalidHandle :> CanThrow 'HandleNotFound :> ZUser @@ -452,6 +467,21 @@ type UserHandleAPI = '[Respond 200 "Handle is taken" ()] () ) + :<|> Named + "check-user-handle" + ( Summary "Check whether a user handle can be taken" + :> From V7 + :> CanThrow 'InvalidHandle + :> CanThrow 'HandleNotFound + :> ZUser + :> "handles" + :> Capture "handle" Text + :> MultiVerb + 'HEAD + '[JSON] + '[Respond 200 "Handle is taken" ()] + () + ) type AccountAPI = Named diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Brig/Bot.hs b/libs/wire-api/src/Wire/API/Routes/Public/Brig/Bot.hs index 782e29fbb59..b81f765a261 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Brig/Bot.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Brig/Bot.hs @@ -43,8 +43,9 @@ type DeleteResponses = type BotAPI = Named - "add-bot" + "add-bot@v6" ( Summary "Add bot" + :> Until V7 :> CanThrow 'AccessDenied :> CanThrow 'InvalidConversation :> CanThrow 'TooManyConversationMembers @@ -58,8 +59,25 @@ type BotAPI = :> MultiVerb1 'POST '[JSON] (Respond 201 "" AddBotResponse) ) :<|> Named - "remove-bot" + "add-bot" + ( Summary "Add bot" + :> From V7 + :> CanThrow 'AccessDenied + :> CanThrow 'InvalidConversation + :> CanThrow 'TooManyConversationMembers + :> CanThrow 'ServiceDisabled + :> ZAccess + :> ZConn + :> "bots" + :> "conversations" + :> Capture "conv" ConvId + :> ReqBody '[JSON] AddBot + :> MultiVerb1 'POST '[JSON] (Respond 201 "" AddBotResponse) + ) + :<|> Named + "remove-bot@v6" ( Summary "Remove bot" + :> Until V7 :> CanThrow 'AccessDenied :> CanThrow 'InvalidConversation :> ZAccess @@ -70,6 +88,20 @@ type BotAPI = :> Capture "bot" BotId :> MultiVerb 'DELETE '[JSON] DeleteResponses (Maybe RemoveBotResponse) ) + :<|> Named + "remove-bot" + ( Summary "Remove bot" + :> From V7 + :> CanThrow 'AccessDenied + :> CanThrow 'InvalidConversation + :> ZAccess + :> ZConn + :> "bots" + :> "conversations" + :> Capture "conv" ConvId + :> Capture "bot" BotId + :> MultiVerb 'DELETE '[JSON] DeleteResponses (Maybe RemoveBotResponse) + ) :<|> Named "bot-get-self" ( Summary "Get self" diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Galley/Conversation.hs b/libs/wire-api/src/Wire/API/Routes/Public/Galley/Conversation.hs index 7cbc9adeb16..0e731994511 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Galley/Conversation.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Galley/Conversation.hs @@ -621,9 +621,10 @@ type ConversationAPI = :> ConversationVerb 'V2 Conversation ) :<|> Named - "create-one-to-one-conversation" + "create-one-to-one-conversation@v6" ( Summary "Create a 1:1 conversation" :> From 'V3 + :> Until 'V7 :> CanThrow 'ConvAccessDenied :> CanThrow 'InvalidOperation :> CanThrow 'NoBindingTeamMembers @@ -641,6 +642,27 @@ type ConversationAPI = :> ReqBody '[JSON] NewConv :> ConversationVerb 'V3 Conversation ) + :<|> Named + "create-one-to-one-conversation" + ( Summary "Create a 1:1 conversation" + :> "on-conversation-created" + :> From 'V7 + :> CanThrow 'ConvAccessDenied + :> CanThrow 'InvalidOperation + :> CanThrow 'NoBindingTeamMembers + :> CanThrow 'NonBindingTeam + :> CanThrow 'NotATeamMember + :> CanThrow 'NotConnected + :> CanThrow OperationDenied + :> CanThrow 'TeamNotFound + :> CanThrow 'MissingLegalholdConsent + :> CanThrow UnreachableBackendsLegacy + :> ZLocalUser + :> ZConn + :> "one2one-conversations" + :> ReqBody '[JSON] NewConv + :> ConversationVerb 'V3 Conversation + ) :<|> Named "get-one-to-one-mls-conversation@v5" ( Summary "Get an MLS 1:1 conversation" @@ -675,8 +697,7 @@ type ConversationAPI = :> ZLocalUser :> CanThrow 'MLSNotEnabled :> CanThrow 'NotConnected - :> "conversations" - :> "one2one" + :> "one2one-conversations" :> QualifiedCapture "usr" UserId :> QueryParam "format" MLSPublicKeyFormat :> MultiVerb1 'GET '[JSON] (Respond 200 "MLS 1-1 conversation" (MLSOne2OneConversation SomeKey)) @@ -964,6 +985,7 @@ type ConversationAPI = :<|> Named "update-other-member-unqualified" ( Summary "Update membership of the specified user (deprecated)" + :> Until V7 :> Deprecated :> Description "Use `PUT /conversations/:cnv_domain/:cnv/members/:usr_domain/:usr` instead" :> ZLocalUser diff --git a/services/brig/src/Brig/API/Public.hs b/services/brig/src/Brig/API/Public.hs index 2485961ce68..b9e0f8f0c16 100644 --- a/services/brig/src/Brig/API/Public.hs +++ b/services/brig/src/Brig/API/Public.hs @@ -438,7 +438,9 @@ servantSitemap = userHandleAPI :: ServerT UserHandleAPI (Handler r) userHandleAPI = - Named @"check-user-handles" checkHandles + Named @"check-user-handles@v6" checkHandles + :<|> Named @"check-user-handles" checkHandles + :<|> Named @"check-user-handle@v6" checkHandle :<|> Named @"check-user-handle" checkHandle searchAPI :: ServerT SearchAPI (Handler r) diff --git a/services/brig/src/Brig/Provider/API.hs b/services/brig/src/Brig/Provider/API.hs index 5d2f9c8e313..162a1109060 100644 --- a/services/brig/src/Brig/Provider/API.hs +++ b/services/brig/src/Brig/Provider/API.hs @@ -145,7 +145,9 @@ botAPI :: ) => ServerT BotAPI (Handler r) botAPI = - Named @"add-bot" addBot + Named @"add-bot@v6" addBot + :<|> Named @"add-bot" addBot + :<|> Named @"remove-bot@v6" removeBot :<|> Named @"remove-bot" removeBot :<|> Named @"bot-get-self" botGetSelf :<|> Named @"bot-delete-self" botDeleteSelf diff --git a/services/galley/src/Galley/API/Public/Conversation.hs b/services/galley/src/Galley/API/Public/Conversation.hs index a234ec89b92..532d4f4dffa 100644 --- a/services/galley/src/Galley/API/Public/Conversation.hs +++ b/services/galley/src/Galley/API/Public/Conversation.hs @@ -60,6 +60,7 @@ conversationAPI = <@> mkNamedAPI @"delete-subconversation" deleteSubConversation <@> mkNamedAPI @"get-subconversation-group-info" getSubConversationGroupInfo <@> mkNamedAPI @"create-one-to-one-conversation@v2" createOne2OneConversation + <@> mkNamedAPI @"create-one-to-one-conversation@v6" createOne2OneConversation <@> mkNamedAPI @"create-one-to-one-conversation" createOne2OneConversation <@> mkNamedAPI @"get-one-to-one-mls-conversation@v5" getMLSOne2OneConversationV5 <@> mkNamedAPI @"get-one-to-one-mls-conversation@v6" getMLSOne2OneConversationV6 From c63d2a6c0b6b5d7bd9aa628dd6a801802bdda18e Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Tue, 22 Oct 2024 16:48:46 +0200 Subject: [PATCH 18/19] Revert "Fix overlapping paths in API v7" This reverts commit 0ee611978d4e3a0562435cbb027372daa97d5d26. --- .../src/Wire/API/Routes/Public/Brig.hs | 34 ++---------------- .../src/Wire/API/Routes/Public/Brig/Bot.hs | 36 ++----------------- .../API/Routes/Public/Galley/Conversation.hs | 28 ++------------- services/brig/src/Brig/API/Public.hs | 4 +-- services/brig/src/Brig/Provider/API.hs | 4 +-- .../src/Galley/API/Public/Conversation.hs | 1 - 6 files changed, 9 insertions(+), 98 deletions(-) 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 d377fc79835..424ac403d81 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs @@ -425,9 +425,8 @@ type SelfAPI = type UserHandleAPI = Named - "check-user-handles@v6" + "check-user-handles" ( Summary "Check availability of user handles" - :> Until V7 :> ZUser :> "users" :> "handles" @@ -438,42 +437,13 @@ type UserHandleAPI = '[Respond 200 "List of free handles" [Handle]] [Handle] ) - :<|> Named - "check-user-handles" - ( Summary "Check availability of user handles" - :> From V7 - :> ZUser - :> "handles" - :> ReqBody '[JSON] CheckHandles - :> MultiVerb - 'POST - '[JSON] - '[Respond 200 "List of free handles" [Handle]] - [Handle] - ) - :<|> Named - "check-user-handle@v6" - ( Summary "Check whether a user handle can be taken" - :> Until V7 - :> CanThrow 'InvalidHandle - :> CanThrow 'HandleNotFound - :> ZUser - :> "users" - :> "handles" - :> Capture "handle" Text - :> MultiVerb - 'HEAD - '[JSON] - '[Respond 200 "Handle is taken" ()] - () - ) :<|> Named "check-user-handle" ( Summary "Check whether a user handle can be taken" - :> From V7 :> CanThrow 'InvalidHandle :> CanThrow 'HandleNotFound :> ZUser + :> "users" :> "handles" :> Capture "handle" Text :> MultiVerb diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Brig/Bot.hs b/libs/wire-api/src/Wire/API/Routes/Public/Brig/Bot.hs index b81f765a261..782e29fbb59 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Brig/Bot.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Brig/Bot.hs @@ -43,9 +43,8 @@ type DeleteResponses = type BotAPI = Named - "add-bot@v6" + "add-bot" ( Summary "Add bot" - :> Until V7 :> CanThrow 'AccessDenied :> CanThrow 'InvalidConversation :> CanThrow 'TooManyConversationMembers @@ -58,47 +57,16 @@ type BotAPI = :> ReqBody '[JSON] AddBot :> MultiVerb1 'POST '[JSON] (Respond 201 "" AddBotResponse) ) - :<|> Named - "add-bot" - ( Summary "Add bot" - :> From V7 - :> CanThrow 'AccessDenied - :> CanThrow 'InvalidConversation - :> CanThrow 'TooManyConversationMembers - :> CanThrow 'ServiceDisabled - :> ZAccess - :> ZConn - :> "bots" - :> "conversations" - :> Capture "conv" ConvId - :> ReqBody '[JSON] AddBot - :> MultiVerb1 'POST '[JSON] (Respond 201 "" AddBotResponse) - ) - :<|> Named - "remove-bot@v6" - ( Summary "Remove bot" - :> Until V7 - :> CanThrow 'AccessDenied - :> CanThrow 'InvalidConversation - :> ZAccess - :> ZConn - :> "conversations" - :> Capture "conv" ConvId - :> "bots" - :> Capture "bot" BotId - :> MultiVerb 'DELETE '[JSON] DeleteResponses (Maybe RemoveBotResponse) - ) :<|> Named "remove-bot" ( Summary "Remove bot" - :> From V7 :> CanThrow 'AccessDenied :> CanThrow 'InvalidConversation :> ZAccess :> ZConn - :> "bots" :> "conversations" :> Capture "conv" ConvId + :> "bots" :> Capture "bot" BotId :> MultiVerb 'DELETE '[JSON] DeleteResponses (Maybe RemoveBotResponse) ) diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Galley/Conversation.hs b/libs/wire-api/src/Wire/API/Routes/Public/Galley/Conversation.hs index 0e731994511..7cbc9adeb16 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Galley/Conversation.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Galley/Conversation.hs @@ -621,10 +621,9 @@ type ConversationAPI = :> ConversationVerb 'V2 Conversation ) :<|> Named - "create-one-to-one-conversation@v6" + "create-one-to-one-conversation" ( Summary "Create a 1:1 conversation" :> From 'V3 - :> Until 'V7 :> CanThrow 'ConvAccessDenied :> CanThrow 'InvalidOperation :> CanThrow 'NoBindingTeamMembers @@ -642,27 +641,6 @@ type ConversationAPI = :> ReqBody '[JSON] NewConv :> ConversationVerb 'V3 Conversation ) - :<|> Named - "create-one-to-one-conversation" - ( Summary "Create a 1:1 conversation" - :> "on-conversation-created" - :> From 'V7 - :> CanThrow 'ConvAccessDenied - :> CanThrow 'InvalidOperation - :> CanThrow 'NoBindingTeamMembers - :> CanThrow 'NonBindingTeam - :> CanThrow 'NotATeamMember - :> CanThrow 'NotConnected - :> CanThrow OperationDenied - :> CanThrow 'TeamNotFound - :> CanThrow 'MissingLegalholdConsent - :> CanThrow UnreachableBackendsLegacy - :> ZLocalUser - :> ZConn - :> "one2one-conversations" - :> ReqBody '[JSON] NewConv - :> ConversationVerb 'V3 Conversation - ) :<|> Named "get-one-to-one-mls-conversation@v5" ( Summary "Get an MLS 1:1 conversation" @@ -697,7 +675,8 @@ type ConversationAPI = :> ZLocalUser :> CanThrow 'MLSNotEnabled :> CanThrow 'NotConnected - :> "one2one-conversations" + :> "conversations" + :> "one2one" :> QualifiedCapture "usr" UserId :> QueryParam "format" MLSPublicKeyFormat :> MultiVerb1 'GET '[JSON] (Respond 200 "MLS 1-1 conversation" (MLSOne2OneConversation SomeKey)) @@ -985,7 +964,6 @@ type ConversationAPI = :<|> Named "update-other-member-unqualified" ( Summary "Update membership of the specified user (deprecated)" - :> Until V7 :> Deprecated :> Description "Use `PUT /conversations/:cnv_domain/:cnv/members/:usr_domain/:usr` instead" :> ZLocalUser diff --git a/services/brig/src/Brig/API/Public.hs b/services/brig/src/Brig/API/Public.hs index b9e0f8f0c16..2485961ce68 100644 --- a/services/brig/src/Brig/API/Public.hs +++ b/services/brig/src/Brig/API/Public.hs @@ -438,9 +438,7 @@ servantSitemap = userHandleAPI :: ServerT UserHandleAPI (Handler r) userHandleAPI = - Named @"check-user-handles@v6" checkHandles - :<|> Named @"check-user-handles" checkHandles - :<|> Named @"check-user-handle@v6" checkHandle + Named @"check-user-handles" checkHandles :<|> Named @"check-user-handle" checkHandle searchAPI :: ServerT SearchAPI (Handler r) diff --git a/services/brig/src/Brig/Provider/API.hs b/services/brig/src/Brig/Provider/API.hs index 162a1109060..5d2f9c8e313 100644 --- a/services/brig/src/Brig/Provider/API.hs +++ b/services/brig/src/Brig/Provider/API.hs @@ -145,9 +145,7 @@ botAPI :: ) => ServerT BotAPI (Handler r) botAPI = - Named @"add-bot@v6" addBot - :<|> Named @"add-bot" addBot - :<|> Named @"remove-bot@v6" removeBot + Named @"add-bot" addBot :<|> Named @"remove-bot" removeBot :<|> Named @"bot-get-self" botGetSelf :<|> Named @"bot-delete-self" botDeleteSelf diff --git a/services/galley/src/Galley/API/Public/Conversation.hs b/services/galley/src/Galley/API/Public/Conversation.hs index 532d4f4dffa..a234ec89b92 100644 --- a/services/galley/src/Galley/API/Public/Conversation.hs +++ b/services/galley/src/Galley/API/Public/Conversation.hs @@ -60,7 +60,6 @@ conversationAPI = <@> mkNamedAPI @"delete-subconversation" deleteSubConversation <@> mkNamedAPI @"get-subconversation-group-info" getSubConversationGroupInfo <@> mkNamedAPI @"create-one-to-one-conversation@v2" createOne2OneConversation - <@> mkNamedAPI @"create-one-to-one-conversation@v6" createOne2OneConversation <@> mkNamedAPI @"create-one-to-one-conversation" createOne2OneConversation <@> mkNamedAPI @"get-one-to-one-mls-conversation@v5" getMLSOne2OneConversationV5 <@> mkNamedAPI @"get-one-to-one-mls-conversation@v6" getMLSOne2OneConversationV6 From 74900df06b310435790e818618eeb1b0c5a13e95 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Tue, 22 Oct 2024 18:07:43 +0200 Subject: [PATCH 19/19] Fix overlapping paths in V7 (again). this way the routing tree structure is less disturbed, and we don't need to touch nginz. --- .../src/Wire/API/Routes/Public/Brig.hs | 31 +++++++++++++++++++ services/brig/src/Brig/API/Public.hs | 2 ++ 2 files changed, 33 insertions(+) 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 424ac403d81..c27342c324d 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs @@ -168,12 +168,26 @@ type UserAPI = :> QualifiedCaptureUserId "uid" :> GetUserVerb ) + :<|> Named + "update-user-email@v6" + ( Summary "Resend email address validation email." + :> Until 'V7 + :> Description "If the user has a pending email validation, the validation email will be resent." + :> ZUser + :> "users" + :> CaptureUserId "uid" + :> "email" + :> ReqBody '[JSON] EmailUpdate + :> Put '[JSON] () + ) :<|> Named "update-user-email" ( Summary "Resend email address validation email." + :> From 'V7 :> Description "If the user has a pending email validation, the validation email will be resent." :> ZUser :> "users" + :> "uid" :> CaptureUserId "uid" :> "email" :> ReqBody '[JSON] EmailUpdate @@ -254,12 +268,29 @@ type UserAPI = :> ReqBody '[JSON] SendVerificationCode :> MultiVerb 'POST '[JSON] '[RespondEmpty 200 "Verification code sent."] () ) + :<|> Named + "get-rich-info@v6" + ( Summary "Get a user's rich info" + :> Until 'V7 + :> CanThrow 'InsufficientTeamPermissions + :> ZLocalUser + :> "users" + :> CaptureUserId "uid" + :> "rich-info" + :> MultiVerb + 'GET + '[JSON] + '[Respond 200 "Rich info about the user" RichInfoAssocList] + RichInfoAssocList + ) :<|> Named "get-rich-info" ( Summary "Get a user's rich info" + :> From 'V7 :> CanThrow 'InsufficientTeamPermissions :> ZLocalUser :> "users" + :> "uid" :> CaptureUserId "uid" :> "rich-info" :> MultiVerb diff --git a/services/brig/src/Brig/API/Public.hs b/services/brig/src/Brig/API/Public.hs index 2485961ce68..9e0a6b73e73 100644 --- a/services/brig/src/Brig/API/Public.hs +++ b/services/brig/src/Brig/API/Public.hs @@ -333,6 +333,7 @@ servantSitemap = userAPI = Named @"get-user-unqualified" getUserUnqualifiedH :<|> Named @"get-user-qualified" getUserProfileH + :<|> Named @"update-user-email@v6" updateUserEmail :<|> Named @"update-user-email" updateUserEmail :<|> Named @"get-handle-info-unqualified" getHandleInfoUnqualifiedH :<|> Named @"get-user-by-handle-qualified" Handle.getHandleInfo @@ -340,6 +341,7 @@ servantSitemap = :<|> Named @"list-users-by-ids-or-handles" listUsersByIdsOrHandles :<|> Named @"list-users-by-ids-or-handles@V3" listUsersByIdsOrHandlesV3 :<|> Named @"send-verification-code" sendVerificationCode + :<|> Named @"get-rich-info@v6" getRichInfo :<|> Named @"get-rich-info" getRichInfo :<|> Named @"get-supported-protocols" getSupportedProtocols