{-# OPTIONS -Wno-ambiguous-fields #-}
module Test.Search where

import qualified API.Brig as BrigP
import qualified API.BrigInternal as BrigI
import qualified API.Common as API
import API.Galley
import qualified API.Galley as Galley
import qualified API.GalleyInternal as GalleyI
import GHC.Stack
import SetupHelpers
import Testlib.Assertions
import Testlib.Prelude

--------------------------------------------------------------------------------
-- LOCAL SEARCH

testSearchContactForExternalUsers :: (HasCallStack) => App ()
testSearchContactForExternalUsers :: HasCallStack => App ()
testSearchContactForExternalUsers = do
  Value
owner <- Domain -> CreateUser -> App Value
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> CreateUser -> App Value
randomUser Domain
OwnDomain CreateUser
forall a. Default a => a
def {BrigI.team = True}
  String
tid <- Value
owner Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"team" App Value -> (App Value -> App String) -> App String
forall a b. a -> (a -> b) -> b
& App Value -> App String
forall a. (HasCallStack, MakesValue a) => a -> App String
asString

  Value
partner <- Value -> CreateTeamMember -> App Value
forall inviter.
(HasCallStack, MakesValue inviter) =>
inviter -> CreateTeamMember -> App Value
createTeamMember Value
owner CreateTeamMember
forall a. Default a => a
def {role = "partner"}
  Value
tm1 <- Value -> CreateTeamMember -> App Value
forall inviter.
(HasCallStack, MakesValue inviter) =>
inviter -> CreateTeamMember -> App Value
createTeamMember Value
owner CreateTeamMember
forall a. Default a => a
def
  Value
tm2 <- Value -> CreateTeamMember -> App Value
forall inviter.
(HasCallStack, MakesValue inviter) =>
inviter -> CreateTeamMember -> App Value
createTeamMember Value
owner CreateTeamMember
forall a. Default a => a
def

  -- a team member can search for contacts
  App Response -> (Response -> App ()) -> App ()
forall a.
HasCallStack =>
App Response -> (Response -> App a) -> App a
bindResponse (Value -> App Value -> Domain -> App Response
forall user searchTerm domain.
(MakesValue user, MakesValue searchTerm, MakesValue domain) =>
user -> searchTerm -> domain -> App Response
BrigP.searchContacts Value
tm1 (Value
owner Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"name") Domain
OwnDomain) ((Response -> App ()) -> App ()) -> (Response -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ \Response
resp ->
    Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
200

  -- a partner is not allowed to search for contacts
  App Response -> (Response -> App ()) -> App ()
forall a.
HasCallStack =>
App Response -> (Response -> App a) -> App a
bindResponse (Value -> App Value -> Domain -> App Response
forall user searchTerm domain.
(MakesValue user, MakesValue searchTerm, MakesValue domain) =>
user -> searchTerm -> domain -> App Response
BrigP.searchContacts Value
partner (Value
owner Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"name") Domain
OwnDomain) ((Response -> App ()) -> App ()) -> (Response -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ \Response
resp ->
    Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
403

  -- a team member can see all other team members
  App Response -> (Response -> App ()) -> App ()
forall a.
HasCallStack =>
App Response -> (Response -> App a) -> App a
bindResponse (Value -> String -> App Response
forall user tid.
(HasCallStack, MakesValue user, MakesValue tid) =>
user -> tid -> App Response
Galley.getTeamMembers Value
tm1 String
tid) ((Response -> App ()) -> App ()) -> (Response -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ \Response
resp -> do
    Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
200
    Response -> [Value] -> App ()
assertContainsUserIds Response
resp [Value
owner, Value
tm1, Value
tm2, Value
partner]

  -- an external partner should see the person who invited them
  App Response -> (Response -> App ()) -> App ()
forall a.
HasCallStack =>
App Response -> (Response -> App a) -> App a
bindResponse (Value -> String -> App Response
forall user tid.
(HasCallStack, MakesValue user, MakesValue tid) =>
user -> tid -> App Response
Galley.getTeamMembers Value
partner String
tid) ((Response -> App ()) -> App ()) -> (Response -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ \Response
resp -> do
    Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
200
    Response -> [Value] -> App ()
assertContainsUserIds Response
resp [Value
owner, Value
partner]

  -- the team owner creates a conversation with the partner and another team member
  App Value -> App ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (App Value -> App ()) -> App Value -> App ()
forall a b. (a -> b) -> a -> b
$ Value -> CreateConv -> App Response
forall user.
(HasCallStack, MakesValue user) =>
user -> CreateConv -> App Response
postConversation Value
owner (CreateConv
defProteus {qualifiedUsers = [tm1, partner], team = Just tid}) App Response -> (Response -> App Value) -> App Value
forall a b. App a -> (a -> App b) -> App b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= HasCallStack => Int -> Response -> App Value
Int -> Response -> App Value
getJSON Int
201

  -- now the external partner should still only see the person who invited them
  App Response -> (Response -> App ()) -> App ()
forall a.
HasCallStack =>
App Response -> (Response -> App a) -> App a
bindResponse (Value -> String -> App Response
forall user tid.
(HasCallStack, MakesValue user, MakesValue tid) =>
user -> tid -> App Response
Galley.getTeamMembers Value
partner String
tid) ((Response -> App ()) -> App ()) -> (Response -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ \Response
resp -> do
    Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
200
    Response -> [Value] -> App ()
assertContainsUserIds Response
resp [Value
owner, Value
partner]
  where
    assertContainsUserIds :: Response -> [Value] -> App ()
    assertContainsUserIds :: Response -> [Value] -> App ()
assertContainsUserIds Response
resp [Value]
users = do
      [Value]
members <- Response
resp.json App Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"members" App Value -> (App Value -> App [Value]) -> App [Value]
forall a b. a -> (a -> b) -> b
& App Value -> App [Value]
forall a. (HasCallStack, MakesValue a) => a -> App [Value]
asList
      [Value]
userIds <- [Value] -> (Value -> App Value) -> App [Value]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
t a -> (a -> f b) -> f (t b)
for [Value]
members (\Value
m -> Value
m Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"user")
      [String]
expected <- [Value] -> (Value -> App String) -> App [String]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
t a -> (a -> f b) -> f (t b)
for [Value]
users Value -> App String
forall a. (HasCallStack, MakesValue a) => a -> App String
objId
      [Value]
userIds [Value] -> [String] -> App ()
forall a b.
(MakesValue a, MakesValue b, HasCallStack) =>
a -> b -> App ()
`shouldMatchSet` [String]
expected

--------------------------------------------------------------------------------
-- FEDERATION SEARCH

-- | Enumeration of the possible restrictions that can be applied to a federated user search
data Restriction = AllowAll | TeamAllowed | TeamNotAllowed
  deriving (Restriction -> Restriction -> Bool
(Restriction -> Restriction -> Bool)
-> (Restriction -> Restriction -> Bool) -> Eq Restriction
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Restriction -> Restriction -> Bool
== :: Restriction -> Restriction -> Bool
$c/= :: Restriction -> Restriction -> Bool
/= :: Restriction -> Restriction -> Bool
Eq, Eq Restriction
Eq Restriction =>
(Restriction -> Restriction -> Ordering)
-> (Restriction -> Restriction -> Bool)
-> (Restriction -> Restriction -> Bool)
-> (Restriction -> Restriction -> Bool)
-> (Restriction -> Restriction -> Bool)
-> (Restriction -> Restriction -> Restriction)
-> (Restriction -> Restriction -> Restriction)
-> Ord Restriction
Restriction -> Restriction -> Bool
Restriction -> Restriction -> Ordering
Restriction -> Restriction -> Restriction
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Restriction -> Restriction -> Ordering
compare :: Restriction -> Restriction -> Ordering
$c< :: Restriction -> Restriction -> Bool
< :: Restriction -> Restriction -> Bool
$c<= :: Restriction -> Restriction -> Bool
<= :: Restriction -> Restriction -> Bool
$c> :: Restriction -> Restriction -> Bool
> :: Restriction -> Restriction -> Bool
$c>= :: Restriction -> Restriction -> Bool
>= :: Restriction -> Restriction -> Bool
$cmax :: Restriction -> Restriction -> Restriction
max :: Restriction -> Restriction -> Restriction
$cmin :: Restriction -> Restriction -> Restriction
min :: Restriction -> Restriction -> Restriction
Ord, Int -> Restriction -> ShowS
[Restriction] -> ShowS
Restriction -> String
(Int -> Restriction -> ShowS)
-> (Restriction -> String)
-> ([Restriction] -> ShowS)
-> Show Restriction
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Restriction -> ShowS
showsPrec :: Int -> Restriction -> ShowS
$cshow :: Restriction -> String
show :: Restriction -> String
$cshowList :: [Restriction] -> ShowS
showList :: [Restriction] -> ShowS
Show)

data FedUserSearchTestCase = FedUserSearchTestCase
  { FedUserSearchTestCase -> String
searchPolicy :: String,
    -- restriction settings of the calling backend
    FedUserSearchTestCase -> Restriction
restrictionD1D2 :: Restriction,
    -- restriction settings of the remote backend
    FedUserSearchTestCase -> Restriction
restrictionD2D1 :: Restriction,
    FedUserSearchTestCase -> Bool
exactHandleSearchExpectFound :: Bool,
    FedUserSearchTestCase -> Bool
fullSearchExpectFound :: Bool
  }
  deriving (FedUserSearchTestCase -> FedUserSearchTestCase -> Bool
(FedUserSearchTestCase -> FedUserSearchTestCase -> Bool)
-> (FedUserSearchTestCase -> FedUserSearchTestCase -> Bool)
-> Eq FedUserSearchTestCase
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FedUserSearchTestCase -> FedUserSearchTestCase -> Bool
== :: FedUserSearchTestCase -> FedUserSearchTestCase -> Bool
$c/= :: FedUserSearchTestCase -> FedUserSearchTestCase -> Bool
/= :: FedUserSearchTestCase -> FedUserSearchTestCase -> Bool
Eq, Eq FedUserSearchTestCase
Eq FedUserSearchTestCase =>
(FedUserSearchTestCase -> FedUserSearchTestCase -> Ordering)
-> (FedUserSearchTestCase -> FedUserSearchTestCase -> Bool)
-> (FedUserSearchTestCase -> FedUserSearchTestCase -> Bool)
-> (FedUserSearchTestCase -> FedUserSearchTestCase -> Bool)
-> (FedUserSearchTestCase -> FedUserSearchTestCase -> Bool)
-> (FedUserSearchTestCase
    -> FedUserSearchTestCase -> FedUserSearchTestCase)
-> (FedUserSearchTestCase
    -> FedUserSearchTestCase -> FedUserSearchTestCase)
-> Ord FedUserSearchTestCase
FedUserSearchTestCase -> FedUserSearchTestCase -> Bool
FedUserSearchTestCase -> FedUserSearchTestCase -> Ordering
FedUserSearchTestCase
-> FedUserSearchTestCase -> FedUserSearchTestCase
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: FedUserSearchTestCase -> FedUserSearchTestCase -> Ordering
compare :: FedUserSearchTestCase -> FedUserSearchTestCase -> Ordering
$c< :: FedUserSearchTestCase -> FedUserSearchTestCase -> Bool
< :: FedUserSearchTestCase -> FedUserSearchTestCase -> Bool
$c<= :: FedUserSearchTestCase -> FedUserSearchTestCase -> Bool
<= :: FedUserSearchTestCase -> FedUserSearchTestCase -> Bool
$c> :: FedUserSearchTestCase -> FedUserSearchTestCase -> Bool
> :: FedUserSearchTestCase -> FedUserSearchTestCase -> Bool
$c>= :: FedUserSearchTestCase -> FedUserSearchTestCase -> Bool
>= :: FedUserSearchTestCase -> FedUserSearchTestCase -> Bool
$cmax :: FedUserSearchTestCase
-> FedUserSearchTestCase -> FedUserSearchTestCase
max :: FedUserSearchTestCase
-> FedUserSearchTestCase -> FedUserSearchTestCase
$cmin :: FedUserSearchTestCase
-> FedUserSearchTestCase -> FedUserSearchTestCase
min :: FedUserSearchTestCase
-> FedUserSearchTestCase -> FedUserSearchTestCase
Ord, Int -> FedUserSearchTestCase -> ShowS
[FedUserSearchTestCase] -> ShowS
FedUserSearchTestCase -> String
(Int -> FedUserSearchTestCase -> ShowS)
-> (FedUserSearchTestCase -> String)
-> ([FedUserSearchTestCase] -> ShowS)
-> Show FedUserSearchTestCase
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FedUserSearchTestCase -> ShowS
showsPrec :: Int -> FedUserSearchTestCase -> ShowS
$cshow :: FedUserSearchTestCase -> String
show :: FedUserSearchTestCase -> String
$cshowList :: [FedUserSearchTestCase] -> ShowS
showList :: [FedUserSearchTestCase] -> ShowS
Show)

testFederatedUserSearch :: (HasCallStack) => App ()
testFederatedUserSearch :: HasCallStack => App ()
testFederatedUserSearch = do
  let tcs :: [FedUserSearchTestCase]
tcs =
        [ -- no search
          String
-> Restriction
-> Restriction
-> Bool
-> Bool
-> FedUserSearchTestCase
FedUserSearchTestCase String
"no_search" Restriction
AllowAll Restriction
AllowAll Bool
False Bool
False,
          String
-> Restriction
-> Restriction
-> Bool
-> Bool
-> FedUserSearchTestCase
FedUserSearchTestCase String
"no_search" Restriction
TeamAllowed Restriction
TeamAllowed Bool
False Bool
False,
          -- exact handle search allow all/team allowed
          String
-> Restriction
-> Restriction
-> Bool
-> Bool
-> FedUserSearchTestCase
FedUserSearchTestCase String
"exact_handle_search" Restriction
AllowAll Restriction
AllowAll Bool
True Bool
False,
          String
-> Restriction
-> Restriction
-> Bool
-> Bool
-> FedUserSearchTestCase
FedUserSearchTestCase String
"exact_handle_search" Restriction
TeamAllowed Restriction
TeamAllowed Bool
True Bool
False,
          String
-> Restriction
-> Restriction
-> Bool
-> Bool
-> FedUserSearchTestCase
FedUserSearchTestCase String
"exact_handle_search" Restriction
AllowAll Restriction
TeamAllowed Bool
True Bool
False,
          String
-> Restriction
-> Restriction
-> Bool
-> Bool
-> FedUserSearchTestCase
FedUserSearchTestCase String
"exact_handle_search" Restriction
TeamAllowed Restriction
AllowAll Bool
True Bool
False,
          -- exact handle search team not allowed
          String
-> Restriction
-> Restriction
-> Bool
-> Bool
-> FedUserSearchTestCase
FedUserSearchTestCase String
"exact_handle_search" Restriction
TeamNotAllowed Restriction
AllowAll Bool
False Bool
False,
          String
-> Restriction
-> Restriction
-> Bool
-> Bool
-> FedUserSearchTestCase
FedUserSearchTestCase String
"exact_handle_search" Restriction
AllowAll Restriction
TeamNotAllowed Bool
False Bool
False,
          -- full search allow all/team allowed
          String
-> Restriction
-> Restriction
-> Bool
-> Bool
-> FedUserSearchTestCase
FedUserSearchTestCase String
"full_search" Restriction
AllowAll Restriction
AllowAll Bool
True Bool
True,
          String
-> Restriction
-> Restriction
-> Bool
-> Bool
-> FedUserSearchTestCase
FedUserSearchTestCase String
"full_search" Restriction
TeamAllowed Restriction
TeamAllowed Bool
True Bool
True,
          String
-> Restriction
-> Restriction
-> Bool
-> Bool
-> FedUserSearchTestCase
FedUserSearchTestCase String
"full_search" Restriction
TeamAllowed Restriction
AllowAll Bool
True Bool
True,
          String
-> Restriction
-> Restriction
-> Bool
-> Bool
-> FedUserSearchTestCase
FedUserSearchTestCase String
"full_search" Restriction
AllowAll Restriction
TeamAllowed Bool
True Bool
True,
          -- full search team not allowed
          String
-> Restriction
-> Restriction
-> Bool
-> Bool
-> FedUserSearchTestCase
FedUserSearchTestCase String
"full_search" Restriction
TeamNotAllowed Restriction
AllowAll Bool
False Bool
False,
          String
-> Restriction
-> Restriction
-> Bool
-> Bool
-> FedUserSearchTestCase
FedUserSearchTestCase String
"full_search" Restriction
AllowAll Restriction
TeamNotAllowed Bool
False Bool
False
        ]
  [ServiceOverrides] -> ([String] -> App ()) -> App ()
forall a. [ServiceOverrides] -> ([String] -> App a) -> App a
startDynamicBackends [ServiceOverrides
forall a. Default a => a
def, ServiceOverrides
forall a. Default a => a
def] (([String] -> App ()) -> App ()) -> ([String] -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ \[String
d1, String
d2] -> do
    App Response -> App ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (App Response -> App ()) -> App Response -> App ()
forall a b. (a -> b) -> a -> b
$ String -> FedConn -> App Response
forall user tid.
(HasCallStack, MakesValue user, MakesValue tid) =>
user -> tid -> App Response
BrigI.createFedConn String
d2 (String -> String -> Maybe [String] -> FedConn
BrigI.FedConn String
d1 String
"full_search" Maybe [String]
forall a. Maybe a
Nothing)
    App Response -> App ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (App Response -> App ()) -> App Response -> App ()
forall a b. (a -> b) -> a -> b
$ String -> FedConn -> App Response
forall user tid.
(HasCallStack, MakesValue user, MakesValue tid) =>
user -> tid -> App Response
BrigI.createFedConn String
d1 (String -> String -> Maybe [String] -> FedConn
BrigI.FedConn String
d2 String
"full_search" Maybe [String]
forall a. Maybe a
Nothing)
    [FedUserSearchTestCase]
-> (FedUserSearchTestCase -> App ()) -> App ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [FedUserSearchTestCase]
tcs (HasCallStack => String -> String -> FedUserSearchTestCase -> App ()
String -> String -> FedUserSearchTestCase -> App ()
federatedUserSearch String
d1 String
d2)

federatedUserSearch :: (HasCallStack) => String -> String -> FedUserSearchTestCase -> App ()
federatedUserSearch :: HasCallStack => String -> String -> FedUserSearchTestCase -> App ()
federatedUserSearch String
d1 String
d2 FedUserSearchTestCase
test = do
  App Response -> App ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (App Response -> App ()) -> App Response -> App ()
forall a b. (a -> b) -> a -> b
$ String -> String -> FedConn -> App Response
forall owndom fedConn.
(HasCallStack, MakesValue owndom, MakesValue fedConn) =>
owndom -> String -> fedConn -> App Response
BrigI.updateFedConn String
d2 String
d1 (String -> String -> Maybe [String] -> FedConn
BrigI.FedConn String
d1 FedUserSearchTestCase
test.searchPolicy (Restriction -> Maybe [String]
restriction FedUserSearchTestCase
test.restrictionD2D1))
  App Response -> App ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (App Response -> App ()) -> App Response -> App ()
forall a b. (a -> b) -> a -> b
$ String -> String -> FedConn -> App Response
forall owndom fedConn.
(HasCallStack, MakesValue owndom, MakesValue fedConn) =>
owndom -> String -> fedConn -> App Response
BrigI.updateFedConn String
d1 String
d2 (String -> String -> Maybe [String] -> FedConn
BrigI.FedConn String
d2 FedUserSearchTestCase
test.searchPolicy (Restriction -> Maybe [String]
restriction FedUserSearchTestCase
test.restrictionD1D2))

  Value
u1 <- String -> CreateUser -> App Value
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> CreateUser -> App Value
randomUser String
d1 CreateUser
forall a. Default a => a
def {BrigI.team = True}
  Value
teamU1 <- Value
u1 Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"team"
  Value
u2 <- String -> CreateUser -> App Value
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> CreateUser -> App Value
randomUser String
d2 CreateUser
forall a. Default a => a
def {BrigI.team = True}
  String
uidD2 <- Value -> App String
forall a. (HasCallStack, MakesValue a) => a -> App String
objId Value
u2
  Value
team2 <- Value
u2 Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"team"
  HasCallStack => Response -> App ()
Response -> App ()
assertSuccess (Response -> App ()) -> App Response -> App ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< String -> Value -> String -> String -> App Response
forall domain team.
(HasCallStack, MakesValue domain, MakesValue team) =>
domain -> team -> String -> String -> App Response
GalleyI.setTeamFeatureStatus String
d2 Value
team2 String
"searchVisibilityInbound" String
"enabled"

  String -> String -> Value -> Restriction -> App ()
forall ownDomain remoteDomain remoteTeam.
(MakesValue ownDomain, MakesValue remoteDomain,
 MakesValue remoteTeam) =>
ownDomain -> remoteDomain -> remoteTeam -> Restriction -> App ()
addTeamRestriction String
d1 String
d2 Value
team2 FedUserSearchTestCase
test.restrictionD1D2
  String -> String -> Value -> Restriction -> App ()
forall ownDomain remoteDomain remoteTeam.
(MakesValue ownDomain, MakesValue remoteDomain,
 MakesValue remoteTeam) =>
ownDomain -> remoteDomain -> remoteTeam -> Restriction -> App ()
addTeamRestriction String
d2 String
d1 Value
teamU1 FedUserSearchTestCase
test.restrictionD2D1

  String
u2Handle <- App String
API.randomHandle
  App Response -> (Response -> App ()) -> App ()
forall a.
HasCallStack =>
App Response -> (Response -> App a) -> App a
bindResponse (Value -> String -> App Response
forall user.
(HasCallStack, MakesValue user) =>
user -> String -> App Response
BrigP.putHandle Value
u2 String
u2Handle) ((Response -> App ()) -> App ()) -> (Response -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ HasCallStack => Response -> App ()
Response -> App ()
assertSuccess
  String -> App ()
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> App ()
BrigI.refreshIndex String
d2

  App Response -> (Response -> App ()) -> App ()
forall a.
HasCallStack =>
App Response -> (Response -> App a) -> App a
bindResponse (Value -> String -> String -> App Response
forall user searchTerm domain.
(MakesValue user, MakesValue searchTerm, MakesValue domain) =>
user -> searchTerm -> domain -> App Response
BrigP.searchContacts Value
u1 String
u2Handle String
d2) ((Response -> App ()) -> App ()) -> (Response -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ \Response
resp -> do
    Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
200
    [Value]
docs <- Response
resp.json App Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"documents" App Value -> (Value -> App [Value]) -> App [Value]
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 [Value]
forall a. (HasCallStack, MakesValue a) => a -> App [Value]
asList
    case [Value]
docs of
      [] ->
        Bool -> App () -> App ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (FedUserSearchTestCase
test.exactHandleSearchExpectFound) (App () -> App ()) -> App () -> App ()
forall a b. (a -> b) -> a -> b
$ String -> App ()
forall a. HasCallStack => String -> App a
assertFailure (String -> App ()) -> String -> App ()
forall a b. (a -> b) -> a -> b
$ String
"Expected a non empty result, but got an empty one, for test case " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> FedUserSearchTestCase -> String
forall a. Show a => a -> String
show FedUserSearchTestCase
test
      Value
doc : [Value]
_ ->
        if FedUserSearchTestCase
test.exactHandleSearchExpectFound
          then Value
doc Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"id" App Value -> String -> App ()
forall a b.
(MakesValue a, MakesValue b, HasCallStack) =>
a -> b -> App ()
`shouldMatch` String
uidD2
          else String -> App ()
forall a. HasCallStack => String -> App a
assertFailure (String -> App ()) -> String -> App ()
forall a b. (a -> b) -> a -> b
$ String
"Expected an empty result, but got " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Value -> String
forall a. Show a => a -> String
show Value
doc String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
" for test case " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> FedUserSearchTestCase -> String
forall a. Show a => a -> String
show FedUserSearchTestCase
test

  App Response -> (Response -> App ()) -> App ()
forall a.
HasCallStack =>
App Response -> (Response -> App a) -> App a
bindResponse (Value -> App Value -> String -> App Response
forall user searchTerm domain.
(MakesValue user, MakesValue searchTerm, MakesValue domain) =>
user -> searchTerm -> domain -> App Response
BrigP.searchContacts Value
u1 (Value
u2 Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"name") String
d2) ((Response -> App ()) -> App ()) -> (Response -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ \Response
resp -> do
    Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
200
    [Value]
docs <- Response
resp.json App Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"documents" App Value -> (Value -> App [Value]) -> App [Value]
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 [Value]
forall a. (HasCallStack, MakesValue a) => a -> App [Value]
asList
    case [Value]
docs of
      [] -> Bool -> App () -> App ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (FedUserSearchTestCase
test.fullSearchExpectFound) (App () -> App ()) -> App () -> App ()
forall a b. (a -> b) -> a -> b
$ String -> App ()
forall a. HasCallStack => String -> App a
assertFailure (String -> App ()) -> String -> App ()
forall a b. (a -> b) -> a -> b
$ String
"Expected a non empty result, but got an empty one, for test case " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> FedUserSearchTestCase -> String
forall a. Show a => a -> String
show FedUserSearchTestCase
test
      Value
doc : [Value]
_ ->
        if FedUserSearchTestCase
test.fullSearchExpectFound
          then Value
doc Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"id" App Value -> String -> App ()
forall a b.
(MakesValue a, MakesValue b, HasCallStack) =>
a -> b -> App ()
`shouldMatch` String
uidD2
          else String -> App ()
forall a. HasCallStack => String -> App a
assertFailure (String -> App ()) -> String -> App ()
forall a b. (a -> b) -> a -> b
$ String
"Expected an empty result, but got " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Value -> String
forall a. Show a => a -> String
show Value
doc String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
" for test case " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> FedUserSearchTestCase -> String
forall a. Show a => a -> String
show FedUserSearchTestCase
test
  where
    restriction :: Restriction -> Maybe [String]
    restriction :: Restriction -> Maybe [String]
restriction = \case
      Restriction
AllowAll -> Maybe [String]
forall a. Maybe a
Nothing
      Restriction
TeamAllowed -> [String] -> Maybe [String]
forall a. a -> Maybe a
Just []
      Restriction
TeamNotAllowed -> [String] -> Maybe [String]
forall a. a -> Maybe a
Just []

    addTeamRestriction :: (MakesValue ownDomain, MakesValue remoteDomain, MakesValue remoteTeam) => ownDomain -> remoteDomain -> remoteTeam -> Restriction -> App ()
    addTeamRestriction :: forall ownDomain remoteDomain remoteTeam.
(MakesValue ownDomain, MakesValue remoteDomain,
 MakesValue remoteTeam) =>
ownDomain -> remoteDomain -> remoteTeam -> Restriction -> App ()
addTeamRestriction ownDomain
ownDomain remoteDomain
remoteDomain remoteTeam
remoteTeam = \case
      Restriction
AllowAll ->
        () -> App ()
forall a. a -> App a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
      Restriction
TeamNotAllowed ->
        -- if the team is not allowed, the restriction was set to by team earlier and we do not need to do anything
        () -> App ()
forall a. a -> App a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
      Restriction
TeamAllowed -> do
        ownDomain -> remoteDomain -> remoteTeam -> App ()
forall domain remoteDomain team.
(HasCallStack, MakesValue domain, MakesValue remoteDomain,
 MakesValue team) =>
domain -> remoteDomain -> team -> App ()
BrigI.addFederationRemoteTeam ownDomain
ownDomain remoteDomain
remoteDomain remoteTeam
remoteTeam

testFederatedUserSearchNonTeamSearcher :: (HasCallStack) => App ()
testFederatedUserSearchNonTeamSearcher :: HasCallStack => App ()
testFederatedUserSearchNonTeamSearcher = do
  [ServiceOverrides] -> ([String] -> App ()) -> App ()
forall a. [ServiceOverrides] -> ([String] -> App a) -> App a
startDynamicBackends [ServiceOverrides
forall a. Default a => a
def, ServiceOverrides
forall a. Default a => a
def] (([String] -> App ()) -> App ()) -> ([String] -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ \[String
d1, String
d2] -> do
    App Response -> App ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (App Response -> App ()) -> App Response -> App ()
forall a b. (a -> b) -> a -> b
$ String -> FedConn -> App Response
forall user tid.
(HasCallStack, MakesValue user, MakesValue tid) =>
user -> tid -> App Response
BrigI.createFedConn String
d2 (String -> String -> Maybe [String] -> FedConn
BrigI.FedConn String
d1 String
"full_search" ([String] -> Maybe [String]
forall a. a -> Maybe a
Just []))
    App Response -> App ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (App Response -> App ()) -> App Response -> App ()
forall a b. (a -> b) -> a -> b
$ String -> FedConn -> App Response
forall user tid.
(HasCallStack, MakesValue user, MakesValue tid) =>
user -> tid -> App Response
BrigI.createFedConn String
d1 (String -> String -> Maybe [String] -> FedConn
BrigI.FedConn String
d2 String
"full_search" Maybe [String]
forall a. Maybe a
Nothing)

    Value
u1 <- String -> CreateUser -> App Value
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> CreateUser -> App Value
randomUser String
d1 CreateUser
forall a. Default a => a
def
    Value
u2 <- String -> CreateUser -> App Value
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> CreateUser -> App Value
randomUser String
d2 CreateUser
forall a. Default a => a
def {BrigI.team = True}
    Value
team2 <- Value
u2 Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"team"
    HasCallStack => Response -> App ()
Response -> App ()
assertSuccess (Response -> App ()) -> App Response -> App ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< String -> Value -> String -> String -> App Response
forall domain team.
(HasCallStack, MakesValue domain, MakesValue team) =>
domain -> team -> String -> String -> App Response
GalleyI.setTeamFeatureStatus String
d2 Value
team2 String
"searchVisibilityInbound" String
"enabled"

    String
u2Handle <- App String
API.randomHandle
    App Response -> (Response -> App ()) -> App ()
forall a.
HasCallStack =>
App Response -> (Response -> App a) -> App a
bindResponse (Value -> String -> App Response
forall user.
(HasCallStack, MakesValue user) =>
user -> String -> App Response
BrigP.putHandle Value
u2 String
u2Handle) ((Response -> App ()) -> App ()) -> (Response -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ HasCallStack => Response -> App ()
Response -> App ()
assertSuccess
    String -> App ()
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> App ()
BrigI.refreshIndex String
d2

    App Response -> (Response -> App ()) -> App ()
forall a.
HasCallStack =>
App Response -> (Response -> App a) -> App a
bindResponse (Value -> String -> String -> App Response
forall user searchTerm domain.
(MakesValue user, MakesValue searchTerm, MakesValue domain) =>
user -> searchTerm -> domain -> App Response
BrigP.searchContacts Value
u1 String
u2Handle String
d2) ((Response -> App ()) -> App ()) -> (Response -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ \Response
resp -> do
      Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
200
      [Value]
docs <- Response
resp.json App Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"documents" App Value -> (Value -> App [Value]) -> App [Value]
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 [Value]
forall a. (HasCallStack, MakesValue a) => a -> App [Value]
asList
      case [Value]
docs of
        [] -> () -> App ()
forall a. a -> App a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
        Value
doc : [Value]
_ ->
          String -> App ()
forall a. HasCallStack => String -> App a
assertFailure (String -> App ()) -> String -> App ()
forall a b. (a -> b) -> a -> b
$ String
"Expected an empty result, but got " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Value -> String
forall a. Show a => a -> String
show Value
doc

    App Response -> (Response -> App ()) -> App ()
forall a.
HasCallStack =>
App Response -> (Response -> App a) -> App a
bindResponse (Value -> App Value -> String -> App Response
forall user searchTerm domain.
(MakesValue user, MakesValue searchTerm, MakesValue domain) =>
user -> searchTerm -> domain -> App Response
BrigP.searchContacts Value
u1 (Value
u2 Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"name") String
d2) ((Response -> App ()) -> App ()) -> (Response -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ \Response
resp -> do
      Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
200
      [Value]
docs <- Response
resp.json App Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"documents" App Value -> (Value -> App [Value]) -> App [Value]
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 [Value]
forall a. (HasCallStack, MakesValue a) => a -> App [Value]
asList
      case [Value]
docs of
        [] -> () -> App ()
forall a. a -> App a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
        Value
doc : [Value]
_ ->
          String -> App ()
forall a. HasCallStack => String -> App a
assertFailure (String -> App ()) -> String -> App ()
forall a b. (a -> b) -> a -> b
$ String
"Expected an empty result, but got " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Value -> String
forall a. Show a => a -> String
show Value
doc String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
" for test case "

testFederatedUserSearchForNonTeamUser :: (HasCallStack) => App ()
testFederatedUserSearchForNonTeamUser :: HasCallStack => App ()
testFederatedUserSearchForNonTeamUser = do
  [ServiceOverrides] -> ([String] -> App ()) -> App ()
forall a. [ServiceOverrides] -> ([String] -> App a) -> App a
startDynamicBackends [ServiceOverrides
forall a. Default a => a
def, ServiceOverrides
forall a. Default a => a
def] (([String] -> App ()) -> App ()) -> ([String] -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ \[String
d1, String
d2] -> do
    App Response -> App ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (App Response -> App ()) -> App Response -> App ()
forall a b. (a -> b) -> a -> b
$ String -> FedConn -> App Response
forall user tid.
(HasCallStack, MakesValue user, MakesValue tid) =>
user -> tid -> App Response
BrigI.createFedConn String
d2 (String -> String -> Maybe [String] -> FedConn
BrigI.FedConn String
d1 String
"full_search" Maybe [String]
forall a. Maybe a
Nothing)
    App Response -> App ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (App Response -> App ()) -> App Response -> App ()
forall a b. (a -> b) -> a -> b
$ String -> FedConn -> App Response
forall user tid.
(HasCallStack, MakesValue user, MakesValue tid) =>
user -> tid -> App Response
BrigI.createFedConn String
d1 (String -> String -> Maybe [String] -> FedConn
BrigI.FedConn String
d2 String
"full_search" ([String] -> Maybe [String]
forall a. a -> Maybe a
Just []))

    Value
u1 <- String -> CreateUser -> App Value
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> CreateUser -> App Value
randomUser String
d1 CreateUser
forall a. Default a => a
def {BrigI.team = True}
    Value
u2 <- String -> CreateUser -> App Value
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> CreateUser -> App Value
randomUser String
d2 CreateUser
forall a. Default a => a
def

    String
u2Handle <- App String
API.randomHandle
    App Response -> (Response -> App ()) -> App ()
forall a.
HasCallStack =>
App Response -> (Response -> App a) -> App a
bindResponse (Value -> String -> App Response
forall user.
(HasCallStack, MakesValue user) =>
user -> String -> App Response
BrigP.putHandle Value
u2 String
u2Handle) ((Response -> App ()) -> App ()) -> (Response -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ HasCallStack => Response -> App ()
Response -> App ()
assertSuccess
    String -> App ()
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> App ()
BrigI.refreshIndex String
d2

    App Response -> (Response -> App ()) -> App ()
forall a.
HasCallStack =>
App Response -> (Response -> App a) -> App a
bindResponse (Value -> String -> String -> App Response
forall user searchTerm domain.
(MakesValue user, MakesValue searchTerm, MakesValue domain) =>
user -> searchTerm -> domain -> App Response
BrigP.searchContacts Value
u1 String
u2Handle String
d2) ((Response -> App ()) -> App ()) -> (Response -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ \Response
resp -> do
      Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
200
      [Value]
docs <- Response
resp.json App Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"documents" App Value -> (Value -> App [Value]) -> App [Value]
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 [Value]
forall a. (HasCallStack, MakesValue a) => a -> App [Value]
asList
      case [Value]
docs of
        [] -> () -> App ()
forall a. a -> App a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
        Value
doc : [Value]
_ ->
          String -> App ()
forall a. HasCallStack => String -> App a
assertFailure (String -> App ()) -> String -> App ()
forall a b. (a -> b) -> a -> b
$ String
"Expected an empty result, but got " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Value -> String
forall a. Show a => a -> String
show Value
doc

    App Response -> (Response -> App ()) -> App ()
forall a.
HasCallStack =>
App Response -> (Response -> App a) -> App a
bindResponse (Value -> App Value -> String -> App Response
forall user searchTerm domain.
(MakesValue user, MakesValue searchTerm, MakesValue domain) =>
user -> searchTerm -> domain -> App Response
BrigP.searchContacts Value
u1 (Value
u2 Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"name") String
d2) ((Response -> App ()) -> App ()) -> (Response -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ \Response
resp -> do
      Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
200
      [Value]
docs <- Response
resp.json App Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"documents" App Value -> (Value -> App [Value]) -> App [Value]
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 [Value]
forall a. (HasCallStack, MakesValue a) => a -> App [Value]
asList
      case [Value]
docs of
        [] -> () -> App ()
forall a. a -> App a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
        Value
doc : [Value]
_ ->
          String -> App ()
forall a. HasCallStack => String -> App a
assertFailure (String -> App ()) -> String -> App ()
forall a b. (a -> b) -> a -> b
$ String
"Expected an empty result, but got " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Value -> String
forall a. Show a => a -> String
show Value
doc String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
" for test case "