From 2a5e689fa0f63b1901b015f96bb7f4aa3ad81318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Tue, 16 Sep 2025 15:39:59 +0300 Subject: [PATCH 01/30] Remove references to non-existent note Note [ephemeral user sideeffect] was removed in commit: b0934a3b75 WPB-15801 GET and DELETE Registered Domains (#4438) --- libs/wire-api/src/Wire/API/Routes/Public/Brig.hs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs b/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs index a81fcd5496..6ae00025fc 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs @@ -161,7 +161,6 @@ instance AsUnion DeleteSelfResponses (Maybe Timeout) where type ConnectionUpdateResponses = UpdateResponses "Connection unchanged" "Connection updated" UserConnection type UserAPI = - -- See Note [ephemeral user sideeffect] Named "get-user-unqualified" ( Summary "Get a user by UserId" @@ -172,7 +171,6 @@ type UserAPI = :> GetUserVerb ) :<|> - -- See Note [ephemeral user sideeffect] Named "get-user-qualified" ( Summary "Get a user by Domain and UserId" @@ -225,7 +223,6 @@ type UserAPI = (Maybe UserProfile) ) :<|> - -- See Note [ephemeral user sideeffect] Named "list-users-by-unqualified-ids-or-handles" ( Summary "List users (deprecated)" @@ -248,7 +245,6 @@ type UserAPI = :> Post '[JSON] ListUsersById ) :<|> - -- See Note [ephemeral user sideeffect] Named "list-users-by-ids-or-handles@V3" ( Summary "List users" From 4d51c98c3ed1148656af62a763c497bc5699b543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Wed, 1 Oct 2025 19:44:32 +0300 Subject: [PATCH 02/30] Make the `Wire.API.Team.Member.userId` lens more general --- libs/wire-api/src/Wire/API/Team/Member.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/wire-api/src/Wire/API/Team/Member.hs b/libs/wire-api/src/Wire/API/Team/Member.hs index f6a75b1ebc..94fd562cbc 100644 --- a/libs/wire-api/src/Wire/API/Team/Member.hs +++ b/libs/wire-api/src/Wire/API/Team/Member.hs @@ -654,7 +654,7 @@ makeLenses ''TeamMemberList' makeLenses ''NewTeamMember' makeLenses ''TeamMemberDeleteData -userId :: Lens' TeamMember UserId +userId :: Lens' (TeamMember' tag) UserId userId = newTeamMember . nUserId permissions :: Lens (TeamMember' tag1) (TeamMember' tag2) (PermissionType tag1) (PermissionType tag2) From 68b6c6e3179869615878ae9cdd273e97f20e0ab0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Fri, 19 Sep 2025 12:42:37 +0300 Subject: [PATCH 03/30] Minor refactor - make `!!!` definition easier to understand - extract `getProfile` --- libs/bilge/src/Bilge/Assert.hs | 2 +- libs/wire-api/src/Wire/API/Team/Permission.hs | 5 +++-- .../brig/test/integration/API/User/Account.hs | 15 ++++++++------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/libs/bilge/src/Bilge/Assert.hs b/libs/bilge/src/Bilge/Assert.hs index 5f44fd9d68..a13e624aa5 100644 --- a/libs/bilge/src/Bilge/Assert.hs +++ b/libs/bilge/src/Bilge/Assert.hs @@ -106,7 +106,7 @@ io Assertions () -> m () -(!!!) io = void . ( userExpire bob) "bob/register" - resAlice <- getProfile (userId u1) (userId alice) - resBob <- getProfile (userId u1) (userId bob) + resAlice <- getProfile b (userId u1) (userId alice) + resBob <- getProfile b (userId u1) (userId bob) selfBob <- get (b . zUser (userId bob) . path "self") UserId -> Http ResponseLBS - getProfile zusr uid = get (apiVersion "v1" . b . zUser zusr . paths ["users", toByteString' uid]) UserId -> UserId -> Http () awaitExpiry n zusr uid = do -- after expiration, a profile lookup should trigger garbage collection of ephemeral users - r <- getProfile zusr uid + r <- getProfile b zusr uid when (statusCode r == 200 && isNothing (deleted r) && n > 0) $ do liftIO $ threadDelay 1000000 awaitExpiry (n - 1) zusr uid @@ -1587,3 +1584,7 @@ execAndAssertUserDeletion brig cannon u hdl others userJournalWatcher execDelete ) ) . responseJsonMaybe + +-- | Get user profile (while asserting that result is successful) +getProfile :: Brig -> UserId -> UserId -> Http ResponseLBS +getProfile b zusr uid = get (apiVersion "v1" . b . zUser zusr . paths ["users", toByteString' uid]) Date: Tue, 16 Sep 2025 17:11:32 +0300 Subject: [PATCH 04/30] Add `searchable` field to data types --- libs/wire-api/src/Wire/API/User.hs | 11 ++++++++--- .../API/Golden/Generated/SelfProfile_user.hs | 3 ++- .../API/Golden/Generated/UserProfile_user.hs | 6 ++++-- .../Wire/API/Golden/Generated/User_user.hs | 15 ++++++++++----- .../Wire/API/Golden/Manual/ListUsersById.hs | 6 ++++-- .../Test/Wire/API/Golden/Manual/UserEvent.hs | 6 ++++-- libs/wire-api/test/unit/Test/Wire/API/User.hs | 2 +- .../src/Wire/AppSubsystem/Interpreter.hs | 3 ++- libs/wire-subsystems/src/Wire/StoredUser.hs | 15 ++++++++++----- .../src/Wire/UserStore/Cassandra.hs | 6 +++--- .../unit/Wire/MockInterpreters/UserStore.hs | 3 ++- services/brig/src/Brig/Data/User.hs | 18 ++++++++++++------ services/brig/src/Brig/Provider/API.hs | 3 ++- .../brig/test/integration/API/User/Account.hs | 3 ++- services/galley/test/integration/API/Util.hs | 3 ++- 15 files changed, 68 insertions(+), 35 deletions(-) diff --git a/libs/wire-api/src/Wire/API/User.hs b/libs/wire-api/src/Wire/API/User.hs index f8072e95d6..138ded4356 100644 --- a/libs/wire-api/src/Wire/API/User.hs +++ b/libs/wire-api/src/Wire/API/User.hs @@ -509,7 +509,8 @@ data UserProfile = UserProfile profileEmail :: Maybe EmailAddress, profileLegalholdStatus :: UserLegalHoldStatus, profileSupportedProtocols :: Set BaseProtocolTag, - profileType :: UserType + profileType :: UserType, + profileSearchable :: Bool } deriving stock (Eq, Show, Generic) deriving (Arbitrary) via (GenericUniform UserProfile) @@ -549,6 +550,7 @@ instance ToSchema UserProfile where .= field "legalhold_status" schema <*> profileSupportedProtocols .= supportedProtocolsObjectSchema <*> profileType .= fmap (fromMaybe UserTypeRegular) (optField "type" schema) + <*> profileSearchable .= fmap (fromMaybe True) (optField "searchable" schema) -------------------------------------------------------------------------------- -- SelfProfile @@ -603,7 +605,8 @@ data User = User -- | How is the user profile managed (e.g. if it's via SCIM then the user profile -- can't be edited via normal means) userManagedBy :: ManagedBy, - userSupportedProtocols :: Set BaseProtocolTag + userSupportedProtocols :: Set BaseProtocolTag, + userSearchable :: Bool } deriving stock (Eq, Ord, Show, Generic) deriving (Arbitrary) via (GenericUniform User) @@ -654,6 +657,7 @@ userObjectSchema = .= (fromMaybe ManagedByWire <$> optField "managed_by" schema) <*> userSupportedProtocols .= supportedProtocolsObjectSchema <* (fromMaybe False <$> (\u -> if userDeleted u then Just True else Nothing) .= maybe_ (optField "deleted" schema)) + <*> userSearchable .= (fromMaybe True <$> optField "searchable" schema) userEmail :: User -> Maybe EmailAddress userEmail = emailIdentity <=< userIdentity @@ -732,7 +736,8 @@ mkUserProfileWithEmail memail u legalHoldStatus = profileEmail = memail, profileLegalholdStatus = legalHoldStatus, profileSupportedProtocols = userSupportedProtocols u, - profileType = ty + profileType = ty, + profileSearchable = userSearchable u } mkUserProfile :: EmailVisibilityConfigWithViewer -> User -> UserLegalHoldStatus -> UserProfile diff --git a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/SelfProfile_user.hs b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/SelfProfile_user.hs index 9841fd014e..608fd5a96a 100644 --- a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/SelfProfile_user.hs +++ b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/SelfProfile_user.hs @@ -62,6 +62,7 @@ testObject_SelfProfile_user_1 = userExpire = Just (fromJust (readUTCTimeMillis "1864-05-07T21:09:29.342Z")), userTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0002-0000-000000000002"))), userManagedBy = ManagedByScim, - userSupportedProtocols = defSupportedProtocols + userSupportedProtocols = defSupportedProtocols, + userSearchable = True } } diff --git a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/UserProfile_user.hs b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/UserProfile_user.hs index 038c216140..5f47e25dff 100644 --- a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/UserProfile_user.hs +++ b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/UserProfile_user.hs @@ -51,7 +51,8 @@ testObject_UserProfile_user_1 = profileEmail = Nothing, profileLegalholdStatus = UserLegalHoldDisabled, profileSupportedProtocols = defSupportedProtocols, - profileType = UserTypeRegular + profileType = UserTypeRegular, + profileSearchable = True } testObject_UserProfile_user_2 :: UserProfile @@ -82,5 +83,6 @@ testObject_UserProfile_user_2 = profileEmail = Just (unsafeEmailAddress "some" "example"), profileLegalholdStatus = UserLegalHoldNoConsent, profileSupportedProtocols = defSupportedProtocols, - profileType = UserTypeApp + profileType = UserTypeApp, + profileSearchable = True } diff --git a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/User_user.hs b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/User_user.hs index 8d45d8da2a..3d46bf5bf9 100644 --- a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/User_user.hs +++ b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/User_user.hs @@ -68,7 +68,8 @@ testObject_User_user_1 = userExpire = Nothing, userTeam = Nothing, userManagedBy = ManagedByWire, - userSupportedProtocols = defSupportedProtocols + userSupportedProtocols = defSupportedProtocols, + userSearchable = True } testObject_User_user_2 :: User @@ -107,7 +108,8 @@ testObject_User_user_2 = userExpire = Just (fromJust (readUTCTimeMillis "1864-05-11T17:06:58.936Z")), userTeam = Nothing, userManagedBy = ManagedByWire, - userSupportedProtocols = mempty + userSupportedProtocols = mempty, + userSearchable = True } testObject_User_user_3 :: User @@ -139,7 +141,8 @@ testObject_User_user_3 = userExpire = Just (fromJust (readUTCTimeMillis "1864-05-09T20:12:05.821Z")), userTeam = Just (Id (fromJust (UUID.fromString "00000002-0000-0001-0000-000200000000"))), userManagedBy = ManagedByWire, - userSupportedProtocols = defSupportedProtocols + userSupportedProtocols = defSupportedProtocols, + userSearchable = True } testObject_User_user_4 :: User @@ -176,7 +179,8 @@ testObject_User_user_4 = userExpire = Just (fromJust (readUTCTimeMillis "1864-05-09T14:25:26.089Z")), userTeam = Just (Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000002"))), userManagedBy = ManagedByScim, - userSupportedProtocols = defSupportedProtocols + userSupportedProtocols = defSupportedProtocols, + userSearchable = True } testObject_User_user_5 :: User @@ -213,5 +217,6 @@ testObject_User_user_5 = userExpire = Just (fromJust (readUTCTimeMillis "1864-05-09T14:25:26.089Z")), userTeam = Just (Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000002"))), userManagedBy = ManagedByScim, - userSupportedProtocols = defSupportedProtocols + userSupportedProtocols = defSupportedProtocols, + userSearchable = True } diff --git a/libs/wire-api/test/golden/Test/Wire/API/Golden/Manual/ListUsersById.hs b/libs/wire-api/test/golden/Test/Wire/API/Golden/Manual/ListUsersById.hs index 827ab7d3e2..34e78a8f40 100644 --- a/libs/wire-api/test/golden/Test/Wire/API/Golden/Manual/ListUsersById.hs +++ b/libs/wire-api/test/golden/Test/Wire/API/Golden/Manual/ListUsersById.hs @@ -53,7 +53,8 @@ profile1 = profileEmail = Nothing, profileLegalholdStatus = UserLegalHoldDisabled, profileSupportedProtocols = defSupportedProtocols, - profileType = UserTypeRegular + profileType = UserTypeRegular, + profileSearchable = True } profile2 = UserProfile @@ -71,7 +72,8 @@ profile2 = profileEmail = Nothing, profileLegalholdStatus = UserLegalHoldDisabled, profileSupportedProtocols = Set.fromList [BaseProtocolProteusTag, BaseProtocolMLSTag], - profileType = UserTypeRegular + profileType = UserTypeRegular, + profileSearchable = True } testObject_ListUsersById_user_1 :: ListUsersById diff --git a/libs/wire-api/test/golden/Test/Wire/API/Golden/Manual/UserEvent.hs b/libs/wire-api/test/golden/Test/Wire/API/Golden/Manual/UserEvent.hs index 9c8fa6666f..e24036faaa 100644 --- a/libs/wire-api/test/golden/Test/Wire/API/Golden/Manual/UserEvent.hs +++ b/libs/wire-api/test/golden/Test/Wire/API/Golden/Manual/UserEvent.hs @@ -242,7 +242,8 @@ alice = userExpire = Nothing, userTeam = Just $ Id (fromJust (UUID.fromString "bb843450-b2f5-4ec8-90bd-52c7d5f1d22e")), userManagedBy = ManagedByWire, - userSupportedProtocols = defSupportedProtocols + userSupportedProtocols = defSupportedProtocols, + userSearchable = True } bob :: User @@ -271,5 +272,6 @@ bob = userExpire = Nothing, userTeam = Nothing, userManagedBy = ManagedByWire, - userSupportedProtocols = defSupportedProtocols + userSupportedProtocols = defSupportedProtocols, + userSearchable = True } diff --git a/libs/wire-api/test/unit/Test/Wire/API/User.hs b/libs/wire-api/test/unit/Test/Wire/API/User.hs index 32edb7f18c..011d0df5f7 100644 --- a/libs/wire-api/test/unit/Test/Wire/API/User.hs +++ b/libs/wire-api/test/unit/Test/Wire/API/User.hs @@ -117,7 +117,7 @@ testUserProfile = do uid <- Id <$> UUID.nextRandom let domain = Domain "example.com" let colour = ColourId 0 - let userProfile = UserProfile (Qualified uid domain) (Name "name") Nothing (Pict []) [] colour False Nothing Nothing Nothing Nothing Nothing UserLegalHoldNoConsent defSupportedProtocols UserTypeRegular + let userProfile = UserProfile (Qualified uid domain) (Name "name") Nothing (Pict []) [] colour False Nothing Nothing Nothing Nothing Nothing UserLegalHoldNoConsent defSupportedProtocols UserTypeRegular True let profileJSONAsText = show $ Aeson.encode userProfile let msg = "toJSON encoding must not convert Nothing to null, but instead omit those json fields for backwards compatibility. UserProfileJSON:" <> profileJSONAsText assertBool msg (not $ "null" `isInfixOf` profileJSONAsText) diff --git a/libs/wire-subsystems/src/Wire/AppSubsystem/Interpreter.hs b/libs/wire-subsystems/src/Wire/AppSubsystem/Interpreter.hs index d7cf1f05ad..43a1d316a8 100644 --- a/libs/wire-subsystems/src/Wire/AppSubsystem/Interpreter.hs +++ b/libs/wire-subsystems/src/Wire/AppSubsystem/Interpreter.hs @@ -156,7 +156,8 @@ appNewStoredUser creator new = do expires = Nothing, teamId = creator.teamId, managedBy = defaultManagedBy, - supportedProtocols = defAppSupportedProtocols + supportedProtocols = defAppSupportedProtocols, + searchable = True } defAppSupportedProtocols :: Set BaseProtocolTag diff --git a/libs/wire-subsystems/src/Wire/StoredUser.hs b/libs/wire-subsystems/src/Wire/StoredUser.hs index 5627f9a063..fad8c513fb 100644 --- a/libs/wire-subsystems/src/Wire/StoredUser.hs +++ b/libs/wire-subsystems/src/Wire/StoredUser.hs @@ -40,7 +40,8 @@ data StoredUser = StoredUser handle :: Maybe Handle, teamId :: Maybe TeamId, managedBy :: Maybe ManagedBy, - supportedProtocols :: Maybe (Set BaseProtocolTag) + supportedProtocols :: Maybe (Set BaseProtocolTag), + searchable :: Maybe Bool } deriving (Show, Eq, Ord, Generic) deriving (Arbitrary) via (GenericUniform StoredUser) @@ -98,7 +99,8 @@ mkUserFromStored domain defaultLocale storedUser = userManagedBy = fromMaybe ManagedByWire storedUser.managedBy, userSupportedProtocols = case storedUser.supportedProtocols of Nothing -> defSupportedProtocols - Just ps -> if S.null ps then defSupportedProtocols else ps + Just ps -> if S.null ps then defSupportedProtocols else ps, + userSearchable = (fromMaybe True storedUser.searchable) } toLocale :: Locale -> (Maybe Language, Maybe Country) -> Locale @@ -147,7 +149,8 @@ data NewStoredUser = NewStoredUser handle :: Maybe Handle, teamId :: Maybe TeamId, managedBy :: ManagedBy, - supportedProtocols :: Set BaseProtocolTag + supportedProtocols :: Set BaseProtocolTag, + searchable :: Bool } deriving (Show) @@ -178,7 +181,8 @@ deriving instance Maybe Handle, Maybe TeamId, ManagedBy, - Set BaseProtocolTag + Set BaseProtocolTag, + Bool ) instance HasField "service" NewStoredUser (Maybe ServiceRef) where @@ -203,5 +207,6 @@ newStoredUserToUser (Qualified new domain) = userExpire = new.expires, userTeam = new.teamId, userManagedBy = new.managedBy, - userSupportedProtocols = new.supportedProtocols + userSupportedProtocols = new.supportedProtocols, + userSearchable = new.searchable } diff --git a/libs/wire-subsystems/src/Wire/UserStore/Cassandra.hs b/libs/wire-subsystems/src/Wire/UserStore/Cassandra.hs index 07d101c096..b55bd0a60f 100644 --- a/libs/wire-subsystems/src/Wire/UserStore/Cassandra.hs +++ b/libs/wire-subsystems/src/Wire/UserStore/Cassandra.hs @@ -241,8 +241,8 @@ insertUser :: PrepQuery W (TupleType NewStoredUser) () insertUser = "INSERT INTO user (id, name, text_status, picture, assets, email, sso_id, \ \accent_id, password, activated, status, expires, language, \ - \country, provider, service, handle, team, managed_by, supported_protocols) \ - \VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" + \country, provider, service, handle, team, managed_by, supported_protocols, searchable) \ + \VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" insertServiceUser :: PrepQuery W (ProviderId, ServiceId, BotId, ConvId, Maybe TeamId) () insertServiceUser = @@ -259,7 +259,7 @@ selectUsers = [sql| SELECT id, name, text_status, picture, email, email_unvalidated, sso_id, accent_id, assets, activated, status, expires, language, country, provider, - service, handle, team, managed_by, supported_protocols + service, handle, team, managed_by, supported_protocols, searchable FROM user WHERE id IN ? |] diff --git a/libs/wire-subsystems/test/unit/Wire/MockInterpreters/UserStore.hs b/libs/wire-subsystems/test/unit/Wire/MockInterpreters/UserStore.hs index ae5396691c..8bb0b58597 100644 --- a/libs/wire-subsystems/test/unit/Wire/MockInterpreters/UserStore.hs +++ b/libs/wire-subsystems/test/unit/Wire/MockInterpreters/UserStore.hs @@ -160,5 +160,6 @@ newStoredUserToStoredUser new = handle = new.handle, teamId = new.teamId, managedBy = Just new.managedBy, - supportedProtocols = Just new.supportedProtocols + supportedProtocols = Just new.supportedProtocols, + searchable = Just new.searchable } diff --git a/services/brig/src/Brig/Data/User.hs b/services/brig/src/Brig/Data/User.hs index e285999741..6345813536 100644 --- a/services/brig/src/Brig/Data/User.hs +++ b/services/brig/src/Brig/Data/User.hs @@ -141,7 +141,8 @@ newStoredUser u inv tid mbHandle = do expires = e, teamId = tid, managedBy = managedBy, - supportedProtocols = prots + supportedProtocols = prots, + searchable = True -- NewUser doesn't have this field. TODO: should a defSearchable be added to Wire.API.User to be used everywhere? } newStoredUserViaScim :: (MonadReader Env m) => UserId -> Text -> TeamId -> Maybe Locale -> Name -> EmailAddress -> m NewStoredUser @@ -172,7 +173,8 @@ newStoredUserViaScim uid externalId tid locale name email = do expires = Nothing, teamId = Just tid, managedBy = ManagedByScim, - supportedProtocols = defSupportedProtocols + supportedProtocols = defSupportedProtocols, + searchable = True } updateEmail :: (MonadClient m) => UserId -> EmailAddress -> m () @@ -341,14 +343,15 @@ type UserRow = Maybe Handle, Maybe TeamId, Maybe ManagedBy, - Maybe (Set BaseProtocolTag) + Maybe (Set BaseProtocolTag), + Maybe Bool ) usersSelect :: PrepQuery R (Identity [UserId]) UserRow usersSelect = "SELECT id, name, text_status, picture, email, email_unvalidated, sso_id, accent_id, assets, \ \activated, status, expires, language, country, provider, service, \ - \handle, team, managed_by, supported_protocols \ + \handle, team, managed_by, supported_protocols, searchable \ \FROM user where id IN ?" idSelect :: PrepQuery R (Identity UserId) (Identity UserId) @@ -417,7 +420,8 @@ toUsers domain defLocale havePendingInvitations = fmap mk . filter fp _handle, _tid, _managed_by, - _prots + _prots, + _searchable ) -> status /= Just PendingInvitation ) @@ -442,7 +446,8 @@ toUsers domain defLocale havePendingInvitations = fmap mk . filter fp handle, tid, managed_by, - prots + prots, + searchable ) = let ident = toIdentity activated email ssoid expiration = if status == Just Ephemeral then expires else Nothing @@ -465,6 +470,7 @@ toUsers domain defLocale havePendingInvitations = fmap mk . filter fp tid (fromMaybe ManagedByWire managed_by) (fromMaybe defSupportedProtocols prots) + (fromMaybe True searchable) toLocaleWithDefault :: Locale -> (Maybe Language, Maybe Country) -> Locale toLocaleWithDefault _ (Just l, c) = Locale l c diff --git a/services/brig/src/Brig/Provider/API.hs b/services/brig/src/Brig/Provider/API.hs index 80304f53f8..70864ca180 100644 --- a/services/brig/src/Brig/Provider/API.hs +++ b/services/brig/src/Brig/Provider/API.hs @@ -831,7 +831,8 @@ addBot zuid zcon cid add = do handle = Nothing, teamId = Nothing, managedBy = ManagedByWire, - supportedProtocols = defSupportedProtocols + supportedProtocols = defSupportedProtocols, + searchable = True -- TODO: what is the default for bots? } let newClt = diff --git a/services/brig/test/integration/API/User/Account.hs b/services/brig/test/integration/API/User/Account.hs index 921f1f8a5b..879bc30549 100644 --- a/services/brig/test/integration/API/User/Account.hs +++ b/services/brig/test/integration/API/User/Account.hs @@ -808,7 +808,8 @@ testMultipleUsers opts brig = do profileEmail = Nothing, profileLegalholdStatus = UserLegalHoldDisabled, profileSupportedProtocols = defSupportedProtocols, - profileType = UserTypeRegular + profileType = UserTypeRegular, + profileSearchable = True } users = [u1, u2, u3] q = ListUsersByIds $ u5 : u4 : map userQualifiedId users diff --git a/services/galley/test/integration/API/Util.hs b/services/galley/test/integration/API/Util.hs index 0edd71133b..b26c80ab3d 100644 --- a/services/galley/test/integration/API/Util.hs +++ b/services/galley/test/integration/API/Util.hs @@ -2587,7 +2587,8 @@ mkProfile quid name = profileEmail = Nothing, profileLegalholdStatus = defUserLegalHoldStatus, profileSupportedProtocols = defSupportedProtocols, - profileType = UserTypeRegular + profileType = UserTypeRegular, + profileSearchable = True } -- mock federator From ede3f7f582099da9233630ea1f04fd3238f15b9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Thu, 25 Sep 2025 10:31:03 +0300 Subject: [PATCH 05/30] Add Elastic Search boolean field type --- services/brig/src/Brig/User/Search/Index.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/brig/src/Brig/User/Search/Index.hs b/services/brig/src/Brig/User/Search/Index.hs index 9d34dc8753..a1e91e62ec 100644 --- a/services/brig/src/Brig/User/Search/Index.hs +++ b/services/brig/src/Brig/User/Search/Index.hs @@ -475,7 +475,7 @@ data MappingField = MappingField mfSearchAnalyzer :: Maybe Text } -data MappingPropertyType = MPText | MPKeyword | MPByte | MPDate +data MappingPropertyType = MPText | MPKeyword | MPByte | MPDate | MPBoolean deriving (Eq) instance ToJSON MappingProperty where @@ -494,6 +494,7 @@ instance ToJSON MappingPropertyType where toJSON MPKeyword = Aeson.String "keyword" toJSON MPByte = Aeson.String "byte" toJSON MPDate = Aeson.String "date" + toJSON MPBoolean = Aeson.String "boolean" instance ToJSON MappingField where toJSON mf = From 07685fd4f9d797329e419e0ed7517fc8c7fd3cb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Fri, 19 Sep 2025 17:01:42 +0300 Subject: [PATCH 06/30] Add `POST /users/:uid/searchable` --- .../src/Wire/API/Routes/Public/Brig.hs | 12 +++++++++++ libs/wire-api/src/Wire/API/Team/Member.hs | 3 ++- libs/wire-api/src/Wire/API/Team/Permission.hs | 3 +++ libs/wire-subsystems/src/Wire/UserStore.hs | 1 + .../src/Wire/UserStore/Cassandra.hs | 7 +++++++ .../wire-subsystems/src/Wire/UserSubsystem.hs | 1 + .../src/Wire/UserSubsystem/Interpreter.hs | 20 +++++++++++++++++++ .../unit/Wire/MockInterpreters/UserStore.hs | 6 ++++++ .../Wire/MockInterpreters/UserSubsystem.hs | 1 + services/brig/src/Brig/API/Public.hs | 15 +++++++++++++- 10 files changed, 67 insertions(+), 2 deletions(-) diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs b/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs index 6ae00025fc..816aca8ce0 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs @@ -290,6 +290,18 @@ type UserAPI = '[JSON] (Respond 200 "Protocols supported by the user" (Set BaseProtocolTag)) ) + :<|> Named + "set-user-searchable" + ( Summary "Set user's visibility in search" + :> From 'V12 + :> ZLocalUser + :> "users" + :> CaptureUserId "uid" + :> Capture "tid" TeamId + :> ReqBody '[JSON] Bool + :> "searchable" + :> Post '[JSON] () + ) type LastSeenNameDesc = Description "`name` of the last seen user group, used to get the next page when sorting by name." diff --git a/libs/wire-api/src/Wire/API/Team/Member.hs b/libs/wire-api/src/Wire/API/Team/Member.hs index 94fd562cbc..d56daf960d 100644 --- a/libs/wire-api/src/Wire/API/Team/Member.hs +++ b/libs/wire-api/src/Wire/API/Team/Member.hs @@ -533,7 +533,8 @@ rolePerms RoleAdmin = [ AddTeamMember, RemoveTeamMember, SetTeamData, - SetMemberPermissions + SetMemberPermissions, + SetMemberSearchable ] rolePerms RoleMember = rolePerms RoleExternalPartner diff --git a/libs/wire-api/src/Wire/API/Team/Permission.hs b/libs/wire-api/src/Wire/API/Team/Permission.hs index 974ef98926..a85c8a3625 100644 --- a/libs/wire-api/src/Wire/API/Team/Permission.hs +++ b/libs/wire-api/src/Wire/API/Team/Permission.hs @@ -154,6 +154,7 @@ data Perm | SetMemberPermissions | GetTeamConversations | DeleteTeam + | SetMemberSearchable -- FUTUREWORK: make the verbs in the roles more consistent -- (CRUD vs. Add,Remove vs; Get,Set vs. Create,Delete etc). deriving stock (Eq, Ord, Show, Enum, Bounded, Generic) @@ -184,6 +185,7 @@ permToInt GetMemberPermissions = 0x0200 permToInt GetTeamConversations = 0x0400 permToInt DeleteTeam = 0x0800 permToInt SetMemberPermissions = 0x1000 +permToInt SetMemberSearchable = 0x2000 intToPerm :: Word64 -> Maybe Perm intToPerm 0x0001 = Just CreateConversation @@ -199,6 +201,7 @@ intToPerm 0x0200 = Just GetMemberPermissions intToPerm 0x0400 = Just GetTeamConversations intToPerm 0x0800 = Just DeleteTeam intToPerm 0x1000 = Just SetMemberPermissions +intToPerm 0x2000 = Just SetMemberSearchable intToPerm _ = Nothing instance Cql.Cql Permissions where diff --git a/libs/wire-subsystems/src/Wire/UserStore.hs b/libs/wire-subsystems/src/Wire/UserStore.hs index 9ab0ee7b0e..e8bde66108 100644 --- a/libs/wire-subsystems/src/Wire/UserStore.hs +++ b/libs/wire-subsystems/src/Wire/UserStore.hs @@ -78,6 +78,7 @@ data UserStore m a where GetRichInfo :: UserId -> UserStore m (Maybe RichInfoAssocList) GetUserAuthenticationInfo :: UserId -> UserStore m (Maybe (Maybe Password, AccountStatus)) DeleteEmail :: UserId -> UserStore m () + SetUserSearchable :: UserId -> Bool -> UserStore m () makeSem ''UserStore diff --git a/libs/wire-subsystems/src/Wire/UserStore/Cassandra.hs b/libs/wire-subsystems/src/Wire/UserStore/Cassandra.hs index b55bd0a60f..8445304341 100644 --- a/libs/wire-subsystems/src/Wire/UserStore/Cassandra.hs +++ b/libs/wire-subsystems/src/Wire/UserStore/Cassandra.hs @@ -43,6 +43,7 @@ interpretUserStoreCassandra casClient = GetRichInfo uid -> getRichInfoImpl uid GetUserAuthenticationInfo uid -> getUserAuthenticationInfoImpl uid DeleteEmail uid -> deleteEmailImpl uid + SetUserSearchable uid searchable -> setUserSearchableImpl uid searchable createUserImpl :: NewStoredUser -> Maybe (ConvId, Maybe TeamId) -> Client () createUserImpl new mbConv = retry x5 . batch $ do @@ -234,6 +235,12 @@ getRichInfoImpl uid = deleteEmailImpl :: UserId -> Client () deleteEmailImpl u = retry x5 $ write userEmailDelete (params LocalQuorum (Identity u)) +setUserSearchableImpl :: UserId -> Bool -> Client () +setUserSearchableImpl uid searchable = retry x5 $ write q (params LocalQuorum (searchable, uid)) + where + q :: PrepQuery W (Bool, UserId) () + q = "UPDATE user SET searchable = ? WHERE id = ?" + -------------------------------------------------------------------------------- -- Queries diff --git a/libs/wire-subsystems/src/Wire/UserSubsystem.hs b/libs/wire-subsystems/src/Wire/UserSubsystem.hs index 9ba1e37285..9a4a3a8619 100644 --- a/libs/wire-subsystems/src/Wire/UserSubsystem.hs +++ b/libs/wire-subsystems/src/Wire/UserSubsystem.hs @@ -179,6 +179,7 @@ data UserSubsystem m a where RemoveEmailEither :: Local UserId -> UserSubsystem m (Either UserSubsystemError ()) GetUserTeam :: UserId -> UserSubsystem m (Maybe TeamId) CheckUserIsAdmin :: UserId -> UserSubsystem m TeamId + SetUserSearchable :: Local UserId -> UserId -> TeamId -> Bool -> UserSubsystem m () -- | the return type of 'CheckHandle' data CheckHandleResp diff --git a/libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs b/libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs index 426699b662..22a2a07845 100644 --- a/libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs +++ b/libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs @@ -165,6 +165,7 @@ runUserSubsystem authInterpreter = interpret $ RemoveEmailEither luid -> removeEmailEitherImpl luid UserSubsystem.GetUserTeam uid -> getUserTeamImpl uid CheckUserIsAdmin uid -> checkUserIsAdminImpl uid + UserSubsystem.SetUserSearchable luid uid tid searchability -> setUserSearchableImpl luid uid tid searchability scimExtId :: StoredUser -> Maybe Text scimExtId su = do @@ -1120,3 +1121,22 @@ checkUserIsAdminImpl uid = do tid <- maybe (throw UserSubsystemInsufficientPermissions) pure =<< UserStore.getUserTeam uid ensurePermissions uid tid [CreateUpdateDeleteIdp] pure tid + +setUserSearchableImpl :: + ( Member UserStore r, + Member (Error UserSubsystemError) r, + Member TeamSubsystem r, + Member GalleyAPIAccess r, + Member IndexedUserStore r, + Member Metrics r + ) => + Local UserId -> + UserId -> + TeamId -> + Bool -> + Sem r () +setUserSearchableImpl luid uid tid searchable = do + ensurePermissions (tUnqualified luid) tid [Permission.SetMemberSearchable] + UserStore.setUserSearchable uid searchable + -- TODO generate an event? + syncUserIndex uid diff --git a/libs/wire-subsystems/test/unit/Wire/MockInterpreters/UserStore.hs b/libs/wire-subsystems/test/unit/Wire/MockInterpreters/UserStore.hs index 8bb0b58597..cc407941bb 100644 --- a/libs/wire-subsystems/test/unit/Wire/MockInterpreters/UserStore.hs +++ b/libs/wire-subsystems/test/unit/Wire/MockInterpreters/UserStore.hs @@ -90,6 +90,12 @@ inMemoryUserStoreInterpreter = interpret $ \case gets $ \users -> do user <- find (\user -> user.id == uid) users user.teamId + SetUserSearchable uid searchable -> modify $ map f + where + f u = + if u.id == uid + then u {Wire.StoredUser.searchable = Just searchable} :: StoredUser + else u storedUserToIndexUser :: StoredUser -> IndexUser storedUserToIndexUser storedUser = diff --git a/libs/wire-subsystems/test/unit/Wire/MockInterpreters/UserSubsystem.hs b/libs/wire-subsystems/test/unit/Wire/MockInterpreters/UserSubsystem.hs index f412a6c076..66e43c6b9d 100644 --- a/libs/wire-subsystems/test/unit/Wire/MockInterpreters/UserSubsystem.hs +++ b/libs/wire-subsystems/test/unit/Wire/MockInterpreters/UserSubsystem.hs @@ -47,6 +47,7 @@ userSubsystemTestInterpreter initialUsers = SearchUsers {} -> error "SearchUsers: implement on demand (userSubsystemInterpreter)" BrowseTeam {} -> error "BrowseTeam: implement on demand (userSubsystemInterpreter)" CheckUserIsAdmin {} -> error "CheckUserIsAdmin: implement on demand (userSubsystemInterpreter)" + SetUserSearchable {} -> error "SetUserSearchable: implement on demand (userSubsystemInterpreter)" toProfile :: User -> UserProfile toProfile u = mkUserProfileWithEmail (userEmail u) u UserLegalHoldDisabled diff --git a/services/brig/src/Brig/API/Public.hs b/services/brig/src/Brig/API/Public.hs index 96f7a8a637..03a149d1de 100644 --- a/services/brig/src/Brig/API/Public.hs +++ b/services/brig/src/Brig/API/Public.hs @@ -105,6 +105,8 @@ import System.Logger.Class qualified as Log import Util.Logging (logFunction, logHandle, logTeam, logUser) import Wire.API.App import Wire.API.Connection qualified as Public +import Wire.API.Conversation.Member qualified as Member +import Wire.API.Conversation.Role (roleNameWireAdmin) import Wire.API.EnterpriseLogin import Wire.API.Error import Wire.API.Error.Brig qualified as E @@ -140,7 +142,8 @@ import Wire.API.SwaggerHelper (cleanupSwagger) import Wire.API.SystemSettings import Wire.API.Team qualified as Public import Wire.API.Team.LegalHold (LegalholdProtectee (..)) -import Wire.API.Team.Member (HiddenPerm (..), hasPermission) +import Wire.API.Team.Member (HiddenPerm (..), IsPerm (..), TeamMember, hasPermission) +import Wire.API.Team.Permission (Perm (SetMemberSearchable)) import Wire.API.User (RegisterError (RegisterErrorAllowlistError)) import Wire.API.User qualified as Public import Wire.API.User.Activation qualified as Public @@ -454,6 +457,7 @@ servantSitemap = :<|> Named @"send-verification-code" sendVerificationCode :<|> Named @"get-rich-info" getRichInfo :<|> Named @"get-supported-protocols" getSupportedProtocols + :<|> Named @"set-user-searchable" setUserSearchableH userGroupAPI :: ServerT UserGroupAPI (Handler r) userGroupAPI = @@ -854,6 +858,15 @@ getSupportedProtocols lself quid = do user <- maybe (throwStd (errorToWai @'E.UserNotFound)) pure muser pure (Public.profileSupportedProtocols user) +setUserSearchableH :: + (Member UserSubsystem r) => + Local UserId -> + UserId -> + TeamId -> + Bool -> + Handler r () +setUserSearchableH zusr uid tid searchable = lift $ liftSem $ User.setUserSearchable zusr uid tid searchable + getClientPrekeys :: UserId -> ClientId -> (Handler r) [Public.PrekeyId] getClientPrekeys usr clt = lift (wrapClient $ API.lookupPrekeyIds usr clt) From dbfa24089059cebe6a8c3d729bef3e3b37bee949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Thu, 25 Sep 2025 10:30:30 +0300 Subject: [PATCH 07/30] Add Elastic Search indexing --- .../wire-subsystems/src/Wire/UserSearch/Types.hs | 7 +++++-- .../src/Wire/UserStore/Cassandra.hs | 1 + .../src/Wire/UserStore/IndexUser.hs | 16 ++++++++++++---- .../test/unit/Wire/MockInterpreters/UserStore.hs | 1 + .../test/unit/Wire/UserSearch/TypesSpec.hs | 3 ++- services/brig/src/Brig/User/Search/Index.hs | 9 +++++++++ 6 files changed, 30 insertions(+), 7 deletions(-) diff --git a/libs/wire-subsystems/src/Wire/UserSearch/Types.hs b/libs/wire-subsystems/src/Wire/UserSearch/Types.hs index 2fe0abbb4f..6e65a92695 100644 --- a/libs/wire-subsystems/src/Wire/UserSearch/Types.hs +++ b/libs/wire-subsystems/src/Wire/UserSearch/Types.hs @@ -58,7 +58,8 @@ data UserDoc = UserDoc udSearchVisibilityInbound :: Maybe SearchVisibilityInbound, udScimExternalId :: Maybe Text, udSso :: Maybe Sso, - udEmailUnvalidated :: Maybe EmailAddress + udEmailUnvalidated :: Maybe EmailAddress, + udSearchable :: Maybe Bool } deriving (Eq, Show, Generic) deriving (Arbitrary) via (GenericUniform UserDoc) @@ -81,7 +82,8 @@ instance ToJSON UserDoc where searchVisibilityInboundFieldName .= udSearchVisibilityInbound ud, "scim_external_id" .= udScimExternalId ud, "sso" .= udSso ud, - "email_unvalidated" .= udEmailUnvalidated ud + "email_unvalidated" .= udEmailUnvalidated ud, + "searchable" .= udSearchable ud ] instance FromJSON UserDoc where @@ -103,6 +105,7 @@ instance FromJSON UserDoc where <*> o .:? "scim_external_id" <*> o .:? "sso" <*> o .:? "email_unvalidated" + <*> o .:? "searchable" searchVisibilityInboundFieldName :: Key searchVisibilityInboundFieldName = "search_visibility_inbound" diff --git a/libs/wire-subsystems/src/Wire/UserStore/Cassandra.hs b/libs/wire-subsystems/src/Wire/UserStore/Cassandra.hs index 8445304341..e585dba8e0 100644 --- a/libs/wire-subsystems/src/Wire/UserStore/Cassandra.hs +++ b/libs/wire-subsystems/src/Wire/UserStore/Cassandra.hs @@ -103,6 +103,7 @@ getIndexUserBaseQuery = managed_by, writetime(managed_by), sso_id, writetime(sso_id), email_unvalidated, writetime(email_unvalidated), + searchable, writetime(searchable), writetime(write_time_bumper) FROM user |] diff --git a/libs/wire-subsystems/src/Wire/UserStore/IndexUser.hs b/libs/wire-subsystems/src/Wire/UserStore/IndexUser.hs index 563ebb8d96..6c5456283f 100644 --- a/libs/wire-subsystems/src/Wire/UserStore/IndexUser.hs +++ b/libs/wire-subsystems/src/Wire/UserStore/IndexUser.hs @@ -38,6 +38,7 @@ data IndexUser = IndexUser managedBy :: Maybe (WithWritetime ManagedBy), ssoId :: Maybe (WithWritetime UserSSOId), unverifiedEmail :: Maybe (WithWritetime EmailAddress), + searchable :: Maybe (WithWritetime Bool), writeTimeBumper :: Maybe (Writetime WriteTimeBumper) } deriving (Eq, Show) @@ -57,6 +58,7 @@ type instance Maybe ManagedBy, Maybe (Writetime ManagedBy), Maybe UserSSOId, Maybe (Writetime UserSSOId), Maybe EmailAddress, Maybe (Writetime EmailAddress), + Maybe Bool, Maybe (Writetime Bool), Maybe (Writetime WriteTimeBumper) ) @@ -74,6 +76,7 @@ instance Record IndexUser where value <$> managedBy, writetime <$> managedBy, value <$> ssoId, writetime <$> ssoId, value <$> unverifiedEmail, writetime <$> unverifiedEmail, + value <$> searchable, writetime <$> searchable, writeTimeBumper ) @@ -90,6 +93,7 @@ instance Record IndexUser where managedBy, tManagedBy, ssoId, tSsoId, emailUnvalidated, tEmailUnvalidated, + searchable, tSearchable, tWriteTimeBumper ) = IndexUser { userId = u, @@ -104,6 +108,7 @@ instance Record IndexUser where managedBy = WithWriteTime <$> managedBy <*> tManagedBy, ssoId = WithWriteTime <$> ssoId <*> tSsoId, unverifiedEmail = WithWriteTime <$> emailUnvalidated <*> tEmailUnvalidated, + searchable = WithWriteTime <$> searchable <*> tSearchable, writeTimeBumper = tWriteTimeBumper } {- ORMOLU_ENABLE -} @@ -122,8 +127,9 @@ indexUserToVersion role IndexUser {..} = const () <$$> fmap writetime managedBy, const () <$$> fmap writetime ssoId, const () <$$> fmap writetime unverifiedEmail, - const () <$$> writeTimeBumper, - const () <$$> fmap writetime role + const () <$$> fmap writetime role, + const () <$$> fmap writetime searchable, + const () <$$> writeTimeBumper ] indexUserToDoc :: SearchVisibilityInbound -> Maybe Role -> IndexUser -> UserDoc @@ -131,7 +137,8 @@ indexUserToDoc searchVisInbound mRole IndexUser {..} = if shouldIndex then UserDoc - { udEmailUnvalidated = value <$> unverifiedEmail, + { udSearchable = value <$> searchable, + udEmailUnvalidated = value <$> unverifiedEmail, udSso = sso . value =<< ssoId, udScimExternalId = join $ scimExternalId <$> (value <$> managedBy) <*> (value <$> ssoId), udSearchVisibilityInbound = Just searchVisInbound, @@ -190,7 +197,8 @@ normalized = transliterate (trans "Any-Latin; Latin-ASCII; Lower") emptyUserDoc :: UserId -> UserDoc emptyUserDoc uid = UserDoc - { udEmailUnvalidated = Nothing, + { udSearchable = Nothing, + udEmailUnvalidated = Nothing, udSso = Nothing, udScimExternalId = Nothing, udSearchVisibilityInbound = Nothing, diff --git a/libs/wire-subsystems/test/unit/Wire/MockInterpreters/UserStore.hs b/libs/wire-subsystems/test/unit/Wire/MockInterpreters/UserStore.hs index cc407941bb..9c8330f756 100644 --- a/libs/wire-subsystems/test/unit/Wire/MockInterpreters/UserStore.hs +++ b/libs/wire-subsystems/test/unit/Wire/MockInterpreters/UserStore.hs @@ -115,6 +115,7 @@ storedUserToIndexUser storedUser = managedBy = withDefaultTime <$> storedUser.managedBy, ssoId = withDefaultTime <$> storedUser.ssoId, unverifiedEmail = Nothing, + searchable = withDefaultTime <$> storedUser.searchable, writeTimeBumper = Nothing } diff --git a/libs/wire-subsystems/test/unit/Wire/UserSearch/TypesSpec.hs b/libs/wire-subsystems/test/unit/Wire/UserSearch/TypesSpec.hs index 5e82d9a569..db2c728507 100644 --- a/libs/wire-subsystems/test/unit/Wire/UserSearch/TypesSpec.hs +++ b/libs/wire-subsystems/test/unit/Wire/UserSearch/TypesSpec.hs @@ -46,7 +46,8 @@ userDoc1 = udSearchVisibilityInbound = Nothing, udScimExternalId = Nothing, udSso = Nothing, - udEmailUnvalidated = Nothing + udEmailUnvalidated = Nothing, + udSearchable = Nothing -- TODO: or Just True? } -- Dont touch this. This represents serialized legacy data. diff --git a/services/brig/src/Brig/User/Search/Index.hs b/services/brig/src/Brig/User/Search/Index.hs index a1e91e62ec..634f059559 100644 --- a/services/brig/src/Brig/User/Search/Index.hs +++ b/services/brig/src/Brig/User/Search/Index.hs @@ -278,6 +278,7 @@ traceES descr act = liftIndexIO $ do -- saml_idp: URL of SAML issuer, not indexed, used for sorting -- managed_by: possible values "scim" or "wire", indexed as keyword -- created_at: date when "activated" state last chagned in epoch-millis, not indexed, used for sorting +-- searchable: Used to filter searchable users -- -- The prefix fields use "prefix_index" analyzer for indexing and "prefix_search" -- analyzer for searching. The "prefix_search" analyzer uses "edge_ngram" filter, this @@ -419,6 +420,14 @@ indexMapping = mpAnalyzer = Nothing, mpFields = mempty }, + "searchable" + .= MappingProperty + { mpType = MPBoolean, + mpStore = False, + mpIndex = True, + mpAnalyzer = Nothing, + mpFields = mempty + }, "scim_external_id" .= MappingProperty { mpType = MPKeyword, From 0de7f7d3b6966e3470408c2b6a55b4c53e5256d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Thu, 25 Sep 2025 09:43:31 +0300 Subject: [PATCH 08/30] Filter by searchable in Elastic Search --- .../wire-subsystems/src/Wire/IndexedUserStore/ElasticSearch.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/wire-subsystems/src/Wire/IndexedUserStore/ElasticSearch.hs b/libs/wire-subsystems/src/Wire/IndexedUserStore/ElasticSearch.hs index 28a5e61227..de5438416d 100644 --- a/libs/wire-subsystems/src/Wire/IndexedUserStore/ElasticSearch.hs +++ b/libs/wire-subsystems/src/Wire/IndexedUserStore/ElasticSearch.hs @@ -222,7 +222,8 @@ defaultUserQuery searcher mSearcherTeamId teamSearchInfo (normalized -> term') = ES.boolQueryMustNotMatch = [termQ "handle" term'] } ], - ES.boolQueryShouldMatch = [ES.QueryExistsQuery (ES.FieldName "handle")] + ES.boolQueryShouldMatch = [ES.QueryExistsQuery (ES.FieldName "handle")], + ES.boolQueryMustNotMatch = [ES.TermQuery (ES.Term "searchable" "false") Nothing] } -- This reduces relevance on users not in team of search by 90% (no -- science behind that number). If the searcher is not part of a team the From b8d7ad80198760dfe93c70c39982fad6bbd52f74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Wed, 1 Oct 2025 16:40:58 +0300 Subject: [PATCH 09/30] Filter by `searchable` in exact handle search --- libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs b/libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs index 22a2a07845..253332ddc5 100644 --- a/libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs +++ b/libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs @@ -852,7 +852,7 @@ searchLocally searcher searchTerm maybeMaxResults = do isContactVisible = (config.searchSameTeamOnly && (snd . tUnqualified $ searcher) == storedUser.teamId) || (not config.searchSameTeamOnly) - if isContactVisible + if isContactVisible && fromMaybe True storedUser.searchable then pure contact else MaybeT $ pure Nothing From 0d6dfc783519e2274cb9c31d56f6d7d5bdf23504 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Fri, 19 Sep 2025 12:49:32 +0300 Subject: [PATCH 10/30] Test searchable field and contact search --- .../brig/test/integration/API/User/Account.hs | 95 +++++++++++++++++++ services/brig/test/integration/Util.hs | 9 ++ 2 files changed, 104 insertions(+) diff --git a/services/brig/test/integration/API/User/Account.hs b/services/brig/test/integration/API/User/Account.hs index 879bc30549..04124082b6 100644 --- a/services/brig/test/integration/API/User/Account.hs +++ b/services/brig/test/integration/API/User/Account.hs @@ -87,12 +87,16 @@ import Wire.API.Conversation import Wire.API.Routes.MultiTablePaging import Wire.API.Team.Feature import Wire.API.Team.Invitation +import Wire.API.Team.Member (rolePermissions) +import Wire.API.Team.Member qualified as Team.Member import Wire.API.Team.Permission hiding (self) +import Wire.API.Team.Role import Wire.API.User import Wire.API.User.Activation import Wire.API.User.Auth import Wire.API.User.Auth qualified as Auth import Wire.API.User.Client +import Wire.API.User.Search tests :: ConnectionLimit -> Timeout -> Opt.Opts -> Manager -> Brig -> Cannon -> CargoHold -> Galley -> AWS.Env -> UserJournalWatcher -> TestTree tests _ at opts p b c ch g aws userJournalWatcher = @@ -117,6 +121,7 @@ tests _ at opts p b c ch g aws userJournalWatcher = test p "get /users//:uid - 404" $ testNonExistingUser b, test p "get /users/:domain/:uid - 422" $ testUserInvalidDomain b, test p "get /users/:uid - 200" $ testExistingUserUnqualified b, + test p "testUserSearchable" $ testUserSearchable b g, test p "get /users//:uid - 200" $ testExistingUser b, test p "get /users?:id=.... - 200" $ testMultipleUsersUnqualified b, test p "head /users/:uid - 200" $ testUserExistsUnqualified b, @@ -641,6 +646,89 @@ testExistingUserUnqualified brig = do b ^? key "id" >>= maybeFromJSON ) +testUserSearchable :: Brig -> Galley -> Http () +testUserSearchable brig galley = do + (owner, tid) <- createUserWithTeam brig + + -- Make a member in the current team + let mkTeamMember :: Permissions -> Http User + mkTeamMember perms = do + member <- createTeamMember brig galley owner tid perms + selfUser <$> (responseJsonError =<< get (brig . path "/self" . zUser (userId member))) + + -- Helper to change user searchability. + setSearchable :: UserId -> UserId -> Bool -> Request -> Request + setSearchable byZuid uid searchable = + brig + . paths ["users", pack $ show uid, pack $ show tid, "searchable"] + . zUser byZuid + . toJsonBody searchable + + -- Create user in team, default is searchable = True. + u1id <- userId <$> mkTeamMember (rolePermissions RoleMember) + u1p <- parseOrFail "UserProfile" (getProfile brig owner u1id) + liftIO $ assertBool "created users are searchable by default" $ profileSearchable u1p + + -- Setting self to non-searchable won't work -- only admin can do it. + post (setSearchable u1id u1id False) !!! do + const 403 === statusCode + const (Just "insufficient-permissions") === fmap Error.label . responseJsonMaybe + liftIO . assertBool "Searchable is still True" . profileSearchable =<< parseOrFail "UserProfile" (getProfile brig owner u1id) + + -- Team admin can set user to non-searchable. + admin <- userId <$> mkTeamMember (rolePermissions RoleAdmin) + post (setSearchable admin u1id False) !!! const 200 === statusCode + liftIO . assertBool "Searchable is now False" . not . profileSearchable =<< parseOrFail "UserProfile" (getProfile brig owner u1id) + + -- Team owner can, too. + post (setSearchable owner u1id True) !!! const 200 === statusCode + post (setSearchable owner u1id False) !!! const 200 === statusCode + + -- By default created team members are found. + u3 <- mkTeamMember (rolePermissions RoleMember) + Search.refreshIndex brig + s <- Search.executeSearch brig u1id $ fromName $ userDisplayName u3 + liftIO $ assertBool "u1 must find u3 as they are searchable by default" $ uidsInResult [userId u3] s + + -- Use set to non-searchable is not found by other team members. + u4 <- mkTeamMember (rolePermissions RoleMember) + post (setSearchable owner (userId u4) False) !!! const 200 === statusCode + Search.refreshIndex brig + s <- Search.executeSearch brig u1id $ fromName $ userDisplayName u4 + liftIO $ assertBool "u1 must not find u4 as they are set non-searchable" $ not $ uidsInResult [userId u4] s + + -- Even admin nor owner won't find non-searchable users via /search/contacts + sAdmin <- Search.executeSearch brig admin $ fromName $ userDisplayName u4 + liftIO $ assertBool "Team admin won't find non-searchable user from /search/concatcs" $ not $ uidsInResult [userId u4] sAdmin + sOwner <- Search.executeSearch brig owner $ fromName $ userDisplayName u4 + liftIO $ assertBool "Team owner won't find non-searchable user from /search/concatcs" $ not $ uidsInResult [userId u4] sOwner + + -- Exact handle search with HTTP HEAD still works for non-searchable users + u4' <- setRandomHandle brig u4 -- Add handle to the non-searchable u4 + let u4handle = fromJust $ userHandle u4' + Bilge.head (brig . paths ["handles", toByteString' u4handle] . zUser (userId u3)) + !!! const 200 === statusCode + + -- Regular user can't find non-searchable team member by exact handle. + s <- Search.executeSearch brig u1id $ fromHandle u4handle + liftIO $ assertBool "u1 must not find non-searchable u4 by exact handle" $ not $ uidsInResult [userId u4] s + + -- /teams/:tid/members gets all fields + r :: Team.Member.TeamMembersPage <- parseOrFail "TeamMembersPage" $ get (galley . paths ["teams", toByteString' tid, "members"] . zUser u1id) UserId + contactUid = qUnqualified . contactQualifiedId + + uidsInResult :: [UserId] -> SearchResult Contact -> Bool + uidsInResult uids r = all (`elem` foundUids) uids + where + foundUids = map contactUid (searchResults r) + testExistingUser :: Brig -> Http () testExistingUser brig = do quser <- userQualifiedId <$> randomUser brig @@ -1589,3 +1677,10 @@ execAndAssertUserDeletion brig cannon u hdl others userJournalWatcher execDelete -- | Get user profile (while asserting that result is successful) getProfile :: Brig -> UserId -> UserId -> Http ResponseLBS getProfile b zusr uid = get (apiVersion "v1" . b . zUser zusr . paths ["users", toByteString' uid]) String -> Http ResponseLBS -> Http a +parseOrFail what action = maybe (liftIO $ assertFailure $ "Can't parse from JSON: " <> what) pure . responseJsonMaybe =<< action + +-- | Add any ToJSON value to request and set content-type to JSON as well. +toJsonBody :: ToJSON a => a -> Request -> Request +toJsonBody a req = contentJson $ body (RequestBodyLBS $ encode a) req diff --git a/services/brig/test/integration/Util.hs b/services/brig/test/integration/Util.hs index 97b5afc199..674bd1973c 100644 --- a/services/brig/test/integration/Util.hs +++ b/services/brig/test/integration/Util.hs @@ -288,6 +288,15 @@ randomUser :: m User randomUser = randomUser' True +randomUserPrefix :: + (MonadCatch m, MonadIO m, MonadHttp m, HasCallStack) => + Text -> + Brig -> + m User +randomUserPrefix prefix brig = do + n <- fromName <$> randomName + createUser' True (prefix <> n) brig + randomUser' :: (MonadCatch m, MonadIO m, MonadHttp m, HasCallStack) => Bool -> From d02426bac76dd5cfe9e30aef5502adca77dfe1c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Fri, 3 Oct 2025 10:12:33 +0300 Subject: [PATCH 11/30] Use common CQL splice for team member queries --- .../galley/src/Galley/Cassandra/Queries.hs | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/services/galley/src/Galley/Cassandra/Queries.hs b/services/galley/src/Galley/Cassandra/Queries.hs index fd190ff53e..b143103b55 100644 --- a/services/galley/src/Galley/Cassandra/Queries.hs +++ b/services/galley/src/Galley/Cassandra/Queries.hs @@ -135,6 +135,12 @@ selectTeamMember :: ) selectTeamMember = "select perms, invited_by, invited_at, legalhold_status from team_member where team = ? and user = ?" +selectTeamMembersBase :: (IsString a) => [String] -> a +selectTeamMembersBase conds = fromString $ selectFrom <> " where team = ?" <> whereClause <> " order by user" + where + selectFrom = "select user, perms, invited_by, invited_at, legalhold_status from team_member" + whereClause = concatMap (" and " <>) conds + -- | This query fetches **all** members of a team, it should always be paginated selectTeamMembers :: PrepQuery @@ -146,12 +152,7 @@ selectTeamMembers :: Maybe UTCTimeMillis, Maybe UserLegalHoldStatus ) -selectTeamMembers = - [r| - select user, perms, invited_by, invited_at, legalhold_status - from team_member - where team = ? order by user - |] +selectTeamMembers = selectTeamMembersBase [] selectTeamMembersFrom :: PrepQuery @@ -163,12 +164,7 @@ selectTeamMembersFrom :: Maybe UTCTimeMillis, Maybe UserLegalHoldStatus ) -selectTeamMembersFrom = - [r| - select user, perms, invited_by, invited_at, legalhold_status - from team_member - where team = ? and user > ? order by user - |] +selectTeamMembersFrom = selectTeamMembersBase ["user > ?"] selectTeamMembers' :: PrepQuery From 1dd211050b258a694f7b6687b47b914a270bccd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Thu, 2 Oct 2025 18:48:46 +0300 Subject: [PATCH 12/30] Test /team/:tid/members?searchable=false --- services/brig/test/integration/API/User/Account.hs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/services/brig/test/integration/API/User/Account.hs b/services/brig/test/integration/API/User/Account.hs index 04124082b6..9f1c35b053 100644 --- a/services/brig/test/integration/API/User/Account.hs +++ b/services/brig/test/integration/API/User/Account.hs @@ -713,13 +713,22 @@ testUserSearchable brig galley = do s <- Search.executeSearch brig u1id $ fromHandle u4handle liftIO $ assertBool "u1 must not find non-searchable u4 by exact handle" $ not $ uidsInResult [userId u4] s - -- /teams/:tid/members gets all fields + -- /teams/:tid/members gets all members r :: Team.Member.TeamMembersPage <- parseOrFail "TeamMembersPage" $ get (galley . paths ["teams", toByteString' tid, "members"] . zUser u1id) UserId contactUid = qUnqualified . contactQualifiedId From a1c8e3402c371f768bbbd2592249c340eda50a34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Fri, 3 Oct 2025 10:12:46 +0300 Subject: [PATCH 13/30] [wip] Filter `searchable` with `/team/:tid/members?searchable=false` --- .../API/Routes/Public/Galley/TeamMember.hs | 8 +++++ .../brig/test/integration/API/User/Account.hs | 16 ++++----- services/galley/src/Galley/API/LegalHold.hs | 2 +- services/galley/src/Galley/API/Teams.hs | 9 +++-- .../galley/src/Galley/API/Teams/Export.hs | 2 +- .../galley/src/Galley/Cassandra/Queries.hs | 30 ++++++++++++++++ services/galley/src/Galley/Cassandra/Team.hs | 34 ++++++++++++------- .../src/Galley/Effects/TeamMemberStore.hs | 1 + 8 files changed, 77 insertions(+), 25 deletions(-) diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Galley/TeamMember.hs b/libs/wire-api/src/Wire/API/Routes/Public/Galley/TeamMember.hs index f3aee85819..fc1e19022d 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Galley/TeamMember.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Galley/TeamMember.hs @@ -17,6 +17,7 @@ module Wire.API.Routes.Public.Galley.TeamMember where +import Data.Bool import Data.Id import Data.Int import Data.Range @@ -60,6 +61,13 @@ type TeamMemberAPI = ] "pagingState" TeamMembersPagingState + :> QueryParam' + [ Optional, + Strict, + Description "Optional, return only non-seacrhable members when false." + ] + "searchable" + Bool :> Get '[JSON] TeamMembersPage ) :<|> Named diff --git a/services/brig/test/integration/API/User/Account.hs b/services/brig/test/integration/API/User/Account.hs index 9f1c35b053..f162ccfc4d 100644 --- a/services/brig/test/integration/API/User/Account.hs +++ b/services/brig/test/integration/API/User/Account.hs @@ -720,14 +720,14 @@ testUserSearchable brig galley = do liftIO $ assertBool "/teams/:tid/members returns searchable and non-searchable users from team" $ all (`elem` uids) $ u1id : map userId [u3, u4] -- /teams/:tid/members?searchable=false gets only non-searchable members - r :: Team.Member.TeamMembersPage <- parseOrFail "TeamMembersPage" $ - get ( galley - . paths ["teams", toByteString' tid, "members"] - . queryItem "searchable" "false" - . zUser u1id) UserId diff --git a/services/galley/src/Galley/API/LegalHold.hs b/services/galley/src/Galley/API/LegalHold.hs index 97c16b8369..f9b2d941d0 100644 --- a/services/galley/src/Galley/API/LegalHold.hs +++ b/services/galley/src/Galley/API/LegalHold.hs @@ -275,7 +275,7 @@ removeSettings' :: Sem r () removeSettings' tid = withChunks - (\mps -> listTeamMembers @p tid mps maxBound) + (\mps -> listTeamMembers @p tid mps maxBound Nothing) -- TODO_searchable: Pass Nothing here? action where action :: [TeamMember] -> Sem r () diff --git a/services/galley/src/Galley/API/Teams.hs b/services/galley/src/Galley/API/Teams.hs index 652c6e1b3b..60b01024c5 100644 --- a/services/galley/src/Galley/API/Teams.hs +++ b/services/galley/src/Galley/API/Teams.hs @@ -477,20 +477,23 @@ getTeamMembers :: TeamId -> Maybe (Range 1 Public.HardTruncationLimit Int32) -> Maybe TeamMembersPagingState -> + Maybe Bool -> Sem r TeamMembersPage -getTeamMembers lzusr tid mbMaxResults mbPagingState = do +getTeamMembers lzusr tid mbMaxResults mbPagingState mbSearchable = do let uid = tUnqualified lzusr member <- E.getTeamMember tid uid >>= noteS @'NotATeamMember let mState = C.PagingState . LBS.fromStrict <$> (mbPagingState >>= mtpsState) let mLimit = fromMaybe (unsafeRange Public.hardTruncationLimit) mbMaxResults if member `hasPermission` SearchContacts - then E.listTeamMembers @CassandraPaging tid mState mLimit <&> toTeamMembersPage member + then case mbSearchable of + Just False -> E.listTeamMembers @CassandraPaging tid mState mLimit mbSearchable <&> toTeamMembersPage member + _ -> E.listTeamMembers @CassandraPaging tid mState mLimit mbSearchable <&> toTeamMembersPage member else do -- If the user does not have the SearchContacts permission (e.g. the external partner), -- we only return the person who invited them and the self user. let invitee = member ^. invitation <&> fst let uids = uid : maybeToList invitee - E.selectTeamMembersPaginated tid uids mState mLimit <&> toTeamMembersPage member + E.selectTeamMembersPaginated tid uids mState mLimit <&> toTeamMembersPage member -- TODO_searchable: Use `mbSearchable` in this branch of the if as well? where toTeamMembersPage :: TeamMember -> C.PageWithState TeamMember -> TeamMembersPage toTeamMembersPage member p = diff --git a/services/galley/src/Galley/API/Teams/Export.hs b/services/galley/src/Galley/API/Teams/Export.hs index 6fbbf9cc02..99e569f4db 100644 --- a/services/galley/src/Galley/API/Teams/Export.hs +++ b/services/galley/src/Galley/API/Teams/Export.hs @@ -122,7 +122,7 @@ getTeamMembersCSV lusr tid = do let encodeRow r = encodeDefaultOrderedByNameWith customEncodeOptions [r] let produceTeamExportUsers = do embedFinal $ writeChan chan (Just headerLine) - E.withChunks (\mps -> listTeamMembers @InternalPaging tid mps maxBound) $ + E.withChunks (\mps -> listTeamMembers @InternalPaging tid mps maxBound Nothing) $ -- TODO_searchable: Pass Nothing here? \members -> unsafePooledForConcurrentlyN_ 8 members $ \member -> do mRecord <- runErrorS @TeamMemberNotFound $ diff --git a/services/galley/src/Galley/Cassandra/Queries.hs b/services/galley/src/Galley/Cassandra/Queries.hs index b143103b55..dca858a671 100644 --- a/services/galley/src/Galley/Cassandra/Queries.hs +++ b/services/galley/src/Galley/Cassandra/Queries.hs @@ -74,6 +74,7 @@ module Galley.Cassandra.Queries selectTeam, selectUserTeamsIn, selectTeamMembers, + selectTeamMembersSearchable, selectOneUserTeam, selectTeamBindingWritetime, selectTeamBinding, @@ -154,6 +155,23 @@ selectTeamMembers :: ) selectTeamMembers = selectTeamMembersBase [] +selectTeamMembersNonSearchable :: + PrepQuery + R + (TeamId, Bool) + ( UserId, + Permissions, + Maybe UserId, + Maybe UTCTimeMillis, + Maybe UserLegalHoldStatus + ) +selectTeamMembersNonSearchable = + [r| + select user, perms, invited_by, invited_at, legalhold_status + from team_member + where team = ? and searchable = false order by user + |] + selectTeamMembersFrom :: PrepQuery R @@ -184,6 +202,18 @@ selectTeamMembers' = where team = ? and user in ? order by user |] +selectTeamMembersSearchable :: + PrepQuery + R + (TeamId, Bool) + ( UserId, + Permissions, + Maybe UserId, + Maybe UTCTimeMillis, + Maybe UserLegalHoldStatus + ) +selectTeamMembersSearchable = selectTeamMembersBase ["searchable = ?"] + selectUserTeams :: PrepQuery R (Identity UserId) (Identity TeamId) selectUserTeams = "select team from user_team where user = ? order by team" diff --git a/services/galley/src/Galley/Cassandra/Team.hs b/services/galley/src/Galley/Cassandra/Team.hs index 7a7296ff07..57a09792c0 100644 --- a/services/galley/src/Galley/Cassandra/Team.hs +++ b/services/galley/src/Galley/Cassandra/Team.hs @@ -199,13 +199,13 @@ interpretTeamMemberStoreToCassandra :: Sem (TeamMemberStore InternalPaging ': r) a -> Sem r a interpretTeamMemberStoreToCassandra lh = interpret $ \case - ListTeamMembers tid mps lim -> do + ListTeamMembers tid mps lim ms -> do logEffect "TeamMemberStore.ListTeamMembers" embedClient $ case mps of Nothing -> do - page <- teamMembersForPagination tid Nothing lim + page <- teamMembersForPagination tid Nothing lim ms mkInternalPage page (newTeamMember' lh tid) - Just ps -> ipNext ps + Just ps -> ipNext ps -- TODO_searchable: do I need to pass ms (Maybe Bool) to here as well? interpretTeamMemberStoreToCassandraWithPaging :: ( Member (Embed IO) r, @@ -216,9 +216,9 @@ interpretTeamMemberStoreToCassandraWithPaging :: Sem (TeamMemberStore CassandraPaging ': r) a -> Sem r a interpretTeamMemberStoreToCassandraWithPaging lh = interpret $ \case - ListTeamMembers tid mps lim -> do + ListTeamMembers tid mps lim ms -> do logEffect "TeamMemberStore.ListTeamMembers" - embedClient $ teamMembersPageFrom lh tid mps lim + embedClient $ teamMembersPageFrom lh tid mps lim ms createTeam :: ( Member (Input ClientState) r, @@ -377,7 +377,7 @@ teamMembersWithLimit lh t (fromRange -> limit) = do -- Maybe should be left explicitly for the caller? teamMembersCollectedWithPagination :: FeatureDefaults LegalholdConfig -> TeamId -> Client [TeamMember] teamMembersCollectedWithPagination lh tid = do - mems <- teamMembersForPagination tid Nothing (unsafeRange 2000) + mems <- teamMembersForPagination tid Nothing (unsafeRange 2000) Nothing -- TODO_searchable: pass Nothing (the last argument to the call)? collectTeamMembersPaginated [] mems where collectTeamMembersPaginated acc mems = do @@ -458,7 +458,7 @@ markTeamDeletedAndRemoveTeamMembers :: TeamId -> Client () markTeamDeletedAndRemoveTeamMembers tid = do -- TODO: delete service_whitelist records that mention this team retry x5 $ write Cql.markTeamDeleted (params LocalQuorum (PendingDelete, tid)) - mems <- teamMembersForPagination tid Nothing (unsafeRange 2000) + mems <- teamMembersForPagination tid Nothing (unsafeRange 2000) Nothing -- TODO_searchable: pass Nothing? removeTeamMembers mems where removeTeamMembers :: @@ -532,20 +532,30 @@ type RawTeamMember = (UserId, Permissions, Maybe UserId, Maybe UTCTimeMillis, Ma -- have a pure function of type RawTeamMember -> TeamMember so we cannot fmap -- over the ResultSet. We don't want to mess around with the Result size -- nextPage either otherwise -teamMembersForPagination :: TeamId -> Maybe UserId -> Range 1 HardTruncationLimit Int32 -> Client (Page RawTeamMember) -teamMembersForPagination tid start (fromRange -> max) = +teamMembersForPagination :: TeamId -> Maybe UserId -> Range 1 HardTruncationLimit Int32 -> Maybe Bool -> Client (Page RawTeamMember) +teamMembersForPagination tid start (fromRange -> max) ms = case start of Just u -> paginate Cql.selectTeamMembersFrom (paramsP LocalQuorum (tid, u) max) - Nothing -> paginate Cql.selectTeamMembers (paramsP LocalQuorum (Identity tid) max) + Nothing -> case ms of + Just searchable -> paginate Cql.selectTeamMembersSearchable (paramsP LocalQuorum (tid, searchable) max) + Nothing -> paginate Cql.selectTeamMembers (paramsP LocalQuorum (Identity tid) max) teamMembersPageFrom :: FeatureDefaults LegalholdConfig -> TeamId -> Maybe PagingState -> Range 1 HardTruncationLimit Int32 -> + Maybe Bool -> Client (PageWithState TeamMember) -teamMembersPageFrom lh tid pagingState (fromRange -> max) = do - page <- paginateWithState Cql.selectTeamMembers (paramsPagingState LocalQuorum (Identity tid) max pagingState) +teamMembersPageFrom lh tid pagingState (fromRange -> max) ms = do + page <- case ms of + Just searchable -> paginateWithState Cql.selectTeamMembersSearchable (paramsPagingState LocalQuorum (tid, searchable) max pagingState) + -- WIP_searchable: This is what is called from + -- /team/:tid/members?searchable=true. The issue is that this + -- queries the team_members table from cassandra and not the + -- users' table where the searchable field is. Cassandra doesn't + -- seem to support joins, so am currently stomped on how to proceed. + Nothing -> paginateWithState Cql.selectTeamMembers (paramsPagingState LocalQuorum (Identity tid) max pagingState) members <- mapM (newTeamMember' lh tid) (pwsResults page) pure $ PageWithState members (pwsState page) diff --git a/services/galley/src/Galley/Effects/TeamMemberStore.hs b/services/galley/src/Galley/Effects/TeamMemberStore.hs index 84f2dbca28..e3a8b45bef 100644 --- a/services/galley/src/Galley/Effects/TeamMemberStore.hs +++ b/services/galley/src/Galley/Effects/TeamMemberStore.hs @@ -37,6 +37,7 @@ data TeamMemberStore p m a where TeamId -> Maybe (PagingState p TeamMember) -> PagingBounds p TeamMember -> + Maybe Bool -> TeamMemberStore p m (Page p TeamMember) makeSem ''TeamMemberStore From c3301be2423592325688c636c5b317557d16e2f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Mon, 6 Oct 2025 15:40:19 +0300 Subject: [PATCH 14/30] Revert "[wip] Filter `searchable` with `/team/:tid/members?searchable=false`" This reverts commit 4790b05326e9cb9cba8715776a31dafb272c95e1. --- .../API/Routes/Public/Galley/TeamMember.hs | 8 ----- .../brig/test/integration/API/User/Account.hs | 16 ++++----- services/galley/src/Galley/API/LegalHold.hs | 2 +- services/galley/src/Galley/API/Teams.hs | 9 ++--- .../galley/src/Galley/API/Teams/Export.hs | 2 +- .../galley/src/Galley/Cassandra/Queries.hs | 30 ---------------- services/galley/src/Galley/Cassandra/Team.hs | 34 +++++++------------ .../src/Galley/Effects/TeamMemberStore.hs | 1 - 8 files changed, 25 insertions(+), 77 deletions(-) diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Galley/TeamMember.hs b/libs/wire-api/src/Wire/API/Routes/Public/Galley/TeamMember.hs index fc1e19022d..f3aee85819 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Galley/TeamMember.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Galley/TeamMember.hs @@ -17,7 +17,6 @@ module Wire.API.Routes.Public.Galley.TeamMember where -import Data.Bool import Data.Id import Data.Int import Data.Range @@ -61,13 +60,6 @@ type TeamMemberAPI = ] "pagingState" TeamMembersPagingState - :> QueryParam' - [ Optional, - Strict, - Description "Optional, return only non-seacrhable members when false." - ] - "searchable" - Bool :> Get '[JSON] TeamMembersPage ) :<|> Named diff --git a/services/brig/test/integration/API/User/Account.hs b/services/brig/test/integration/API/User/Account.hs index f162ccfc4d..9f1c35b053 100644 --- a/services/brig/test/integration/API/User/Account.hs +++ b/services/brig/test/integration/API/User/Account.hs @@ -720,14 +720,14 @@ testUserSearchable brig galley = do liftIO $ assertBool "/teams/:tid/members returns searchable and non-searchable users from team" $ all (`elem` uids) $ u1id : map userId [u3, u4] -- /teams/:tid/members?searchable=false gets only non-searchable members - -- r :: Team.Member.TeamMembersPage <- parseOrFail "TeamMembersPage" $ - -- get ( galley - -- . paths ["teams", toByteString' tid, "members"] - -- . queryItem "searchable" "false" - -- . zUser u1id) UserId diff --git a/services/galley/src/Galley/API/LegalHold.hs b/services/galley/src/Galley/API/LegalHold.hs index f9b2d941d0..97c16b8369 100644 --- a/services/galley/src/Galley/API/LegalHold.hs +++ b/services/galley/src/Galley/API/LegalHold.hs @@ -275,7 +275,7 @@ removeSettings' :: Sem r () removeSettings' tid = withChunks - (\mps -> listTeamMembers @p tid mps maxBound Nothing) -- TODO_searchable: Pass Nothing here? + (\mps -> listTeamMembers @p tid mps maxBound) action where action :: [TeamMember] -> Sem r () diff --git a/services/galley/src/Galley/API/Teams.hs b/services/galley/src/Galley/API/Teams.hs index 60b01024c5..652c6e1b3b 100644 --- a/services/galley/src/Galley/API/Teams.hs +++ b/services/galley/src/Galley/API/Teams.hs @@ -477,23 +477,20 @@ getTeamMembers :: TeamId -> Maybe (Range 1 Public.HardTruncationLimit Int32) -> Maybe TeamMembersPagingState -> - Maybe Bool -> Sem r TeamMembersPage -getTeamMembers lzusr tid mbMaxResults mbPagingState mbSearchable = do +getTeamMembers lzusr tid mbMaxResults mbPagingState = do let uid = tUnqualified lzusr member <- E.getTeamMember tid uid >>= noteS @'NotATeamMember let mState = C.PagingState . LBS.fromStrict <$> (mbPagingState >>= mtpsState) let mLimit = fromMaybe (unsafeRange Public.hardTruncationLimit) mbMaxResults if member `hasPermission` SearchContacts - then case mbSearchable of - Just False -> E.listTeamMembers @CassandraPaging tid mState mLimit mbSearchable <&> toTeamMembersPage member - _ -> E.listTeamMembers @CassandraPaging tid mState mLimit mbSearchable <&> toTeamMembersPage member + then E.listTeamMembers @CassandraPaging tid mState mLimit <&> toTeamMembersPage member else do -- If the user does not have the SearchContacts permission (e.g. the external partner), -- we only return the person who invited them and the self user. let invitee = member ^. invitation <&> fst let uids = uid : maybeToList invitee - E.selectTeamMembersPaginated tid uids mState mLimit <&> toTeamMembersPage member -- TODO_searchable: Use `mbSearchable` in this branch of the if as well? + E.selectTeamMembersPaginated tid uids mState mLimit <&> toTeamMembersPage member where toTeamMembersPage :: TeamMember -> C.PageWithState TeamMember -> TeamMembersPage toTeamMembersPage member p = diff --git a/services/galley/src/Galley/API/Teams/Export.hs b/services/galley/src/Galley/API/Teams/Export.hs index 99e569f4db..6fbbf9cc02 100644 --- a/services/galley/src/Galley/API/Teams/Export.hs +++ b/services/galley/src/Galley/API/Teams/Export.hs @@ -122,7 +122,7 @@ getTeamMembersCSV lusr tid = do let encodeRow r = encodeDefaultOrderedByNameWith customEncodeOptions [r] let produceTeamExportUsers = do embedFinal $ writeChan chan (Just headerLine) - E.withChunks (\mps -> listTeamMembers @InternalPaging tid mps maxBound Nothing) $ -- TODO_searchable: Pass Nothing here? + E.withChunks (\mps -> listTeamMembers @InternalPaging tid mps maxBound) $ \members -> unsafePooledForConcurrentlyN_ 8 members $ \member -> do mRecord <- runErrorS @TeamMemberNotFound $ diff --git a/services/galley/src/Galley/Cassandra/Queries.hs b/services/galley/src/Galley/Cassandra/Queries.hs index dca858a671..b143103b55 100644 --- a/services/galley/src/Galley/Cassandra/Queries.hs +++ b/services/galley/src/Galley/Cassandra/Queries.hs @@ -74,7 +74,6 @@ module Galley.Cassandra.Queries selectTeam, selectUserTeamsIn, selectTeamMembers, - selectTeamMembersSearchable, selectOneUserTeam, selectTeamBindingWritetime, selectTeamBinding, @@ -155,23 +154,6 @@ selectTeamMembers :: ) selectTeamMembers = selectTeamMembersBase [] -selectTeamMembersNonSearchable :: - PrepQuery - R - (TeamId, Bool) - ( UserId, - Permissions, - Maybe UserId, - Maybe UTCTimeMillis, - Maybe UserLegalHoldStatus - ) -selectTeamMembersNonSearchable = - [r| - select user, perms, invited_by, invited_at, legalhold_status - from team_member - where team = ? and searchable = false order by user - |] - selectTeamMembersFrom :: PrepQuery R @@ -202,18 +184,6 @@ selectTeamMembers' = where team = ? and user in ? order by user |] -selectTeamMembersSearchable :: - PrepQuery - R - (TeamId, Bool) - ( UserId, - Permissions, - Maybe UserId, - Maybe UTCTimeMillis, - Maybe UserLegalHoldStatus - ) -selectTeamMembersSearchable = selectTeamMembersBase ["searchable = ?"] - selectUserTeams :: PrepQuery R (Identity UserId) (Identity TeamId) selectUserTeams = "select team from user_team where user = ? order by team" diff --git a/services/galley/src/Galley/Cassandra/Team.hs b/services/galley/src/Galley/Cassandra/Team.hs index 57a09792c0..7a7296ff07 100644 --- a/services/galley/src/Galley/Cassandra/Team.hs +++ b/services/galley/src/Galley/Cassandra/Team.hs @@ -199,13 +199,13 @@ interpretTeamMemberStoreToCassandra :: Sem (TeamMemberStore InternalPaging ': r) a -> Sem r a interpretTeamMemberStoreToCassandra lh = interpret $ \case - ListTeamMembers tid mps lim ms -> do + ListTeamMembers tid mps lim -> do logEffect "TeamMemberStore.ListTeamMembers" embedClient $ case mps of Nothing -> do - page <- teamMembersForPagination tid Nothing lim ms + page <- teamMembersForPagination tid Nothing lim mkInternalPage page (newTeamMember' lh tid) - Just ps -> ipNext ps -- TODO_searchable: do I need to pass ms (Maybe Bool) to here as well? + Just ps -> ipNext ps interpretTeamMemberStoreToCassandraWithPaging :: ( Member (Embed IO) r, @@ -216,9 +216,9 @@ interpretTeamMemberStoreToCassandraWithPaging :: Sem (TeamMemberStore CassandraPaging ': r) a -> Sem r a interpretTeamMemberStoreToCassandraWithPaging lh = interpret $ \case - ListTeamMembers tid mps lim ms -> do + ListTeamMembers tid mps lim -> do logEffect "TeamMemberStore.ListTeamMembers" - embedClient $ teamMembersPageFrom lh tid mps lim ms + embedClient $ teamMembersPageFrom lh tid mps lim createTeam :: ( Member (Input ClientState) r, @@ -377,7 +377,7 @@ teamMembersWithLimit lh t (fromRange -> limit) = do -- Maybe should be left explicitly for the caller? teamMembersCollectedWithPagination :: FeatureDefaults LegalholdConfig -> TeamId -> Client [TeamMember] teamMembersCollectedWithPagination lh tid = do - mems <- teamMembersForPagination tid Nothing (unsafeRange 2000) Nothing -- TODO_searchable: pass Nothing (the last argument to the call)? + mems <- teamMembersForPagination tid Nothing (unsafeRange 2000) collectTeamMembersPaginated [] mems where collectTeamMembersPaginated acc mems = do @@ -458,7 +458,7 @@ markTeamDeletedAndRemoveTeamMembers :: TeamId -> Client () markTeamDeletedAndRemoveTeamMembers tid = do -- TODO: delete service_whitelist records that mention this team retry x5 $ write Cql.markTeamDeleted (params LocalQuorum (PendingDelete, tid)) - mems <- teamMembersForPagination tid Nothing (unsafeRange 2000) Nothing -- TODO_searchable: pass Nothing? + mems <- teamMembersForPagination tid Nothing (unsafeRange 2000) removeTeamMembers mems where removeTeamMembers :: @@ -532,30 +532,20 @@ type RawTeamMember = (UserId, Permissions, Maybe UserId, Maybe UTCTimeMillis, Ma -- have a pure function of type RawTeamMember -> TeamMember so we cannot fmap -- over the ResultSet. We don't want to mess around with the Result size -- nextPage either otherwise -teamMembersForPagination :: TeamId -> Maybe UserId -> Range 1 HardTruncationLimit Int32 -> Maybe Bool -> Client (Page RawTeamMember) -teamMembersForPagination tid start (fromRange -> max) ms = +teamMembersForPagination :: TeamId -> Maybe UserId -> Range 1 HardTruncationLimit Int32 -> Client (Page RawTeamMember) +teamMembersForPagination tid start (fromRange -> max) = case start of Just u -> paginate Cql.selectTeamMembersFrom (paramsP LocalQuorum (tid, u) max) - Nothing -> case ms of - Just searchable -> paginate Cql.selectTeamMembersSearchable (paramsP LocalQuorum (tid, searchable) max) - Nothing -> paginate Cql.selectTeamMembers (paramsP LocalQuorum (Identity tid) max) + Nothing -> paginate Cql.selectTeamMembers (paramsP LocalQuorum (Identity tid) max) teamMembersPageFrom :: FeatureDefaults LegalholdConfig -> TeamId -> Maybe PagingState -> Range 1 HardTruncationLimit Int32 -> - Maybe Bool -> Client (PageWithState TeamMember) -teamMembersPageFrom lh tid pagingState (fromRange -> max) ms = do - page <- case ms of - Just searchable -> paginateWithState Cql.selectTeamMembersSearchable (paramsPagingState LocalQuorum (tid, searchable) max pagingState) - -- WIP_searchable: This is what is called from - -- /team/:tid/members?searchable=true. The issue is that this - -- queries the team_members table from cassandra and not the - -- users' table where the searchable field is. Cassandra doesn't - -- seem to support joins, so am currently stomped on how to proceed. - Nothing -> paginateWithState Cql.selectTeamMembers (paramsPagingState LocalQuorum (Identity tid) max pagingState) +teamMembersPageFrom lh tid pagingState (fromRange -> max) = do + page <- paginateWithState Cql.selectTeamMembers (paramsPagingState LocalQuorum (Identity tid) max pagingState) members <- mapM (newTeamMember' lh tid) (pwsResults page) pure $ PageWithState members (pwsState page) diff --git a/services/galley/src/Galley/Effects/TeamMemberStore.hs b/services/galley/src/Galley/Effects/TeamMemberStore.hs index e3a8b45bef..84f2dbca28 100644 --- a/services/galley/src/Galley/Effects/TeamMemberStore.hs +++ b/services/galley/src/Galley/Effects/TeamMemberStore.hs @@ -37,7 +37,6 @@ data TeamMemberStore p m a where TeamId -> Maybe (PagingState p TeamMember) -> PagingBounds p TeamMember -> - Maybe Bool -> TeamMemberStore p m (Page p TeamMember) makeSem ''TeamMemberStore From 201cceae67645825becaf486e0ff7d45938f9a64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Tue, 7 Oct 2025 09:28:36 +0300 Subject: [PATCH 15/30] Add query param to Brig --- .../src/Wire/API/Routes/Public/Brig.hs | 7 + libs/wire-api/src/Wire/API/User/Search.hs | 4 +- .../SearchResult_20TeamContact_user.hs | 168 ++++++++++++------ .../API/Golden/Generated/TeamContact_user.hs | 60 ++++--- .../Wire/IndexedUserStore/ElasticSearch.hs | 20 ++- .../src/Wire/UserSearch/Types.hs | 6 +- services/brig/src/Brig/API/Public.hs | 5 +- .../brig/test/integration/API/User/Account.hs | 15 +- 8 files changed, 188 insertions(+), 97 deletions(-) diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs b/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs index 816aca8ce0..572ab0202f 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs @@ -1743,6 +1743,13 @@ type SearchAPI = ] "email" EmailVerificationFilter + :> QueryParam' + [ Optional, + Strict, + Description "Optional, return only non-seacrhable members when false." + ] + "searchable" + Bool :> MultiVerb 'GET '[JSON] diff --git a/libs/wire-api/src/Wire/API/User/Search.hs b/libs/wire-api/src/Wire/API/User/Search.hs index 0082e11f22..906ebb8438 100644 --- a/libs/wire-api/src/Wire/API/User/Search.hs +++ b/libs/wire-api/src/Wire/API/User/Search.hs @@ -192,7 +192,8 @@ data TeamContact = TeamContact teamContactRole :: Maybe Role, teamContactScimExternalId :: Maybe Text, teamContactSso :: Maybe Sso, - teamContactEmailUnvalidated :: Maybe EmailAddress + teamContactEmailUnvalidated :: Maybe EmailAddress, + teamContactSearchable :: Maybe Bool } deriving stock (Eq, Show, Generic) deriving (Arbitrary) via (GenericUniform TeamContact) @@ -215,6 +216,7 @@ instance ToSchema TeamContact where <*> teamContactScimExternalId .= optField "scim_external_id" (maybeWithDefault Aeson.Null schema) <*> teamContactSso .= optField "sso" (maybeWithDefault Aeson.Null schema) <*> teamContactEmailUnvalidated .= optField "email_unvalidated" (maybeWithDefault Aeson.Null schema) + <*> teamContactSearchable .= optField "searchable" (maybeWithDefault Aeson.Null schema) data TeamUserSearchSortBy = SortByName diff --git a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/SearchResult_20TeamContact_user.hs b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/SearchResult_20TeamContact_user.hs index 56887040f6..0508b56106 100644 --- a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/SearchResult_20TeamContact_user.hs +++ b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/SearchResult_20TeamContact_user.hs @@ -47,7 +47,8 @@ testObject_SearchResult_20TeamContact_user_1 = teamContactRole = Just RoleAdmin, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000000")), @@ -62,7 +63,8 @@ testObject_SearchResult_20TeamContact_user_1 = teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } ], searchPolicy = FullSearch, @@ -102,7 +104,8 @@ testObject_SearchResult_20TeamContact_user_3 = teamContactRole = Just RoleAdmin, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001")), @@ -117,7 +120,8 @@ testObject_SearchResult_20TeamContact_user_3 = teamContactRole = Nothing, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000000000000")), @@ -132,7 +136,8 @@ testObject_SearchResult_20TeamContact_user_3 = teamContactRole = Nothing, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } ], searchPolicy = FullSearch, @@ -160,7 +165,8 @@ testObject_SearchResult_20TeamContact_user_4 = teamContactRole = Just RoleOwner, teamContactScimExternalId = Nothing, teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001")), @@ -175,7 +181,8 @@ testObject_SearchResult_20TeamContact_user_4 = teamContactRole = Just RoleAdmin, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001")), @@ -190,7 +197,8 @@ testObject_SearchResult_20TeamContact_user_4 = teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000000")), @@ -205,7 +213,8 @@ testObject_SearchResult_20TeamContact_user_4 = teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } ], searchPolicy = ExactHandleSearch, @@ -233,7 +242,8 @@ testObject_SearchResult_20TeamContact_user_5 = teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } ], searchPolicy = FullSearch, @@ -261,7 +271,8 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactRole = Just RoleOwner, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000001")), @@ -276,7 +287,8 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactRole = Just RoleOwner, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000001")), @@ -291,7 +303,8 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactRole = Nothing, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000000")), @@ -306,7 +319,8 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactRole = Just RoleOwner, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000000000001")), @@ -321,7 +335,8 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactRole = Nothing, teamContactScimExternalId = Nothing, teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000001")), @@ -336,7 +351,8 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactRole = Just RoleMember, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001")), @@ -351,7 +367,8 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactRole = Just RoleAdmin, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000000")), @@ -366,7 +383,8 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactRole = Nothing, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000000")), @@ -381,7 +399,8 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000001")), @@ -396,7 +415,8 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactRole = Just RoleOwner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000001")), @@ -411,7 +431,8 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactRole = Just RoleMember, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000000")), @@ -426,7 +447,8 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000001")), @@ -441,7 +463,8 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } ], searchPolicy = FullSearch, @@ -469,7 +492,8 @@ testObject_SearchResult_20TeamContact_user_7 = teamContactRole = Nothing, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000000")), @@ -484,7 +508,8 @@ testObject_SearchResult_20TeamContact_user_7 = teamContactRole = Just RoleMember, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000000")), @@ -499,7 +524,8 @@ testObject_SearchResult_20TeamContact_user_7 = teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000001")), @@ -514,7 +540,8 @@ testObject_SearchResult_20TeamContact_user_7 = teamContactRole = Nothing, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001")), @@ -529,7 +556,8 @@ testObject_SearchResult_20TeamContact_user_7 = teamContactRole = Just RoleMember, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000001")), @@ -544,7 +572,8 @@ testObject_SearchResult_20TeamContact_user_7 = teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Nothing, teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } ], searchPolicy = FullSearch, @@ -572,7 +601,8 @@ testObject_SearchResult_20TeamContact_user_8 = teamContactRole = Just RoleOwner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000000")), @@ -587,7 +617,8 @@ testObject_SearchResult_20TeamContact_user_8 = teamContactRole = Just RoleOwner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000000")), @@ -602,7 +633,8 @@ testObject_SearchResult_20TeamContact_user_8 = teamContactRole = Nothing, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000000000000")), @@ -617,7 +649,8 @@ testObject_SearchResult_20TeamContact_user_8 = teamContactRole = Nothing, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } ], searchPolicy = FullSearch, @@ -645,7 +678,8 @@ testObject_SearchResult_20TeamContact_user_9 = teamContactRole = Just RoleMember, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000001")), @@ -660,7 +694,8 @@ testObject_SearchResult_20TeamContact_user_9 = teamContactRole = Nothing, teamContactScimExternalId = Nothing, teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001")), @@ -675,7 +710,8 @@ testObject_SearchResult_20TeamContact_user_9 = teamContactRole = Just RoleMember, teamContactScimExternalId = Nothing, teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000000000001")), @@ -690,7 +726,8 @@ testObject_SearchResult_20TeamContact_user_9 = teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } ], searchPolicy = FullSearch, @@ -730,7 +767,8 @@ testObject_SearchResult_20TeamContact_user_11 = teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000001")), @@ -745,7 +783,8 @@ testObject_SearchResult_20TeamContact_user_11 = teamContactRole = Just RoleOwner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000000")), @@ -760,7 +799,8 @@ testObject_SearchResult_20TeamContact_user_11 = teamContactRole = Just RoleAdmin, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000000")), @@ -775,7 +815,8 @@ testObject_SearchResult_20TeamContact_user_11 = teamContactRole = Nothing, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000000")), @@ -790,7 +831,8 @@ testObject_SearchResult_20TeamContact_user_11 = teamContactRole = Nothing, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000001")), @@ -805,7 +847,8 @@ testObject_SearchResult_20TeamContact_user_11 = teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001")), @@ -820,7 +863,8 @@ testObject_SearchResult_20TeamContact_user_11 = teamContactRole = Just RoleOwner, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000001")), @@ -835,7 +879,8 @@ testObject_SearchResult_20TeamContact_user_11 = teamContactRole = Nothing, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } ], searchPolicy = FullSearch, @@ -863,7 +908,8 @@ testObject_SearchResult_20TeamContact_user_12 = teamContactRole = Nothing, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } ], searchPolicy = FullSearch, @@ -891,7 +937,8 @@ testObject_SearchResult_20TeamContact_user_13 = teamContactRole = Just RoleMember, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000001")), @@ -906,7 +953,8 @@ testObject_SearchResult_20TeamContact_user_13 = teamContactRole = Just RoleMember, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000001")), @@ -921,7 +969,8 @@ testObject_SearchResult_20TeamContact_user_13 = teamContactRole = Nothing, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } ], searchPolicy = FullSearch, @@ -949,7 +998,8 @@ testObject_SearchResult_20TeamContact_user_14 = teamContactRole = Just RoleAdmin, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } ], searchPolicy = FullSearch, @@ -977,7 +1027,8 @@ testObject_SearchResult_20TeamContact_user_15 = teamContactRole = Just RoleOwner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } ], searchPolicy = FullSearch, @@ -1005,7 +1056,8 @@ testObject_SearchResult_20TeamContact_user_16 = teamContactRole = Just RoleAdmin, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000000")), @@ -1020,7 +1072,8 @@ testObject_SearchResult_20TeamContact_user_16 = teamContactRole = Just RoleAdmin, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000000")), @@ -1035,7 +1088,8 @@ testObject_SearchResult_20TeamContact_user_16 = teamContactRole = Just RoleAdmin, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } ], searchPolicy = FullSearch, @@ -1063,7 +1117,8 @@ testObject_SearchResult_20TeamContact_user_17 = teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } ], searchPolicy = FullSearch, @@ -1091,7 +1146,8 @@ testObject_SearchResult_20TeamContact_user_18 = teamContactRole = Just RoleOwner, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } ], searchPolicy = FullSearch, diff --git a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/TeamContact_user.hs b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/TeamContact_user.hs index 4171affd0c..90eb99974f 100644 --- a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/TeamContact_user.hs +++ b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/TeamContact_user.hs @@ -40,7 +40,8 @@ testObject_TeamContact_user_1 = teamContactRole = Just RoleAdmin, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } testObject_TeamContact_user_2 :: TeamContact @@ -58,7 +59,8 @@ testObject_TeamContact_user_2 = teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } testObject_TeamContact_user_3 :: TeamContact @@ -76,7 +78,8 @@ testObject_TeamContact_user_3 = teamContactRole = Just RoleMember, teamContactScimExternalId = Nothing, teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } testObject_TeamContact_user_4 :: TeamContact @@ -94,7 +97,8 @@ testObject_TeamContact_user_4 = teamContactRole = Nothing, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), + teamContactSearchable = Nothing } testObject_TeamContact_user_5 :: TeamContact @@ -112,7 +116,8 @@ testObject_TeamContact_user_5 = teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } testObject_TeamContact_user_6 :: TeamContact @@ -130,7 +135,8 @@ testObject_TeamContact_user_6 = teamContactRole = Nothing, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } testObject_TeamContact_user_7 :: TeamContact @@ -148,7 +154,8 @@ testObject_TeamContact_user_7 = teamContactRole = Just RoleAdmin, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), + teamContactSearchable = Nothing } testObject_TeamContact_user_8 :: TeamContact @@ -166,7 +173,8 @@ testObject_TeamContact_user_8 = teamContactRole = Just RoleMember, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } testObject_TeamContact_user_9 :: TeamContact @@ -184,7 +192,8 @@ testObject_TeamContact_user_9 = teamContactRole = Just RoleAdmin, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } testObject_TeamContact_user_10 :: TeamContact @@ -202,7 +211,8 @@ testObject_TeamContact_user_10 = teamContactRole = Just RoleMember, teamContactScimExternalId = Nothing, teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } testObject_TeamContact_user_11 :: TeamContact @@ -220,7 +230,8 @@ testObject_TeamContact_user_11 = teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } testObject_TeamContact_user_12 :: TeamContact @@ -238,7 +249,8 @@ testObject_TeamContact_user_12 = teamContactRole = Nothing, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } testObject_TeamContact_user_13 :: TeamContact @@ -256,7 +268,8 @@ testObject_TeamContact_user_13 = teamContactRole = Just RoleMember, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } testObject_TeamContact_user_14 :: TeamContact @@ -274,7 +287,8 @@ testObject_TeamContact_user_14 = teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } testObject_TeamContact_user_15 :: TeamContact @@ -292,7 +306,8 @@ testObject_TeamContact_user_15 = teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Nothing, teamContactSso = Nothing, - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), + teamContactSearchable = Nothing } testObject_TeamContact_user_16 :: TeamContact @@ -310,7 +325,8 @@ testObject_TeamContact_user_16 = teamContactRole = Nothing, teamContactScimExternalId = Nothing, teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), + teamContactSearchable = Nothing } testObject_TeamContact_user_17 :: TeamContact @@ -328,7 +344,8 @@ testObject_TeamContact_user_17 = teamContactRole = Just RoleOwner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } testObject_TeamContact_user_18 :: TeamContact @@ -346,7 +363,8 @@ testObject_TeamContact_user_18 = teamContactRole = Just RoleOwner, teamContactScimExternalId = Nothing, teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } testObject_TeamContact_user_19 :: TeamContact @@ -364,7 +382,8 @@ testObject_TeamContact_user_19 = teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Nothing, teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = Nothing } testObject_TeamContact_user_20 :: TeamContact @@ -382,5 +401,6 @@ testObject_TeamContact_user_20 = teamContactRole = Just RoleOwner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), + teamContactSearchable = Nothing } diff --git a/libs/wire-subsystems/src/Wire/IndexedUserStore/ElasticSearch.hs b/libs/wire-subsystems/src/Wire/IndexedUserStore/ElasticSearch.hs index de5438416d..e6249d4ed3 100644 --- a/libs/wire-subsystems/src/Wire/IndexedUserStore/ElasticSearch.hs +++ b/libs/wire-subsystems/src/Wire/IndexedUserStore/ElasticSearch.hs @@ -246,7 +246,7 @@ paginateTeamMembersImpl :: Sem r (SearchResult UserDoc) paginateTeamMembersImpl cfg BrowseTeamFilters {..} maxResults mPagingState = do let (IndexQuery q f sortSpecs) = - teamUserSearchQuery teamId mQuery mRoleFilter mSortBy mSortOrder mEmailVerificationFilter + teamUserSearchQuery teamId mQuery mRoleFilter mSortBy mSortOrder mEmailVerificationFilter mSearchable let search = (ES.mkSearch (Just q) (Just f)) { -- we are requesting one more result than the page size to determine if there is a next page @@ -312,8 +312,9 @@ teamUserSearchQuery :: Maybe TeamUserSearchSortBy -> Maybe TeamUserSearchSortOrder -> Maybe EmailVerificationFilter -> + Maybe Bool -> IndexQuery TeamContact -teamUserSearchQuery tid mbSearchText mRoleFilter mSortBy mSortOrder mEmailFilter = +teamUserSearchQuery tid mbSearchText mRoleFilter mSortBy mSortOrder mEmailFilter mSearchable = IndexQuery ( maybe (ES.MatchAllQuery Nothing) @@ -365,13 +366,16 @@ teamUserSearchQuery tid mbSearchText mRoleFilter mSortBy mSortOrder mEmailFilter } teamFilter :: ES.Filter - teamFilter = - ES.Filter $ - ES.QueryBoolQuery - boolQuery - { ES.boolQueryMustMatch = ES.TermQuery (ES.Term "team" $ idToText tid) Nothing : roleFilter <> emailFilter - } + teamFilter = ES.Filter $ ES.QueryBoolQuery boolQuery { ES.boolQueryMustMatch = mustMatch } where + mustMatch :: [ES.Query] + mustMatch = ES.TermQuery (ES.Term "team" $ idToText tid) Nothing : roleFilter <> emailFilter <> searchableFilter + + searchableFilter :: [ES.Query] + searchableFilter = case mSearchable of + Just b -> [ES.TermQuery (ES.Term "searchable" $ bool "false" "true" b) Nothing] + Nothing -> [] + roleFilter :: [ES.Query] roleFilter = case mRoleFilter of diff --git a/libs/wire-subsystems/src/Wire/UserSearch/Types.hs b/libs/wire-subsystems/src/Wire/UserSearch/Types.hs index 6e65a92695..fe6f6b3f7d 100644 --- a/libs/wire-subsystems/src/Wire/UserSearch/Types.hs +++ b/libs/wire-subsystems/src/Wire/UserSearch/Types.hs @@ -125,7 +125,8 @@ userDocToTeamContact UserDoc {..} = teamContactEmailUnvalidated = udEmailUnvalidated, teamContactEmail = udEmail, teamContactCreatedAt = udCreatedAt, - teamContactColorId = fromIntegral . fromColourId <$> udColourId + teamContactColorId = fromIntegral . fromColourId <$> udColourId, + teamContactSearchable = udSearchable } -- | Outbound search restrictions configured by team admin of the searcher. This @@ -204,7 +205,8 @@ data BrowseTeamFilters = BrowseTeamFilters mRoleFilter :: Maybe RoleFilter, mSortBy :: Maybe TeamUserSearchSortBy, mSortOrder :: Maybe TeamUserSearchSortOrder, - mEmailVerificationFilter :: Maybe EmailVerificationFilter + mEmailVerificationFilter :: Maybe EmailVerificationFilter, + mSearchable :: Maybe Bool } deriving (Eq, Show) diff --git a/services/brig/src/Brig/API/Public.hs b/services/brig/src/Brig/API/Public.hs index 03a149d1de..b6f0343c12 100644 --- a/services/brig/src/Brig/API/Public.hs +++ b/services/brig/src/Brig/API/Public.hs @@ -648,9 +648,10 @@ browseTeamHandler :: Maybe (Range 1 500 Int) -> Maybe Public.PagingState -> Maybe EmailVerificationFilter -> + Maybe Bool -> Handler r (Public.SearchResult Public.TeamContact) -browseTeamHandler uid tid mQuery mRoleFilter mTeamUserSearchSortBy mTeamUserSearchSortOrder mMaxResults mPagingState mEmailFilter = do - let browseTeamFilters = BrowseTeamFilters tid mQuery mRoleFilter mTeamUserSearchSortBy mTeamUserSearchSortOrder mEmailFilter +browseTeamHandler uid tid mQuery mRoleFilter mTeamUserSearchSortBy mTeamUserSearchSortOrder mMaxResults mPagingState mEmailFilter mSearchable = do + let browseTeamFilters = BrowseTeamFilters tid mQuery mRoleFilter mTeamUserSearchSortBy mTeamUserSearchSortOrder mEmailFilter mSearchable lift . liftSem $ User.browseTeam uid browseTeamFilters mMaxResults mPagingState setPropertyH :: (Member PropertySubsystem r) => UserId -> ConnId -> Public.PropertyKey -> Public.RawPropertyValue -> Handler r () diff --git a/services/brig/test/integration/API/User/Account.hs b/services/brig/test/integration/API/User/Account.hs index 9f1c35b053..13e7f4e27a 100644 --- a/services/brig/test/integration/API/User/Account.hs +++ b/services/brig/test/integration/API/User/Account.hs @@ -719,15 +719,14 @@ testUserSearchable brig galley = do uids = map (^. Team.Member.userId) teamMembers liftIO $ assertBool "/teams/:tid/members returns searchable and non-searchable users from team" $ all (`elem` uids) $ u1id : map userId [u3, u4] - -- /teams/:tid/members?searchable=false gets only non-searchable members - r :: Team.Member.TeamMembersPage <- parseOrFail "TeamMembersPage" $ - get ( galley - . paths ["teams", toByteString' tid, "members"] + -- /teams/:tid/search?searchable=false gets only non-searchable members + r :: SearchResult TeamContact <- parseOrFail "SearchResult TeamContact" $ + get ( brig + . paths ["teams", toByteString' tid, "search"] . queryItem "searchable" "false" - . zUser u1id) UserId From 842e955e6521bbb025f0d5c64c6f2c4396f74250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Wed, 8 Oct 2025 09:20:50 +0300 Subject: [PATCH 16/30] Update services/brig/src/Brig/Provider/API.hs Co-authored-by: Akshay Mankar --- services/brig/src/Brig/Provider/API.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/brig/src/Brig/Provider/API.hs b/services/brig/src/Brig/Provider/API.hs index 70864ca180..10285f1306 100644 --- a/services/brig/src/Brig/Provider/API.hs +++ b/services/brig/src/Brig/Provider/API.hs @@ -832,7 +832,7 @@ addBot zuid zcon cid add = do teamId = Nothing, managedBy = ManagedByWire, supportedProtocols = defSupportedProtocols, - searchable = True -- TODO: what is the default for bots? + searchable = True } let newClt = From fa7beb8471e3393aec102ad113801f1bff1c4695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Wed, 8 Oct 2025 09:21:29 +0300 Subject: [PATCH 17/30] Update libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs Co-authored-by: Akshay Mankar --- libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs b/libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs index 253332ddc5..6661358862 100644 --- a/libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs +++ b/libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs @@ -1138,5 +1138,4 @@ setUserSearchableImpl :: setUserSearchableImpl luid uid tid searchable = do ensurePermissions (tUnqualified luid) tid [Permission.SetMemberSearchable] UserStore.setUserSearchable uid searchable - -- TODO generate an event? syncUserIndex uid From f1ff0ebd706293615862b8a423e01ab9dba00724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Wed, 8 Oct 2025 11:34:29 +0300 Subject: [PATCH 18/30] fixup! Add `POST /users/:uid/searchable` --- libs/wire-api/src/Wire/API/Routes/Public/Brig.hs | 1 - libs/wire-subsystems/src/Wire/UserSubsystem.hs | 2 +- libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs | 6 +++--- services/brig/src/Brig/API/Public.hs | 3 +-- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs b/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs index 572ab0202f..29927468a7 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs @@ -297,7 +297,6 @@ type UserAPI = :> ZLocalUser :> "users" :> CaptureUserId "uid" - :> Capture "tid" TeamId :> ReqBody '[JSON] Bool :> "searchable" :> Post '[JSON] () diff --git a/libs/wire-subsystems/src/Wire/UserSubsystem.hs b/libs/wire-subsystems/src/Wire/UserSubsystem.hs index 9a4a3a8619..6de770e73d 100644 --- a/libs/wire-subsystems/src/Wire/UserSubsystem.hs +++ b/libs/wire-subsystems/src/Wire/UserSubsystem.hs @@ -179,7 +179,7 @@ data UserSubsystem m a where RemoveEmailEither :: Local UserId -> UserSubsystem m (Either UserSubsystemError ()) GetUserTeam :: UserId -> UserSubsystem m (Maybe TeamId) CheckUserIsAdmin :: UserId -> UserSubsystem m TeamId - SetUserSearchable :: Local UserId -> UserId -> TeamId -> Bool -> UserSubsystem m () + SetUserSearchable :: Local UserId -> UserId -> Bool -> UserSubsystem m () -- | the return type of 'CheckHandle' data CheckHandleResp diff --git a/libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs b/libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs index 6661358862..ccb57b0a54 100644 --- a/libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs +++ b/libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs @@ -165,7 +165,7 @@ runUserSubsystem authInterpreter = interpret $ RemoveEmailEither luid -> removeEmailEitherImpl luid UserSubsystem.GetUserTeam uid -> getUserTeamImpl uid CheckUserIsAdmin uid -> checkUserIsAdminImpl uid - UserSubsystem.SetUserSearchable luid uid tid searchability -> setUserSearchableImpl luid uid tid searchability + UserSubsystem.SetUserSearchable luid uid searchability -> setUserSearchableImpl luid uid searchability scimExtId :: StoredUser -> Maybe Text scimExtId su = do @@ -1132,10 +1132,10 @@ setUserSearchableImpl :: ) => Local UserId -> UserId -> - TeamId -> Bool -> Sem r () -setUserSearchableImpl luid uid tid searchable = do +setUserSearchableImpl luid uid searchable = do + tid <- maybe (throw UserSubsystemInsufficientPermissions) pure =<< UserStore.getUserTeam uid ensurePermissions (tUnqualified luid) tid [Permission.SetMemberSearchable] UserStore.setUserSearchable uid searchable syncUserIndex uid diff --git a/services/brig/src/Brig/API/Public.hs b/services/brig/src/Brig/API/Public.hs index b6f0343c12..8f699f12a2 100644 --- a/services/brig/src/Brig/API/Public.hs +++ b/services/brig/src/Brig/API/Public.hs @@ -863,10 +863,9 @@ setUserSearchableH :: (Member UserSubsystem r) => Local UserId -> UserId -> - TeamId -> Bool -> Handler r () -setUserSearchableH zusr uid tid searchable = lift $ liftSem $ User.setUserSearchable zusr uid tid searchable +setUserSearchableH zusr uid searchable = lift $ liftSem $ User.setUserSearchable zusr uid searchable getClientPrekeys :: UserId -> ClientId -> (Handler r) [Public.PrekeyId] getClientPrekeys usr clt = lift (wrapClient $ API.lookupPrekeyIds usr clt) From 221c23ce555db68ed123a4b14865928661dc71c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Wed, 8 Oct 2025 11:35:12 +0300 Subject: [PATCH 19/30] fixup! Test searchable field and contact search --- services/brig/test/integration/API/User/Account.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/brig/test/integration/API/User/Account.hs b/services/brig/test/integration/API/User/Account.hs index 13e7f4e27a..b35f46708c 100644 --- a/services/brig/test/integration/API/User/Account.hs +++ b/services/brig/test/integration/API/User/Account.hs @@ -660,7 +660,7 @@ testUserSearchable brig galley = do setSearchable :: UserId -> UserId -> Bool -> Request -> Request setSearchable byZuid uid searchable = brig - . paths ["users", pack $ show uid, pack $ show tid, "searchable"] + . paths ["users", pack $ show uid, "searchable"] . zUser byZuid . toJsonBody searchable From 33a1956762ba02ce17dd9a783c94028ede71d1eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Wed, 8 Oct 2025 16:02:12 +0300 Subject: [PATCH 20/30] fixup! Add `POST /users/:uid/searchable` Make SetMemberSearchable from Perm to HiddenPerm. --- libs/wire-api/src/Wire/API/Team/Member.hs | 7 ++++--- libs/wire-api/src/Wire/API/Team/Permission.hs | 3 --- libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs | 2 +- services/brig/src/Brig/API/Public.hs | 1 - 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/libs/wire-api/src/Wire/API/Team/Member.hs b/libs/wire-api/src/Wire/API/Team/Member.hs index d56daf960d..bc6f339fd2 100644 --- a/libs/wire-api/src/Wire/API/Team/Member.hs +++ b/libs/wire-api/src/Wire/API/Team/Member.hs @@ -483,6 +483,7 @@ data HiddenPerm | CreateApp | ManageApps | RemoveTeamCollaborator + | SetMemberSearchable deriving (Eq, Ord, Show) -- | See Note [hidden team roles] @@ -533,8 +534,7 @@ rolePerms RoleAdmin = [ AddTeamMember, RemoveTeamMember, SetTeamData, - SetMemberPermissions, - SetMemberSearchable + SetMemberPermissions ] rolePerms RoleMember = rolePerms RoleExternalPartner @@ -571,7 +571,8 @@ roleHiddenPermissions role = HiddenPermissions p p NewTeamCollaborator, CreateApp, ManageApps, - RemoveTeamCollaborator + RemoveTeamCollaborator, + SetMemberSearchable ] roleHiddenPerms RoleMember = (roleHiddenPerms RoleExternalPartner <>) $ diff --git a/libs/wire-api/src/Wire/API/Team/Permission.hs b/libs/wire-api/src/Wire/API/Team/Permission.hs index a85c8a3625..974ef98926 100644 --- a/libs/wire-api/src/Wire/API/Team/Permission.hs +++ b/libs/wire-api/src/Wire/API/Team/Permission.hs @@ -154,7 +154,6 @@ data Perm | SetMemberPermissions | GetTeamConversations | DeleteTeam - | SetMemberSearchable -- FUTUREWORK: make the verbs in the roles more consistent -- (CRUD vs. Add,Remove vs; Get,Set vs. Create,Delete etc). deriving stock (Eq, Ord, Show, Enum, Bounded, Generic) @@ -185,7 +184,6 @@ permToInt GetMemberPermissions = 0x0200 permToInt GetTeamConversations = 0x0400 permToInt DeleteTeam = 0x0800 permToInt SetMemberPermissions = 0x1000 -permToInt SetMemberSearchable = 0x2000 intToPerm :: Word64 -> Maybe Perm intToPerm 0x0001 = Just CreateConversation @@ -201,7 +199,6 @@ intToPerm 0x0200 = Just GetMemberPermissions intToPerm 0x0400 = Just GetTeamConversations intToPerm 0x0800 = Just DeleteTeam intToPerm 0x1000 = Just SetMemberPermissions -intToPerm 0x2000 = Just SetMemberSearchable intToPerm _ = Nothing instance Cql.Cql Permissions where diff --git a/libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs b/libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs index ccb57b0a54..75b5e939c9 100644 --- a/libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs +++ b/libs/wire-subsystems/src/Wire/UserSubsystem/Interpreter.hs @@ -1136,6 +1136,6 @@ setUserSearchableImpl :: Sem r () setUserSearchableImpl luid uid searchable = do tid <- maybe (throw UserSubsystemInsufficientPermissions) pure =<< UserStore.getUserTeam uid - ensurePermissions (tUnqualified luid) tid [Permission.SetMemberSearchable] + ensurePermissions (tUnqualified luid) tid [SetMemberSearchable] UserStore.setUserSearchable uid searchable syncUserIndex uid diff --git a/services/brig/src/Brig/API/Public.hs b/services/brig/src/Brig/API/Public.hs index 8f699f12a2..a6bb217212 100644 --- a/services/brig/src/Brig/API/Public.hs +++ b/services/brig/src/Brig/API/Public.hs @@ -143,7 +143,6 @@ import Wire.API.SystemSettings import Wire.API.Team qualified as Public import Wire.API.Team.LegalHold (LegalholdProtectee (..)) import Wire.API.Team.Member (HiddenPerm (..), IsPerm (..), TeamMember, hasPermission) -import Wire.API.Team.Permission (Perm (SetMemberSearchable)) import Wire.API.User (RegisterError (RegisterErrorAllowlistError)) import Wire.API.User qualified as Public import Wire.API.User.Activation qualified as Public From 6700261e5884b351729b161380edf83ab6eb5990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Wed, 8 Oct 2025 18:24:01 +0300 Subject: [PATCH 21/30] Move test from brig to integration package --- integration/test/Test/Search.hs | 99 +++++++++++++++++ .../brig/test/integration/API/User/Account.hs | 103 ------------------ 2 files changed, 99 insertions(+), 103 deletions(-) diff --git a/integration/test/Test/Search.hs b/integration/test/Test/Search.hs index 3e83ca1348..2189c88a64 100644 --- a/integration/test/Test/Search.hs +++ b/integration/test/Test/Search.hs @@ -335,3 +335,102 @@ testTeamSearchEmailFilter = do ownerId <- objId owner memberId <- objId mem uids `shouldMatchSet` [ownerId, memberId] + +withFoundDocs :: + (MakesValue user, MakesValue searchTerm) => + user -> + searchTerm -> + ([Value] -> App a) -> + App a +withFoundDocs self term f = do + BrigP.searchContacts self term OwnDomain `bindResponse` \resp -> do + resp.status `shouldMatchInt` 200 + docs <- resp.json %. "documents" >>= asList + f docs + +testUserSearchable :: App () +testUserSearchable = do + (owner, tid, []) <- createTeam OwnDomain 1 + + let -- Helper to change user searchability. + setSearchable self uid searchable = do + req <- baseRequest self Brig Versioned $ joinHttpPath ["users", uid, "searchable"] + submit "POST" $ addJSON searchable req + + -- Create user in team, default is searchable = True. + u1 <- createTeamMember owner def + assertBool "created users are searchable by default" =<< (u1 %. "searchable" & asBool) + + -- Setting self to non-searchable won't work -- only admin can do it. + u1id <- u1 %. "id" & asString + setSearchable u1id u1id False `bindResponse` \resp -> do + resp.status `shouldMatchInt` 403 + resp.json %. "label" `shouldMatch` "insufficient-permissions" + + u1' <- BrigP.getUser u1 u1 >>= getJSON 200 + assertBool "Searchable is still True" =<< (u1' %. "searchable" & asBool) + + -- Team admin can set user to non-searchable. + admin <- createTeamMember owner def {role = "admin"} + setSearchable admin u1id False `bindResponse` \resp -> resp.status `shouldMatchInt` 200 + u1'' <- BrigP.getUser u1 u1 >>= getJSON 200 + assertBool "Searchable is now False" =<< (u1'' %. "searchable" & asBool) + + -- Team owner can, too. + setSearchable owner u1id True `bindResponse` \resp -> resp.status `shouldMatchInt` 200 + setSearchable owner u1id False `bindResponse` \resp -> resp.status `shouldMatchInt` 200 + + -- By default created team members are found. + u3 <- createTeamMember owner def + BrigI.refreshIndex OwnDomain + withFoundDocs u1 (u3 %. "name") $ \docs -> do + foundUids <- for docs objId + assertBool "u1 must find u3 as they are searchable by default" $ u1id `elem` foundUids + + -- User set to non-searchable is not found by other team members. + u4 <- createTeamMember owner def + u4id <- u4 %. "id" & asString + setSearchable owner u4id False `bindResponse` \resp -> resp.status `shouldMatchInt` 200 + BrigI.refreshIndex OwnDomain + withFoundDocs u1 (u4 %. "name") $ \docs -> do + foundUids <- for docs objId + assertBool "u1 must not find u4 as they are set non-searchable" $ notElem u4id foundUids + + -- Even admin nor owner won't find non-searchable users via /search/contacts + withFoundDocs admin (u4 %. "name") $ \docs -> do + foundUids <- for docs objId + assertBool "Team admin won't find non-searchable user" $ notElem u4id foundUids + withFoundDocs owner (u4 %. "name") $ \docs -> do + foundUids <- for docs objId + assertBool "Team owner won't find non-searchable user from /search/concatcs" $ notElem u4id foundUids + + -- Exact handle search with HTTP HEAD still works for non-searchable users + u4handle <- API.randomHandle + bindResponse (BrigP.putHandle u4 u4handle) assertSuccess + req <- baseRequest u3 Brig Versioned $ joinHttpPath ["handles", u4handle] + submit "HEAD" req `bindResponse` \resp -> resp.status `shouldMatchInt` 200 + + -- Regular user can't find non-searchable team member by exact handle. + withFoundDocs u1 u4handle $ \docs -> do + foundUids <- for docs objId + assertBool "u1 must not find non-searchable u4 by exact handle" $ notElem u4id foundUids + + -- /teams/:tid/members gets all members, both searchable and non-searchable + req <- baseRequest u1 Galley Versioned $ joinHttpPath ["teams", tid, "members"] + submit "GET" req `bindResponse` \resp -> do + resp.status `shouldMatchInt` 200 + docs <- resp.json %. "documents" >>= asList + foundUids <- for docs objId -- todo + u3id <- u3 %. "id" & asString + assertBool "/teams/:tid/members returns searchable and non-searchable users from team" $ all (`elem` foundUids) $ [u1id, u3id, u4id] + + -- /teams/:tid/search?searchable=false gets only non-searchable members + req <- baseRequest admin Brig Versioned $ joinHttpPath ["teams", tid, "search"] + let req' = addQueryParams [("searchable", "false")] + submit "GET" req `bindResponse` \resp -> do + resp.status `shouldMatchInt` 200 + docs <- resp.json %. "documents" >>= asList + foundUids <- for docs objId -- todo + assertBool "/teams/:tid/members?searchable=false returns only non-searchable members" $ all (`elem` foundUids) [u1id, u4id] + + pure () diff --git a/services/brig/test/integration/API/User/Account.hs b/services/brig/test/integration/API/User/Account.hs index b35f46708c..879bc30549 100644 --- a/services/brig/test/integration/API/User/Account.hs +++ b/services/brig/test/integration/API/User/Account.hs @@ -87,16 +87,12 @@ import Wire.API.Conversation import Wire.API.Routes.MultiTablePaging import Wire.API.Team.Feature import Wire.API.Team.Invitation -import Wire.API.Team.Member (rolePermissions) -import Wire.API.Team.Member qualified as Team.Member import Wire.API.Team.Permission hiding (self) -import Wire.API.Team.Role import Wire.API.User import Wire.API.User.Activation import Wire.API.User.Auth import Wire.API.User.Auth qualified as Auth import Wire.API.User.Client -import Wire.API.User.Search tests :: ConnectionLimit -> Timeout -> Opt.Opts -> Manager -> Brig -> Cannon -> CargoHold -> Galley -> AWS.Env -> UserJournalWatcher -> TestTree tests _ at opts p b c ch g aws userJournalWatcher = @@ -121,7 +117,6 @@ tests _ at opts p b c ch g aws userJournalWatcher = test p "get /users//:uid - 404" $ testNonExistingUser b, test p "get /users/:domain/:uid - 422" $ testUserInvalidDomain b, test p "get /users/:uid - 200" $ testExistingUserUnqualified b, - test p "testUserSearchable" $ testUserSearchable b g, test p "get /users//:uid - 200" $ testExistingUser b, test p "get /users?:id=.... - 200" $ testMultipleUsersUnqualified b, test p "head /users/:uid - 200" $ testUserExistsUnqualified b, @@ -646,97 +641,6 @@ testExistingUserUnqualified brig = do b ^? key "id" >>= maybeFromJSON ) -testUserSearchable :: Brig -> Galley -> Http () -testUserSearchable brig galley = do - (owner, tid) <- createUserWithTeam brig - - -- Make a member in the current team - let mkTeamMember :: Permissions -> Http User - mkTeamMember perms = do - member <- createTeamMember brig galley owner tid perms - selfUser <$> (responseJsonError =<< get (brig . path "/self" . zUser (userId member))) - - -- Helper to change user searchability. - setSearchable :: UserId -> UserId -> Bool -> Request -> Request - setSearchable byZuid uid searchable = - brig - . paths ["users", pack $ show uid, "searchable"] - . zUser byZuid - . toJsonBody searchable - - -- Create user in team, default is searchable = True. - u1id <- userId <$> mkTeamMember (rolePermissions RoleMember) - u1p <- parseOrFail "UserProfile" (getProfile brig owner u1id) - liftIO $ assertBool "created users are searchable by default" $ profileSearchable u1p - - -- Setting self to non-searchable won't work -- only admin can do it. - post (setSearchable u1id u1id False) !!! do - const 403 === statusCode - const (Just "insufficient-permissions") === fmap Error.label . responseJsonMaybe - liftIO . assertBool "Searchable is still True" . profileSearchable =<< parseOrFail "UserProfile" (getProfile brig owner u1id) - - -- Team admin can set user to non-searchable. - admin <- userId <$> mkTeamMember (rolePermissions RoleAdmin) - post (setSearchable admin u1id False) !!! const 200 === statusCode - liftIO . assertBool "Searchable is now False" . not . profileSearchable =<< parseOrFail "UserProfile" (getProfile brig owner u1id) - - -- Team owner can, too. - post (setSearchable owner u1id True) !!! const 200 === statusCode - post (setSearchable owner u1id False) !!! const 200 === statusCode - - -- By default created team members are found. - u3 <- mkTeamMember (rolePermissions RoleMember) - Search.refreshIndex brig - s <- Search.executeSearch brig u1id $ fromName $ userDisplayName u3 - liftIO $ assertBool "u1 must find u3 as they are searchable by default" $ uidsInResult [userId u3] s - - -- Use set to non-searchable is not found by other team members. - u4 <- mkTeamMember (rolePermissions RoleMember) - post (setSearchable owner (userId u4) False) !!! const 200 === statusCode - Search.refreshIndex brig - s <- Search.executeSearch brig u1id $ fromName $ userDisplayName u4 - liftIO $ assertBool "u1 must not find u4 as they are set non-searchable" $ not $ uidsInResult [userId u4] s - - -- Even admin nor owner won't find non-searchable users via /search/contacts - sAdmin <- Search.executeSearch brig admin $ fromName $ userDisplayName u4 - liftIO $ assertBool "Team admin won't find non-searchable user from /search/concatcs" $ not $ uidsInResult [userId u4] sAdmin - sOwner <- Search.executeSearch brig owner $ fromName $ userDisplayName u4 - liftIO $ assertBool "Team owner won't find non-searchable user from /search/concatcs" $ not $ uidsInResult [userId u4] sOwner - - -- Exact handle search with HTTP HEAD still works for non-searchable users - u4' <- setRandomHandle brig u4 -- Add handle to the non-searchable u4 - let u4handle = fromJust $ userHandle u4' - Bilge.head (brig . paths ["handles", toByteString' u4handle] . zUser (userId u3)) - !!! const 200 === statusCode - - -- Regular user can't find non-searchable team member by exact handle. - s <- Search.executeSearch brig u1id $ fromHandle u4handle - liftIO $ assertBool "u1 must not find non-searchable u4 by exact handle" $ not $ uidsInResult [userId u4] s - - -- /teams/:tid/members gets all members - r :: Team.Member.TeamMembersPage <- parseOrFail "TeamMembersPage" $ get (galley . paths ["teams", toByteString' tid, "members"] . zUser u1id) UserId - contactUid = qUnqualified . contactQualifiedId - - uidsInResult :: [UserId] -> SearchResult Contact -> Bool - uidsInResult uids r = all (`elem` foundUids) uids - where - foundUids = map contactUid (searchResults r) - testExistingUser :: Brig -> Http () testExistingUser brig = do quser <- userQualifiedId <$> randomUser brig @@ -1685,10 +1589,3 @@ execAndAssertUserDeletion brig cannon u hdl others userJournalWatcher execDelete -- | Get user profile (while asserting that result is successful) getProfile :: Brig -> UserId -> UserId -> Http ResponseLBS getProfile b zusr uid = get (apiVersion "v1" . b . zUser zusr . paths ["users", toByteString' uid]) String -> Http ResponseLBS -> Http a -parseOrFail what action = maybe (liftIO $ assertFailure $ "Can't parse from JSON: " <> what) pure . responseJsonMaybe =<< action - --- | Add any ToJSON value to request and set content-type to JSON as well. -toJsonBody :: ToJSON a => a -> Request -> Request -toJsonBody a req = contentJson $ body (RequestBodyLBS $ encode a) req From 83679d1d6ca896d8e2d5964969e2bc5f6cb7231b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Thu, 9 Oct 2025 21:20:34 +0300 Subject: [PATCH 22/30] Test POST /handles as well --- integration/test/Test/Search.hs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/integration/test/Test/Search.hs b/integration/test/Test/Search.hs index 2189c88a64..7b09c8d034 100644 --- a/integration/test/Test/Search.hs +++ b/integration/test/Test/Search.hs @@ -410,6 +410,16 @@ testUserSearchable = do req <- baseRequest u3 Brig Versioned $ joinHttpPath ["handles", u4handle] submit "HEAD" req `bindResponse` \resp -> resp.status `shouldMatchInt` 200 + -- Handle for POST /handles still works for non-searchable users + u3handle <- API.randomHandle + bindResponse (BrigP.putHandle u3 u3handle) assertSuccess + req <- baseRequest u1 Brig Versioned $ joinHttpPath ["handles"] + let req' = req & addJSONObject ["handles" .= [u4handle, u3handle]] + submit "POST" req' `bindResponse` \resp -> do + resp.status `shouldMatchInt` 200 + freeHandles <- resp.json & asList + assertBool "POST /handles flters all taken handles, even for regular members" $ null freeHandles + -- Regular user can't find non-searchable team member by exact handle. withFoundDocs u1 u4handle $ \docs -> do foundUids <- for docs objId From 67c042eb7aeefbbc445d9038f8dd13aa3fb20622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Thu, 9 Oct 2025 21:44:21 +0300 Subject: [PATCH 23/30] fixup! Add query param to Brig --- libs/wire-api/src/Wire/API/User/Search.hs | 4 +- .../SearchResult_20TeamContact_user.hs | 112 +++++++++--------- .../API/Golden/Generated/TeamContact_user.hs | 41 +++---- .../src/Wire/UserSearch/Types.hs | 2 +- 4 files changed, 80 insertions(+), 79 deletions(-) diff --git a/libs/wire-api/src/Wire/API/User/Search.hs b/libs/wire-api/src/Wire/API/User/Search.hs index 906ebb8438..d91762b920 100644 --- a/libs/wire-api/src/Wire/API/User/Search.hs +++ b/libs/wire-api/src/Wire/API/User/Search.hs @@ -193,7 +193,7 @@ data TeamContact = TeamContact teamContactScimExternalId :: Maybe Text, teamContactSso :: Maybe Sso, teamContactEmailUnvalidated :: Maybe EmailAddress, - teamContactSearchable :: Maybe Bool + teamContactSearchable :: Bool } deriving stock (Eq, Show, Generic) deriving (Arbitrary) via (GenericUniform TeamContact) @@ -216,7 +216,7 @@ instance ToSchema TeamContact where <*> teamContactScimExternalId .= optField "scim_external_id" (maybeWithDefault Aeson.Null schema) <*> teamContactSso .= optField "sso" (maybeWithDefault Aeson.Null schema) <*> teamContactEmailUnvalidated .= optField "email_unvalidated" (maybeWithDefault Aeson.Null schema) - <*> teamContactSearchable .= optField "searchable" (maybeWithDefault Aeson.Null schema) + <*> teamContactSearchable .= field "searchable" schema data TeamUserSearchSortBy = SortByName diff --git a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/SearchResult_20TeamContact_user.hs b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/SearchResult_20TeamContact_user.hs index 0508b56106..00fee6f1b6 100644 --- a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/SearchResult_20TeamContact_user.hs +++ b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/SearchResult_20TeamContact_user.hs @@ -48,7 +48,7 @@ testObject_SearchResult_20TeamContact_user_1 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000000")), @@ -64,7 +64,7 @@ testObject_SearchResult_20TeamContact_user_1 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } ], searchPolicy = FullSearch, @@ -105,7 +105,7 @@ testObject_SearchResult_20TeamContact_user_3 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001")), @@ -121,7 +121,7 @@ testObject_SearchResult_20TeamContact_user_3 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000000000000")), @@ -137,7 +137,7 @@ testObject_SearchResult_20TeamContact_user_3 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } ], searchPolicy = FullSearch, @@ -166,7 +166,7 @@ testObject_SearchResult_20TeamContact_user_4 = teamContactScimExternalId = Nothing, teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001")), @@ -182,7 +182,7 @@ testObject_SearchResult_20TeamContact_user_4 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001")), @@ -198,7 +198,7 @@ testObject_SearchResult_20TeamContact_user_4 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000000")), @@ -214,7 +214,7 @@ testObject_SearchResult_20TeamContact_user_4 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } ], searchPolicy = ExactHandleSearch, @@ -243,7 +243,7 @@ testObject_SearchResult_20TeamContact_user_5 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } ], searchPolicy = FullSearch, @@ -272,7 +272,7 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000001")), @@ -288,7 +288,7 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000001")), @@ -304,7 +304,7 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000000")), @@ -320,7 +320,7 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000000000001")), @@ -336,7 +336,7 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactScimExternalId = Nothing, teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000001")), @@ -352,7 +352,7 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001")), @@ -368,7 +368,7 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000000")), @@ -384,7 +384,7 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000000")), @@ -400,7 +400,7 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000001")), @@ -416,7 +416,7 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000001")), @@ -432,7 +432,7 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000000")), @@ -448,7 +448,7 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000001")), @@ -464,7 +464,7 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } ], searchPolicy = FullSearch, @@ -493,7 +493,7 @@ testObject_SearchResult_20TeamContact_user_7 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000000")), @@ -509,7 +509,7 @@ testObject_SearchResult_20TeamContact_user_7 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000000")), @@ -525,7 +525,7 @@ testObject_SearchResult_20TeamContact_user_7 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000001")), @@ -541,7 +541,7 @@ testObject_SearchResult_20TeamContact_user_7 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001")), @@ -557,7 +557,7 @@ testObject_SearchResult_20TeamContact_user_7 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000001")), @@ -573,7 +573,7 @@ testObject_SearchResult_20TeamContact_user_7 = teamContactScimExternalId = Nothing, teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } ], searchPolicy = FullSearch, @@ -602,7 +602,7 @@ testObject_SearchResult_20TeamContact_user_8 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000000")), @@ -618,7 +618,7 @@ testObject_SearchResult_20TeamContact_user_8 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000000")), @@ -634,7 +634,7 @@ testObject_SearchResult_20TeamContact_user_8 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000000000000")), @@ -650,7 +650,7 @@ testObject_SearchResult_20TeamContact_user_8 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } ], searchPolicy = FullSearch, @@ -679,7 +679,7 @@ testObject_SearchResult_20TeamContact_user_9 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000001")), @@ -695,7 +695,7 @@ testObject_SearchResult_20TeamContact_user_9 = teamContactScimExternalId = Nothing, teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001")), @@ -711,7 +711,7 @@ testObject_SearchResult_20TeamContact_user_9 = teamContactScimExternalId = Nothing, teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000000000001")), @@ -727,7 +727,7 @@ testObject_SearchResult_20TeamContact_user_9 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } ], searchPolicy = FullSearch, @@ -768,7 +768,7 @@ testObject_SearchResult_20TeamContact_user_11 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000001")), @@ -784,7 +784,7 @@ testObject_SearchResult_20TeamContact_user_11 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000000")), @@ -800,7 +800,7 @@ testObject_SearchResult_20TeamContact_user_11 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000000")), @@ -816,7 +816,7 @@ testObject_SearchResult_20TeamContact_user_11 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000000")), @@ -832,7 +832,7 @@ testObject_SearchResult_20TeamContact_user_11 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000001")), @@ -848,7 +848,7 @@ testObject_SearchResult_20TeamContact_user_11 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001")), @@ -864,7 +864,7 @@ testObject_SearchResult_20TeamContact_user_11 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000001")), @@ -880,7 +880,7 @@ testObject_SearchResult_20TeamContact_user_11 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } ], searchPolicy = FullSearch, @@ -909,7 +909,7 @@ testObject_SearchResult_20TeamContact_user_12 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } ], searchPolicy = FullSearch, @@ -938,7 +938,7 @@ testObject_SearchResult_20TeamContact_user_13 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000001")), @@ -954,7 +954,7 @@ testObject_SearchResult_20TeamContact_user_13 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000001")), @@ -970,7 +970,7 @@ testObject_SearchResult_20TeamContact_user_13 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } ], searchPolicy = FullSearch, @@ -999,7 +999,7 @@ testObject_SearchResult_20TeamContact_user_14 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } ], searchPolicy = FullSearch, @@ -1028,7 +1028,7 @@ testObject_SearchResult_20TeamContact_user_15 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } ], searchPolicy = FullSearch, @@ -1057,7 +1057,7 @@ testObject_SearchResult_20TeamContact_user_16 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000000")), @@ -1073,7 +1073,7 @@ testObject_SearchResult_20TeamContact_user_16 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True }, TeamContact { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000000")), @@ -1089,7 +1089,7 @@ testObject_SearchResult_20TeamContact_user_16 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } ], searchPolicy = FullSearch, @@ -1118,7 +1118,7 @@ testObject_SearchResult_20TeamContact_user_17 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } ], searchPolicy = FullSearch, @@ -1147,7 +1147,7 @@ testObject_SearchResult_20TeamContact_user_18 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } ], searchPolicy = FullSearch, diff --git a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/TeamContact_user.hs b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/TeamContact_user.hs index 90eb99974f..c2b158b69f 100644 --- a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/TeamContact_user.hs +++ b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/TeamContact_user.hs @@ -17,6 +17,7 @@ module Test.Wire.API.Golden.Generated.TeamContact_user where +import Data.Bool (Bool(True)) import Data.Id (Id (Id)) import Data.Json.Util (readUTCTimeMillis) import Data.UUID qualified as UUID (fromString) @@ -41,7 +42,7 @@ testObject_TeamContact_user_1 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } testObject_TeamContact_user_2 :: TeamContact @@ -60,7 +61,7 @@ testObject_TeamContact_user_2 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } testObject_TeamContact_user_3 :: TeamContact @@ -79,7 +80,7 @@ testObject_TeamContact_user_3 = teamContactScimExternalId = Nothing, teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } testObject_TeamContact_user_4 :: TeamContact @@ -98,7 +99,7 @@ testObject_TeamContact_user_4 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = Nothing + teamContactSearchable = True } testObject_TeamContact_user_5 :: TeamContact @@ -117,7 +118,7 @@ testObject_TeamContact_user_5 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } testObject_TeamContact_user_6 :: TeamContact @@ -136,7 +137,7 @@ testObject_TeamContact_user_6 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } testObject_TeamContact_user_7 :: TeamContact @@ -155,7 +156,7 @@ testObject_TeamContact_user_7 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = Nothing + teamContactSearchable = True } testObject_TeamContact_user_8 :: TeamContact @@ -174,7 +175,7 @@ testObject_TeamContact_user_8 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } testObject_TeamContact_user_9 :: TeamContact @@ -193,7 +194,7 @@ testObject_TeamContact_user_9 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } testObject_TeamContact_user_10 :: TeamContact @@ -212,7 +213,7 @@ testObject_TeamContact_user_10 = teamContactScimExternalId = Nothing, teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } testObject_TeamContact_user_11 :: TeamContact @@ -231,7 +232,7 @@ testObject_TeamContact_user_11 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } testObject_TeamContact_user_12 :: TeamContact @@ -250,7 +251,7 @@ testObject_TeamContact_user_12 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } testObject_TeamContact_user_13 :: TeamContact @@ -269,7 +270,7 @@ testObject_TeamContact_user_13 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } testObject_TeamContact_user_14 :: TeamContact @@ -288,7 +289,7 @@ testObject_TeamContact_user_14 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } testObject_TeamContact_user_15 :: TeamContact @@ -307,7 +308,7 @@ testObject_TeamContact_user_15 = teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = Nothing + teamContactSearchable = True } testObject_TeamContact_user_16 :: TeamContact @@ -326,7 +327,7 @@ testObject_TeamContact_user_16 = teamContactScimExternalId = Nothing, teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = Nothing + teamContactSearchable = True } testObject_TeamContact_user_17 :: TeamContact @@ -345,7 +346,7 @@ testObject_TeamContact_user_17 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } testObject_TeamContact_user_18 :: TeamContact @@ -364,7 +365,7 @@ testObject_TeamContact_user_18 = teamContactScimExternalId = Nothing, teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } testObject_TeamContact_user_19 :: TeamContact @@ -383,7 +384,7 @@ testObject_TeamContact_user_19 = teamContactScimExternalId = Nothing, teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), teamContactEmailUnvalidated = Nothing, - teamContactSearchable = Nothing + teamContactSearchable = True } testObject_TeamContact_user_20 :: TeamContact @@ -402,5 +403,5 @@ testObject_TeamContact_user_20 = teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Nothing, teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = Nothing + teamContactSearchable = True } diff --git a/libs/wire-subsystems/src/Wire/UserSearch/Types.hs b/libs/wire-subsystems/src/Wire/UserSearch/Types.hs index fe6f6b3f7d..f8a0ae7ae4 100644 --- a/libs/wire-subsystems/src/Wire/UserSearch/Types.hs +++ b/libs/wire-subsystems/src/Wire/UserSearch/Types.hs @@ -126,7 +126,7 @@ userDocToTeamContact UserDoc {..} = teamContactEmail = udEmail, teamContactCreatedAt = udCreatedAt, teamContactColorId = fromIntegral . fromColourId <$> udColourId, - teamContactSearchable = udSearchable + teamContactSearchable = fromMaybe True udSearchable } -- | Outbound search restrictions configured by team admin of the searcher. This From 457ce7b05cc58bbc44ec14dca2a4fa0852ff4010 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Thu, 9 Oct 2025 21:46:41 +0300 Subject: [PATCH 24/30] Partially revert "Minor refactor": inline getProfile back again This reverts commit 68b6c6e3179869615878ae9cdd273e97f20e0ab0. --- .../brig/test/integration/API/User/Account.hs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/services/brig/test/integration/API/User/Account.hs b/services/brig/test/integration/API/User/Account.hs index 879bc30549..4bde9dcd18 100644 --- a/services/brig/test/integration/API/User/Account.hs +++ b/services/brig/test/integration/API/User/Account.hs @@ -860,21 +860,24 @@ testCreateUserAnonExpiry b = do bob <- createAnonUserExpiry (Just 5 {- 2 was flaky, so it's 5 now; make sure to re-align with 'awaitExpiry' below! -}) "bob" b liftIO $ assertBool "expiry not set on regular creation" (isNothing (userExpire alice)) ensureExpiry (fromUTCTimeMillis <$> userExpire bob) "bob/register" - resAlice <- getProfile b (userId u1) (userId alice) - resBob <- getProfile b (userId u1) (userId bob) + resAlice <- getProfile (userId u1) (userId alice) + resBob <- getProfile (userId u1) (userId bob) selfBob <- get (b . zUser (userId bob) . path "self") UserId -> Http ResponseLBS + getProfile zusr uid = get (apiVersion "v1" . b . zUser zusr . paths ["users", toByteString' uid]) UserId -> UserId -> Http () awaitExpiry n zusr uid = do -- after expiration, a profile lookup should trigger garbage collection of ephemeral users - r <- getProfile b zusr uid + r <- getProfile zusr uid when (statusCode r == 200 && isNothing (deleted r) && n > 0) $ do liftIO $ threadDelay 1000000 awaitExpiry (n - 1) zusr uid @@ -1585,7 +1588,3 @@ execAndAssertUserDeletion brig cannon u hdl others userJournalWatcher execDelete ) ) . responseJsonMaybe - --- | Get user profile (while asserting that result is successful) -getProfile :: Brig -> UserId -> UserId -> Http ResponseLBS -getProfile b zusr uid = get (apiVersion "v1" . b . zUser zusr . paths ["users", toByteString' uid]) Date: Thu, 9 Oct 2025 22:04:47 +0300 Subject: [PATCH 25/30] Minor refactor: use record syntax, deduplicate golden tests --- .../SearchResult_20TeamContact_user.hs | 587 ++++-------------- .../API/Golden/Generated/TeamContact_user.hs | 214 ++----- libs/wire-api/test/unit/Test/Wire/API/User.hs | 20 +- 3 files changed, 208 insertions(+), 613 deletions(-) diff --git a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/SearchResult_20TeamContact_user.hs b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/SearchResult_20TeamContact_user.hs index 00fee6f1b6..a052b2eb5a 100644 --- a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/SearchResult_20TeamContact_user.hs +++ b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/SearchResult_20TeamContact_user.hs @@ -27,6 +27,25 @@ import Wire.API.Team.Role (Role (RoleAdmin, RoleExternalPartner, RoleMember, Rol import Wire.API.User import Wire.API.User.Search (FederatedUserSearchPolicy (ExactHandleSearch, FullSearch), PagingState (..), SearchResult (..), Sso (..), TeamContact (..)) +teamContactTemplate :: TeamContact +teamContactTemplate = + TeamContact + { teamContactUserId = Id (fromJust (UUID.fromString "")), + teamContactName = "", + teamContactColorId = Nothing, + teamContactHandle = Nothing, + teamContactTeam = Nothing, + teamContactEmail = Nothing, + teamContactCreatedAt = Nothing, + teamContactManagedBy = Nothing, + teamContactSAMLIdp = Nothing, + teamContactRole = Nothing, + teamContactScimExternalId = Nothing, + teamContactSso = Nothing, + teamContactEmailUnvalidated = Nothing, + teamContactSearchable = True + } + testObject_SearchResult_20TeamContact_user_1 :: SearchResult TeamContact testObject_SearchResult_20TeamContact_user_1 = SearchResult @@ -34,37 +53,27 @@ testObject_SearchResult_20TeamContact_user_1 = searchReturned = 2, searchTook = 0, searchResults = - [ TeamContact + [ teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000000")), - teamContactName = "", teamContactColorId = Just 0, - teamContactHandle = Nothing, teamContactTeam = Just (Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000001"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T20:48:17.263Z")), - teamContactManagedBy = Nothing, teamContactSAMLIdp = Just "", teamContactRole = Just RoleAdmin, - teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f" }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000000")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000001"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T17:17:18.225Z")), teamContactManagedBy = Just ManagedByWire, - teamContactSAMLIdp = Nothing, teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f") } ], searchPolicy = FullSearch, @@ -91,53 +100,28 @@ testObject_SearchResult_20TeamContact_user_3 = searchReturned = -2, searchTook = -7, searchResults = - [ TeamContact + [ teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000000")), - teamContactName = "", - teamContactColorId = Nothing, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000000"))), - teamContactEmail = Nothing, - teamContactCreatedAt = Nothing, teamContactManagedBy = Just ManagedByWire, - teamContactSAMLIdp = Nothing, - teamContactRole = Just RoleAdmin, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactRole = Just RoleAdmin }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", - teamContactTeam = Nothing, - teamContactEmail = Nothing, teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T04:59:07.086Z")), teamContactManagedBy = Just ManagedByWire, - teamContactSAMLIdp = Just "", - teamContactRole = Nothing, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSAMLIdp = Just "" }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000000000000")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", - teamContactTeam = Nothing, - teamContactEmail = Nothing, teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T05:39:37.370Z")), teamContactManagedBy = Just ManagedByScim, - teamContactSAMLIdp = Just "", - teamContactRole = Nothing, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSAMLIdp = Just "" } ], searchPolicy = FullSearch, @@ -152,69 +136,46 @@ testObject_SearchResult_20TeamContact_user_4 = searchReturned = 4, searchTook = 2, searchResults = - [ TeamContact + [ teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000001")), - teamContactName = "", - teamContactColorId = Nothing, - teamContactHandle = Nothing, teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000001"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), - teamContactCreatedAt = Nothing, teamContactManagedBy = Just ManagedByWire, - teamContactSAMLIdp = Nothing, teamContactRole = Just RoleOwner, - teamContactScimExternalId = Nothing, teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = True + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", - teamContactTeam = Nothing, - teamContactEmail = Nothing, teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T01:29:06.597Z")), teamContactManagedBy = Just ManagedByScim, teamContactSAMLIdp = Just "", teamContactRole = Just RoleAdmin, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f") }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001")), - teamContactName = "", - teamContactColorId = Nothing, - teamContactHandle = Nothing, teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000000"))), - teamContactEmail = Nothing, teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T17:38:20.677Z")), teamContactManagedBy = Just ManagedByWire, teamContactSAMLIdp = Just "", teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f") }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000000")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", - teamContactTeam = Nothing, teamContactEmail = Just (unsafeEmailAddress "some" "example"), - teamContactCreatedAt = Nothing, teamContactManagedBy = Just ManagedByScim, teamContactSAMLIdp = Just "", teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f") } ], searchPolicy = ExactHandleSearch, @@ -229,21 +190,16 @@ testObject_SearchResult_20TeamContact_user_5 = searchReturned = -3, searchTook = -7, searchResults = - [ TeamContact + [ teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000000")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", - teamContactTeam = Nothing, teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T12:39:20.984Z")), teamContactManagedBy = Just ManagedByScim, teamContactSAMLIdp = Just "", teamContactRole = Just RoleExternalPartner, - teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f" } ], searchPolicy = FullSearch, @@ -258,57 +214,36 @@ testObject_SearchResult_20TeamContact_user_6 = searchReturned = -7, searchTook = -4, searchResults = - [ TeamContact + [ teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000000")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000000"))), - teamContactEmail = Nothing, - teamContactCreatedAt = Nothing, teamContactManagedBy = Just ManagedByWire, teamContactSAMLIdp = Just "", - teamContactRole = Just RoleOwner, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactRole = Just RoleOwner }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000001")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", - teamContactTeam = Nothing, teamContactEmail = Just (unsafeEmailAddress "some" "example"), - teamContactCreatedAt = Nothing, teamContactManagedBy = Just ManagedByWire, teamContactSAMLIdp = Just "", teamContactRole = Just RoleOwner, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = True + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000001")), - teamContactName = "", - teamContactColorId = Nothing, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000000"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T10:59:12.538Z")), teamContactManagedBy = Just ManagedByScim, - teamContactSAMLIdp = Just "", - teamContactRole = Nothing, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSAMLIdp = Just "" }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000000")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000000"))), @@ -316,95 +251,54 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T23:24:12.000Z")), teamContactManagedBy = Just ManagedByScim, teamContactSAMLIdp = Just "", - teamContactRole = Just RoleOwner, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactRole = Just RoleOwner }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000000000001")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", - teamContactTeam = Nothing, teamContactEmail = Just (unsafeEmailAddress "some" "example"), - teamContactCreatedAt = Nothing, - teamContactManagedBy = Nothing, teamContactSAMLIdp = Just "", - teamContactRole = Nothing, - teamContactScimExternalId = Nothing, - teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f") }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000001")), - teamContactName = "", - teamContactColorId = Nothing, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000001"))), - teamContactEmail = Nothing, teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T19:59:50.883Z")), teamContactManagedBy = Just ManagedByScim, teamContactSAMLIdp = Just "", - teamContactRole = Just RoleMember, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactRole = Just RoleMember }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", - teamContactTeam = Nothing, - teamContactEmail = Nothing, teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T13:56:02.433Z")), teamContactManagedBy = Just ManagedByWire, - teamContactSAMLIdp = Nothing, - teamContactRole = Just RoleAdmin, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactRole = Just RoleAdmin }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000000")), - teamContactName = "", teamContactColorId = Just 0, - teamContactHandle = Nothing, teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000000"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T01:45:42.970Z")), - teamContactManagedBy = Nothing, teamContactSAMLIdp = Just "", - teamContactRole = Nothing, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = True + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000000")), - teamContactName = "", - teamContactColorId = Nothing, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001"))), - teamContactEmail = Nothing, - teamContactCreatedAt = Nothing, teamContactManagedBy = Just ManagedByWire, - teamContactSAMLIdp = Nothing, teamContactRole = Just RoleExternalPartner, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = True + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000001")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000001"))), @@ -414,57 +308,39 @@ testObject_SearchResult_20TeamContact_user_6 = teamContactSAMLIdp = Just "", teamContactRole = Just RoleOwner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Nothing, - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = True + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000001")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000000"))), - teamContactEmail = Nothing, teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T14:01:50.906Z")), teamContactManagedBy = Just ManagedByScim, teamContactSAMLIdp = Just "", teamContactRole = Just RoleMember, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = True + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000000")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000000"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), - teamContactCreatedAt = Nothing, teamContactManagedBy = Just ManagedByScim, teamContactSAMLIdp = Just "", teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f") }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000001")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", - teamContactTeam = Nothing, teamContactEmail = Just (unsafeEmailAddress "some" "example"), - teamContactCreatedAt = Nothing, teamContactManagedBy = Just ManagedByScim, - teamContactSAMLIdp = Nothing, teamContactRole = Just RoleExternalPartner, - teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f" } ], searchPolicy = FullSearch, @@ -479,101 +355,65 @@ testObject_SearchResult_20TeamContact_user_7 = searchReturned = 5, searchTook = 5, searchResults = - [ TeamContact + [ teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000001")), - teamContactName = "", - teamContactColorId = Nothing, teamContactHandle = Just "", - teamContactTeam = Nothing, teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T19:22:39.660Z")), - teamContactManagedBy = Nothing, teamContactSAMLIdp = Just "", - teamContactRole = Nothing, - teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f" }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000000")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", - teamContactTeam = Nothing, - teamContactEmail = Nothing, teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T19:42:55.525Z")), teamContactManagedBy = Just ManagedByWire, teamContactSAMLIdp = Just "", - teamContactRole = Just RoleMember, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactRole = Just RoleMember }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000000")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000000"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), - teamContactCreatedAt = Nothing, teamContactManagedBy = Just ManagedByWire, teamContactSAMLIdp = Just "", teamContactRole = Just RoleExternalPartner, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = True + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000001")), teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", - teamContactTeam = Nothing, - teamContactEmail = Nothing, - teamContactCreatedAt = Nothing, teamContactManagedBy = Just ManagedByWire, teamContactSAMLIdp = Just "", - teamContactRole = Nothing, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = True + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001")), teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000000"))), - teamContactEmail = Nothing, teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T00:45:08.016Z")), teamContactManagedBy = Just ManagedByScim, teamContactSAMLIdp = Just "", teamContactRole = Just RoleMember, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = True + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000001")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000001"))), - teamContactEmail = Nothing, teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T21:18:46.647Z")), teamContactManagedBy = Just ManagedByScim, teamContactSAMLIdp = Just "", teamContactRole = Just RoleExternalPartner, - teamContactScimExternalId = Nothing, - teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f") } ], searchPolicy = FullSearch, @@ -588,41 +428,27 @@ testObject_SearchResult_20TeamContact_user_8 = searchReturned = 2, searchTook = -7, searchResults = - [ TeamContact + [ teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000001")), - teamContactName = "", - teamContactColorId = Nothing, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000001"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), - teamContactCreatedAt = Nothing, teamContactManagedBy = Just ManagedByScim, teamContactSAMLIdp = Just "", teamContactRole = Just RoleOwner, - teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f" }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000000")), - teamContactName = "", teamContactColorId = Just 0, - teamContactHandle = Nothing, - teamContactTeam = Nothing, teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T13:46:22.701Z")), teamContactManagedBy = Just ManagedByWire, - teamContactSAMLIdp = Nothing, teamContactRole = Just RoleOwner, - teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f" }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000000")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000001"))), @@ -630,15 +456,10 @@ testObject_SearchResult_20TeamContact_user_8 = teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T09:25:11.685Z")), teamContactManagedBy = Just ManagedByWire, teamContactSAMLIdp = Just "", - teamContactRole = Nothing, - teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f" }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000000000000")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000000000001"))), @@ -646,11 +467,7 @@ testObject_SearchResult_20TeamContact_user_8 = teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T11:37:20.763Z")), teamContactManagedBy = Just ManagedByWire, teamContactSAMLIdp = Just "", - teamContactRole = Nothing, - teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f" } ], searchPolicy = FullSearch, @@ -665,25 +482,16 @@ testObject_SearchResult_20TeamContact_user_9 = searchReturned = 3, searchTook = -3, searchResults = - [ TeamContact + [ teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000000")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", - teamContactTeam = Nothing, - teamContactEmail = Nothing, - teamContactCreatedAt = Nothing, teamContactManagedBy = Just ManagedByWire, teamContactSAMLIdp = Just "", - teamContactRole = Just RoleMember, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactRole = Just RoleMember }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000001")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000001"))), @@ -691,43 +499,29 @@ testObject_SearchResult_20TeamContact_user_9 = teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T16:22:05.429Z")), teamContactManagedBy = Just ManagedByScim, teamContactSAMLIdp = Just "", - teamContactRole = Nothing, - teamContactScimExternalId = Nothing, - teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f") }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000000"))), - teamContactEmail = Nothing, teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T17:19:11.439Z")), teamContactManagedBy = Just ManagedByScim, teamContactSAMLIdp = Just "", teamContactRole = Just RoleMember, - teamContactScimExternalId = Nothing, - teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f") }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000000000001")), - teamContactName = "", - teamContactColorId = Nothing, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000001"))), - teamContactEmail = Nothing, teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T05:44:15.175Z")), teamContactManagedBy = Just ManagedByWire, teamContactSAMLIdp = Just "", teamContactRole = Just RoleExternalPartner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f") } ], searchPolicy = FullSearch, @@ -754,42 +548,29 @@ testObject_SearchResult_20TeamContact_user_11 = searchReturned = 7, searchTook = 1, searchResults = - [ TeamContact + [ teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000001")), - teamContactName = "", - teamContactColorId = Nothing, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000001"))), - teamContactEmail = Nothing, teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T23:32:15.171Z")), teamContactManagedBy = Just ManagedByWire, teamContactSAMLIdp = Just "", teamContactRole = Just RoleExternalPartner, - teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f" }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000001")), - teamContactName = "", teamContactColorId = Just 0, - teamContactHandle = Nothing, teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000001"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T09:36:08.567Z")), teamContactManagedBy = Just ManagedByScim, teamContactSAMLIdp = Just "", teamContactRole = Just RoleOwner, - teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f" }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000000")), - teamContactName = "", - teamContactColorId = Nothing, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000001"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), @@ -797,78 +578,41 @@ testObject_SearchResult_20TeamContact_user_11 = teamContactManagedBy = Just ManagedByWire, teamContactSAMLIdp = Just "", teamContactRole = Just RoleAdmin, - teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f" }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000000")), - teamContactName = "", - teamContactColorId = Nothing, teamContactHandle = Just "", - teamContactTeam = Nothing, - teamContactEmail = Nothing, teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T00:23:34.413Z")), teamContactManagedBy = Just ManagedByScim, - teamContactSAMLIdp = Just "", - teamContactRole = Nothing, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSAMLIdp = Just "" }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000000")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000000"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), - teamContactCreatedAt = Nothing, - teamContactManagedBy = Just ManagedByWire, - teamContactSAMLIdp = Nothing, - teamContactRole = Nothing, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactManagedBy = Just ManagedByWire }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000001")), - teamContactName = "", - teamContactColorId = Nothing, teamContactHandle = Just "", - teamContactTeam = Nothing, teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T02:39:28.838Z")), - teamContactManagedBy = Nothing, teamContactSAMLIdp = Just "", - teamContactRole = Just RoleExternalPartner, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactRole = Just RoleExternalPartner }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000000000000"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), - teamContactCreatedAt = Nothing, - teamContactManagedBy = Nothing, - teamContactSAMLIdp = Nothing, - teamContactRole = Just RoleOwner, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactRole = Just RoleOwner }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000001")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001"))), @@ -876,11 +620,8 @@ testObject_SearchResult_20TeamContact_user_11 = teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T01:15:59.694Z")), teamContactManagedBy = Just ManagedByWire, teamContactSAMLIdp = Just "", - teamContactRole = Nothing, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f") } ], searchPolicy = FullSearch, @@ -895,21 +636,15 @@ testObject_SearchResult_20TeamContact_user_12 = searchReturned = 0, searchTook = 0, searchResults = - [ TeamContact + [ teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000001")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", - teamContactTeam = Nothing, teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T06:59:36.374Z")), - teamContactManagedBy = Nothing, teamContactSAMLIdp = Just "", - teamContactRole = Nothing, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f") } ], searchPolicy = FullSearch, @@ -924,41 +659,28 @@ testObject_SearchResult_20TeamContact_user_13 = searchReturned = 3, searchTook = 1, searchResults = - [ TeamContact + [ teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000001")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", - teamContactTeam = Nothing, teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T17:55:15.951Z")), teamContactManagedBy = Just ManagedByWire, teamContactSAMLIdp = Just "", - teamContactRole = Just RoleMember, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactRole = Just RoleMember }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000001")), - teamContactName = "", - teamContactColorId = Nothing, - teamContactHandle = Nothing, teamContactTeam = Just (Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000000000000"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T05:08:55.558Z")), teamContactManagedBy = Just ManagedByScim, teamContactSAMLIdp = Just "", teamContactRole = Just RoleMember, - teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f" }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000001")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000000"))), @@ -966,11 +688,7 @@ testObject_SearchResult_20TeamContact_user_13 = teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T11:18:47.121Z")), teamContactManagedBy = Just ManagedByScim, teamContactSAMLIdp = Just "", - teamContactRole = Nothing, - teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f" } ], searchPolicy = FullSearch, @@ -985,21 +703,14 @@ testObject_SearchResult_20TeamContact_user_14 = searchReturned = 4, searchTook = -4, searchResults = - [ TeamContact + [ teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000000")), - teamContactName = "", teamContactColorId = Just 0, - teamContactHandle = Nothing, - teamContactTeam = Nothing, - teamContactEmail = Nothing, teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T06:35:15.745Z")), teamContactManagedBy = Just ManagedByWire, teamContactSAMLIdp = Just "", teamContactRole = Just RoleAdmin, - teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f" } ], searchPolicy = FullSearch, @@ -1014,21 +725,15 @@ testObject_SearchResult_20TeamContact_user_15 = searchReturned = 6, searchTook = -6, searchResults = - [ TeamContact + [ teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000001")), - teamContactName = "", - teamContactColorId = Nothing, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000000"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), - teamContactCreatedAt = Nothing, teamContactManagedBy = Just ManagedByWire, - teamContactSAMLIdp = Nothing, teamContactRole = Just RoleOwner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f") } ], searchPolicy = FullSearch, @@ -1043,41 +748,29 @@ testObject_SearchResult_20TeamContact_user_16 = searchReturned = 2, searchTook = -5, searchResults = - [ TeamContact + [ teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000001")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", - teamContactTeam = Nothing, teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T23:38:23.560Z")), teamContactManagedBy = Just ManagedByWire, teamContactSAMLIdp = Just "", teamContactRole = Just RoleAdmin, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f") }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000000")), - teamContactName = "", - teamContactColorId = Nothing, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000001"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), - teamContactCreatedAt = Nothing, teamContactManagedBy = Just ManagedByScim, - teamContactSAMLIdp = Nothing, teamContactRole = Just RoleAdmin, - teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f" }, - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000000")), - teamContactName = "", teamContactColorId = Just 0, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000000000000"))), @@ -1086,10 +779,7 @@ testObject_SearchResult_20TeamContact_user_16 = teamContactManagedBy = Just ManagedByScim, teamContactSAMLIdp = Just "", teamContactRole = Just RoleAdmin, - teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f" } ], searchPolicy = FullSearch, @@ -1104,21 +794,13 @@ testObject_SearchResult_20TeamContact_user_17 = searchReturned = -5, searchTook = 4, searchResults = - [ TeamContact + [ teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000000")), - teamContactName = "", - teamContactColorId = Nothing, teamContactHandle = Just "", - teamContactTeam = Nothing, - teamContactEmail = Nothing, teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T02:22:14.746Z")), teamContactManagedBy = Just ManagedByWire, teamContactSAMLIdp = Just "", - teamContactRole = Just RoleExternalPartner, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactRole = Just RoleExternalPartner } ], searchPolicy = FullSearch, @@ -1133,21 +815,14 @@ testObject_SearchResult_20TeamContact_user_18 = searchReturned = -7, searchTook = -7, searchResults = - [ TeamContact + [ teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000000")), - teamContactName = "", - teamContactColorId = Nothing, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000001"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T12:35:16.437Z")), - teamContactManagedBy = Nothing, teamContactSAMLIdp = Just "", - teamContactRole = Just RoleOwner, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactRole = Just RoleOwner } ], searchPolicy = FullSearch, diff --git a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/TeamContact_user.hs b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/TeamContact_user.hs index c2b158b69f..03a177ac34 100644 --- a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/TeamContact_user.hs +++ b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/TeamContact_user.hs @@ -17,7 +17,7 @@ module Test.Wire.API.Golden.Generated.TeamContact_user where -import Data.Bool (Bool(True)) +import Data.Bool (Bool (True)) import Data.Id (Id (Id)) import Data.Json.Util (readUTCTimeMillis) import Data.UUID qualified as UUID (fromString) @@ -26,28 +26,39 @@ import Wire.API.Team.Role (Role (RoleAdmin, RoleExternalPartner, RoleMember, Rol import Wire.API.User import Wire.API.User.Search (Sso (..), TeamContact (..)) -testObject_TeamContact_user_1 :: TeamContact -testObject_TeamContact_user_1 = +teamContactTemplate :: TeamContact +teamContactTemplate = TeamContact - { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000200000001")), + { teamContactUserId = Id (fromJust (UUID.fromString "")), teamContactName = "", teamContactColorId = Nothing, teamContactHandle = Nothing, teamContactTeam = Nothing, - teamContactEmail = Just (unsafeEmailAddress "some" "example"), - teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-11T12:52:22.086Z")), + teamContactEmail = Nothing, + teamContactCreatedAt = Nothing, teamContactManagedBy = Nothing, - teamContactSAMLIdp = Just "r", - teamContactRole = Just RoleAdmin, - teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", + teamContactSAMLIdp = Nothing, + teamContactRole = Nothing, + teamContactScimExternalId = Nothing, teamContactSso = Nothing, teamContactEmailUnvalidated = Nothing, teamContactSearchable = True } +testObject_TeamContact_user_1 :: TeamContact +testObject_TeamContact_user_1 = + teamContactTemplate + { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000200000001")), + teamContactEmail = Just (unsafeEmailAddress "some" "example"), + teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-11T12:52:22.086Z")), + teamContactSAMLIdp = Just "r", + teamContactRole = Just RoleAdmin, + teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f" + } + testObject_TeamContact_user_2 :: TeamContact testObject_TeamContact_user_2 = - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000002")), teamContactName = "\160469\35044", teamContactColorId = Just 2, @@ -55,21 +66,14 @@ testObject_TeamContact_user_2 = teamContactTeam = Just (Id (fromJust (UUID.fromString "00000002-0000-0000-0000-000200000001"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-08T03:35:20.125Z")), - teamContactManagedBy = Nothing, teamContactSAMLIdp = Just "N\DC4", - teamContactRole = Just RoleExternalPartner, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactRole = Just RoleExternalPartner } testObject_TeamContact_user_3 :: TeamContact testObject_TeamContact_user_3 = - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000002-0000-0000-0000-000000000000")), - teamContactName = "", - teamContactColorId = Nothing, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000002-0000-0002-0000-000100000000"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), @@ -77,91 +81,55 @@ testObject_TeamContact_user_3 = teamContactManagedBy = Just ManagedByScim, teamContactSAMLIdp = Just "\"c`", teamContactRole = Just RoleMember, - teamContactScimExternalId = Nothing, - teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f") } testObject_TeamContact_user_4 :: TeamContact testObject_TeamContact_user_4 = - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000002-0000-0001-0000-000000000002")), - teamContactName = "", - teamContactColorId = Nothing, teamContactHandle = Just "U6", - teamContactTeam = Nothing, teamContactEmail = Just (unsafeEmailAddress "some" "example"), - teamContactCreatedAt = Nothing, - teamContactManagedBy = Nothing, - teamContactSAMLIdp = Nothing, - teamContactRole = Nothing, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = True + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") } testObject_TeamContact_user_5 :: TeamContact testObject_TeamContact_user_5 = - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000200000000")), teamContactName = "8", teamContactColorId = Just (-3), teamContactHandle = Just "\RS", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000002-0000-0000-0000-000200000000"))), - teamContactEmail = Nothing, teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-09T19:22:27.168Z")), - teamContactManagedBy = Nothing, teamContactSAMLIdp = Just "\12641", - teamContactRole = Just RoleExternalPartner, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactRole = Just RoleExternalPartner } testObject_TeamContact_user_6 :: TeamContact testObject_TeamContact_user_6 = - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000000")), teamContactName = "z", - teamContactColorId = Nothing, - teamContactHandle = Nothing, - teamContactTeam = Nothing, - teamContactEmail = Nothing, - teamContactCreatedAt = Nothing, - teamContactManagedBy = Just ManagedByWire, - teamContactSAMLIdp = Nothing, - teamContactRole = Nothing, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactManagedBy = Just ManagedByWire } testObject_TeamContact_user_7 :: TeamContact testObject_TeamContact_user_7 = - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000002-0000-0002-0000-000000000000")), teamContactName = "7", - teamContactColorId = Nothing, - teamContactHandle = Nothing, - teamContactTeam = Nothing, teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-06T11:54:20.119Z")), teamContactManagedBy = Just ManagedByWire, - teamContactSAMLIdp = Nothing, teamContactRole = Just RoleAdmin, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Nothing, - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = True + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") } testObject_TeamContact_user_8 :: TeamContact testObject_TeamContact_user_8 = - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000000")), teamContactName = "\1067719Z", teamContactColorId = Just (-1), @@ -171,172 +139,123 @@ testObject_TeamContact_user_8 = teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-06T04:27:11.179Z")), teamContactManagedBy = Just ManagedByScim, teamContactSAMLIdp = Just "", - teamContactRole = Just RoleMember, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactRole = Just RoleMember } testObject_TeamContact_user_9 :: TeamContact testObject_TeamContact_user_9 = - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000000")), teamContactName = "h,", teamContactColorId = Just 2, - teamContactHandle = Nothing, teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000200000001"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-11T18:31:16.554Z")), teamContactManagedBy = Just ManagedByWire, teamContactSAMLIdp = Just "\164542\US", - teamContactRole = Just RoleAdmin, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactRole = Just RoleAdmin } testObject_TeamContact_user_10 :: TeamContact testObject_TeamContact_user_10 = - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000002-0000-0000-0000-000100000001")), teamContactName = "or", teamContactColorId = Just 2, teamContactHandle = Just "", - teamContactTeam = Nothing, - teamContactEmail = Nothing, teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-06T05:51:36.680Z")), teamContactManagedBy = Just ManagedByScim, teamContactSAMLIdp = Just "P-\EM", teamContactRole = Just RoleMember, - teamContactScimExternalId = Nothing, - teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f") } testObject_TeamContact_user_11 :: TeamContact testObject_TeamContact_user_11 = - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000002")), teamContactName = "\ACK", teamContactColorId = Just (-3), - teamContactHandle = Nothing, - teamContactTeam = Nothing, teamContactEmail = Just (unsafeEmailAddress "some" "example"), - teamContactCreatedAt = Nothing, teamContactManagedBy = Just ManagedByScim, - teamContactSAMLIdp = Nothing, - teamContactRole = Just RoleExternalPartner, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactRole = Just RoleExternalPartner } testObject_TeamContact_user_12 :: TeamContact testObject_TeamContact_user_12 = - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000002-0000-0000-0000-000200000000")), teamContactName = "\10652w", - teamContactColorId = Nothing, teamContactHandle = Just "", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000000"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-06T13:09:44.601Z")), - teamContactManagedBy = Nothing, - teamContactSAMLIdp = Just "\SUB:", - teamContactRole = Nothing, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSAMLIdp = Just "\SUB:" } testObject_TeamContact_user_13 :: TeamContact testObject_TeamContact_user_13 = - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000002-0000-0002-0000-000100000001")), teamContactName = "\SUB\983552P", teamContactColorId = Just 0, teamContactHandle = Just "S", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000000-0000-0002-0000-000200000000"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), - teamContactCreatedAt = Nothing, teamContactManagedBy = Just ManagedByScim, teamContactSAMLIdp = Just "\993657\a", teamContactRole = Just RoleMember, - teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f" } testObject_TeamContact_user_14 :: TeamContact testObject_TeamContact_user_14 = - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000000")), teamContactName = "`+", teamContactColorId = Just (-3), teamContactHandle = Just "\"\US\DC4", - teamContactTeam = Nothing, teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-08T20:31:37.388Z")), teamContactManagedBy = Just ManagedByScim, - teamContactSAMLIdp = Nothing, teamContactRole = Just RoleExternalPartner, - teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Nothing, - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f" } testObject_TeamContact_user_15 :: TeamContact testObject_TeamContact_user_15 = - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000002-0000-0002-0000-000100000002")), teamContactName = "\54517}O", - teamContactColorId = Nothing, teamContactHandle = Just "J", - teamContactTeam = Nothing, teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-11T14:15:19.890Z")), - teamContactManagedBy = Nothing, teamContactSAMLIdp = Just "", teamContactRole = Just RoleExternalPartner, - teamContactScimExternalId = Nothing, - teamContactSso = Nothing, - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = True + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") } testObject_TeamContact_user_16 :: TeamContact testObject_TeamContact_user_16 = - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000002")), teamContactName = "\ACK6J", teamContactColorId = Just (-1), - teamContactHandle = Nothing, teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0002-0000-000200000001"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-08T15:43:05.866Z")), teamContactManagedBy = Just ManagedByWire, teamContactSAMLIdp = Just "k", - teamContactRole = Nothing, - teamContactScimExternalId = Nothing, teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = True + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") } testObject_TeamContact_user_17 :: TeamContact testObject_TeamContact_user_17 = - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000200000001")), teamContactName = "/MB", teamContactColorId = Just (-3), - teamContactHandle = Nothing, teamContactTeam = Just (Id (fromJust (UUID.fromString "00000002-0000-0000-0000-000200000001"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-10T20:50:28.410Z")), @@ -344,54 +263,39 @@ testObject_TeamContact_user_17 = teamContactSAMLIdp = Just "\138052", teamContactRole = Just RoleOwner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f") } testObject_TeamContact_user_18 :: TeamContact testObject_TeamContact_user_18 = - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000002-0000-0001-0000-000000000002")), teamContactName = "[\1078188C", teamContactColorId = Just 3, - teamContactHandle = Nothing, teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0002-0000-000000000000"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), - teamContactCreatedAt = Nothing, teamContactManagedBy = Just ManagedByWire, teamContactSAMLIdp = Just "\DC2", teamContactRole = Just RoleOwner, - teamContactScimExternalId = Nothing, - teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f") } testObject_TeamContact_user_19 :: TeamContact testObject_TeamContact_user_19 = - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0002-0000-000200000002")), - teamContactName = "", teamContactColorId = Just (-3), - teamContactHandle = Nothing, teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0002-0000-000200000002"))), teamContactEmail = Just (unsafeEmailAddress "some" "example"), teamContactCreatedAt = Just (fromJust (readUTCTimeMillis "1864-05-10T11:20:36.673Z")), - teamContactManagedBy = Nothing, - teamContactSAMLIdp = Nothing, teamContactRole = Just RoleExternalPartner, - teamContactScimExternalId = Nothing, - teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f"), - teamContactEmailUnvalidated = Nothing, - teamContactSearchable = True + teamContactSso = Just (Sso "https://example.com/issuer/123" "0307979d-c742-4421-954a-9ceb1f22e58f") } testObject_TeamContact_user_20 :: TeamContact testObject_TeamContact_user_20 = - TeamContact + teamContactTemplate { teamContactUserId = Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000000")), - teamContactName = "", teamContactColorId = Just (-3), teamContactHandle = Just "0\1085403\1021449", teamContactTeam = Just (Id (fromJust (UUID.fromString "00000001-0000-0002-0000-000100000001"))), @@ -401,7 +305,5 @@ testObject_TeamContact_user_20 = teamContactSAMLIdp = Just "", teamContactRole = Just RoleOwner, teamContactScimExternalId = Just "0307979d-c742-4421-954a-9ceb1f22e58f", - teamContactSso = Nothing, - teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example"), - teamContactSearchable = True + teamContactEmailUnvalidated = Just (unsafeEmailAddress "some" "example") } diff --git a/libs/wire-api/test/unit/Test/Wire/API/User.hs b/libs/wire-api/test/unit/Test/Wire/API/User.hs index 011d0df5f7..11ce3d914e 100644 --- a/libs/wire-api/test/unit/Test/Wire/API/User.hs +++ b/libs/wire-api/test/unit/Test/Wire/API/User.hs @@ -117,7 +117,25 @@ testUserProfile = do uid <- Id <$> UUID.nextRandom let domain = Domain "example.com" let colour = ColourId 0 - let userProfile = UserProfile (Qualified uid domain) (Name "name") Nothing (Pict []) [] colour False Nothing Nothing Nothing Nothing Nothing UserLegalHoldNoConsent defSupportedProtocols UserTypeRegular True + let userProfile = + UserProfile + { profileQualifiedId = Qualified uid domain, + profileName = Name "name", + profileTextStatus = Nothing, + profilePict = Pict [], + profileAssets = [], + profileAccentId = colour, + profileDeleted = False, + profileService = Nothing, + profileHandle = Nothing, + profileExpire = Nothing, + profileTeam = Nothing, + profileEmail = Nothing, + profileLegalholdStatus = UserLegalHoldNoConsent, + profileSupportedProtocols = defSupportedProtocols, + profileType = UserTypeRegular, + profileSearchable = True + } let profileJSONAsText = show $ Aeson.encode userProfile let msg = "toJSON encoding must not convert Nothing to null, but instead omit those json fields for backwards compatibility. UserProfileJSON:" <> profileJSONAsText assertBool msg (not $ "null" `isInfixOf` profileJSONAsText) From a892f4bc02a43a1618cb00cd7f650d542d450df2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Thu, 9 Oct 2025 22:57:43 +0300 Subject: [PATCH 26/30] `make sanitize-pr` --- .../src/Wire/API/Routes/Public/Brig.hs | 61 +++++++++---------- 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs b/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs index 29927468a7..83b6706a49 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs @@ -170,15 +170,14 @@ type UserAPI = :> CaptureUserId "uid" :> GetUserVerb ) - :<|> - Named - "get-user-qualified" - ( Summary "Get a user by Domain and UserId" - :> ZLocalUser - :> "users" - :> QualifiedCaptureUserId "uid" - :> GetUserVerb - ) + :<|> Named + "get-user-qualified" + ( Summary "Get a user by Domain and UserId" + :> ZLocalUser + :> "users" + :> QualifiedCaptureUserId "uid" + :> GetUserVerb + ) :<|> Named "update-user-email" ( Summary "Resend email address validation email." @@ -222,18 +221,17 @@ type UserAPI = ] (Maybe UserProfile) ) - :<|> - Named - "list-users-by-unqualified-ids-or-handles" - ( Summary "List users (deprecated)" - :> Until 'V2 - :> Description "The 'ids' and 'handles' parameters are mutually exclusive." - :> ZUser - :> "users" - :> QueryParam' [Optional, Strict, Description "User IDs of users to fetch"] "ids" (CommaSeparatedList UserId) - :> QueryParam' [Optional, Strict, Description "Handles of users to fetch, min 1 and max 4 (the check for handles is rather expensive)"] "handles" (Range 1 4 (CommaSeparatedList Handle)) - :> Get '[JSON] [UserProfile] - ) + :<|> Named + "list-users-by-unqualified-ids-or-handles" + ( Summary "List users (deprecated)" + :> Until 'V2 + :> Description "The 'ids' and 'handles' parameters are mutually exclusive." + :> ZUser + :> "users" + :> QueryParam' [Optional, Strict, Description "User IDs of users to fetch"] "ids" (CommaSeparatedList UserId) + :> QueryParam' [Optional, Strict, Description "Handles of users to fetch, min 1 and max 4 (the check for handles is rather expensive)"] "handles" (Range 1 4 (CommaSeparatedList Handle)) + :> Get '[JSON] [UserProfile] + ) :<|> Named "list-users-by-ids-or-handles" ( Summary "List users" @@ -244,17 +242,16 @@ type UserAPI = :> ReqBody '[JSON] ListUsersQuery :> Post '[JSON] ListUsersById ) - :<|> - Named - "list-users-by-ids-or-handles@V3" - ( Summary "List users" - :> Description "The 'qualified_ids' and 'qualified_handles' parameters are mutually exclusive." - :> ZUser - :> Until 'V4 - :> "list-users" - :> ReqBody '[JSON] ListUsersQuery - :> Post '[JSON] [UserProfile] - ) + :<|> Named + "list-users-by-ids-or-handles@V3" + ( Summary "List users" + :> Description "The 'qualified_ids' and 'qualified_handles' parameters are mutually exclusive." + :> ZUser + :> Until 'V4 + :> "list-users" + :> ReqBody '[JSON] ListUsersQuery + :> Post '[JSON] [UserProfile] + ) :<|> Named "send-verification-code" ( Summary "Send a verification code to a given email address." From b5503d9e0ae61b885112f87a636f135aff9a47b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Thu, 9 Oct 2025 22:58:32 +0300 Subject: [PATCH 27/30] fixup! Add query param to Brig --- libs/wire-subsystems/src/Wire/IndexedUserStore/ElasticSearch.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/wire-subsystems/src/Wire/IndexedUserStore/ElasticSearch.hs b/libs/wire-subsystems/src/Wire/IndexedUserStore/ElasticSearch.hs index e6249d4ed3..2aa07e7385 100644 --- a/libs/wire-subsystems/src/Wire/IndexedUserStore/ElasticSearch.hs +++ b/libs/wire-subsystems/src/Wire/IndexedUserStore/ElasticSearch.hs @@ -366,7 +366,7 @@ teamUserSearchQuery tid mbSearchText mRoleFilter mSortBy mSortOrder mEmailFilter } teamFilter :: ES.Filter - teamFilter = ES.Filter $ ES.QueryBoolQuery boolQuery { ES.boolQueryMustMatch = mustMatch } + teamFilter = ES.Filter $ ES.QueryBoolQuery boolQuery {ES.boolQueryMustMatch = mustMatch} where mustMatch :: [ES.Query] mustMatch = ES.TermQuery (ES.Term "team" $ idToText tid) Nothing : roleFilter <> emailFilter <> searchableFilter From 618416209a20e586b9b720be193c4c1da7d7ba6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Thu, 9 Oct 2025 22:59:26 +0300 Subject: [PATCH 28/30] fixup! Add `POST /users/:uid/searchable` --- services/brig/src/Brig/API/Public.hs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/services/brig/src/Brig/API/Public.hs b/services/brig/src/Brig/API/Public.hs index a6bb217212..468f41859e 100644 --- a/services/brig/src/Brig/API/Public.hs +++ b/services/brig/src/Brig/API/Public.hs @@ -105,8 +105,6 @@ import System.Logger.Class qualified as Log import Util.Logging (logFunction, logHandle, logTeam, logUser) import Wire.API.App import Wire.API.Connection qualified as Public -import Wire.API.Conversation.Member qualified as Member -import Wire.API.Conversation.Role (roleNameWireAdmin) import Wire.API.EnterpriseLogin import Wire.API.Error import Wire.API.Error.Brig qualified as E @@ -142,7 +140,7 @@ import Wire.API.SwaggerHelper (cleanupSwagger) import Wire.API.SystemSettings import Wire.API.Team qualified as Public import Wire.API.Team.LegalHold (LegalholdProtectee (..)) -import Wire.API.Team.Member (HiddenPerm (..), IsPerm (..), TeamMember, hasPermission) +import Wire.API.Team.Member (HiddenPerm (..), IsPerm (..), hasPermission) import Wire.API.User (RegisterError (RegisterErrorAllowlistError)) import Wire.API.User qualified as Public import Wire.API.User.Activation qualified as Public From 671e93aaa8ab1bc2c8c84d953d6dfc4493ac6dbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Thu, 9 Oct 2025 23:15:07 +0300 Subject: [PATCH 29/30] fixup! Add query param to Brig --- .../src/Wire/IndexedUserStore/ElasticSearch.hs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libs/wire-subsystems/src/Wire/IndexedUserStore/ElasticSearch.hs b/libs/wire-subsystems/src/Wire/IndexedUserStore/ElasticSearch.hs index 2aa07e7385..c91f7c3ffe 100644 --- a/libs/wire-subsystems/src/Wire/IndexedUserStore/ElasticSearch.hs +++ b/libs/wire-subsystems/src/Wire/IndexedUserStore/ElasticSearch.hs @@ -223,6 +223,11 @@ defaultUserQuery searcher mSearcherTeamId teamSearchInfo (normalized -> term') = } ], ES.boolQueryShouldMatch = [ES.QueryExistsQuery (ES.FieldName "handle")], + -- The following matches both where searchable is true + -- or where the field is missing. There didn't seem to + -- be a more readable way to express + -- "not(exists(searchable) or searchable = true" in + -- Elastic Search. ES.boolQueryMustNotMatch = [ES.TermQuery (ES.Term "searchable" "false") Nothing] } -- This reduces relevance on users not in team of search by 90% (no From c0e5357ca9bd68474b20fe635a4185a40c00d138 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20L=C3=A4ll?= Date: Fri, 10 Oct 2025 10:52:05 +0300 Subject: [PATCH 30/30] wip --- integration/test/Test/Search.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/integration/test/Test/Search.hs b/integration/test/Test/Search.hs index 7b09c8d034..977341e733 100644 --- a/integration/test/Test/Search.hs +++ b/integration/test/Test/Search.hs @@ -367,6 +367,7 @@ testUserSearchable = do resp.status `shouldMatchInt` 403 resp.json %. "label" `shouldMatch` "insufficient-permissions" +{- u1' <- BrigP.getUser u1 u1 >>= getJSON 200 assertBool "Searchable is still True" =<< (u1' %. "searchable" & asBool) @@ -442,5 +443,5 @@ testUserSearchable = do docs <- resp.json %. "documents" >>= asList foundUids <- for docs objId -- todo assertBool "/teams/:tid/members?searchable=false returns only non-searchable members" $ all (`elem` foundUids) [u1id, u4id] - +-} pure ()