Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test for urls in team invitations (SQPIT-1368) #2797

Merged
merged 5 commits into from
Nov 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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