Skip to content

Commit 9891c56

Browse files
committed
[wip] Filter searchable with /team/:tid/members?searchable=false
1 parent 9716367 commit 9891c56

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
@@ -722,14 +722,14 @@ testUserSearchable brig galley = do
722722
liftIO $ assertBool "/teams/:tid/members returns searchable and non-searchable users from team" $ all (`elem` uids) $ u1id : map userId [u3, u4]
723723

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

734734
where
735735
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
@@ -473,20 +473,23 @@ getTeamMembers ::
473473
TeamId ->
474474
Maybe (Range 1 Public.HardTruncationLimit Int32) ->
475475
Maybe TeamMembersPagingState ->
476+
Maybe Bool ->
476477
Sem r TeamMembersPage
477-
getTeamMembers lzusr tid mbMaxResults mbPagingState = do
478+
getTeamMembers lzusr tid mbMaxResults mbPagingState mbSearchable = do
478479
let uid = tUnqualified lzusr
479480
member <- E.getTeamMember tid uid >>= noteS @'NotATeamMember
480481
let mState = C.PagingState . LBS.fromStrict <$> (mbPagingState >>= mtpsState)
481482
let mLimit = fromMaybe (unsafeRange Public.hardTruncationLimit) mbMaxResults
482483
if member `hasPermission` SearchContacts
483-
then E.listTeamMembers @CassandraPaging tid mState mLimit <&> toTeamMembersPage member
484+
then case mbSearchable of
485+
Just False -> E.listTeamMembers @CassandraPaging tid mState mLimit mbSearchable <&> toTeamMembersPage member
486+
_ -> E.listTeamMembers @CassandraPaging tid mState mLimit mbSearchable <&> toTeamMembersPage member
484487
else do
485488
-- If the user does not have the SearchContacts permission (e.g. the external partner),
486489
-- we only return the person who invited them and the self user.
487490
let invitee = member ^. invitation <&> fst
488491
let uids = uid : maybeToList invitee
489-
E.selectTeamMembersPaginated tid uids mState mLimit <&> toTeamMembersPage member
492+
E.selectTeamMembersPaginated tid uids mState mLimit <&> toTeamMembersPage member -- TODO_searchable: Use `mbSearchable` in this branch of the if as well?
490493
where
491494
toTeamMembersPage :: TeamMember -> C.PageWithState TeamMember -> TeamMembersPage
492495
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
@@ -178,6 +196,18 @@ selectTeamMembers' ::
178196
)
179197
selectTeamMembers' = selectTeamMembersBase ["user in ?"]
180198

