Skip to content

Commit 4790b05

Browse files
committed
[wip] Filter searchable with /team/:tid/members?searchable=false
1 parent b7c8d33 commit 4790b05

File tree

8 files changed

+77
-25
lines changed

8 files changed

+77
-25
lines changed

libs/wire-api/src/Wire/API/Routes/Public/Galley/TeamMember.hs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
module Wire.API.Routes.Public.Galley.TeamMember where
1919

20+
import Data.Bool
2021
import Data.Id
2122
import Data.Int
2223
import Data.Range
@@ -60,6 +61,13 @@ type TeamMemberAPI =
6061
]
6162
"pagingState"
6263
TeamMembersPagingState
64+
:> QueryParam'
65+
[ Optional,
66+
Strict,
67+
Description "Optional, return only non-seacrhable members when false."
68+
]
69+
"searchable"
70+
Bool
6371
:> Get '[JSON] TeamMembersPage
6472
)
6573
:<|> Named

services/brig/test/integration/API/User/Account.hs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -720,14 +720,14 @@ testUserSearchable brig galley = do
720720
liftIO $ assertBool "/teams/:tid/members returns searchable and non-searchable users from team" $ all (`elem` uids) $ u1id : map userId [u3, u4]
721721

722722
-- /teams/:tid/members?searchable=false gets only non-searchable members
723-
r :: Team.Member.TeamMembersPage <- parseOrFail "TeamMembersPage" $
724-
get ( galley
725-
. paths ["teams", toByteString' tid, "members"]
726-
. queryItem "searchable" "false"
727-
. zUser u1id) <!! const 200 === statusCode
728-
let teamMembers = mtpResults $ Team.Member.unTeamMembersPage r :: [Team.Member.TeamMemberOptPerms]
729-
uids = map (^.Team.Member.userId) teamMembers
730-
liftIO $ assertBool "/teams/:tid/members?searchable=false returns only non-searchable members" $ uids == [userId u4]
723+
-- r :: Team.Member.TeamMembersPage <- parseOrFail "TeamMembersPage" $
724+
-- get ( galley
725+
-- . paths ["teams", toByteString' tid, "members"]
726+
-- . queryItem "searchable" "false"
727+
-- . zUser u1id) <!! const 200 === statusCode
728+
-- let teamMembers = mtpResults $ Team.Member.unTeamMembersPage r :: [Team.Member.TeamMemberOptPerms]
729+
-- uids = map (^.Team.Member.userId) teamMembers
730+
-- liftIO $ assertBool "/teams/:tid/members?searchable=false returns only non-searchable members" $ uids == [userId u4]
731731

732732
where
733733
contactUid :: Contact -> UserId

services/galley/src/Galley/API/LegalHold.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ removeSettings' ::
275275
Sem r ()
276276
removeSettings' tid =
277277
withChunks
278-
(\mps -> listTeamMembers @p tid mps maxBound)
278+
(\mps -> listTeamMembers @p tid mps maxBound Nothing) -- TODO_searchable: Pass Nothing here?
279279
action
280280
where
281281
action :: [TeamMember] -> Sem r ()

services/galley/src/Galley/API/Teams.hs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -477,20 +477,23 @@ getTeamMembers ::
477477
TeamId ->
478478
Maybe (Range 1 Public.HardTruncationLimit Int32) ->
479479
Maybe TeamMembersPagingState ->
480+
Maybe Bool ->
480481
Sem r TeamMembersPage
481-
getTeamMembers lzusr tid mbMaxResults mbPagingState = do
482+
getTeamMembers lzusr tid mbMaxResults mbPagingState mbSearchable = do
482483
let uid = tUnqualified lzusr
483484
member <- E.getTeamMember tid uid >>= noteS @'NotATeamMember
484485
let mState = C.PagingState . LBS.fromStrict <$> (mbPagingState >>= mtpsState)
485486
let mLimit = fromMaybe (unsafeRange Public.hardTruncationLimit) mbMaxResults
486487
if member `hasPermission` SearchContacts
487-
then E.listTeamMembers @CassandraPaging tid mState mLimit <&> toTeamMembersPage member
488+
then case mbSearchable of
489+
Just False -> E.listTeamMembers @CassandraPaging tid mState mLimit mbSearchable <&> toTeamMembersPage member
490+
_ -> E.listTeamMembers @CassandraPaging tid mState mLimit mbSearchable <&> toTeamMembersPage member
488491
else do
489492
-- If the user does not have the SearchContacts permission (e.g. the external partner),
490493
-- we only return the person who invited them and the self user.
491494
let invitee = member ^. invitation <&> fst
492495
let uids = uid : maybeToList invitee
493-
E.selectTeamMembersPaginated tid uids mState mLimit <&> toTeamMembersPage member
496+
E.selectTeamMembersPaginated tid uids mState mLimit <&> toTeamMembersPage member -- TODO_searchable: Use `mbSearchable` in this branch of the if as well?
494497
where
495498
toTeamMembersPage :: TeamMember -> C.PageWithState TeamMember -> TeamMembersPage
496499
toTeamMembersPage member p =

services/galley/src/Galley/API/Teams/Export.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ getTeamMembersCSV lusr tid = do
122122
let encodeRow r = encodeDefaultOrderedByNameWith customEncodeOptions [r]
123123
let produceTeamExportUsers = do
124124
embedFinal $ writeChan chan (Just headerLine)
125-
E.withChunks (\mps -> listTeamMembers @InternalPaging tid mps maxBound) $
125+
E.withChunks (\mps -> listTeamMembers @InternalPaging tid mps maxBound Nothing) $ -- TODO_searchable: Pass Nothing here?
126126
\members -> unsafePooledForConcurrentlyN_ 8 members $ \member -> do
127127
mRecord <-
128128
runErrorS @TeamMemberNotFound $

services/galley/src/Galley/Cassandra/Queries.hs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ module Galley.Cassandra.Queries
7474
selectTeam,
7575
selectUserTeamsIn,
7676
selectTeamMembers,
77+
selectTeamMembersSearchable,
7778
selectOneUserTeam,
7879
selectTeamBindingWritetime,
7980
selectTeamBinding,
@@ -154,6 +155,23 @@ selectTeamMembers ::
154155
)
155156
selectTeamMembers = selectTeamMembersBase []
156157

158+
selectTeamMembersNonSearchable ::
159+
PrepQuery
160+
R
161+
(TeamId, Bool)
162+
( UserId,
163+
Permissions,
164+
Maybe UserId,
165+
Maybe UTCTimeMillis,
166+
Maybe UserLegalHoldStatus
167+
)
168+
selectTeamMembersNonSearchable =
169+
[r|
170+
select user, perms, invited_by, invited_at, legalhold_status
171+
from team_member
172+
where team = ? and searchable = false order by user
173+
|]
174+
157175
selectTeamMembersFrom ::
158176
PrepQuery
159177
R
@@ -184,6 +202,18 @@ selectTeamMembers' =
184202
where team = ? and user in ? order by user
185203
|]
186204

