Skip to content

Commit c28f62e

Browse files
committed
[UNVETTED AI SLOP]
Summary of the full implementation: wire-subsystems builds clean. galley builds clean. brig compiles clean (only fails at link due to a pre-existing missing native lib). Here's what was changed across the implementation: 1. Wire.API.Team.Collaborator — Added CollaboratorStatus, TeamCollaboratorView, collaboratorToView 2. Wire.API.Routes.Public.Brig — Changed get-team-collaborators response type to [TeamCollaboratorView] 3. Wire.TeamSubsystem — Added pseudoSuspendedCollaborators, isPseudoSuspended; updated lookupTeamPrincipal to return Nothing for pseudo-suspended collaborators 4. Wire.ConversationSubsystem.Action — Updated checkLocals to filter pseudo-suspended collaborators before building userMembershipMap; added FeaturesConfigSubsystem to HasConversationActionEffects 'ConversationJoinTag, updateLocalConversationJoin, and updateLocalConversationUncheckedJoin 5. Wire.ConversationSubsystem.MLS.Commit.Core — Added FeaturesConfigSubsystem to HasProposalActionEffects 6. Wire.ConversationSubsystem.MLS.Proposal — Added FeaturesConfigSubsystem to HasProposalEffects 7. Wire.ConversationSubsystem.Federation — Added FeaturesConfigSubsystem to sendMLSMessage 8. Wire.ConversationSubsystem.Update — Added FeaturesConfigSubsystem to addMembers, addQualifiedMembersUnqualified, replaceMembers 9. Brig.Team.API — Added enrichCollaboratorsWithStatus using GalleyAPIAccess.getFeatureConfigForTeam @_ @AppsConfig
1 parent a5f351a commit c28f62e

11 files changed

Lines changed: 142 additions & 12 deletions

File tree

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2082,7 +2082,7 @@ type TeamsAPI =
20822082
:> "teams"
20832083
:> Capture "tid" TeamId
20842084
:> "collaborators"
2085-
:> MultiVerb1 'GET '[JSON] (Respond 200 "Return collaborators" [TeamCollaborator])
2085+
:> MultiVerb1 'GET '[JSON] (Respond 200 "Return collaborators" [TeamCollaboratorView])
20862086
)
20872087

20882088
type SystemSettingsAPI =

libs/wire-api/src/Wire/API/Team/Collaborator.hs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,40 @@ instance ToSchema TeamCollaborator where
7474
<$> (gUser .= field "user" schema)
7575
<*> (gTeam .= field "team" schema)
7676
<*> (gPermissions .= field "permissions" (set schema))
77+
78+
data CollaboratorStatus = CollaboratorActive | CollaboratorPseudoSuspended
79+
deriving (Eq, Ord, Show, Generic)
80+
deriving (Arbitrary) via GenericUniform CollaboratorStatus
81+
deriving (A.FromJSON, A.ToJSON, S.ToSchema) via (Schema CollaboratorStatus)
82+
83+
instance ToSchema CollaboratorStatus where
84+
schema =
85+
enum @Text $
86+
mconcat
87+
[ element "active" CollaboratorActive,
88+
element "pseudo_suspended" CollaboratorPseudoSuspended
89+
]
90+
91+
-- | API response type for collaborators, enriched with a computed status field.
92+
-- The status is not stored; it is derived server-side from the user type and
93+
-- the team's feature configuration.
94+
data TeamCollaboratorView = TeamCollaboratorView
95+
{ tcvUser :: UserId,
96+
tcvTeam :: TeamId,
97+
tcvPermissions :: Set CollaboratorPermission,
98+
tcvStatus :: CollaboratorStatus
99+
}
100+
deriving (Eq, Show)
101+
deriving (A.FromJSON, A.ToJSON, S.ToSchema) via (Schema TeamCollaboratorView)
102+
103+
instance ToSchema TeamCollaboratorView where
104+
schema =
105+
object $
106+
TeamCollaboratorView
107+
<$> (.tcvUser) .= field "user" schema
108+
<*> (.tcvTeam) .= field "team" schema
109+
<*> (.tcvPermissions) .= field "permissions" (set schema)
110+
<*> (.tcvStatus) .= field "status" schema
111+
112+
collaboratorToView :: CollaboratorStatus -> TeamCollaborator -> TeamCollaboratorView
113+
collaboratorToView status c = TeamCollaboratorView c.gUser c.gTeam c.gPermissions status

