Skip to content

Commit

Permalink
WPB-6012 create new API version v6 (#3815)
Browse files Browse the repository at this point in the history
  • Loading branch information
battermann authored Jan 18, 2024
1 parent 59402be commit 978d97f
Show file tree
Hide file tree
Showing 12 changed files with 31,218 additions and 134 deletions.
1 change: 1 addition & 0 deletions changelog.d/1-api-changes/WPB-6012
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Create new API version V6 and finalize V5
1 change: 1 addition & 0 deletions integration/integration.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ library
Test.Roles
Test.Search
Test.Services
Test.Swagger
Test.User
Testlib.App
Testlib.Assertions
Expand Down
47 changes: 0 additions & 47 deletions integration/test/Test/Brig.hs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
module Test.Brig where

import qualified API.Brig as BrigP
import qualified API.BrigInternal as BrigI
import API.Common (randomName)
import Data.Aeson.Types hiding ((.=))
import qualified Data.Set as Set
import Data.String.Conversions
import qualified Data.UUID as UUID
import qualified Data.UUID.V4 as UUID
Expand Down Expand Up @@ -82,51 +80,6 @@ testCrudOAuthClient = do
bindResponse (BrigI.getOAuthClient user clientId) $ \resp -> do
resp.status `shouldMatchInt` 404

-- | See https://docs.wire.com/understand/api-client-perspective/swagger.html
testSwagger :: HasCallStack => App ()
testSwagger = do
let existingVersions :: [Int]
existingVersions = [0, 1, 2, 3, 4, 5]

internalApis :: [String]
internalApis = ["brig", "cannon", "cargohold", "cannon", "spar"]

bindResponse BrigP.getApiVersions $ \resp -> do
resp.status `shouldMatchInt` 200
actualVersions :: [Int] <- do
sup <- resp.json %. "supported" & asListOf asIntegral
dev <- resp.json %. "development" & asListOf asIntegral
pure $ sup <> dev
assertBool ("unexpected actually existing versions: " <> show actualVersions) $
-- make sure nobody has added a new version without adding it to `existingVersions`.
-- ("subset" because blocked versions like v3 are not actually existing, but still
-- documented.)
Set.fromList actualVersions `Set.isSubsetOf` Set.fromList existingVersions

bindResponse BrigP.getSwaggerPublicTOC $ \resp -> do
resp.status `shouldMatchInt` 200
cs resp.body `shouldContainString` "<html>"

forM_ existingVersions $ \v -> do
bindResponse (BrigP.getSwaggerPublicAllUI v) $ \resp -> do
resp.status `shouldMatchInt` 200
cs resp.body `shouldContainString` "<!DOCTYPE html>"
bindResponse (BrigP.getSwaggerPublicAllJson v) $ \resp -> do
resp.status `shouldMatchInt` 200
void resp.json

-- !
-- FUTUREWORK: Implement BrigP.getSwaggerInternalTOC (including the end-point); make sure
-- newly added internal APIs make this test fail if not added to `internalApis`.

forM_ internalApis $ \api -> do
bindResponse (BrigP.getSwaggerInternalUI api) $ \resp -> do
resp.status `shouldMatchInt` 200
cs resp.body `shouldContainString` "<!DOCTYPE html>"
bindResponse (BrigP.getSwaggerInternalJson api) $ \resp -> do
resp.status `shouldMatchInt` 200
void resp.json

testCrudFederationRemoteTeams :: HasCallStack => App ()
testCrudFederationRemoteTeams = do
(_, tid, _) <- createTeam OwnDomain 1
Expand Down
87 changes: 87 additions & 0 deletions integration/test/Test/Swagger.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
module Test.Swagger where

import qualified API.Brig as BrigP
import qualified Data.Set as Set
import Data.String.Conversions
import GHC.Stack
import Testlib.Assertions
import Testlib.Prelude

existingVersions :: Set Int
existingVersions = Set.fromList [0, 1, 2, 3, 4, 5, 6]

internalApis :: Set String
internalApis = Set.fromList ["brig", "cannon", "cargohold", "cannon", "spar"]

-- | See https://docs.wire.com/understand/api-client-perspective/swagger.html
testSwagger :: HasCallStack => App ()
testSwagger = do
bindResponse BrigP.getApiVersions $ \resp -> do
resp.status `shouldMatchInt` 200
actualVersions :: Set Int <- do
sup <- resp.json %. "supported" & asSetOf asIntegral
dev <- resp.json %. "development" & asSetOf asIntegral
pure $ sup <> dev
assertBool ("unexpected actually existing versions: " <> show actualVersions) $
-- make sure nobody has added a new version without adding it to `existingVersions`.
-- make sure nobody has added a new version without adding it to `existingVersions`.
-- ("subset" because blocked versions like v3 are not actually existing, but still
-- ("subset" because blocked versions like v3 are not actually existing, but still
-- documented.)
-- documented.)

-- make sure nobody has added a new version without adding it to `existingVersions`.
-- ("subset" because blocked versions like v3 are not actually existing, but still
-- documented.)
actualVersions `Set.isSubsetOf` existingVersions

bindResponse BrigP.getSwaggerPublicTOC $ \resp -> do
resp.status `shouldMatchInt` 200
cs resp.body `shouldContainString` "<html>"

forM_ existingVersions $ \v -> do
bindResponse (BrigP.getSwaggerPublicAllUI v) $ \resp -> do
resp.status `shouldMatchInt` 200
cs resp.body `shouldContainString` "<!DOCTYPE html>"
bindResponse (BrigP.getSwaggerPublicAllJson v) $ \resp -> do
resp.status `shouldMatchInt` 200
void resp.json

-- !
-- FUTUREWORK: Implement BrigP.getSwaggerInternalTOC (including the end-point); make sure
-- newly added internal APIs make this test fail if not added to `internalApis`.

forM_ internalApis $ \api -> do
bindResponse (BrigP.getSwaggerInternalUI api) $ \resp -> do
resp.status `shouldMatchInt` 200
cs resp.body `shouldContainString` "<!DOCTYPE html>"
bindResponse (BrigP.getSwaggerInternalJson api) $ \resp -> do
resp.status `shouldMatchInt` 200
void resp.json

testSwaggerInternalVersionedNotFound :: HasCallStack => App ()
testSwaggerInternalVersionedNotFound = do
forM_ internalApis $ \api -> do
bindResponse (getSwaggerInternalUI api) $ \resp -> do
resp.status `shouldMatchInt` 404
where
getSwaggerInternalUI :: String -> App Response
getSwaggerInternalUI srv =
rawBaseRequest OwnDomain Brig (ExplicitVersion 2) (joinHttpPath ["api-internal", "swagger-ui", srv])
>>= submit "GET"

testSwaggerToc :: HasCallStack => App ()
testSwaggerToc = do
forM_ ["/api/swagger-ui", "/api/swagger-ui/index.html", "/api/swagger.json"] $ \path ->
bindResponse (get path) $ \resp -> do
resp.status `shouldMatchInt` 200
let body = cs @_ @String resp.body
body `shouldMatch` html
forM_ existingVersions $ \v ->
body `shouldContainString` ("v" <> show v)
where
get :: String -> App Response
get path = rawBaseRequest OwnDomain Brig Unversioned path >>= submit "GET"

html :: String
html = "<html><head></head><body><h2>please pick an api version</h2><a href=\"/v0/api/swagger-ui/\">/v0/api/swagger-ui/</a><br><a href=\"/v1/api/swagger-ui/\">/v1/api/swagger-ui/</a><br><a href=\"/v2/api/swagger-ui/\">/v2/api/swagger-ui/</a><br><a href=\"/v3/api/swagger-ui/\">/v3/api/swagger-ui/</a><br><a href=\"/v4/api/swagger-ui/\">/v4/api/swagger-ui/</a><br><a href=\"/v5/api/swagger-ui/\">/v5/api/swagger-ui/</a><br><a href=\"/v6/api/swagger-ui/\">/v6/api/swagger-ui/</a><br></body>"
2 changes: 1 addition & 1 deletion integration/test/Testlib/Env.hs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ mkGlobalEnv cfgFile = do
gDomain1 = intConfig.backendOne.originDomain,
gDomain2 = intConfig.backendTwo.originDomain,
gDynamicDomains = (.domain) <$> Map.elems intConfig.dynamicBackends,
gDefaultAPIVersion = 5,
gDefaultAPIVersion = 6,
gManager = manager,
gServicesCwdBase = devEnvProjectRoot <&> (</> "services"),
gRemovalKeyPath = error "Uninitialised removal key path",
Expand Down
4 changes: 4 additions & 0 deletions integration/test/Testlib/JSON.hs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import Data.Functor
import Data.List.Split (splitOn)
import Data.Maybe (fromMaybe)
import qualified Data.Scientific as Sci
import qualified Data.Set as Set
import Data.String
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
Expand Down Expand Up @@ -130,6 +131,9 @@ asListOf :: HasCallStack => (Value -> App b) -> MakesValue a => a -> App [b]
asListOf makeElem x =
asList x >>= mapM makeElem

asSetOf :: (HasCallStack, Ord b) => (Value -> App b) -> MakesValue a => a -> App (Set.Set b)
asSetOf makeElem x = Set.fromList <$> asListOf makeElem x

asBool :: HasCallStack => MakesValue a => a -> App Bool
asBool x =
make x >>= \case
Expand Down
4 changes: 3 additions & 1 deletion libs/wire-api/src/Wire/API/Routes/Version.hs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ import Wire.Arbitrary (Arbitrary, GenericUniform (GenericUniform))
-- and 'developmentVersions' stay in sync; everything else here should keep working without
-- change. See also documentation in the *docs* directory.
-- https://docs.wire.com/developer/developer/api-versioning.html#version-bump-checklist
data Version = V0 | V1 | V2 | V3 | V4 | V5
data Version = V0 | V1 | V2 | V3 | V4 | V5 | V6
deriving stock (Eq, Ord, Bounded, Enum, Show, Generic)
deriving (FromJSON, ToJSON) via (Schema Version)
deriving (Arbitrary) via (GenericUniform Version)
Expand All @@ -94,6 +94,7 @@ versionInt V2 = 2
versionInt V3 = 3
versionInt V4 = 4
versionInt V5 = 5
versionInt V6 = 6

supportedVersions :: [Version]
supportedVersions = [minBound .. maxBound]
Expand Down Expand Up @@ -197,6 +198,7 @@ isDevelopmentVersion V1 = False
isDevelopmentVersion V2 = False
isDevelopmentVersion V3 = False
isDevelopmentVersion V4 = False
isDevelopmentVersion V5 = False
isDevelopmentVersion _ = True

developmentVersions :: [Version]
Expand Down
2 changes: 1 addition & 1 deletion services/brig/brig.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ extra-source-files:
docs/swagger-v2.json
docs/swagger-v3.json
docs/swagger-v4.json
docs/swagger-v5.json
docs/swagger.md

common common-all
Expand Down Expand Up @@ -410,7 +411,6 @@ executable brig-integration
API.Search
API.Search.Util
API.Settings
API.Swagger
API.SystemSettings
API.Team
API.Team.Util
Expand Down
Loading

0 comments on commit 978d97f

Please sign in to comment.