199+
selectTeamMembersSearchable ::
200+
PrepQuery
201+
R
202+
(TeamId, Bool)
203+
( UserId,
204+
Permissions,
205+
Maybe UserId,
206+
Maybe UTCTimeMillis,
207+
Maybe UserLegalHoldStatus
208+
)
209+
selectTeamMembersSearchable = selectTeamMembersBase ["searchable = ?"]
210+
181211
selectUserTeams :: PrepQuery R (Identity UserId) (Identity TeamId)
182212
selectUserTeams = "select team from user_team where user = ? order by team"
183213

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

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -194,13 +194,13 @@ interpretTeamMemberStoreToCassandra ::
194194
Sem (TeamMemberStore InternalPaging ': r) a ->
195195
Sem r a
196196
interpretTeamMemberStoreToCassandra lh = interpret $ \case
197-
ListTeamMembers tid mps lim -> do
197+
ListTeamMembers tid mps lim ms -> do
198198
logEffect "TeamMemberStore.ListTeamMembers"
199199
embedClient $ case mps of
200200
Nothing -> do
201-
page <- teamMembersForPagination tid Nothing lim
201+
page <- teamMembersForPagination tid Nothing lim ms
202202
mkInternalPage page (newTeamMember' lh tid)
203-
Just ps -> ipNext ps
203+
Just ps -> ipNext ps -- TODO_searchable: do I need to pass ms (Maybe Bool) to here as well?
204204

205205
interpretTeamMemberStoreToCassandraWithPaging ::
206206
( Member (Embed IO) r,
@@ -211,9 +211,9 @@ interpretTeamMemberStoreToCassandraWithPaging ::
211211
Sem (TeamMemberStore CassandraPaging ': r) a ->
212212
Sem r a
213213
interpretTeamMemberStoreToCassandraWithPaging lh = interpret $ \case
214-
ListTeamMembers tid mps lim -> do
214+
ListTeamMembers tid mps lim ms -> do
215215
logEffect "TeamMemberStore.ListTeamMembers"
216-
embedClient $ teamMembersPageFrom lh tid mps lim
216+
embedClient $ teamMembersPageFrom lh tid mps lim ms
217217

218218
createTeam ::
219219
( Member (Input ClientState) r,
@@ -372,7 +372,7 @@ teamMembersWithLimit lh t (fromRange -> limit) = do
372372
-- Maybe should be left explicitly for the caller?
373373
teamMembersCollectedWithPagination :: FeatureDefaults LegalholdConfig -> TeamId -> Client [TeamMember]
374374
teamMembersCollectedWithPagination lh tid = do
375-
mems <- teamMembersForPagination tid Nothing (unsafeRange 2000)
375+
mems <- teamMembersForPagination tid Nothing (unsafeRange 2000) Nothing -- TODO_searchable: pass Nothing (the last argument to the call)?
376376
collectTeamMembersPaginated [] mems
377377
where
378378
collectTeamMembersPaginated acc mems = do
@@ -440,7 +440,7 @@ markTeamDeletedAndRemoveTeamMembers :: TeamId -> Client ()
440440
markTeamDeletedAndRemoveTeamMembers tid = do
441441
-- TODO: delete service_whitelist records that mention this team
442442
retry x5 $ write Cql.markTeamDeleted (params LocalQuorum (PendingDelete, tid))
443-
mems <- teamMembersForPagination tid Nothing (unsafeRange 2000)
443+
mems <- teamMembersForPagination tid Nothing (unsafeRange 2000) Nothing -- TODO_searchable: pass Nothing?
444444
removeTeamMembers mems
445445
where
446446
removeTeamMembers ::
@@ -514,20 +514,30 @@ type RawTeamMember = (UserId, Permissions, Maybe UserId, Maybe UTCTimeMillis, Ma
514514
-- have a pure function of type RawTeamMember -> TeamMember so we cannot fmap
515515
-- over the ResultSet. We don't want to mess around with the Result size
516516
-- nextPage either otherwise
517-
teamMembersForPagination :: TeamId -> Maybe UserId -> Range 1 HardTruncationLimit Int32 -> Client (Page RawTeamMember)
518-
teamMembersForPagination tid start (fromRange -> max) =
517+
teamMembersForPagination :: TeamId -> Maybe UserId -> Range 1 HardTruncationLimit Int32 -> Maybe Bool -> Client (Page RawTeamMember)
518+
teamMembersForPagination tid start (fromRange -> max) ms =
519519
case start of
520520
Just u -> paginate Cql.selectTeamMembersFrom (paramsP LocalQuorum (tid, u) max)
521-
Nothing -> paginate Cql.selectTeamMembers (paramsP LocalQuorum (Identity tid) max)
521+
Nothing -> case ms of
522+
Just searchable -> paginate Cql.selectTeamMembersSearchable (paramsP LocalQuorum (tid, searchable) max)
523+
Nothing -> paginate Cql.selectTeamMembers (paramsP LocalQuorum (Identity tid) max)
522524

523525
teamMembersPageFrom ::
524526
FeatureDefaults LegalholdConfig ->
525527
TeamId ->
526528
Maybe PagingState ->
527529
Range 1 HardTruncationLimit Int32 ->
530+
Maybe Bool ->
528531
Client (PageWithState TeamMember)
529-
teamMembersPageFrom lh tid pagingState (fromRange -> max) = do
530-
page <- paginateWithState Cql.selectTeamMembers (paramsPagingState LocalQuorum (Identity tid) max pagingState)
532+
teamMembersPageFrom lh tid pagingState (fromRange -> max) ms = do
533+
page <- case ms of
534+
Just searchable -> paginateWithState Cql.selectTeamMembersSearchable (paramsPagingState LocalQuorum (tid, searchable) max pagingState)
535+
-- WIP_searchable: This is what is called from
536+
-- /team/:tid/members?searchable=true. The issue is that this
537+
-- queries the team_members table from cassandra and not the
538+
-- users' table where the searchable field is. Cassandra doesn't
539+
-- seem to support joins, so am currently stomped on how to proceed.
540+
Nothing -> paginateWithState Cql.selectTeamMembers (paramsPagingState LocalQuorum (Identity tid) max pagingState)
531541
members <- mapM (newTeamMember' lh tid) (pwsResults page)
532542
pure $ PageWithState members (pwsState page)
533543

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)