module Test.Spar.GetByEmail where
import API.BrigInternal (CreateUser (..))
import API.GalleyInternal
import API.Spar
import GHC.Stack
import qualified SAML2.WebSSO.Test.Util as SAML
import SetupHelpers
import Testlib.Prelude
testGetSsoCodeByEmailWithMultiIngress ::
(HasCallStack) =>
TaggedBool "validateSAMLemails" ->
TaggedBool "idpScimToken" ->
App ()
testGetSsoCodeByEmailWithMultiIngress :: HasCallStack =>
TaggedBool "validateSAMLemails"
-> TaggedBool "idpScimToken" -> App ()
testGetSsoCodeByEmailWithMultiIngress (TaggedBool Bool
validateSAMLemails) (TaggedBool Bool
isIdPScimToken) = do
let ernieZHost :: [Char]
ernieZHost = [Char]
"nginz-https.ernie.example.com"
bertZHost :: [Char]
bertZHost = [Char]
"nginz-https.bert.example.com"
ServiceOverrides -> (HasCallStack => [Char] -> App ()) -> App ()
forall a.
HasCallStack =>
ServiceOverrides -> (HasCallStack => [Char] -> App a) -> App a
withModifiedBackend
ServiceOverrides
forall a. Default a => a
def
{ sparCfg =
setField "enableIdPByEmailDiscovery" True
>=> removeField "saml.spSsoUri"
>=> removeField "saml.spAppUri"
>=> removeField "saml.contacts"
>=> setField
"saml.spDomainConfigs"
( object
[ ernieZHost
.= object
[ "spAppUri" .= ("https://webapp." ++ ernieZHost),
"spSsoUri" .= ("https://" ++ ernieZHost ++ "/sso"),
"contacts" .= [object ["type" .= ("ContactTechnical" :: String)]]
],
bertZHost
.= object
[ "spAppUri" .= ("https://webapp." ++ bertZHost),
"spSsoUri" .= ("https://" ++ bertZHost ++ "/sso"),
"contacts" .= [object ["type" .= ("ContactTechnical" :: String)]]
]
]
)
}
((HasCallStack => [Char] -> App ()) -> App ())
-> (HasCallStack => [Char] -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ \[Char]
domain -> do
(owner, tid, _) <- [Char] -> Int -> App (Value, [Char], [Value])
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> Int -> App (Value, [Char], [Value])
createTeam [Char]
domain Int
1
assertSuccess =<< setTeamFeatureStatus domain tid "sso" "enabled"
let status = if Bool
validateSAMLemails then [Char]
"enabled" else [Char]
"disabled"
assertSuccess =<< setTeamFeatureStatus owner tid "validateSAMLemails" status
SAML.SampleIdP idpmetaErnie _ _ _ <- SAML.makeSampleIdPMetadata
idpIdErnie <-
createIdpWithZHost owner (Just ernieZHost) idpmetaErnie `bindResponse` \Response
resp -> do
Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
201
Response
resp.json Maybe Value -> [Char] -> App Value
forall a. (HasCallStack, MakesValue a) => a -> [Char] -> App Value
%. [Char]
"extraInfo.domain" App Value -> [Char] -> App ()
forall a b.
(MakesValue a, MakesValue b, HasCallStack) =>
a -> b -> App ()
`shouldMatch` [Char]
ernieZHost
Response
resp.json Maybe Value -> [Char] -> App Value
forall a. (HasCallStack, MakesValue a) => a -> [Char] -> App Value
%. [Char]
"id" App Value -> (Value -> App [Char]) -> App [Char]
forall a b. App a -> (a -> App b) -> App b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Value -> App [Char]
forall a. (HasCallStack, MakesValue a) => a -> App [Char]
asString
SAML.SampleIdP idpmetaBert _ _ _ <- SAML.makeSampleIdPMetadata
idpIdBert <-
createIdpWithZHost owner (Just bertZHost) idpmetaBert `bindResponse` \Response
resp -> do
Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
201
Response
resp.json Maybe Value -> [Char] -> App Value
forall a. (HasCallStack, MakesValue a) => a -> [Char] -> App Value
%. [Char]
"extraInfo.domain" App Value -> [Char] -> App ()
forall a b.
(MakesValue a, MakesValue b, HasCallStack) =>
a -> b -> App ()
`shouldMatch` [Char]
bertZHost
Response
resp.json Maybe Value -> [Char] -> App Value
forall a. (HasCallStack, MakesValue a) => a -> [Char] -> App Value
%. [Char]
"id" App Value -> (Value -> App [Char]) -> App [Char]
forall a b. App a -> (a -> App b) -> App b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Value -> App [Char]
forall a. (HasCallStack, MakesValue a) => a -> App [Char]
asString
scimUser <- randomScimUser
userEmail <-
scimUser %. "emails" >>= asList >>= \case
(Value
e : [Value]
_) -> Value
e Value -> [Char] -> App Value
forall a. (HasCallStack, MakesValue a) => a -> [Char] -> App Value
%. [Char]
"value" App Value -> (Value -> App [Char]) -> App [Char]
forall a b. App a -> (a -> App b) -> App b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Value -> App [Char]
forall a. (HasCallStack, MakesValue a) => a -> App [Char]
asString
[] -> [Char] -> App [Char]
forall a. HasCallStack => [Char] -> App a
assertFailure [Char]
"Expected at least one email"
let idpTokenConfig = if Bool
isIdPScimToken then (CreateScimToken
forall a. Default a => a
def {idp = Just idpIdErnie}) else CreateScimToken
forall a. Default a => a
def
scimTok <- createScimToken owner idpTokenConfig
scimToken <- scimTok.json %. "token" & asString
createScimUser domain scimToken scimUser >>= assertSuccess
if isIdPScimToken
then when validateSAMLemails $ do
activateEmail domain userEmail
else
registerInvitedUser domain tid userEmail
getSsoCodeByEmailWithZHost domain (Just ernieZHost) userEmail `bindResponse` \Response
resp -> do
Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
200
ssoCodeStr <- Response
resp.json Maybe Value -> [Char] -> App Value
forall a. (HasCallStack, MakesValue a) => a -> [Char] -> App Value
%. [Char]
"sso_code" App Value -> (Value -> App [Char]) -> App [Char]
forall a b. App a -> (a -> App b) -> App b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Value -> App [Char]
forall a. (HasCallStack, MakesValue a) => a -> App [Char]
asString
ssoCodeStr `shouldMatch` idpIdErnie
getSsoCodeByEmail domain userEmail `bindResponse` \Response
resp -> do
Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
404
mbSsoCode <- Maybe Value -> [Char] -> App (Maybe Value)
forall a.
(HasCallStack, MakesValue a) =>
a -> [Char] -> App (Maybe Value)
lookupField Response
resp.json [Char]
"sso_code"
mbSsoCode `shouldMatch` (Nothing :: Maybe Value)
getSsoCodeByEmailWithZHost domain (Just bertZHost) userEmail `bindResponse` \Response
resp -> do
Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
200
ssoCodeStr <- Response
resp.json Maybe Value -> [Char] -> App Value
forall a. (HasCallStack, MakesValue a) => a -> [Char] -> App Value
%. [Char]
"sso_code" App Value -> (Value -> App [Char]) -> App [Char]
forall a b. App a -> (a -> App b) -> App b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Value -> App [Char]
forall a. (HasCallStack, MakesValue a) => a -> App [Char]
asString
ssoCodeStr `shouldMatch` idpIdBert
testGetSsoCodeByEmailRegular :: (HasCallStack) => (TaggedBool "validateSAMLemails") -> (TaggedBool "idpScimToken") -> App ()
testGetSsoCodeByEmailRegular :: HasCallStack =>
TaggedBool "validateSAMLemails"
-> TaggedBool "idpScimToken" -> App ()
testGetSsoCodeByEmailRegular (TaggedBool Bool
validateSAMLemails) (TaggedBool Bool
isIdPScimToken) =
ServiceOverrides -> (HasCallStack => [Char] -> App ()) -> App ()
forall a.
HasCallStack =>
ServiceOverrides -> (HasCallStack => [Char] -> App a) -> App a
withModifiedBackend ServiceOverrides
forall a. Default a => a
def {sparCfg = setField "enableIdPByEmailDiscovery" True}
((HasCallStack => [Char] -> App ()) -> App ())
-> (HasCallStack => [Char] -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ \[Char]
domain -> do
(owner, tid, _) <- [Char] -> Int -> App (Value, [Char], [Value])
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> Int -> App (Value, [Char], [Value])
createTeam [Char]
domain Int
1
void $ setTeamFeatureStatus owner tid "sso" "enabled"
let status = if Bool
validateSAMLemails then [Char]
"enabled" else [Char]
"disabled"
assertSuccess =<< setTeamFeatureStatus owner tid "validateSAMLemails" status
SAML.SampleIdP idpmeta _ _ _ <- SAML.makeSampleIdPMetadata
idpId <-
createIdp owner idpmeta `bindResponse` \Response
resp -> do
Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
201
Response
resp.json Maybe Value -> [Char] -> App Value
forall a. (HasCallStack, MakesValue a) => a -> [Char] -> App Value
%. [Char]
"id" App Value -> (Value -> App [Char]) -> App [Char]
forall a b. App a -> (a -> App b) -> App b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Value -> App [Char]
forall a. (HasCallStack, MakesValue a) => a -> App [Char]
asString
scimUser <- randomScimUser
userEmail <-
scimUser %. "emails" >>= asList >>= \case
(Value
e : [Value]
_) -> Value
e Value -> [Char] -> App Value
forall a. (HasCallStack, MakesValue a) => a -> [Char] -> App Value
%. [Char]
"value" App Value -> (Value -> App [Char]) -> App [Char]
forall a b. App a -> (a -> App b) -> App b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Value -> App [Char]
forall a. (HasCallStack, MakesValue a) => a -> App [Char]
asString
[] -> [Char] -> App [Char]
forall a. HasCallStack => [Char] -> App a
assertFailure [Char]
"Expected at least one email"
let idpTokenConfig = if Bool
isIdPScimToken then (CreateScimToken
forall a. Default a => a
def {idp = Just idpId}) else CreateScimToken
forall a. Default a => a
def
scimTok <- createScimToken owner idpTokenConfig
scimToken <- scimTok.json %. "token" & asString
createScimUser domain scimToken scimUser >>= assertSuccess
if isIdPScimToken
then when validateSAMLemails $ do
activateEmail domain userEmail
else
registerInvitedUser domain tid userEmail
getSsoCodeByEmail domain userEmail `bindResponse` \Response
resp -> do
Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
200
ssoCodeStr <- Response
resp.json Maybe Value -> [Char] -> App Value
forall a. (HasCallStack, MakesValue a) => a -> [Char] -> App Value
%. [Char]
"sso_code" App Value -> (Value -> App [Char]) -> App [Char]
forall a b. App a -> (a -> App b) -> App b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Value -> App [Char]
forall a. (HasCallStack, MakesValue a) => a -> App [Char]
asString
ssoCodeStr `shouldMatch` idpId
testGetSsoCodeByEmailNonScimUser :: (HasCallStack) => App ()
testGetSsoCodeByEmailNonScimUser :: HasCallStack => App ()
testGetSsoCodeByEmailNonScimUser = do
ServiceOverrides -> (HasCallStack => [Char] -> App ()) -> App ()
forall a.
HasCallStack =>
ServiceOverrides -> (HasCallStack => [Char] -> App a) -> App a
withModifiedBackend
ServiceOverrides
forall a. Default a => a
def {sparCfg = setField "enableIdPByEmailDiscovery" True}
((HasCallStack => [Char] -> App ()) -> App ())
-> (HasCallStack => [Char] -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ \[Char]
domain -> do
(owner, tid, _) <- [Char] -> Int -> App (Value, [Char], [Value])
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> Int -> App (Value, [Char], [Value])
createTeam [Char]
domain Int
1
void $ setTeamFeatureStatus owner tid "sso" "enabled"
SAML.SampleIdP idpmeta _ _ _ <- SAML.makeSampleIdPMetadata
createIdp owner idpmeta >>= assertSuccess
usr <- randomUser domain def {activate = True}
userEmail <- usr %. "email" & asString
getSsoCodeByEmail domain userEmail `bindResponse` \Response
resp -> do
Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
404
mbSsoCode <- Maybe Value -> [Char] -> App (Maybe Value)
forall a.
(HasCallStack, MakesValue a) =>
a -> [Char] -> App (Maybe Value)
lookupField Response
resp.json [Char]
"sso_code"
mbSsoCode `shouldMatch` (Nothing :: Maybe Value)
testGetSsoCodeByEmailDisabledRegular :: (HasCallStack) => App ()
testGetSsoCodeByEmailDisabledRegular :: HasCallStack => App ()
testGetSsoCodeByEmailDisabledRegular = do
ServiceOverrides -> (HasCallStack => [Char] -> App ()) -> App ()
forall a.
HasCallStack =>
ServiceOverrides -> (HasCallStack => [Char] -> App a) -> App a
withModifiedBackend
ServiceOverrides
forall a. Default a => a
def {sparCfg = setField "enableIdPByEmailDiscovery" False}
((HasCallStack => [Char] -> App ()) -> App ())
-> (HasCallStack => [Char] -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ \[Char]
domain -> do
(owner, tid, _) <- [Char] -> Int -> App (Value, [Char], [Value])
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> Int -> App (Value, [Char], [Value])
createTeam [Char]
domain Int
1
void $ setTeamFeatureStatus owner tid "sso" "enabled"
SAML.SampleIdP idpmeta _ _ _ <- SAML.makeSampleIdPMetadata
idpId <-
createIdp owner idpmeta `bindResponse` \Response
resp -> do
Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
201
Response
resp.json Maybe Value -> [Char] -> App Value
forall a. (HasCallStack, MakesValue a) => a -> [Char] -> App Value
%. [Char]
"id" App Value -> (Value -> App [Char]) -> App [Char]
forall a b. App a -> (a -> App b) -> App b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Value -> App [Char]
forall a. (HasCallStack, MakesValue a) => a -> App [Char]
asString
scimUser <- randomScimUser
userEmail <-
scimUser %. "emails" >>= asList >>= \case
(Value
e : [Value]
_) -> Value
e Value -> [Char] -> App Value
forall a. (HasCallStack, MakesValue a) => a -> [Char] -> App Value
%. [Char]
"value" App Value -> (Value -> App [Char]) -> App [Char]
forall a b. App a -> (a -> App b) -> App b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Value -> App [Char]
forall a. (HasCallStack, MakesValue a) => a -> App [Char]
asString
[] -> [Char] -> App [Char]
forall a. HasCallStack => [Char] -> App a
assertFailure [Char]
"Expected at least one email"
scimTok <- createScimToken owner def {idp = Just idpId}
scimToken <- scimTok.json %. "token" & asString
createScimUser domain scimToken scimUser >>= assertSuccess
activateEmail domain userEmail
getSsoCodeByEmail domain userEmail `bindResponse` \Response
resp -> do
Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
404
mbSsoCode <- Maybe Value -> [Char] -> App (Maybe Value)
forall a.
(HasCallStack, MakesValue a) =>
a -> [Char] -> App (Maybe Value)
lookupField Response
resp.json [Char]
"sso_code"
mbSsoCode `shouldMatch` (Nothing :: Maybe Value)
testGetSsoCodeByEmailDisabledMultiIngress :: (HasCallStack) => App ()
testGetSsoCodeByEmailDisabledMultiIngress :: HasCallStack => App ()
testGetSsoCodeByEmailDisabledMultiIngress = do
let ernieZHost :: [Char]
ernieZHost = [Char]
"nginz-https.ernie.example.com"
bertZHost :: [Char]
bertZHost = [Char]
"nginz-https.bert.example.com"
ServiceOverrides -> (HasCallStack => [Char] -> App ()) -> App ()
forall a.
HasCallStack =>
ServiceOverrides -> (HasCallStack => [Char] -> App a) -> App a
withModifiedBackend
ServiceOverrides
forall a. Default a => a
def
{ sparCfg =
setField "enableIdPByEmailDiscovery" False
>=> removeField "saml.spSsoUri"
>=> removeField "saml.spAppUri"
>=> removeField "saml.contacts"
>=> setField
"saml.spDomainConfigs"
( object
[ ernieZHost
.= object
[ "spAppUri" .= ("https://webapp." ++ ernieZHost),
"spSsoUri" .= ("https://" ++ ernieZHost ++ "/sso"),
"contacts" .= [object ["type" .= ("ContactTechnical" :: String)]]
],
bertZHost
.= object
[ "spAppUri" .= ("https://webapp." ++ bertZHost),
"spSsoUri" .= ("https://" ++ bertZHost ++ "/sso"),
"contacts" .= [object ["type" .= ("ContactTechnical" :: String)]]
]
]
)
}
((HasCallStack => [Char] -> App ()) -> App ())
-> (HasCallStack => [Char] -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ \[Char]
domain -> do
(owner, tid, _) <- [Char] -> Int -> App (Value, [Char], [Value])
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> Int -> App (Value, [Char], [Value])
createTeam [Char]
domain Int
1
void $ setTeamFeatureStatus owner tid "sso" "enabled"
SAML.SampleIdP idpmetaErnie _ _ _ <- SAML.makeSampleIdPMetadata
idpIdErnie <-
createIdpWithZHost owner (Just ernieZHost) idpmetaErnie `bindResponse` \Response
resp -> do
Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
201
Response
resp.json Maybe Value -> [Char] -> App Value
forall a. (HasCallStack, MakesValue a) => a -> [Char] -> App Value
%. [Char]
"extraInfo.domain" App Value -> [Char] -> App ()
forall a b.
(MakesValue a, MakesValue b, HasCallStack) =>
a -> b -> App ()
`shouldMatch` [Char]
ernieZHost
Response
resp.json Maybe Value -> [Char] -> App Value
forall a. (HasCallStack, MakesValue a) => a -> [Char] -> App Value
%. [Char]
"id" App Value -> (Value -> App [Char]) -> App [Char]
forall a b. App a -> (a -> App b) -> App b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Value -> App [Char]
forall a. (HasCallStack, MakesValue a) => a -> App [Char]
asString
scimUser <- randomScimUser
userEmail <-
scimUser %. "emails" >>= asList >>= \case
(Value
e : [Value]
_) -> Value
e Value -> [Char] -> App Value
forall a. (HasCallStack, MakesValue a) => a -> [Char] -> App Value
%. [Char]
"value" App Value -> (Value -> App [Char]) -> App [Char]
forall a b. App a -> (a -> App b) -> App b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Value -> App [Char]
forall a. (HasCallStack, MakesValue a) => a -> App [Char]
asString
[] -> [Char] -> App [Char]
forall a. HasCallStack => [Char] -> App a
assertFailure [Char]
"Expected at least one email"
scimTok <- createScimToken owner def {idp = Just idpIdErnie}
scimToken <- scimTok.json %. "token" & asString
createScimUser domain scimToken scimUser >>= assertSuccess
activateEmail domain userEmail
bindResponse (getSsoCodeByEmailWithZHost domain (Just ernieZHost) userEmail) $ \Response
resp -> do
Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
404
mbSsoCode <- Maybe Value -> [Char] -> App (Maybe Value)
forall a.
(HasCallStack, MakesValue a) =>
a -> [Char] -> App (Maybe Value)
lookupField Response
resp.json [Char]
"sso_code"
mbSsoCode `shouldMatch` (Nothing :: Maybe Value)