libs/wire-subsystems/src/Wire/ConversationSubsystem/Action.hs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ instance IsConversationAction 'ConversationJoinTag where
190190
Member BackendNotificationQueueAccess r,
191191
Member TeamCollaboratorsSubsystem r,
192192
Member FederationSubsystem r,
193+
Member FeaturesConfigSubsystem r,
193194
Member TeamSubsystem r,
194195
Member (Input ConversationSubsystemConfig) r,
195196
Member E.BrigAPIAccess r,
@@ -798,9 +799,11 @@ performConversationJoin qusr lconv (ConversationJoin invited role joinType) = do
798799
collabs <-
799800
Map.fromList . map (\c -> (c.gUser, c))
800801
<$> internalGetTeamCollaboratorsWithIds (Set.singleton tid) (Set.fromList newUsers)
801-
let principalFor uid =
802+
pseudoSusp <- TeamSubsystem.pseudoSuspendedCollaborators tid (Map.keys collabs)
803+
let activeCollabs = Map.filterWithKey (\uid _ -> uid `Set.notMember` pseudoSusp) collabs
804+
principalFor uid =
802805
fmap Right (Map.lookup uid tms)
803-
<|> fmap Left (Map.lookup uid collabs)
806+
<|> fmap Left (Map.lookup uid activeCollabs)
804807
userMembershipMap = map (Imports.id &&& principalFor) newUsers
805808
ensureAccessRole (convAccessRoles conv) userMembershipMap
806809
ensureConnectedToLocalsOrSameTeam lusr newUsers
@@ -998,6 +1001,7 @@ updateLocalConversationJoin ::
9981001
Member (ErrorS 'InvalidOperation) r,
9991002
Member (ErrorS 'ConvNotFound) r,
10001003
Member FederationSubsystem r,
1004+
Member FeaturesConfigSubsystem r,
10011005
Member TeamCollaboratorsSubsystem r,
10021006
Member TeamSubsystem r,
10031007
Member (Input ConversationSubsystemConfig) r,
@@ -1322,6 +1326,7 @@ updateLocalConversationUncheckedJoin ::
13221326
Member (ErrorS 'InvalidOperation) r,
13231327
Member (ErrorS 'ConvNotFound) r,
13241328
Member FederationSubsystem r,
1329+
Member FeaturesConfigSubsystem r,
13251330
Member TeamCollaboratorsSubsystem r,
13261331
Member TeamSubsystem r,
13271332
Member (Input ConversationSubsystemConfig) r,

libs/wire-subsystems/src/Wire/ConversationSubsystem/Federation.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,8 @@ sendMLSMessage ::
657657
Member P.TinyLog r,
658658
Member ProposalStore r,
659659
Member TeamCollaboratorsSubsystem r,
660-
Member TeamStore r
660+
Member TeamStore r,
661+
Member FeaturesConfigSubsystem r
661662
) =>
662663
Domain ->
663664
MLSMessageSendRequest ->

libs/wire-subsystems/src/Wire/ConversationSubsystem/MLS/Commit/Core.hs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ import Wire.NotificationSubsystem
7373
import Wire.ProposalStore (ProposalStore)
7474
import Wire.Sem.Now (Now)
7575
import Wire.Sem.Random (Random)
76+
import Wire.FeaturesConfigSubsystem
7677
import Wire.TeamCollaboratorsSubsystem
7778
import Wire.TeamStore
7879

@@ -101,7 +102,8 @@ type HasProposalActionEffects r =
101102
Member TinyLog r,
102103
Member NotificationSubsystem r,
103104
Member Random r,
104-
Member TeamCollaboratorsSubsystem r
105+
Member TeamCollaboratorsSubsystem r,
106+
Member FeaturesConfigSubsystem r
105107
)
106108

107109
getCommitData ::

libs/wire-subsystems/src/Wire/ConversationSubsystem/MLS/Proposal.hs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ import Wire.LegalHoldStore (LegalHoldStore)
7373
import Wire.NotificationSubsystem
7474
import Wire.ProposalStore
7575
import Wire.Sem.Now (Now)
76+
import Wire.FeaturesConfigSubsystem
7677
import Wire.TeamCollaboratorsSubsystem
7778
import Wire.TeamStore
7879
import Wire.Util
@@ -138,7 +139,8 @@ type HasProposalEffects r =
138139
Member ProposalStore r,
139140
Member TeamStore r,
140141
Member TinyLog r,
141-
Member TeamCollaboratorsSubsystem r
142+
Member TeamCollaboratorsSubsystem r,
143+
Member FeaturesConfigSubsystem r
142144
)
143145

144146
derefOrCheckProposal ::

libs/wire-subsystems/src/Wire/ConversationSubsystem/Query.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,9 +645,9 @@ getConversationByReusableCode ::
645645
Member (ErrorS 'ConvAccessDenied) r,
646646
Member (ErrorS 'GuestLinksDisabled) r,
647647
Member (ErrorS 'NotATeamMember) r,
648-
Member FeaturesConfigSubsystem r,
649648
Member HashPassword r,
650649
Member RateLimit r,
650+
Member FeaturesConfigSubsystem r,
651651
Member TeamCollaboratorsSubsystem r,
652652
Member TeamSubsystem r
653653
) =>

libs/wire-subsystems/src/Wire/ConversationSubsystem/Update.hs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,7 @@ joinConversationByReusableCode ::
741741
Member FeaturesConfigSubsystem r,
742742
Member HashPassword r,
743743
Member RateLimit r,
744+
Member FeaturesConfigSubsystem r,
744745
Member TeamCollaboratorsSubsystem r,
745746
Member TeamSubsystem r,
746747
Member Now r,
@@ -770,6 +771,7 @@ joinConversationById ::
770771
Member BackendNotificationQueueAccess r,
771772
Member NotificationSubsystem r,
772773
Member E.ExternalAccess r,
774+
Member FeaturesConfigSubsystem r,
773775
Member Now r,
774776
Member TeamCollaboratorsSubsystem r,
775777
Member TeamSubsystem r
@@ -794,6 +796,7 @@ joinConversation ::
794796
Member BackendNotificationQueueAccess r,
795797
Member E.ExternalAccess r,
796798
Member ConversationStore r,
799+
Member FeaturesConfigSubsystem r,
797800
Member Now r,
798801
Member NotificationSubsystem r,
799802
Member TeamCollaboratorsSubsystem r,
@@ -860,6 +863,7 @@ addMembers ::
860863
Member TeamStore r,
861864
Member TinyLog r,
862865
Member TeamCollaboratorsSubsystem r,
866+
Member FeaturesConfigSubsystem r,
863867
Member FederationSubsystem r,
864868
Member TeamSubsystem r,
865869
Member (Input ConversationSubsystemConfig) r
@@ -911,6 +915,7 @@ addQualifiedMembersUnqualified ::
911915
Member TeamStore r,
912916
Member TinyLog r,
913917
Member TeamCollaboratorsSubsystem r,
918+
Member FeaturesConfigSubsystem r,
914919
Member FederationSubsystem r,
915920
Member TeamSubsystem r,
916921
Member (Input ConversationSubsystemConfig) r
@@ -958,6 +963,7 @@ replaceMembers ::
958963
Member TeamCollaboratorsSubsystem r,
959964
Member UserGroupStore r,
960965
Member FederationSubsystem r,
966+
Member FeaturesConfigSubsystem r,
961967
Member TeamSubsystem r,
962968
Member (Input ConversationSubsystemConfig) r
963969
) =>

libs/wire-subsystems/src/Wire/ConversationSubsystem/Util.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ import Wire.RateLimit
9292
import Wire.Sem.Now (Now)
9393
import Wire.Sem.Now qualified as Now
9494
import Wire.StoredConversation as Data
95+
import Wire.FeaturesConfigSubsystem
9596
import Wire.TeamCollaboratorsSubsystem
9697
import Wire.TeamStore
9798
import Wire.TeamSubsystem (ConsentGiven (..), TeamSubsystem, consentGiven, getLHStatus)
@@ -676,6 +677,7 @@ ensureConversationAccess ::
676677
( Member BrigAPIAccess r,
677678
Member (ErrorS 'ConvAccessDenied) r,
678679
Member (ErrorS 'NotATeamMember) r,
680+
Member FeaturesConfigSubsystem r,
679681
Member TeamCollaboratorsSubsystem r,
680682
Member TeamSubsystem r
681683
) =>

libs/wire-subsystems/src/Wire/TeamSubsystem.hs

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,23 @@ module Wire.TeamSubsystem where
2222
import Data.Id
2323
import Data.LegalHold
2424
import Data.Map qualified as Map
25+
import Data.Proxy (Proxy (..))
2526
import Data.Qualified
2627
import Data.Range
28+
import Data.Set qualified as Set
2729
import Data.Singletons (Demote, Sing, SingKind, fromSing)
2830
import Imports
2931
import Polysemy
3032
import Wire.API.Error
3133
import Wire.API.Error.Galley
34+
import Wire.API.Team.Feature (AppsConfig)
3235
import Wire.API.Team.LegalHold (UserLegalHoldStatusResponse)
3336
import Wire.API.Team.Member
3437
import Wire.API.Team.Member.Error
3538
import Wire.API.Team.Member.Info (TeamMemberInfoList)
39+
import Wire.API.User (User (..), UserType (..))
40+
import Wire.BrigAPIAccess
41+
import Wire.FeaturesConfigSubsystem
3642
import Wire.TeamCollaboratorsSubsystem
3743

3844
data PermissionCheckArgs teamAssociation where
@@ -146,17 +152,54 @@ checkConsent ::
146152
checkConsent teamsOfUsers other = do
147153
consentGiven <$> getLHStatus (Map.lookup other teamsOfUsers) other
148154

155+
-- | Returns the set of user IDs from @uids@ that are pseudo-suspended as
156+
-- collaborators in @tid@. A collaborator is pseudo-suspended when they are an
157+
-- app user and the team's @apps@ feature is disabled. The feature is checked
158+
-- once; user types are only fetched when the feature is off.
159+
pseudoSuspendedCollaborators ::
160+
( Member BrigAPIAccess r,
161+
Member FeaturesConfigSubsystem r
162+
) =>
163+
TeamId ->
164+
[UserId] ->
165+
Sem r (Set UserId)
166+
pseudoSuspendedCollaborators _ [] = pure Set.empty
167+
pseudoSuspendedCollaborators tid uids = do
168+
appsEnabled <- featureEnabledForTeam (Proxy @AppsConfig) tid
169+
if appsEnabled
170+
then pure Set.empty
171+
else do
172+
users <- getUsers uids
173+
pure $ Set.fromList [qUnqualified u.userQualifiedId | u <- users, u.userType == UserTypeApp]
174+
175+
isPseudoSuspended ::
176+
( Member BrigAPIAccess r,
177+
Member FeaturesConfigSubsystem r
178+
) =>
179+
TeamId ->
180+
UserId ->
181+
Sem r Bool
182+
isPseudoSuspended tid uid = Set.member uid <$> pseudoSuspendedCollaborators tid [uid]
183+
149184
-- | Look up a user as a 'TeamPrincipal': a full member (@Right@) takes
150185
-- precedence over a collaborator (@Left@). Returns 'Nothing' if the user has
151-
-- no association with the team.
186+
-- no association with the team, or if they are a pseudo-suspended collaborator
187+
-- (an app user whose team has the @apps@ feature disabled).
152188
lookupTeamPrincipal ::
153189
( Member TeamSubsystem r,
154-
Member TeamCollaboratorsSubsystem r
190+
Member TeamCollaboratorsSubsystem r,
191+
Member BrigAPIAccess r,
192+
Member FeaturesConfigSubsystem r
155193
) =>
156194
TeamId ->
157195
UserId ->
158196
Sem r (Maybe TeamPrincipal)
159197
lookupTeamPrincipal tid uid =
160198
internalGetTeamMember uid tid >>= \case
161199
Just m -> pure (Just (Right m))
162-
Nothing -> fmap Left <$> internalGetTeamCollaborator tid uid
200+
Nothing ->
201+
internalGetTeamCollaborator tid uid >>= \case
202+
Nothing -> pure Nothing
203+
Just c -> do
204+
pseudo <- isPseudoSuspended tid uid
205+
pure $ if pseudo then Nothing else Just (Left c)

0 commit comments

Comments
 (0)