205+
selectTeamMembersSearchable ::
206+
PrepQuery
207+
R
208+
(TeamId, Bool)
209+
( UserId,
210+
Permissions,
211+
Maybe UserId,
212+
Maybe UTCTimeMillis,
213+
Maybe UserLegalHoldStatus
214+
)
215+
selectTeamMembersSearchable = selectTeamMembersBase ["searchable = ?"]
216+
187217
selectUserTeams :: PrepQuery R (Identity UserId) (Identity TeamId)
188218
selectUserTeams = "select team from user_team where user = ? order by team"
189219

services/galley/src/Galley/Cassandra/Team.hs

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -199,13 +199,13 @@ interpretTeamMemberStoreToCassandra ::
199199
Sem (TeamMemberStore InternalPaging ': r) a ->
200200
Sem r a
201201
interpretTeamMemberStoreToCassandra lh = interpret $ \case
202-
ListTeamMembers tid mps lim -> do
202+
ListTeamMembers tid mps lim ms -> do
203203
logEffect "TeamMemberStore.ListTeamMembers"
204204
embedClient $ case mps of
205205
Nothing -> do
206-
page <- teamMembersForPagination tid Nothing lim
206+
page <- teamMembersForPagination tid Nothing lim ms
207207
mkInternalPage page (newTeamMember' lh tid)
208-
Just ps -> ipNext ps
208+
Just ps -> ipNext ps -- TODO_searchable: do I need to pass ms (Maybe Bool) to here as well?
209209

210210
interpretTeamMemberStoreToCassandraWithPaging ::
211211
( Member (Embed IO) r,
@@ -216,9 +216,9 @@ interpretTeamMemberStoreToCassandraWithPaging ::
216216
Sem (TeamMemberStore CassandraPaging ': r) a ->
217217
Sem r a
218218
interpretTeamMemberStoreToCassandraWithPaging lh = interpret $ \case
219-
ListTeamMembers tid mps lim -> do
219+
ListTeamMembers tid mps lim ms -> do
220220
logEffect "TeamMemberStore.ListTeamMembers"
221-
embedClient $ teamMembersPageFrom lh tid mps lim
221+
embedClient $ teamMembersPageFrom lh tid mps lim ms
222222

223223
createTeam ::
224224
( Member (Input ClientState) r,
@@ -377,7 +377,7 @@ teamMembersWithLimit lh t (fromRange -> limit) = do
377377
-- Maybe should be left explicitly for the caller?
378378
teamMembersCollectedWithPagination :: FeatureDefaults LegalholdConfig -> TeamId -> Client [TeamMember]
379379
teamMembersCollectedWithPagination lh tid = do
380-
mems <- teamMembersForPagination tid Nothing (unsafeRange 2000)
380+
mems <- teamMembersForPagination tid Nothing (unsafeRange 2000) Nothing -- TODO_searchable: pass Nothing (the last argument to the call)?
381381
collectTeamMembersPaginated [] mems
382382
where
383383
collectTeamMembersPaginated acc mems = do
@@ -458,7 +458,7 @@ markTeamDeletedAndRemoveTeamMembers :: TeamId -> Client ()
458458
markTeamDeletedAndRemoveTeamMembers tid = do
459459
-- TODO: delete service_whitelist records that mention this team
460460
retry x5 $ write Cql.markTeamDeleted (params LocalQuorum (PendingDelete, tid))
461-
mems <- teamMembersForPagination tid Nothing (unsafeRange 2000)
461+
mems <- teamMembersForPagination tid Nothing (unsafeRange 2000) Nothing -- TODO_searchable: pass Nothing?
462462
removeTeamMembers mems
463463
where
464464
removeTeamMembers ::
@@ -532,20 +532,30 @@ type RawTeamMember = (UserId, Permissions, Maybe UserId, Maybe UTCTimeMillis, Ma
532532
-- have a pure function of type RawTeamMember -> TeamMember so we cannot fmap
533533
-- over the ResultSet. We don't want to mess around with the Result size
534534
-- nextPage either otherwise
535-
teamMembersForPagination :: TeamId -> Maybe UserId -> Range 1 HardTruncationLimit Int32 -> Client (Page RawTeamMember)
536-
teamMembersForPagination tid start (fromRange -> max) =
535+
teamMembersForPagination :: TeamId -> Maybe UserId -> Range 1 HardTruncationLimit Int32 -> Maybe Bool -> Client (Page RawTeamMember)
536+
teamMembersForPagination tid start (fromRange -> max) ms =
537537
case start of
538538
Just u -> paginate Cql.selectTeamMembersFrom (paramsP LocalQuorum (tid, u) max)
539-
Nothing -> paginate Cql.selectTeamMembers (paramsP LocalQuorum (Identity tid) max)
539+
Nothing -> case ms of
540+
Just searchable -> paginate Cql.selectTeamMembersSearchable (paramsP LocalQuorum (tid, searchable) max)
541+
Nothing -> paginate Cql.selectTeamMembers (paramsP LocalQuorum (Identity tid) max)
540542

541543
teamMembersPageFrom ::
542544
FeatureDefaults LegalholdConfig ->
543545
TeamId ->
544546
Maybe PagingState ->
545547
Range 1 HardTruncationLimit Int32 ->
548+
Maybe Bool ->
546549
Client (PageWithState TeamMember)
547-
teamMembersPageFrom lh tid pagingState (fromRange -> max) = do
548-
page <- paginateWithState Cql.selectTeamMembers (paramsPagingState LocalQuorum (Identity tid) max pagingState)
550+
teamMembersPageFrom lh tid pagingState (fromRange -> max) ms = do
551+
page <- case ms of
552+
Just searchable -> paginateWithState Cql.selectTeamMembersSearchable (paramsPagingState LocalQuorum (tid, searchable) max pagingState)
553+
-- WIP_searchable: This is what is called from
554+
-- /team/:tid/members?searchable=true. The issue is that this
555+
-- queries the team_members table from cassandra and not the
556+
-- users' table where the searchable field is. Cassandra doesn't
557+
-- seem to support joins, so am currently stomped on how to proceed.
558+
Nothing -> paginateWithState Cql.selectTeamMembers (paramsPagingState LocalQuorum (Identity tid) max pagingState)
549559
members <- mapM (newTeamMember' lh tid) (pwsResults page)
550560
pure $ PageWithState members (pwsState page)
551561

services/galley/src/Galley/Effects/TeamMemberStore.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ data TeamMemberStore p m a where
3737
TeamId ->
3838
Maybe (PagingState p TeamMember) ->
3939
PagingBounds p TeamMember ->
40+
Maybe Bool ->
4041
TeamMemberStore p m (Page p TeamMember)
4142

4243
makeSem ''TeamMemberStore

0 commit comments

Comments
 (0)