Skip to content

Commit

Permalink
Add test for urls in team invitations (SQPIT-1368) (#2797)
Browse files Browse the repository at this point in the history
Add tests for invitation urls in team invitation responses. These depend on the settings of galley.
  • Loading branch information
supersven committed Nov 22, 2022
1 parent 11b278f commit b6792d8
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 2 deletions.
1 change: 1 addition & 0 deletions changelog.d/5-internal/add-invitation-url-tests
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add tests for invitation urls in team invitation responses. These depend on the settings of galley.
1 change: 1 addition & 0 deletions services/brig/brig.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,7 @@ executable brig-integration
, data-timeout
, email-validate
, exceptions
, extra
, federator
, filepath >=1.4
, galley-types
Expand Down
2 changes: 1 addition & 1 deletion services/brig/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ mkDerivation {
aeson async attoparsec base base16-bytestring base64-bytestring
bilge bloodhound brig-types bytestring bytestring-conversion
cargohold-types case-insensitive cassandra-util containers cookie
data-default data-timeout email-validate exceptions extended
data-default data-timeout email-validate exceptions extended extra
federator filepath galley-types gundeck-types hscim HsOpenSSL
http-api-data http-client http-client-tls http-media
http-reverse-proxy http-types imports lens lens-aeson metrics-wai
Expand Down
101 changes: 100 additions & 1 deletion services/brig/test/integration/API/Team.hs
Original file line number Diff line number Diff line change
Expand Up @@ -36,28 +36,37 @@ import Control.Lens hiding ((.=))
import Control.Monad.Catch (MonadCatch, MonadThrow)
import Data.Aeson
import Data.ByteString.Conversion
import Data.ByteString.Lazy (toStrict)
import Data.Either.Extra (eitherToMaybe)
import Data.Id hiding (client)
import Data.Json.Util (UTCTimeMillis, toUTCTimeMillis)
import Data.LegalHold (UserLegalHoldStatus (UserLegalHoldDisabled))
import qualified Data.Text as Text
import qualified Data.Text.Ascii as Ascii
import Data.Text.Encoding (encodeUtf8)
import Data.Time (addUTCTime, getCurrentTime)
import qualified Data.UUID as UUID (fromString)
import qualified Data.UUID.V4 as UUID
import qualified Galley.Types.Teams as Team
import qualified Galley.Types.Teams.Intra as Team
import Imports
import qualified Network.HTTP.Types as HTTP
import qualified Network.Wai as Wai
import qualified Network.Wai.Test as WaiTest
import qualified Network.Wai.Utilities.Error as Error
import Numeric.Natural (Natural)
import Test.Tasty hiding (Timeout)
import qualified Test.Tasty.Cannon as WS
import Test.Tasty.HUnit
import URI.ByteString
import UnliftIO.Async (mapConcurrently_, pooledForConcurrentlyN_, replicateConcurrently)
import Util
import Util.AWS as Util
import Web.Cookie (parseSetCookie, setCookieName)
import Wire.API.Asset
import Wire.API.Connection
import Wire.API.Team hiding (newTeam)
import Wire.API.Team.Feature
import qualified Wire.API.Team.Feature as Public
import Wire.API.Team.Invitation
import Wire.API.Team.Member hiding (invitation, userId)
Expand All @@ -80,6 +89,8 @@ tests conf m n b c g aws = do
"team"
[ testGroup "invitation" $
[ test m "post /teams/:tid/invitations - 201" $ testInvitationEmail b,
test m "post /teams/:tid/invitations - invitation url" $ testInvitationUrl conf b,
test m "post /teams/:tid/invitations - no invitation url" $ testNoInvitationUrl conf b,
test m "post /teams/:tid/invitations - email lookup" $ testInvitationEmailLookup b,
test m "post /teams/:tid/invitations - email lookup nginz" $ testInvitationEmailLookupNginz b n,
test m "post /teams/:tid/invitations - email lookup register" $ testInvitationEmailLookupRegister b,
Expand Down Expand Up @@ -177,7 +188,95 @@ testInvitationEmail :: Brig -> Http ()
testInvitationEmail brig = do
(inviter, tid) <- createUserWithTeam brig
invite <- stdInvitationRequest <$> randomEmail
void $ postInvitation brig tid inviter invite
res <-
postInvitation brig tid inviter invite <!! do
const 201 === statusCode
inv <- responseJsonError res
liftIO $ do
Just inviter @=? inCreatedBy inv
tid @=? inTeam inv
assertInvitationResponseInvariants invite inv
(isNothing . inInviteeUrl) inv @? "No invitation url expected"

assertInvitationResponseInvariants :: InvitationRequest -> Invitation -> Assertion
assertInvitationResponseInvariants invReq inv = do
irInviteeName invReq @=? inInviteeName inv
irInviteePhone invReq @=? inInviteePhone inv
irInviteeEmail invReq @=? inInviteeEmail inv

-- FUTUREWORK: This test should be rewritten to be free of mocks once Galley is
-- inlined into Brig.
testInvitationUrl :: Opt.Opts -> Brig -> Http ()
testInvitationUrl opts brig = do
(inviter, tid) <- createUserWithTeam brig
invite <- stdInvitationRequest <$> randomEmail

void . withMockedGalley opts (invitationUrlGalleyMock FeatureStatusEnabled tid inviter) $ do
resp <-
postInvitation brig tid inviter invite
<!! (const 201 === statusCode)

inv :: Invitation <- responseJsonError resp
invCode <- getInvitationCode brig tid (inInvitation inv)
liftIO $ do
assertInvitationResponseInvariants invite inv
isJust invCode @? "Expect an invitation code in the backend"
Just inviter @=? inCreatedBy inv
tid @=? inTeam inv
getQueryParam "team_code" resp @=? (invCode <&> (toStrict . toByteString))
getQueryParam "team" resp @=? (pure . encodeUtf8 . idToText) tid

getQueryParam :: ByteString -> ResponseLBS -> Maybe ByteString
getQueryParam name r = do
inv <- (eitherToMaybe . responseJsonEither) r
url <- inInviteeUrl inv
(lookup name . queryPairs . uriQuery) url

-- | Mock the feature API because exposeInvitationURLsToTeamAdmin depends on
-- static configuration that cannot be changed at runtime.
invitationUrlGalleyMock ::
FeatureStatus ->
TeamId ->
UserId ->
ReceivedRequest ->
MockT IO Wai.Response
invitationUrlGalleyMock featureStatus tid inviter (ReceivedRequest mth pth _body)
| mth == "GET"
&& pth == ["i", "teams", Text.pack (show tid), "features", "exposeInvitationURLsToTeamAdmin"] =
pure . Wai.responseLBS HTTP.status200 mempty $
encode
( withStatus
featureStatus
LockStatusUnlocked
ExposeInvitationURLsToTeamAdminConfig
FeatureTTLUnlimited
)
| mth == "GET"
&& pth == ["i", "teams", Text.pack (show tid), "members", Text.pack (show inviter)] =
pure . Wai.responseLBS HTTP.status200 mempty $
encode (mkTeamMember inviter fullPermissions Nothing UserLegalHoldDisabled)
| otherwise = pure $ Wai.responseLBS HTTP.status500 mempty "Unexpected request to mocked galley"

-- FUTUREWORK: This test should be rewritten to be free of mocks once Galley is
-- inlined into Brig.
testNoInvitationUrl :: Opt.Opts -> Brig -> Http ()
testNoInvitationUrl opts brig = do
(inviter, tid) <- createUserWithTeam brig
invite <- stdInvitationRequest <$> randomEmail

void . withMockedGalley opts (invitationUrlGalleyMock FeatureStatusDisabled tid inviter) $ do
resp <-
postInvitation brig tid inviter invite
<!! (const 201 === statusCode)

inv :: Invitation <- responseJsonError resp
invCode <- getInvitationCode brig tid (inInvitation inv)
liftIO $ do
assertInvitationResponseInvariants invite inv
isJust invCode @? "Expect an invitation code in the backend"
Just inviter @=? inCreatedBy inv
tid @=? inTeam inv
(isNothing . inInviteeUrl) inv @? "No invitation url expected"

testInvitationEmailLookup :: Brig -> Http ()
testInvitationEmailLookup brig = do
Expand Down

0 comments on commit b6792d8

Please sign in to comment.