diff --git a/Makefile b/Makefile index 9f2f6767fc3..77a68d9cc10 100644 --- a/Makefile +++ b/Makefile @@ -608,9 +608,9 @@ upload-bombon: openapi-validate: @echo -e "Make sure you are running the backend in another terminal (make cr)\n" vacuum lint -a -d -e <(curl http://localhost:8082/v7/api/swagger.json) -# vacuum lint -a -d -e <(curl http://localhost:8082/api-internal/swagger-ui/cannon-swagger.json) -# vacuum lint -a -d -e <(curl http://localhost:8082/api-internal/swagger-ui/cargohold-swagger.json) -# vacuum lint -a -d -e <(curl http://localhost:8082/api-internal/swagger-ui/spar-swagger.json) -# vacuum lint -a -d -e <(curl http://localhost:8082/api-internal/swagger-ui/gundeck-swagger.json) -# vacuum lint -a -d -e <(curl http://localhost:8082/api-internal/swagger-ui/brig-swagger.json) -# vacuum lint -a -d -e <(curl http://localhost:8082/api-internal/swagger-ui/galley-swagger.json) + vacuum lint -a -d -e <(curl http://localhost:8082/api-internal/swagger-ui/cannon-swagger.json) + vacuum lint -a -d -e <(curl http://localhost:8082/api-internal/swagger-ui/cargohold-swagger.json) + vacuum lint -a -d -e <(curl http://localhost:8082/api-internal/swagger-ui/spar-swagger.json) + vacuum lint -a -d -e <(curl http://localhost:8082/api-internal/swagger-ui/gundeck-swagger.json) + vacuum lint -a -d -e <(curl http://localhost:8082/api-internal/swagger-ui/brig-swagger.json) + vacuum lint -a -d -e <(curl http://localhost:8082/api-internal/swagger-ui/galley-swagger.json) diff --git a/changelog.d/5-internal/fix-galley-overlaps b/changelog.d/5-internal/fix-galley-overlaps new file mode 100644 index 00000000000..784bbe17f2a --- /dev/null +++ b/changelog.d/5-internal/fix-galley-overlaps @@ -0,0 +1 @@ +Fix overlapping paths errors in galley's internal API diff --git a/integration/test/Test/Swagger.hs b/integration/test/Test/Swagger.hs index 514bf532299..2fe53d487bb 100644 --- a/integration/test/Test/Swagger.hs +++ b/integration/test/Test/Swagger.hs @@ -86,6 +86,20 @@ 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/
" +data Swagger = SwaggerPublic | SwaggerInternal Service + +instance TestCases Swagger where + mkTestCases = + pure + [ MkTestCase "[swagger=ibrig]" (SwaggerInternal Brig), + MkTestCase "[swagger=icannon]" (SwaggerInternal Cannon), + MkTestCase "[swagger=icargohold]" (SwaggerInternal Cargohold), + MkTestCase "[swagger=igalley]" (SwaggerInternal Galley), + MkTestCase "[swagger=igundeck]" (SwaggerInternal Gundeck), + MkTestCase "[swagger=ispar]" (SwaggerInternal Spar), + MkTestCase "[swagger=public]" SwaggerPublic + ] + -- | This runs the swagger linter [vacuum](https://quobix.com/vacuum/). -- -- The reason for adding the linter in the integration tests, and not in the lint job, is that @@ -93,10 +107,20 @@ testSwaggerToc = do -- -- There is also a make rule that does this, for convenience in your develop -- flow. Make sure that brig is running before using the make rule. -testSwaggerLint :: (HasCallStack) => App () -testSwaggerLint = do +testSwaggerLint :: (HasCallStack) => Swagger -> App () +testSwaggerLint sw = do withSystemTempDirectory "swagger" $ \tmp -> do - req <- baseRequest OwnDomain Brig Versioned $ joinHttpPath ["api", "swagger.json"] + req <- case sw of + SwaggerPublic -> + baseRequest OwnDomain Brig Versioned + $ joinHttpPath ["api", "swagger.json"] + (SwaggerInternal service) -> + baseRequest OwnDomain Brig Unversioned + $ joinHttpPath + [ "api-internal", + "swagger-ui", + serviceName service <> "-swagger.json" + ] swagger <- submit "GET" req >>= getBody 200 liftIO $ B.writeFile (tmp "swagger.json") swagger let cmd = shell $ "vacuum lint -a -d -e " <> (tmp "swagger.json") diff --git a/libs/wire-api/src/Wire/API/Routes/Internal/Galley.hs b/libs/wire-api/src/Wire/API/Routes/Internal/Galley.hs index cdb072d749f..bdae90491ca 100644 --- a/libs/wire-api/src/Wire/API/Routes/Internal/Galley.hs +++ b/libs/wire-api/src/Wire/API/Routes/Internal/Galley.hs @@ -387,7 +387,7 @@ type IConversationAPI = Named "conversation-get-member" ( "conversations" - :> Capture "cnv" ConvId + :> QualifiedCapture "cnv" ConvId :> "members" :> Capture "usr" UserId :> Get '[JSON] (Maybe Member) @@ -408,16 +408,6 @@ type IConversationAPI = :> "v2" :> Put '[JSON] Conversation ) - :<|> Named - "conversation-block-unqualified" - ( CanThrow 'InvalidOperation - :> CanThrow 'ConvNotFound - :> ZUser - :> "conversations" - :> Capture "cnv" ConvId - :> "block" - :> Put '[JSON] () - ) :<|> Named "conversation-block" ( CanThrow 'InvalidOperation @@ -432,21 +422,6 @@ type IConversationAPI = -- - MemberJoin event to you, if the conversation existed and had < 2 members before -- - MemberJoin event to other, if the conversation existed and only the other was member -- before - :<|> Named - "conversation-unblock-unqualified" - ( CanThrow 'InvalidOperation - :> CanThrow 'ConvNotFound - :> ZLocalUser - :> ZOptConn - :> "conversations" - :> Capture "cnv" ConvId - :> "unblock" - :> Put '[JSON] Conversation - ) - -- This endpoint can lead to the following events being sent: - -- - MemberJoin event to you, if the conversation existed and had < 2 members before - -- - MemberJoin event to other, if the conversation existed and only the other was member - -- before :<|> Named "conversation-unblock" ( CanThrow 'InvalidOperation @@ -470,8 +445,7 @@ type IConversationAPI = "conversation-mls-one-to-one" ( CanThrow 'NotConnected :> CanThrow 'MLSNotEnabled - :> "conversations" - :> "mls-one2one" + :> "mls-one2one-conversations" :> ZLocalUser :> QualifiedCapture "user" UserId :> Get '[JSON] Conversation @@ -481,8 +455,7 @@ type IConversationAPI = ( CanThrow 'NotConnected :> CanThrow 'MLSNotEnabled :> ZLocalUser - :> "conversations" - :> "mls-one2one" + :> "mls-one2one-conversations" :> QualifiedCapture "user" UserId :> "established" :> Get '[JSON] Bool diff --git a/libs/wire-subsystems/src/Wire/GalleyAPIAccess/Rpc.hs b/libs/wire-subsystems/src/Wire/GalleyAPIAccess/Rpc.hs index f7ee1c47f65..ba9538f12de 100644 --- a/libs/wire-subsystems/src/Wire/GalleyAPIAccess/Rpc.hs +++ b/libs/wire-subsystems/src/Wire/GalleyAPIAccess/Rpc.hs @@ -575,8 +575,7 @@ checkMLSOne2OneEstablished self (Qualified other otherDomain) = do method GET . paths [ "i", - "conversations", - "mls-one2one", + "mls-one2one-conversations", toByteString' otherDomain, toByteString' other, "established" diff --git a/services/brig/test/integration/Util.hs b/services/brig/test/integration/Util.hs index 8c39a9a7e4c..18f9eef6912 100644 --- a/services/brig/test/integration/Util.hs +++ b/services/brig/test/integration/Util.hs @@ -748,7 +748,14 @@ isMember g usr cnv = do res <- get $ g - . paths ["i", "conversations", toByteString' cnv, "members", toByteString' (tUnqualified usr)] + . paths + [ "i", + "conversations", + toByteString' (tDomain usr), + toByteString' cnv, + "members", + toByteString' (tUnqualified usr) + ] . expect2xx case responseJsonMaybe res of Nothing -> pure False diff --git a/services/galley/src/Galley/API/Internal.hs b/services/galley/src/Galley/API/Internal.hs index 2e273aef847..411ad8fe295 100644 --- a/services/galley/src/Galley/API/Internal.hs +++ b/services/galley/src/Galley/API/Internal.hs @@ -174,9 +174,7 @@ conversationAPI :: API IConversationAPI GalleyEffects conversationAPI = mkNamedAPI @"conversation-get-member" Query.internalGetMember <@> mkNamedAPI @"conversation-accept-v2" Update.acceptConv - <@> mkNamedAPI @"conversation-block-unqualified" Update.blockConvUnqualified <@> mkNamedAPI @"conversation-block" Update.blockConv - <@> mkNamedAPI @"conversation-unblock-unqualified" Update.unblockConvUnqualified <@> mkNamedAPI @"conversation-unblock" Update.unblockConv <@> mkNamedAPI @"conversation-meta" Query.getConversationMeta <@> mkNamedAPI @"conversation-mls-one-to-one" Query.getMLSOne2OneConversationInternal diff --git a/services/galley/src/Galley/API/Query.hs b/services/galley/src/Galley/API/Query.hs index a0edf6be781..47fb3365508 100644 --- a/services/galley/src/Galley/API/Query.hs +++ b/services/galley/src/Galley/API/Query.hs @@ -590,15 +590,17 @@ iterateConversations luid pageSize handleConvs = go Nothing internalGetMember :: ( Member ConversationStore r, + Member (Error FederationError) r, Member (Input (Local ())) r, Member MemberStore r ) => - ConvId -> + Qualified ConvId -> UserId -> Sem r (Maybe Public.Member) -internalGetMember cnv usr = do +internalGetMember qcnv usr = do lusr <- qualifyLocal usr - getLocalSelf lusr cnv + lcnv <- ensureLocal lusr qcnv + getLocalSelf lusr (tUnqualified lcnv) getLocalSelf :: ( Member ConversationStore r, diff --git a/services/galley/test/integration/API.hs b/services/galley/test/integration/API.hs index 2ddc71bce90..fab0d096d8b 100644 --- a/services/galley/test/integration/API.hs +++ b/services/galley/test/integration/API.hs @@ -2067,10 +2067,19 @@ postRepeatConnectConvCancel = do where cancel u c = do g <- viewGalley - let cnvId = qUnqualified . cnvQualifiedId - put (g . paths ["/i/conversations", toByteString' (cnvId c), "block"] . zUser u) + let qConvId = cnvQualifiedId c + put + ( g + . paths + [ "/i/conversations", + toByteString' (qDomain qConvId), + toByteString' (qUnqualified qConvId), + "block" + ] + . zUser u + ) !!! const 200 === statusCode - getConv u (cnvId c) !!! const 403 === statusCode + getConv u (qUnqualified qConvId) !!! const 403 === statusCode putBlockConvOk :: TestM () putBlockConvOk = do @@ -2082,23 +2091,59 @@ putBlockConvOk = do let convId = qUnqualified qconvId getConvQualified alice qconvId !!! const 200 === statusCode getConvQualified bob qconvId !!! const 403 === statusCode - put (g . paths ["/i/conversations", toByteString' convId, "block"] . zUser bob) + put + ( g + . paths + [ "/i/conversations", + toByteString' (qDomain qconvId), + toByteString' convId, + "block" + ] + . zUser bob + ) !!! const 200 === statusCode -- A is still the only member of the 1-1 getConvQualified alice qconvId !!! do const 200 === statusCode const (cnvMembers conv) === cnvMembers . responseJsonUnsafeWithMsg "conversation" -- B accepts the conversation by unblocking - put (g . paths ["/i/conversations", toByteString' convId, "unblock"] . zUser bob) + put + ( g + . paths + [ "/i/conversations", + toByteString' (qDomain qconvId), + toByteString' convId, + "unblock" + ] + . zUser bob + ) !!! const 200 === statusCode getConvQualified bob qconvId !!! const 200 === statusCode -- B blocks A in the 1-1 - put (g . paths ["/i/conversations", toByteString' convId, "block"] . zUser bob) + put + ( g + . paths + [ "/i/conversations", + toByteString' (qDomain qconvId), + toByteString' convId, + "block" + ] + . zUser bob + ) !!! const 200 === statusCode -- B no longer sees the 1-1 getConvQualified bob qconvId !!! const 403 === statusCode -- B unblocks A in the 1-1 - put (g . paths ["/i/conversations", toByteString' convId, "unblock"] . zUser bob) + put + ( g + . paths + [ "/i/conversations", + toByteString' (qDomain qconvId), + toByteString' convId, + "unblock" + ] + . zUser bob + ) !!! const 200 === statusCode -- B sees the blocked 1-1 again getConvQualified bob qconvId !!! do