@@ -4,6 +4,7 @@ module Share.Web.Share.Orgs.Impl (server) where
44
55import Control.Lens
66import Data.Either (isRight )
7+ import Data.Map qualified as Map
78import Data.Set qualified as Set
89import Servant
910import Servant.Server.Generic
@@ -104,17 +105,39 @@ addRolesEndpoint orgHandle caller (AddRolesRequest {roleAssignments}) = do
104105 assertNoOrgSubjects roleAssignments
105106 PG. runTransaction do
106107 orgRoles <- OrgQ. addOrgRoles orgId roleAssignments
108+ let newMembers =
109+ (computeOrgMembershipChanges roleAssignments)
110+ & Map. filter id
111+ & Map. keysSet
112+ OrgQ. addOrgMembers orgId newMembers
107113 ListRolesResponse True . canonicalRoleAssignmentOrdering <$> displaySubjectsOf (traversed . traversed) orgRoles
108114
109115removeRolesEndpoint :: UserHandle -> UserId -> RemoveRolesRequest -> WebApp ListRolesResponse
110116removeRolesEndpoint orgHandle caller (RemoveRolesRequest {roleAssignments}) = do
111117 orgId <- orgIdByHandle orgHandle
112118 _authZReceipt <- AuthZ. permissionGuard $ AuthZ. checkEditOrgRoles caller orgId
113119 PG. runTransactionOrRespondError do
120+ let updatedUsersMap =
121+ roleAssignments
122+ & foldMap
123+ ( \ RoleAssignment {subject} ->
124+ case subject of
125+ UserSubject userId -> Map. singleton userId Set. empty
126+ _ -> Map. empty
127+ )
114128 orgRoles <- OrgQ. removeOrgRoles orgId roleAssignments
115129 OrgQ. doesOrgHaveOwner orgId >>= \ case
116130 False -> throwError OrgMustHaveOwnerError
117131 True -> pure ()
132+ let remainingRolesMap = computeOrgMembershipChanges orgRoles
133+ let usersWithNoRemainingRoles = Map. keysSet updatedUsersMap `Set.difference` Map. keysSet remainingRolesMap
134+ let evictedMembers =
135+ remainingRolesMap
136+ -- Only keep users who should no longer be members
137+ & Map. filter not
138+ & Map. keysSet
139+ & Set. union usersWithNoRemainingRoles
140+ OrgQ. removeOrgMembers orgId evictedMembers
118141
119142 ListRolesResponse True . canonicalRoleAssignmentOrdering <$> displaySubjectsOf (traversed . traversed) orgRoles
120143
@@ -158,3 +181,35 @@ assertNoOrgSubjects roleAssignments = do
158181 )
159182 when hasOrgSubject do
160183 respondError OrgMemberOfOrgError
184+
185+ -- | This is part of a hack to temporarily fix org membership issues
186+ -- until we have time for a more robust solution.
187+ shouldRoleBeOrgMember :: RoleRef -> Bool
188+ shouldRoleBeOrgMember = \ case
189+ RoleOrgViewer -> False
190+ RoleOrgContributor -> True
191+ RoleOrgMaintainer -> True
192+ RoleOrgAdmin -> True
193+ RoleOrgOwner -> True
194+ RoleOrgDefault -> True
195+ RoleTeamAdmin -> True
196+ RoleProjectViewer -> False
197+ RoleProjectContributor -> True
198+ RoleProjectMaintainer -> True
199+ RoleProjectAdmin -> True
200+ RoleProjectOwner -> True
201+ RoleProjectPublicAccess -> False
202+
203+ -- | Returns a list of users and whether they should end up as members of the org or not
204+ computeOrgMembershipChanges :: [RoleAssignment ResolvedAuthSubject ] -> Map UserId Bool
205+ computeOrgMembershipChanges roleAssignments =
206+ roleAssignments
207+ & foldMap
208+ ( \ RoleAssignment {subject, roles} ->
209+ case subject of
210+ UserSubject userId ->
211+ let shouldBeMember = any shouldRoleBeOrgMember roles
212+ in [(userId, shouldBeMember)]
213+ _ -> mempty
214+ )
215+ & Map. fromListWith (||)
0 commit comments