-- This file is part of the Wire Server implementation.
--
-- Copyright (C) 2022 Wire Swiss GmbH <opensource@wire.com>
--
-- This program is free software: you can redistribute it and/or modify it under
-- the terms of the GNU Affero General Public License as published by the Free
-- Software Foundation, either version 3 of the License, or (at your option) any
-- later version.
--
-- This program is distributed in the hope that it will be useful, but WITHOUT
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-- details.
--
-- You should have received a copy of the GNU Affero General Public License along
-- with this program. If not, see <https://www.gnu.org/licenses/>.

module Galley.Cassandra.Conversation.Members
  ( addMembers,
    members,
    allMembers,
    toMember,
    lookupRemoteMembers,
    removeMembersFromLocalConv,
    toMemberStatus,
    interpretMemberStoreToCassandra,
  )
where

import Cassandra
import Data.Domain
import Data.Id
import Data.List.Extra qualified as List
import Data.Monoid
import Data.Qualified
import Data.Set qualified as Set
import Galley.Cassandra.Conversation.MLS
import Galley.Cassandra.Instances ()
import Galley.Cassandra.Queries qualified as Cql
import Galley.Cassandra.Services
import Galley.Cassandra.Store
import Galley.Cassandra.Util
import Galley.Effects.MemberStore (MemberStore (..))
import Galley.Types.Conversations.Members
import Galley.Types.ToUserRole
import Galley.Types.UserList
import Imports hiding (Set)
import Polysemy
import Polysemy.Input
import Polysemy.TinyLog
import UnliftIO qualified
import Wire.API.Conversation.Member hiding (Member)
import Wire.API.Conversation.Role
import Wire.API.MLS.Credential
import Wire.API.MLS.Group
import Wire.API.MLS.LeafNode (LeafIndex)
import Wire.API.Provider.Service

-- | Add members to a local conversation.
-- Conversation is local, so we can add any member to it (including remote ones).
-- When the role is not specified, it defaults to admin.
-- Please make sure the conversation doesn't exceed the maximum size!
addMembers ::
  (ToUserRole a) =>
  ConvId ->
  UserList a ->
  Client ([LocalMember], [RemoteMember])
addMembers :: forall a.
ToUserRole a =>
ConvId -> UserList a -> Client ([LocalMember], [RemoteMember])
addMembers ConvId
conv ((a -> (UserId, RoleName))
-> UserList a -> UserList (UserId, RoleName)
forall a b. (a -> b) -> UserList a -> UserList b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> (UserId, RoleName)
forall a. ToUserRole a => a -> (UserId, RoleName)
toUserRole -> UserList [(UserId, RoleName)]
lusers [Remote (UserId, RoleName)]
rusers) = do
  -- batch statement with 500 users are known to be above the batch size limit
  -- and throw "Batch too large" errors. Therefor we chunk requests and insert
  -- sequentially. (parallelizing would not aid performance as the partition
  -- key, i.e. the convId, is on the same cassandra node)
  -- chunk size 32 was chosen to lead to batch statements
  -- below the batch threshold
  -- With chunk size of 64:
  -- [galley] Server warning: Batch for [galley_test.member, galley_test.user] is of size 7040, exceeding specified threshold of 5120 by 1920.
  --
  [[(UserId, RoleName)]]
-> ([(UserId, RoleName)] -> Client ()) -> Client ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (Int -> [(UserId, RoleName)] -> [[(UserId, RoleName)]]
forall a. Partial => Int -> [a] -> [[a]]
List.chunksOf Int
32 [(UserId, RoleName)]
lusers) (([(UserId, RoleName)] -> Client ()) -> Client ())
-> ([(UserId, RoleName)] -> Client ()) -> Client ()
forall a b. (a -> b) -> a -> b
$ \[(UserId, RoleName)]
chunk -> do
    RetrySettings -> Client () -> Client ()
forall (m :: * -> *) a.
MonadClient m =>
RetrySettings -> m a -> m a
retry RetrySettings
x5 (Client () -> Client ())
-> (BatchM () -> Client ()) -> BatchM () -> Client ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BatchM () -> Client ()
forall (m :: * -> *). MonadClient m => BatchM () -> m ()
batch (BatchM () -> Client ()) -> BatchM () -> Client ()
forall a b. (a -> b) -> a -> b
$ do
      BatchType -> BatchM ()
setType BatchType
BatchLogged
      Consistency -> BatchM ()
setConsistency Consistency
LocalQuorum
      [(UserId, RoleName)]
-> ((UserId, RoleName) -> BatchM ()) -> BatchM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [(UserId, RoleName)]
chunk (((UserId, RoleName) -> BatchM ()) -> BatchM ())
-> ((UserId, RoleName) -> BatchM ()) -> BatchM ()
forall a b. (a -> b) -> a -> b
$ \(UserId
u, RoleName
r) -> do
        -- User is local, too, so we add it to both the member and the user table
        PrepQuery
  W (ConvId, UserId, Maybe ServiceId, Maybe ProviderId, RoleName) ()
-> (ConvId, UserId, Maybe ServiceId, Maybe ProviderId, RoleName)
-> BatchM ()
forall a b.
(Show a, Tuple a, Tuple b) =>
PrepQuery W a b -> a -> BatchM ()
addPrepQuery PrepQuery
  W (ConvId, UserId, Maybe ServiceId, Maybe ProviderId, RoleName) ()
Cql.insertMember (ConvId
conv, UserId
u, Maybe ServiceId
forall a. Maybe a
Nothing, Maybe ProviderId
forall a. Maybe a
Nothing, RoleName
r)
        PrepQuery W (UserId, ConvId) () -> (UserId, ConvId) -> BatchM ()
forall a b.
(Show a, Tuple a, Tuple b) =>
PrepQuery W a b -> a -> BatchM ()
addPrepQuery PrepQuery W (UserId, ConvId) ()
Cql.insertUserConv (UserId
u, ConvId
conv)

  [[Remote (UserId, RoleName)]]
-> ([Remote (UserId, RoleName)] -> Client ()) -> Client ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (Int -> [Remote (UserId, RoleName)] -> [[Remote (UserId, RoleName)]]
forall a. Partial => Int -> [a] -> [[a]]
List.chunksOf Int
32 [Remote (UserId, RoleName)]
rusers) (([Remote (UserId, RoleName)] -> Client ()) -> Client ())
-> ([Remote (UserId, RoleName)] -> Client ()) -> Client ()
forall a b. (a -> b) -> a -> b
$ \[Remote (UserId, RoleName)]
chunk -> do
    RetrySettings -> Client () -> Client ()
forall (m :: * -> *) a.
MonadClient m =>
RetrySettings -> m a -> m a
retry RetrySettings
x5 (Client () -> Client ())
-> (BatchM () -> Client ()) -> BatchM () -> Client ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BatchM () -> Client ()
forall (m :: * -> *). MonadClient m => BatchM () -> m ()
batch (BatchM () -> Client ()) -> BatchM () -> Client ()
forall a b. (a -> b) -> a -> b
$ do
      BatchType -> BatchM ()
setType BatchType
BatchLogged
      Consistency -> BatchM ()
setConsistency Consistency
LocalQuorum
      [Remote (UserId, RoleName)]
-> (Remote (UserId, RoleName) -> BatchM ()) -> BatchM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Remote (UserId, RoleName)]
chunk ((Remote (UserId, RoleName) -> BatchM ()) -> BatchM ())
-> (Remote (UserId, RoleName) -> BatchM ()) -> BatchM ()
forall a b. (a -> b) -> a -> b
$ \(Remote (UserId, RoleName) -> Qualified (UserId, RoleName)
forall (t :: QTag) a. QualifiedWithTag t a -> Qualified a
tUntagged -> Qualified (UserId
uid, RoleName
role) Domain
domain) -> do
        -- User is remote, so we only add it to the member_remote_user
        -- table, but the reverse mapping has to be done on the remote
        -- backend; so we assume an additional call to their backend has
        -- been (or will be) made separately. See Galley.API.Update.addMembers
        PrepQuery W (ConvId, Domain, UserId, RoleName) ()
-> (ConvId, Domain, UserId, RoleName) -> BatchM ()
forall a b.
(Show a, Tuple a, Tuple b) =>
PrepQuery W a b -> a -> BatchM ()
addPrepQuery PrepQuery W (ConvId, Domain, UserId, RoleName) ()
Cql.insertRemoteMember (ConvId
conv, Domain
domain, UserId
uid, RoleName
role)

  ([LocalMember], [RemoteMember])
-> Client ([LocalMember], [RemoteMember])
forall a. a -> Client a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (((UserId, RoleName) -> LocalMember)
-> [(UserId, RoleName)] -> [LocalMember]
forall a b. (a -> b) -> [a] -> [b]
map (UserId, RoleName) -> LocalMember
newMemberWithRole [(UserId, RoleName)]
lusers, (Remote (UserId, RoleName) -> RemoteMember)
-> [Remote (UserId, RoleName)] -> [RemoteMember]
forall a b. (a -> b) -> [a] -> [b]
map Remote (UserId, RoleName) -> RemoteMember
newRemoteMemberWithRole [Remote (UserId, RoleName)]
rusers)

removeMembersFromLocalConv :: ConvId -> UserList UserId -> Client ()
removeMembersFromLocalConv :: ConvId -> UserList UserId -> Client ()
removeMembersFromLocalConv ConvId
cnv UserList UserId
victims = Client ((), ()) -> Client ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Client ((), ()) -> Client ()) -> Client ((), ()) -> Client ()
forall a b. (a -> b) -> a -> b
$ do
  Client () -> Client () -> Client ((), ())
forall (m :: * -> *) a b. MonadUnliftIO m => m a -> m b -> m (a, b)
UnliftIO.concurrently
    (ConvId -> [UserId] -> Client ()
removeLocalMembersFromLocalConv ConvId
cnv (UserList UserId -> [UserId]
forall a. UserList a -> [a]
ulLocals UserList UserId
victims))
    (ConvId -> [Remote UserId] -> Client ()
removeRemoteMembersFromLocalConv ConvId
cnv (UserList UserId -> [Remote UserId]
forall a. UserList a -> [Remote a]
ulRemotes UserList UserId
victims))

removeLocalMembersFromLocalConv :: ConvId -> [UserId] -> Client ()
removeLocalMembersFromLocalConv :: ConvId -> [UserId] -> Client ()
removeLocalMembersFromLocalConv ConvId
_ [] = () -> Client ()
forall a. a -> Client a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
removeLocalMembersFromLocalConv ConvId
cnv [UserId]
victims = do
  RetrySettings -> Client () -> Client ()
forall (m :: * -> *) a.
MonadClient m =>
RetrySettings -> m a -> m a
retry RetrySettings
x5 (Client () -> Client ())
-> (BatchM () -> Client ()) -> BatchM () -> Client ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BatchM () -> Client ()
forall (m :: * -> *). MonadClient m => BatchM () -> m ()
batch (BatchM () -> Client ()) -> BatchM () -> Client ()
forall a b. (a -> b) -> a -> b
$ do
    BatchType -> BatchM ()
setType BatchType
BatchLogged
    Consistency -> BatchM ()
setConsistency Consistency
LocalQuorum
    [UserId] -> (UserId -> BatchM ()) -> BatchM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [UserId]
victims ((UserId -> BatchM ()) -> BatchM ())
-> (UserId -> BatchM ()) -> BatchM ()
forall a b. (a -> b) -> a -> b
$ \UserId
victim -> do
      PrepQuery W (ConvId, UserId) () -> (ConvId, UserId) -> BatchM ()
forall a b.
(Show a, Tuple a, Tuple b) =>
PrepQuery W a b -> a -> BatchM ()
addPrepQuery PrepQuery W (ConvId, UserId) ()
Cql.removeMember (ConvId
cnv, UserId
victim)
      PrepQuery W (UserId, ConvId) () -> (UserId, ConvId) -> BatchM ()
forall a b.
(Show a, Tuple a, Tuple b) =>
PrepQuery W a b -> a -> BatchM ()
addPrepQuery PrepQuery W (UserId, ConvId) ()
Cql.deleteUserConv (UserId
victim, ConvId
cnv)

removeRemoteMembersFromLocalConv :: ConvId -> [Remote UserId] -> Client ()
removeRemoteMembersFromLocalConv :: ConvId -> [Remote UserId] -> Client ()
removeRemoteMembersFromLocalConv ConvId
_ [] = () -> Client ()
forall a. a -> Client a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
removeRemoteMembersFromLocalConv ConvId
cnv [Remote UserId]
victims = do
  RetrySettings -> Client () -> Client ()
forall (m :: * -> *) a.
MonadClient m =>
RetrySettings -> m a -> m a
retry RetrySettings
x5 (Client () -> Client ())
-> (BatchM () -> Client ()) -> BatchM () -> Client ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BatchM () -> Client ()
forall (m :: * -> *). MonadClient m => BatchM () -> m ()
batch (BatchM () -> Client ()) -> BatchM () -> Client ()
forall a b. (a -> b) -> a -> b
$ do
    BatchType -> BatchM ()
setType BatchType
BatchLogged
    Consistency -> BatchM ()
setConsistency Consistency
LocalQuorum
    [Remote UserId] -> (Remote UserId -> BatchM ()) -> BatchM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Remote UserId]
victims ((Remote UserId -> BatchM ()) -> BatchM ())
-> (Remote UserId -> BatchM ()) -> BatchM ()
forall a b. (a -> b) -> a -> b
$ \(Remote UserId -> Qualified UserId
forall (t :: QTag) a. QualifiedWithTag t a -> Qualified a
tUntagged -> Qualified UserId
uid Domain
domain) ->
      PrepQuery W (ConvId, Domain, UserId) ()
-> (ConvId, Domain, UserId) -> BatchM ()
forall a b.
(Show a, Tuple a, Tuple b) =>
PrepQuery W a b -> a -> BatchM ()
addPrepQuery PrepQuery W (ConvId, Domain, UserId) ()
Cql.removeRemoteMember (ConvId
cnv, Domain
domain, UserId
uid)

members :: ConvId -> Client [LocalMember]
members :: ConvId -> Client [LocalMember]
members ConvId
conv =
  ([(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
   Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
   Maybe Text, Maybe RoleName)]
 -> [LocalMember])
-> Client
     [(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
       Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
       Maybe Text, Maybe RoleName)]
-> Client [LocalMember]
forall a b. (a -> b) -> Client a -> Client b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (((UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
  Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
  Maybe Text, Maybe RoleName)
 -> Maybe LocalMember)
-> [(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
     Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
     Maybe Text, Maybe RoleName)]
-> [LocalMember]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
 Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
 Maybe Text, Maybe RoleName)
-> Maybe LocalMember
toMember) (Client
   [(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
     Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
     Maybe Text, Maybe RoleName)]
 -> Client [LocalMember])
-> (Client
      [(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
        Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
        Maybe Text, Maybe RoleName)]
    -> Client
         [(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
           Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
           Maybe Text, Maybe RoleName)])
-> Client
     [(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
       Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
       Maybe Text, Maybe RoleName)]
-> Client [LocalMember]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RetrySettings
-> Client
     [(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
       Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
       Maybe Text, Maybe RoleName)]
-> Client
     [(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
       Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
       Maybe Text, Maybe RoleName)]
forall (m :: * -> *) a.
MonadClient m =>
RetrySettings -> m a -> m a
retry RetrySettings
x1 (Client
   [(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
     Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
     Maybe Text, Maybe RoleName)]
 -> Client [LocalMember])
-> Client
     [(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
       Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
       Maybe Text, Maybe RoleName)]
-> Client [LocalMember]
forall a b. (a -> b) -> a -> b
$
    PrepQuery
  R
  (Identity ConvId)
  (UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
   Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
   Maybe Text, Maybe RoleName)
-> QueryParams (Identity ConvId)
-> Client
     [(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
       Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
       Maybe Text, Maybe RoleName)]
forall (m :: * -> *) a b (q :: * -> * -> * -> *).
(MonadClient m, Tuple a, Tuple b, RunQ q) =>
q R a b -> QueryParams a -> m [b]
query PrepQuery
  R
  (Identity ConvId)
  (UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
   Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
   Maybe Text, Maybe RoleName)
Cql.selectMembers (Consistency -> Identity ConvId -> QueryParams (Identity ConvId)
forall a. Consistency -> a -> QueryParams a
params Consistency
LocalQuorum (ConvId -> Identity ConvId
forall a. a -> Identity a
Identity ConvId
conv))

allMembers :: Client [LocalMember]
allMembers :: Client [LocalMember]
allMembers =
  ([(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
   Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
   Maybe Text, Maybe RoleName)]
 -> [LocalMember])
-> Client
     [(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
       Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
       Maybe Text, Maybe RoleName)]
-> Client [LocalMember]
forall a b. (a -> b) -> Client a -> Client b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (((UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
  Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
  Maybe Text, Maybe RoleName)
 -> Maybe LocalMember)
-> [(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
     Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
     Maybe Text, Maybe RoleName)]
-> [LocalMember]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
 Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
 Maybe Text, Maybe RoleName)
-> Maybe LocalMember
toMember) (Client
   [(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
     Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
     Maybe Text, Maybe RoleName)]
 -> Client [LocalMember])
-> (Client
      [(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
        Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
        Maybe Text, Maybe RoleName)]
    -> Client
         [(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
           Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
           Maybe Text, Maybe RoleName)])
-> Client
     [(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
       Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
       Maybe Text, Maybe RoleName)]
-> Client [LocalMember]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RetrySettings
-> Client
     [(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
       Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
       Maybe Text, Maybe RoleName)]
-> Client
     [(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
       Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
       Maybe Text, Maybe RoleName)]
forall (m :: * -> *) a.
MonadClient m =>
RetrySettings -> m a -> m a
retry RetrySettings
x1 (Client
   [(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
     Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
     Maybe Text, Maybe RoleName)]
 -> Client [LocalMember])
-> Client
     [(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
       Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
       Maybe Text, Maybe RoleName)]
-> Client [LocalMember]
forall a b. (a -> b) -> a -> b
$
    PrepQuery
  R
  ()
  (UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
   Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
   Maybe Text, Maybe RoleName)
-> QueryParams ()
-> Client
     [(UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
       Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
       Maybe Text, Maybe RoleName)]
forall (m :: * -> *) a b (q :: * -> * -> * -> *).
(MonadClient m, Tuple a, Tuple b, RunQ q) =>
q R a b -> QueryParams a -> m [b]
query PrepQuery
  R
  ()
  (UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
   Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
   Maybe Text, Maybe RoleName)
Cql.selectAllMembers (Consistency -> () -> QueryParams ()
forall a. Consistency -> a -> QueryParams a
params Consistency
LocalQuorum ())

toMemberStatus ::
  ( -- otr muted
    Maybe MutedStatus,
    Maybe Text,
    -- otr archived
    Maybe Bool,
    Maybe Text,
    -- hidden
    Maybe Bool,
    Maybe Text
  ) ->
  MemberStatus
toMemberStatus :: (Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
 Maybe Text)
-> MemberStatus
toMemberStatus (Maybe MutedStatus
omus, Maybe Text
omur, Maybe Bool
oar, Maybe Text
oarr, Maybe Bool
hid, Maybe Text
hidr) =
  MemberStatus
    { $sel:msOtrMutedStatus:MemberStatus :: Maybe MutedStatus
msOtrMutedStatus = Maybe MutedStatus
omus,
      $sel:msOtrMutedRef:MemberStatus :: Maybe Text
msOtrMutedRef = Maybe Text
omur,
      $sel:msOtrArchived:MemberStatus :: Bool
msOtrArchived = Bool -> Maybe Bool -> Bool
forall a. a -> Maybe a -> a
fromMaybe Bool
False Maybe Bool
oar,
      $sel:msOtrArchivedRef:MemberStatus :: Maybe Text
msOtrArchivedRef = Maybe Text
oarr,
      $sel:msHidden:MemberStatus :: Bool
msHidden = Bool -> Maybe Bool -> Bool
forall a. a -> Maybe a -> a
fromMaybe Bool
False Maybe Bool
hid,
      $sel:msHiddenRef:MemberStatus :: Maybe Text
msHiddenRef = Maybe Text
hidr
    }

toMember ::
  ( UserId,
    Maybe ServiceId,
    Maybe ProviderId,
    Maybe Cql.MemberStatus,
    -- otr muted
    Maybe MutedStatus,
    Maybe Text,
    -- otr archived
    Maybe Bool,
    Maybe Text,
    -- hidden
    Maybe Bool,
    Maybe Text,
    -- conversation role name
    Maybe RoleName
  ) ->
  Maybe LocalMember
toMember :: (UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
 Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
 Maybe Text, Maybe RoleName)
-> Maybe LocalMember
toMember (UserId
usr, Maybe ServiceId
srv, Maybe ProviderId
prv, Just Int32
0, Maybe MutedStatus
omus, Maybe Text
omur, Maybe Bool
oar, Maybe Text
oarr, Maybe Bool
hid, Maybe Text
hidr, Maybe RoleName
crn) =
  LocalMember -> Maybe LocalMember
forall a. a -> Maybe a
Just (LocalMember -> Maybe LocalMember)
-> LocalMember -> Maybe LocalMember
forall a b. (a -> b) -> a -> b
$
    LocalMember
      { $sel:lmId:LocalMember :: UserId
lmId = UserId
usr,
        $sel:lmService:LocalMember :: Maybe ServiceRef
lmService = ServiceId -> ProviderId -> ServiceRef
newServiceRef (ServiceId -> ProviderId -> ServiceRef)
-> Maybe ServiceId -> Maybe (ProviderId -> ServiceRef)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe ServiceId
srv Maybe (ProviderId -> ServiceRef)
-> Maybe ProviderId -> Maybe ServiceRef
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe ProviderId
prv,
        $sel:lmStatus:LocalMember :: MemberStatus
lmStatus = (Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
 Maybe Text)
-> MemberStatus
toMemberStatus (Maybe MutedStatus
omus, Maybe Text
omur, Maybe Bool
oar, Maybe Text
oarr, Maybe Bool
hid, Maybe Text
hidr),
        $sel:lmConvRoleName:LocalMember :: RoleName
lmConvRoleName = RoleName -> Maybe RoleName -> RoleName
forall a. a -> Maybe a -> a
fromMaybe RoleName
roleNameWireAdmin Maybe RoleName
crn
      }
toMember (UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
 Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
 Maybe Text, Maybe RoleName)
_ = Maybe LocalMember
forall a. Maybe a
Nothing

newRemoteMemberWithRole :: Remote (UserId, RoleName) -> RemoteMember
newRemoteMemberWithRole :: Remote (UserId, RoleName) -> RemoteMember
newRemoteMemberWithRole ur :: Remote (UserId, RoleName)
ur@(Remote (UserId, RoleName) -> Qualified (UserId, RoleName)
forall (t :: QTag) a. QualifiedWithTag t a -> Qualified a
tUntagged -> (Qualified (UserId
u, RoleName
r) Domain
_)) =
  RemoteMember
    { $sel:rmId:RemoteMember :: Remote UserId
rmId = Remote (UserId, RoleName) -> UserId -> Remote UserId
forall (t :: QTag) x a.
QualifiedWithTag t x -> a -> QualifiedWithTag t a
qualifyAs Remote (UserId, RoleName)
ur UserId
u,
      $sel:rmConvRoleName:RemoteMember :: RoleName
rmConvRoleName = RoleName
r
    }

lookupRemoteMember :: ConvId -> Domain -> UserId -> Client (Maybe RemoteMember)
lookupRemoteMember :: ConvId -> Domain -> UserId -> Client (Maybe RemoteMember)
lookupRemoteMember ConvId
conv Domain
domain UserId
usr = do
  Identity RoleName -> RemoteMember
mkMem (Identity RoleName -> RemoteMember)
-> Client (Maybe (Identity RoleName))
-> Client (Maybe RemoteMember)
forall (f :: * -> *) (g :: * -> *) a b.
(Functor f, Functor g) =>
(a -> b) -> f (g a) -> f (g b)
<$$> RetrySettings
-> Client (Maybe (Identity RoleName))
-> Client (Maybe (Identity RoleName))
forall (m :: * -> *) a.
MonadClient m =>
RetrySettings -> m a -> m a
retry RetrySettings
x1 (PrepQuery R (ConvId, Domain, UserId) (Identity RoleName)
-> QueryParams (ConvId, Domain, UserId)
-> Client (Maybe (Identity RoleName))
forall (m :: * -> *) a b (q :: * -> * -> * -> *).
(MonadClient m, Tuple a, Tuple b, RunQ q) =>
q R a b -> QueryParams a -> m (Maybe b)
query1 PrepQuery R (ConvId, Domain, UserId) (Identity RoleName)
Cql.selectRemoteMember (Consistency
-> (ConvId, Domain, UserId) -> QueryParams (ConvId, Domain, UserId)
forall a. Consistency -> a -> QueryParams a
params Consistency
LocalQuorum (ConvId
conv, Domain
domain, UserId
usr)))
  where
    mkMem :: Identity RoleName -> RemoteMember
mkMem (Identity RoleName
role) =
      RemoteMember
        { $sel:rmId:RemoteMember :: Remote UserId
rmId = Domain -> UserId -> Remote UserId
forall a. Domain -> a -> Remote a
toRemoteUnsafe Domain
domain UserId
usr,
          $sel:rmConvRoleName:RemoteMember :: RoleName
rmConvRoleName = RoleName
role
        }

lookupRemoteMembers :: ConvId -> Client [RemoteMember]
lookupRemoteMembers :: ConvId -> Client [RemoteMember]
lookupRemoteMembers ConvId
conv = do
  ([(Domain, UserId, RoleName)] -> [RemoteMember])
-> Client [(Domain, UserId, RoleName)] -> Client [RemoteMember]
forall a b. (a -> b) -> Client a -> Client b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (((Domain, UserId, RoleName) -> RemoteMember)
-> [(Domain, UserId, RoleName)] -> [RemoteMember]
forall a b. (a -> b) -> [a] -> [b]
map (Domain, UserId, RoleName) -> RemoteMember
mkMem) (Client [(Domain, UserId, RoleName)] -> Client [RemoteMember])
-> (Client [(Domain, UserId, RoleName)]
    -> Client [(Domain, UserId, RoleName)])
-> Client [(Domain, UserId, RoleName)]
-> Client [RemoteMember]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RetrySettings
-> Client [(Domain, UserId, RoleName)]
-> Client [(Domain, UserId, RoleName)]
forall (m :: * -> *) a.
MonadClient m =>
RetrySettings -> m a -> m a
retry RetrySettings
x1 (Client [(Domain, UserId, RoleName)] -> Client [RemoteMember])
-> Client [(Domain, UserId, RoleName)] -> Client [RemoteMember]
forall a b. (a -> b) -> a -> b
$ PrepQuery R (Identity ConvId) (Domain, UserId, RoleName)
-> QueryParams (Identity ConvId)
-> Client [(Domain, UserId, RoleName)]
forall (m :: * -> *) a b (q :: * -> * -> * -> *).
(MonadClient m, Tuple a, Tuple b, RunQ q) =>
q R a b -> QueryParams a -> m [b]
query PrepQuery R (Identity ConvId) (Domain, UserId, RoleName)
Cql.selectRemoteMembers (Consistency -> Identity ConvId -> QueryParams (Identity ConvId)
forall a. Consistency -> a -> QueryParams a
params Consistency
LocalQuorum (ConvId -> Identity ConvId
forall a. a -> Identity a
Identity ConvId
conv))
  where
    mkMem :: (Domain, UserId, RoleName) -> RemoteMember
mkMem (Domain
domain, UserId
usr, RoleName
role) =
      RemoteMember
        { $sel:rmId:RemoteMember :: Remote UserId
rmId = Domain -> UserId -> Remote UserId
forall a. Domain -> a -> Remote a
toRemoteUnsafe Domain
domain UserId
usr,
          $sel:rmConvRoleName:RemoteMember :: RoleName
rmConvRoleName = RoleName
role
        }

lookupRemoteMembersByDomain :: Domain -> Client [(ConvId, RemoteMember)]
lookupRemoteMembersByDomain :: Domain -> Client [(ConvId, RemoteMember)]
lookupRemoteMembersByDomain Domain
dom = do
  ([(ConvId, UserId, RoleName)] -> [(ConvId, RemoteMember)])
-> Client [(ConvId, UserId, RoleName)]
-> Client [(ConvId, RemoteMember)]
forall a b. (a -> b) -> Client a -> Client b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (((ConvId, UserId, RoleName) -> (ConvId, RemoteMember))
-> [(ConvId, UserId, RoleName)] -> [(ConvId, RemoteMember)]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (ConvId, UserId, RoleName) -> (ConvId, RemoteMember)
mkConvMem) (Client [(ConvId, UserId, RoleName)]
 -> Client [(ConvId, RemoteMember)])
-> (Client [(ConvId, UserId, RoleName)]
    -> Client [(ConvId, UserId, RoleName)])
-> Client [(ConvId, UserId, RoleName)]
-> Client [(ConvId, RemoteMember)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RetrySettings
-> Client [(ConvId, UserId, RoleName)]
-> Client [(ConvId, UserId, RoleName)]
forall (m :: * -> *) a.
MonadClient m =>
RetrySettings -> m a -> m a
retry RetrySettings
x1 (Client [(ConvId, UserId, RoleName)]
 -> Client [(ConvId, RemoteMember)])
-> Client [(ConvId, UserId, RoleName)]
-> Client [(ConvId, RemoteMember)]
forall a b. (a -> b) -> a -> b
$ PrepQuery R (Identity Domain) (ConvId, UserId, RoleName)
-> QueryParams (Identity Domain)
-> Client [(ConvId, UserId, RoleName)]
forall (m :: * -> *) a b (q :: * -> * -> * -> *).
(MonadClient m, Tuple a, Tuple b, RunQ q) =>
q R a b -> QueryParams a -> m [b]
query PrepQuery R (Identity Domain) (ConvId, UserId, RoleName)
Cql.selectRemoteMembersByDomain (Consistency -> Identity Domain -> QueryParams (Identity Domain)
forall a. Consistency -> a -> QueryParams a
params Consistency
LocalQuorum (Domain -> Identity Domain
forall a. a -> Identity a
Identity Domain
dom))
  where
    mkConvMem :: (ConvId, UserId, RoleName) -> (ConvId, RemoteMember)
mkConvMem (ConvId
convId, UserId
usr, RoleName
role) = (ConvId
convId, Remote UserId -> RoleName -> RemoteMember
RemoteMember (Domain -> UserId -> Remote UserId
forall a. Domain -> a -> Remote a
toRemoteUnsafe Domain
dom UserId
usr) RoleName
role)

lookupLocalMembersByDomain :: Domain -> Client [(ConvId, UserId)]
lookupLocalMembersByDomain :: Domain -> Client [(ConvId, UserId)]
lookupLocalMembersByDomain Domain
dom = do
  RetrySettings
-> Client [(ConvId, UserId)] -> Client [(ConvId, UserId)]
forall (m :: * -> *) a.
MonadClient m =>
RetrySettings -> m a -> m a
retry RetrySettings
x1 (Client [(ConvId, UserId)] -> Client [(ConvId, UserId)])
-> Client [(ConvId, UserId)] -> Client [(ConvId, UserId)]
forall a b. (a -> b) -> a -> b
$ PrepQuery R (Identity Domain) (ConvId, UserId)
-> QueryParams (Identity Domain) -> Client [(ConvId, UserId)]
forall (m :: * -> *) a b (q :: * -> * -> * -> *).
(MonadClient m, Tuple a, Tuple b, RunQ q) =>
q R a b -> QueryParams a -> m [b]
query PrepQuery R (Identity Domain) (ConvId, UserId)
Cql.selectLocalMembersByDomain (Consistency -> Identity Domain -> QueryParams (Identity Domain)
forall a. Consistency -> a -> QueryParams a
params Consistency
LocalQuorum (Domain -> Identity Domain
forall a. a -> Identity a
Identity Domain
dom))

member ::
  ConvId ->
  UserId ->
  Client (Maybe LocalMember)
member :: ConvId -> UserId -> Client (Maybe LocalMember)
member ConvId
cnv UserId
usr =
  ((UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
 Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
 Maybe Text, Maybe RoleName)
-> Maybe LocalMember
toMember =<<)
    (Maybe
   (UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
    Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
    Maybe Text, Maybe RoleName)
 -> Maybe LocalMember)
-> Client
     (Maybe
        (UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
         Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
         Maybe Text, Maybe RoleName))
-> Client (Maybe LocalMember)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> RetrySettings
-> Client
     (Maybe
        (UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
         Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
         Maybe Text, Maybe RoleName))
-> Client
     (Maybe
        (UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
         Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
         Maybe Text, Maybe RoleName))
forall (m :: * -> *) a.
MonadClient m =>
RetrySettings -> m a -> m a
retry RetrySettings
x1 (PrepQuery
  R
  (ConvId, UserId)
  (UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
   Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
   Maybe Text, Maybe RoleName)
-> QueryParams (ConvId, UserId)
-> Client
     (Maybe
        (UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
         Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
         Maybe Text, Maybe RoleName))
forall (m :: * -> *) a b (q :: * -> * -> * -> *).
(MonadClient m, Tuple a, Tuple b, RunQ q) =>
q R a b -> QueryParams a -> m (Maybe b)
query1 PrepQuery
  R
  (ConvId, UserId)
  (UserId, Maybe ServiceId, Maybe ProviderId, Maybe Int32,
   Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool,
   Maybe Text, Maybe RoleName)
Cql.selectMember (Consistency -> (ConvId, UserId) -> QueryParams (ConvId, UserId)
forall a. Consistency -> a -> QueryParams a
params Consistency
LocalQuorum (ConvId
cnv, UserId
usr)))

-- | Set local users as belonging to a remote conversation. This is invoked by a
-- remote galley when users from the current backend are added to conversations
-- on the remote end.
addLocalMembersToRemoteConv :: Remote ConvId -> [UserId] -> Client ()
addLocalMembersToRemoteConv :: Remote ConvId -> [UserId] -> Client ()
addLocalMembersToRemoteConv Remote ConvId
_ [] = () -> Client ()
forall a. a -> Client a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
addLocalMembersToRemoteConv Remote ConvId
rconv [UserId]
users = do
  -- FUTUREWORK: consider using pooledMapConcurrentlyN
  [[UserId]] -> ([UserId] -> Client ()) -> Client ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (Int -> [UserId] -> [[UserId]]
forall a. Partial => Int -> [a] -> [[a]]
List.chunksOf Int
32 [UserId]
users) (([UserId] -> Client ()) -> Client ())
-> ([UserId] -> Client ()) -> Client ()
forall a b. (a -> b) -> a -> b
$ \[UserId]
chunk ->
    RetrySettings -> Client () -> Client ()
forall (m :: * -> *) a.
MonadClient m =>
RetrySettings -> m a -> m a
retry RetrySettings
x5 (Client () -> Client ())
-> (BatchM () -> Client ()) -> BatchM () -> Client ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BatchM () -> Client ()
forall (m :: * -> *). MonadClient m => BatchM () -> m ()
batch (BatchM () -> Client ()) -> BatchM () -> Client ()
forall a b. (a -> b) -> a -> b
$ do
      BatchType -> BatchM ()
setType BatchType
BatchLogged
      Consistency -> BatchM ()
setConsistency Consistency
LocalQuorum
      [UserId] -> (UserId -> BatchM ()) -> BatchM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [UserId]
chunk ((UserId -> BatchM ()) -> BatchM ())
-> (UserId -> BatchM ()) -> BatchM ()
forall a b. (a -> b) -> a -> b
$ \UserId
u ->
        PrepQuery W (UserId, Domain, ConvId) ()
-> (UserId, Domain, ConvId) -> BatchM ()
forall a b.
(Show a, Tuple a, Tuple b) =>
PrepQuery W a b -> a -> BatchM ()
addPrepQuery
          PrepQuery W (UserId, Domain, ConvId) ()
Cql.insertUserRemoteConv
          (UserId
u, Remote ConvId -> Domain
forall (t :: QTag) a. QualifiedWithTag t a -> Domain
tDomain Remote ConvId
rconv, Remote ConvId -> ConvId
forall (t :: QTag) a. QualifiedWithTag t a -> a
tUnqualified Remote ConvId
rconv)

updateSelfMember ::
  Qualified ConvId ->
  Local UserId ->
  MemberUpdate ->
  Client ()
updateSelfMember :: Qualified ConvId -> Local UserId -> MemberUpdate -> Client ()
updateSelfMember Qualified ConvId
qcnv Local UserId
lusr =
  Local UserId
-> (Local ConvId -> Local UserId -> MemberUpdate -> Client ())
-> (Remote ConvId -> Local UserId -> MemberUpdate -> Client ())
-> Qualified ConvId
-> Local UserId
-> MemberUpdate
-> Client ()
forall x a b.
Local x -> (Local a -> b) -> (Remote a -> b) -> Qualified a -> b
foldQualified
    Local UserId
lusr
    Local ConvId -> Local UserId -> MemberUpdate -> Client ()
updateSelfMemberLocalConv
    Remote ConvId -> Local UserId -> MemberUpdate -> Client ()
updateSelfMemberRemoteConv
    Qualified ConvId
qcnv
    Local UserId
lusr

updateSelfMemberLocalConv ::
  Local ConvId ->
  Local UserId ->
  MemberUpdate ->
  Client ()
updateSelfMemberLocalConv :: Local ConvId -> Local UserId -> MemberUpdate -> Client ()
updateSelfMemberLocalConv Local ConvId
lcid Local UserId
luid MemberUpdate
mup = do
  RetrySettings -> Client () -> Client ()
forall (m :: * -> *) a.
MonadClient m =>
RetrySettings -> m a -> m a
retry RetrySettings
x5 (Client () -> Client ())
-> (BatchM () -> Client ()) -> BatchM () -> Client ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BatchM () -> Client ()
forall (m :: * -> *). MonadClient m => BatchM () -> m ()
batch (BatchM () -> Client ()) -> BatchM () -> Client ()
forall a b. (a -> b) -> a -> b
$ do
    BatchType -> BatchM ()
setType BatchType
BatchUnLogged
    Consistency -> BatchM ()
setConsistency Consistency
LocalQuorum
    Maybe MutedStatus -> (MutedStatus -> BatchM ()) -> BatchM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (MemberUpdate -> Maybe MutedStatus
mupOtrMuteStatus MemberUpdate
mup) ((MutedStatus -> BatchM ()) -> BatchM ())
-> (MutedStatus -> BatchM ()) -> BatchM ()
forall a b. (a -> b) -> a -> b
$ \MutedStatus
ms ->
      PrepQuery W (MutedStatus, Maybe Text, ConvId, UserId) ()
-> (MutedStatus, Maybe Text, ConvId, UserId) -> BatchM ()
forall a b.
(Show a, Tuple a, Tuple b) =>
PrepQuery W a b -> a -> BatchM ()
addPrepQuery
        PrepQuery W (MutedStatus, Maybe Text, ConvId, UserId) ()
Cql.updateOtrMemberMutedStatus
        (MutedStatus
ms, MemberUpdate -> Maybe Text
mupOtrMuteRef MemberUpdate
mup, Local ConvId -> ConvId
forall (t :: QTag) a. QualifiedWithTag t a -> a
tUnqualified Local ConvId
lcid, Local UserId -> UserId
forall (t :: QTag) a. QualifiedWithTag t a -> a
tUnqualified Local UserId
luid)
    Maybe Bool -> (Bool -> BatchM ()) -> BatchM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (MemberUpdate -> Maybe Bool
mupOtrArchive MemberUpdate
mup) ((Bool -> BatchM ()) -> BatchM ())
-> (Bool -> BatchM ()) -> BatchM ()
forall a b. (a -> b) -> a -> b
$ \Bool
a ->
      PrepQuery W (Bool, Maybe Text, ConvId, UserId) ()
-> (Bool, Maybe Text, ConvId, UserId) -> BatchM ()
forall a b.
(Show a, Tuple a, Tuple b) =>
PrepQuery W a b -> a -> BatchM ()
addPrepQuery
        PrepQuery W (Bool, Maybe Text, ConvId, UserId) ()
Cql.updateOtrMemberArchived
        (Bool
a, MemberUpdate -> Maybe Text
mupOtrArchiveRef MemberUpdate
mup, Local ConvId -> ConvId
forall (t :: QTag) a. QualifiedWithTag t a -> a
tUnqualified Local ConvId
lcid, Local UserId -> UserId
forall (t :: QTag) a. QualifiedWithTag t a -> a
tUnqualified Local UserId
luid)
    Maybe Bool -> (Bool -> BatchM ()) -> BatchM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (MemberUpdate -> Maybe Bool
mupHidden MemberUpdate
mup) ((Bool -> BatchM ()) -> BatchM ())
-> (Bool -> BatchM ()) -> BatchM ()
forall a b. (a -> b) -> a -> b
$ \Bool
h ->
      PrepQuery W (Bool, Maybe Text, ConvId, UserId) ()
-> (Bool, Maybe Text, ConvId, UserId) -> BatchM ()
forall a b.
(Show a, Tuple a, Tuple b) =>
PrepQuery W a b -> a -> BatchM ()
addPrepQuery
        PrepQuery W (Bool, Maybe Text, ConvId, UserId) ()
Cql.updateMemberHidden
        (Bool
h, MemberUpdate -> Maybe Text
mupHiddenRef MemberUpdate
mup, Local ConvId -> ConvId
forall (t :: QTag) a. QualifiedWithTag t a -> a
tUnqualified Local ConvId
lcid, Local UserId -> UserId
forall (t :: QTag) a. QualifiedWithTag t a -> a
tUnqualified Local UserId
luid)

updateSelfMemberRemoteConv ::
  Remote ConvId ->
  Local UserId ->
  MemberUpdate ->
  Client ()
updateSelfMemberRemoteConv :: Remote ConvId -> Local UserId -> MemberUpdate -> Client ()
updateSelfMemberRemoteConv (Remote ConvId -> Qualified ConvId
forall (t :: QTag) a. QualifiedWithTag t a -> Qualified a
tUntagged -> Qualified ConvId
cid Domain
domain) Local UserId
luid MemberUpdate
mup = do
  RetrySettings -> Client () -> Client ()
forall (m :: * -> *) a.
MonadClient m =>
RetrySettings -> m a -> m a
retry RetrySettings
x5 (Client () -> Client ())
-> (BatchM () -> Client ()) -> BatchM () -> Client ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BatchM () -> Client ()
forall (m :: * -> *). MonadClient m => BatchM () -> m ()
batch (BatchM () -> Client ()) -> BatchM () -> Client ()
forall a b. (a -> b) -> a -> b
$ do
    BatchType -> BatchM ()
setType BatchType
BatchUnLogged
    Consistency -> BatchM ()
setConsistency Consistency
LocalQuorum
    Maybe MutedStatus -> (MutedStatus -> BatchM ()) -> BatchM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (MemberUpdate -> Maybe MutedStatus
mupOtrMuteStatus MemberUpdate
mup) ((MutedStatus -> BatchM ()) -> BatchM ())
-> (MutedStatus -> BatchM ()) -> BatchM ()
forall a b. (a -> b) -> a -> b
$ \MutedStatus
ms ->
      PrepQuery W (MutedStatus, Maybe Text, Domain, ConvId, UserId) ()
-> (MutedStatus, Maybe Text, Domain, ConvId, UserId) -> BatchM ()
forall a b.
(Show a, Tuple a, Tuple b) =>
PrepQuery W a b -> a -> BatchM ()
addPrepQuery
        PrepQuery W (MutedStatus, Maybe Text, Domain, ConvId, UserId) ()
Cql.updateRemoteOtrMemberMutedStatus
        (MutedStatus
ms, MemberUpdate -> Maybe Text
mupOtrMuteRef MemberUpdate
mup, Domain
domain, ConvId
cid, Local UserId -> UserId
forall (t :: QTag) a. QualifiedWithTag t a -> a
tUnqualified Local UserId
luid)
    Maybe Bool -> (Bool -> BatchM ()) -> BatchM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (MemberUpdate -> Maybe Bool
mupOtrArchive MemberUpdate
mup) ((Bool -> BatchM ()) -> BatchM ())
-> (Bool -> BatchM ()) -> BatchM ()
forall a b. (a -> b) -> a -> b
$ \Bool
a ->
      PrepQuery W (Bool, Maybe Text, Domain, ConvId, UserId) ()
-> (Bool, Maybe Text, Domain, ConvId, UserId) -> BatchM ()
forall a b.
(Show a, Tuple a, Tuple b) =>
PrepQuery W a b -> a -> BatchM ()
addPrepQuery
        PrepQuery W (Bool, Maybe Text, Domain, ConvId, UserId) ()
Cql.updateRemoteOtrMemberArchived
        (Bool
a, MemberUpdate -> Maybe Text
mupOtrArchiveRef MemberUpdate
mup, Domain
domain, ConvId
cid, Local UserId -> UserId
forall (t :: QTag) a. QualifiedWithTag t a -> a
tUnqualified Local UserId
luid)
    Maybe Bool -> (Bool -> BatchM ()) -> BatchM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (MemberUpdate -> Maybe Bool
mupHidden MemberUpdate
mup) ((Bool -> BatchM ()) -> BatchM ())
-> (Bool -> BatchM ()) -> BatchM ()
forall a b. (a -> b) -> a -> b
$ \Bool
h ->
      PrepQuery W (Bool, Maybe Text, Domain, ConvId, UserId) ()
-> (Bool, Maybe Text, Domain, ConvId, UserId) -> BatchM ()
forall a b.
(Show a, Tuple a, Tuple b) =>
PrepQuery W a b -> a -> BatchM ()
addPrepQuery
        PrepQuery W (Bool, Maybe Text, Domain, ConvId, UserId) ()
Cql.updateRemoteMemberHidden
        (Bool
h, MemberUpdate -> Maybe Text
mupHiddenRef MemberUpdate
mup, Domain
domain, ConvId
cid, Local UserId -> UserId
forall (t :: QTag) a. QualifiedWithTag t a -> a
tUnqualified Local UserId
luid)

updateOtherMemberLocalConv ::
  Local ConvId ->
  Qualified UserId ->
  OtherMemberUpdate ->
  Client ()
updateOtherMemberLocalConv :: Local ConvId -> Qualified UserId -> OtherMemberUpdate -> Client ()
updateOtherMemberLocalConv Local ConvId
lcid Qualified UserId
quid OtherMemberUpdate
omu =
  do
    let addQuery :: RoleName -> BatchM ()
addQuery RoleName
r
          | Local ConvId -> Domain
forall (t :: QTag) a. QualifiedWithTag t a -> Domain
tDomain Local ConvId
lcid Domain -> Domain -> Bool
forall a. Eq a => a -> a -> Bool
== Qualified UserId -> Domain
forall a. Qualified a -> Domain
qDomain Qualified UserId
quid =
              PrepQuery W (RoleName, ConvId, UserId) ()
-> (RoleName, ConvId, UserId) -> BatchM ()
forall a b.
(Show a, Tuple a, Tuple b) =>
PrepQuery W a b -> a -> BatchM ()
addPrepQuery
                PrepQuery W (RoleName, ConvId, UserId) ()
Cql.updateMemberConvRoleName
                (RoleName
r, Local ConvId -> ConvId
forall (t :: QTag) a. QualifiedWithTag t a -> a
tUnqualified Local ConvId
lcid, Qualified UserId -> UserId
forall a. Qualified a -> a
qUnqualified Qualified UserId
quid)
          | Bool
otherwise =
              PrepQuery W (RoleName, ConvId, Domain, UserId) ()
-> (RoleName, ConvId, Domain, UserId) -> BatchM ()
forall a b.
(Show a, Tuple a, Tuple b) =>
PrepQuery W a b -> a -> BatchM ()
addPrepQuery
                PrepQuery W (RoleName, ConvId, Domain, UserId) ()
Cql.updateRemoteMemberConvRoleName
                (RoleName
r, Local ConvId -> ConvId
forall (t :: QTag) a. QualifiedWithTag t a -> a
tUnqualified Local ConvId
lcid, Qualified UserId -> Domain
forall a. Qualified a -> Domain
qDomain Qualified UserId
quid, Qualified UserId -> UserId
forall a. Qualified a -> a
qUnqualified Qualified UserId
quid)
    RetrySettings -> Client () -> Client ()
forall (m :: * -> *) a.
MonadClient m =>
RetrySettings -> m a -> m a
retry RetrySettings
x5 (Client () -> Client ())
-> (BatchM () -> Client ()) -> BatchM () -> Client ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BatchM () -> Client ()
forall (m :: * -> *). MonadClient m => BatchM () -> m ()
batch (BatchM () -> Client ()) -> BatchM () -> Client ()
forall a b. (a -> b) -> a -> b
$ do
      BatchType -> BatchM ()
setType BatchType
BatchUnLogged
      Consistency -> BatchM ()
setConsistency Consistency
LocalQuorum
      (RoleName -> BatchM ()) -> Maybe RoleName -> BatchM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ RoleName -> BatchM ()
addQuery (OtherMemberUpdate -> Maybe RoleName
omuConvRoleName OtherMemberUpdate
omu)

-- | Select only the members of a remote conversation from a list of users.
-- Return the filtered list and a boolean indicating whether the all the input
-- users are members.
filterRemoteConvMembers ::
  [UserId] ->
  Remote ConvId ->
  Client ([UserId], Bool)
filterRemoteConvMembers :: [UserId] -> Remote ConvId -> Client ([UserId], Bool)
filterRemoteConvMembers [UserId]
users (Remote ConvId -> Qualified ConvId
forall (t :: QTag) a. QualifiedWithTag t a -> Qualified a
tUntagged -> Qualified ConvId
conv Domain
dom) =
  (All -> Bool) -> ([UserId], All) -> ([UserId], Bool)
forall a b. (a -> b) -> ([UserId], a) -> ([UserId], b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap All -> Bool
Data.Monoid.getAll
    (([UserId], All) -> ([UserId], Bool))
-> ([[UserId]] -> ([UserId], All))
-> [[UserId]]
-> ([UserId], Bool)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([UserId] -> ([UserId], All)) -> [[UserId]] -> ([UserId], All)
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (\[UserId]
muser -> ([UserId]
muser, Bool -> All
Data.Monoid.All (Bool -> Bool
not ([UserId] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [UserId]
muser))))
    ([[UserId]] -> ([UserId], Bool))
-> Client [[UserId]] -> Client ([UserId], Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> (UserId -> Client [UserId]) -> [UserId] -> Client [[UserId]]
forall (m :: * -> *) (t :: * -> *) a b.
(MonadUnliftIO m, Traversable t) =>
Int -> (a -> m b) -> t a -> m (t b)
UnliftIO.pooledMapConcurrentlyN Int
8 UserId -> Client [UserId]
filterMember [UserId]
users
  where
    filterMember :: UserId -> Client [UserId]
    filterMember :: UserId -> Client [UserId]
filterMember UserId
user =
      ([Identity UserId] -> [UserId])
-> Client [Identity UserId] -> Client [UserId]
forall a b. (a -> b) -> Client a -> Client b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Identity UserId -> UserId) -> [Identity UserId] -> [UserId]
forall a b. (a -> b) -> [a] -> [b]
map Identity UserId -> UserId
forall a. Identity a -> a
runIdentity)
        (Client [Identity UserId] -> Client [UserId])
-> (Client [Identity UserId] -> Client [Identity UserId])
-> Client [Identity UserId]
-> Client [UserId]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RetrySettings
-> Client [Identity UserId] -> Client [Identity UserId]
forall (m :: * -> *) a.
MonadClient m =>
RetrySettings -> m a -> m a
retry RetrySettings
x1
        (Client [Identity UserId] -> Client [UserId])
-> Client [Identity UserId] -> Client [UserId]
forall a b. (a -> b) -> a -> b
$ PrepQuery R (UserId, Domain, ConvId) (Identity UserId)
-> QueryParams (UserId, Domain, ConvId) -> Client [Identity UserId]
forall (m :: * -> *) a b (q :: * -> * -> * -> *).
(MonadClient m, Tuple a, Tuple b, RunQ q) =>
q R a b -> QueryParams a -> m [b]
query PrepQuery R (UserId, Domain, ConvId) (Identity UserId)
Cql.selectRemoteConvMembers (Consistency
-> (UserId, Domain, ConvId) -> QueryParams (UserId, Domain, ConvId)
forall a. Consistency -> a -> QueryParams a
params Consistency
LocalQuorum (UserId
user, Domain
dom, ConvId
conv))

lookupLocalMemberRemoteConv ::
  UserId ->
  Remote ConvId ->
  Client (Maybe UserId)
lookupLocalMemberRemoteConv :: UserId -> Remote ConvId -> Client (Maybe UserId)
lookupLocalMemberRemoteConv UserId
userId (Remote ConvId -> Qualified ConvId
forall (t :: QTag) a. QualifiedWithTag t a -> Qualified a
tUntagged -> Qualified ConvId
conv Domain
dom) =
  Identity UserId -> UserId
forall a. Identity a -> a
runIdentity
    (Identity UserId -> UserId)
-> Client (Maybe (Identity UserId)) -> Client (Maybe UserId)
forall (f :: * -> *) (g :: * -> *) a b.
(Functor f, Functor g) =>
(a -> b) -> f (g a) -> f (g b)
<$$> RetrySettings
-> Client (Maybe (Identity UserId))
-> Client (Maybe (Identity UserId))
forall (m :: * -> *) a.
MonadClient m =>
RetrySettings -> m a -> m a
retry
      RetrySettings
x5
      (PrepQuery R (UserId, Domain, ConvId) (Identity UserId)
-> QueryParams (UserId, Domain, ConvId)
-> Client (Maybe (Identity UserId))
forall (m :: * -> *) a b (q :: * -> * -> * -> *).
(MonadClient m, Tuple a, Tuple b, RunQ q) =>
q R a b -> QueryParams a -> m (Maybe b)
query1 PrepQuery R (UserId, Domain, ConvId) (Identity UserId)
Cql.selectRemoteConvMembers (Consistency
-> (UserId, Domain, ConvId) -> QueryParams (UserId, Domain, ConvId)
forall a. Consistency -> a -> QueryParams a
params Consistency
LocalQuorum (UserId
userId, Domain
dom, ConvId
conv)))

removeLocalMembersFromRemoteConv ::
  -- | The conversation to remove members from
  Remote ConvId ->
  -- | Members to remove local to this backend
  [UserId] ->
  Client ()
removeLocalMembersFromRemoteConv :: Remote ConvId -> [UserId] -> Client ()
removeLocalMembersFromRemoteConv Remote ConvId
_ [] = () -> Client ()
forall a. a -> Client a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
removeLocalMembersFromRemoteConv (Remote ConvId -> Qualified ConvId
forall (t :: QTag) a. QualifiedWithTag t a -> Qualified a
tUntagged -> Qualified ConvId
conv Domain
convDomain) [UserId]
victims =
  RetrySettings -> Client () -> Client ()
forall (m :: * -> *) a.
MonadClient m =>
RetrySettings -> m a -> m a
retry RetrySettings
x5 (Client () -> Client ())
-> (BatchM () -> Client ()) -> BatchM () -> Client ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BatchM () -> Client ()
forall (m :: * -> *). MonadClient m => BatchM () -> m ()
batch (BatchM () -> Client ()) -> BatchM () -> Client ()
forall a b. (a -> b) -> a -> b
$ do
    BatchType -> BatchM ()
setType BatchType
BatchLogged
    Consistency -> BatchM ()
setConsistency Consistency
LocalQuorum
    [UserId] -> (UserId -> BatchM ()) -> BatchM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [UserId]
victims ((UserId -> BatchM ()) -> BatchM ())
-> (UserId -> BatchM ()) -> BatchM ()
forall a b. (a -> b) -> a -> b
$ \UserId
u -> PrepQuery W (UserId, Domain, ConvId) ()
-> (UserId, Domain, ConvId) -> BatchM ()
forall a b.
(Show a, Tuple a, Tuple b) =>
PrepQuery W a b -> a -> BatchM ()
addPrepQuery PrepQuery W (UserId, Domain, ConvId) ()
Cql.deleteUserRemoteConv (UserId
u, Domain
convDomain, ConvId
conv)

addMLSClients :: GroupId -> Qualified UserId -> Set.Set (ClientId, LeafIndex) -> Client ()
addMLSClients :: GroupId
-> Qualified UserId -> Set (ClientId, LeafIndex) -> Client ()
addMLSClients GroupId
groupId (Qualified UserId
usr Domain
domain) Set (ClientId, LeafIndex)
cs = RetrySettings -> Client () -> Client ()
forall (m :: * -> *) a.
MonadClient m =>
RetrySettings -> m a -> m a
retry RetrySettings
x5 (Client () -> Client ())
-> (BatchM () -> Client ()) -> BatchM () -> Client ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BatchM () -> Client ()
forall (m :: * -> *). MonadClient m => BatchM () -> m ()
batch (BatchM () -> Client ()) -> BatchM () -> Client ()
forall a b. (a -> b) -> a -> b
$ do
  BatchType -> BatchM ()
setType BatchType
BatchLogged
  Consistency -> BatchM ()
setConsistency Consistency
LocalQuorum
  Set (ClientId, LeafIndex)
-> ((ClientId, LeafIndex) -> BatchM ()) -> BatchM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ Set (ClientId, LeafIndex)
cs (((ClientId, LeafIndex) -> BatchM ()) -> BatchM ())
-> ((ClientId, LeafIndex) -> BatchM ()) -> BatchM ()
forall a b. (a -> b) -> a -> b
$ \(ClientId
c, LeafIndex
idx) ->
    PrepQuery W (GroupId, Domain, UserId, ClientId, Int32) ()
-> (GroupId, Domain, UserId, ClientId, Int32) -> BatchM ()
forall a b.
(Show a, Tuple a, Tuple b) =>
PrepQuery W a b -> a -> BatchM ()
addPrepQuery PrepQuery W (GroupId, Domain, UserId, ClientId, Int32) ()
Cql.addMLSClient (GroupId
groupId, Domain
domain, UserId
usr, ClientId
c, LeafIndex -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral LeafIndex
idx)

planMLSClientRemoval :: (Foldable f) => GroupId -> f ClientIdentity -> Client ()
planMLSClientRemoval :: forall (f :: * -> *).
Foldable f =>
GroupId -> f ClientIdentity -> Client ()
planMLSClientRemoval GroupId
groupId f ClientIdentity
cids =
  RetrySettings -> Client () -> Client ()
forall (m :: * -> *) a.
MonadClient m =>
RetrySettings -> m a -> m a
retry RetrySettings
x5 (Client () -> Client ())
-> (BatchM () -> Client ()) -> BatchM () -> Client ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BatchM () -> Client ()
forall (m :: * -> *). MonadClient m => BatchM () -> m ()
batch (BatchM () -> Client ()) -> BatchM () -> Client ()
forall a b. (a -> b) -> a -> b
$ do
    BatchType -> BatchM ()
setType BatchType
BatchLogged
    Consistency -> BatchM ()
setConsistency Consistency
LocalQuorum
    f ClientIdentity -> (ClientIdentity -> BatchM ()) -> BatchM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ f ClientIdentity
cids ((ClientIdentity -> BatchM ()) -> BatchM ())
-> (ClientIdentity -> BatchM ()) -> BatchM ()
forall a b. (a -> b) -> a -> b
$ \ClientIdentity
cid -> do
      PrepQuery W (GroupId, Domain, UserId, ClientId) ()
-> (GroupId, Domain, UserId, ClientId) -> BatchM ()
forall a b.
(Show a, Tuple a, Tuple b) =>
PrepQuery W a b -> a -> BatchM ()
addPrepQuery
        PrepQuery W (GroupId, Domain, UserId, ClientId) ()
Cql.planMLSClientRemoval
        (GroupId
groupId, ClientIdentity -> Domain
ciDomain ClientIdentity
cid, ClientIdentity -> UserId
ciUser ClientIdentity
cid, ClientIdentity -> ClientId
ciClient ClientIdentity
cid)

removeMLSClients :: GroupId -> Qualified UserId -> Set.Set ClientId -> Client ()
removeMLSClients :: GroupId -> Qualified UserId -> Set ClientId -> Client ()
removeMLSClients GroupId
groupId (Qualified UserId
usr Domain
domain) Set ClientId
cs = RetrySettings -> Client () -> Client ()
forall (m :: * -> *) a.
MonadClient m =>
RetrySettings -> m a -> m a
retry RetrySettings
x5 (Client () -> Client ())
-> (BatchM () -> Client ()) -> BatchM () -> Client ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BatchM () -> Client ()
forall (m :: * -> *). MonadClient m => BatchM () -> m ()
batch (BatchM () -> Client ()) -> BatchM () -> Client ()
forall a b. (a -> b) -> a -> b
$ do
  BatchType -> BatchM ()
setType BatchType
BatchLogged
  Consistency -> BatchM ()
setConsistency Consistency
LocalQuorum
  Set ClientId -> (ClientId -> BatchM ()) -> BatchM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ Set ClientId
cs ((ClientId -> BatchM ()) -> BatchM ())
-> (ClientId -> BatchM ()) -> BatchM ()
forall a b. (a -> b) -> a -> b
$ \ClientId
c ->
    PrepQuery W (GroupId, Domain, UserId, ClientId) ()
-> (GroupId, Domain, UserId, ClientId) -> BatchM ()
forall a b.
(Show a, Tuple a, Tuple b) =>
PrepQuery W a b -> a -> BatchM ()
addPrepQuery PrepQuery W (GroupId, Domain, UserId, ClientId) ()
Cql.removeMLSClient (GroupId
groupId, Domain
domain, UserId
usr, ClientId
c)

removeAllMLSClients :: GroupId -> Client ()
removeAllMLSClients :: GroupId -> Client ()
removeAllMLSClients GroupId
groupId = do
  RetrySettings -> Client () -> Client ()
forall (m :: * -> *) a.
MonadClient m =>
RetrySettings -> m a -> m a
retry RetrySettings
x5 (Client () -> Client ()) -> Client () -> Client ()
forall a b. (a -> b) -> a -> b
$ PrepQuery W (Identity GroupId) ()
-> QueryParams (Identity GroupId) -> Client ()
forall (m :: * -> *) a (q :: * -> * -> * -> *).
(MonadClient m, Tuple a, RunQ q) =>
q W a () -> QueryParams a -> m ()
write PrepQuery W (Identity GroupId) ()
Cql.removeAllMLSClients (Consistency -> Identity GroupId -> QueryParams (Identity GroupId)
forall a. Consistency -> a -> QueryParams a
params Consistency
LocalQuorum (GroupId -> Identity GroupId
forall a. a -> Identity a
Identity GroupId
groupId))

interpretMemberStoreToCassandra ::
  ( Member (Embed IO) r,
    Member (Input ClientState) r,
    Member TinyLog r
  ) =>
  Sem (MemberStore ': r) a ->
  Sem r a
interpretMemberStoreToCassandra :: forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r,
 Member TinyLog r) =>
Sem (MemberStore : r) a -> Sem r a
interpretMemberStoreToCassandra = (forall (rInitial :: EffectRow) x.
 MemberStore (Sem rInitial) x -> Sem r x)
-> Sem (MemberStore : r) a -> Sem r a
forall (e :: (* -> *) -> * -> *) (r :: EffectRow) a.
FirstOrder e "interpret" =>
(forall (rInitial :: EffectRow) x. e (Sem rInitial) x -> Sem r x)
-> Sem (e : r) a -> Sem r a
interpret ((forall (rInitial :: EffectRow) x.
  MemberStore (Sem rInitial) x -> Sem r x)
 -> Sem (MemberStore : r) a -> Sem r a)
-> (forall (rInitial :: EffectRow) x.
    MemberStore (Sem rInitial) x -> Sem r x)
-> Sem (MemberStore : r) a
-> Sem r a
forall a b. (a -> b) -> a -> b
$ \case
  CreateMembers ConvId
cid UserList u
ul -> do
    ByteString -> Sem r ()
forall (r :: EffectRow). Member TinyLog r => ByteString -> Sem r ()
logEffect ByteString
"MemberStore.CreateMembers"
    Client ([LocalMember], [RemoteMember])
-> Sem r ([LocalMember], [RemoteMember])
forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r) =>
Client a -> Sem r a
embedClient (Client ([LocalMember], [RemoteMember])
 -> Sem r ([LocalMember], [RemoteMember]))
-> Client ([LocalMember], [RemoteMember])
-> Sem r ([LocalMember], [RemoteMember])
forall a b. (a -> b) -> a -> b
$ ConvId -> UserList u -> Client ([LocalMember], [RemoteMember])
forall a.
ToUserRole a =>
ConvId -> UserList a -> Client ([LocalMember], [RemoteMember])
addMembers ConvId
cid UserList u
ul
  CreateMembersInRemoteConversation Remote ConvId
rcid [UserId]
uids -> do
    ByteString -> Sem r ()
forall (r :: EffectRow). Member TinyLog r => ByteString -> Sem r ()
logEffect ByteString
"MemberStore.CreateMembersInRemoteConversation"
    Client () -> Sem r ()
forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r) =>
Client a -> Sem r a
embedClient (Client () -> Sem r ()) -> Client () -> Sem r ()
forall a b. (a -> b) -> a -> b
$ Remote ConvId -> [UserId] -> Client ()
addLocalMembersToRemoteConv Remote ConvId
rcid [UserId]
uids
  CreateBotMember ServiceRef
sr BotId
bid ConvId
cid -> do
    ByteString -> Sem r ()
forall (r :: EffectRow). Member TinyLog r => ByteString -> Sem r ()
logEffect ByteString
"MemberStore.CreateBotMember"
    Client BotMember -> Sem r BotMember
forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r) =>
Client a -> Sem r a
embedClient (Client BotMember -> Sem r BotMember)
-> Client BotMember -> Sem r BotMember
forall a b. (a -> b) -> a -> b
$ ServiceRef -> BotId -> ConvId -> Client BotMember
addBotMember ServiceRef
sr BotId
bid ConvId
cid
  GetLocalMember ConvId
cid UserId
uid -> do
    ByteString -> Sem r ()
forall (r :: EffectRow). Member TinyLog r => ByteString -> Sem r ()
logEffect ByteString
"MemberStore.GetLocalMember"
    Client (Maybe LocalMember) -> Sem r (Maybe LocalMember)
forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r) =>
Client a -> Sem r a
embedClient (Client (Maybe LocalMember) -> Sem r (Maybe LocalMember))
-> Client (Maybe LocalMember) -> Sem r (Maybe LocalMember)
forall a b. (a -> b) -> a -> b
$ ConvId -> UserId -> Client (Maybe LocalMember)
member ConvId
cid UserId
uid
  GetLocalMembers ConvId
cid -> do
    ByteString -> Sem r ()
forall (r :: EffectRow). Member TinyLog r => ByteString -> Sem r ()
logEffect ByteString
"MemberStore.GetLocalMembers"
    Client [LocalMember] -> Sem r [LocalMember]
forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r) =>
Client a -> Sem r a
embedClient (Client [LocalMember] -> Sem r [LocalMember])
-> Client [LocalMember] -> Sem r [LocalMember]
forall a b. (a -> b) -> a -> b
$ ConvId -> Client [LocalMember]
members ConvId
cid
  MemberStore (Sem rInitial) x
GetAllLocalMembers -> do
    ByteString -> Sem r ()
forall (r :: EffectRow). Member TinyLog r => ByteString -> Sem r ()
logEffect ByteString
"MemberStore.GetAllLocalMembers"
    Client x -> Sem r x
forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r) =>
Client a -> Sem r a
embedClient Client x
Client [LocalMember]
allMembers
  GetRemoteMember ConvId
cid Remote UserId
uid -> do
    ByteString -> Sem r ()
forall (r :: EffectRow). Member TinyLog r => ByteString -> Sem r ()
logEffect ByteString
"MemberStore.GetRemoteMember"
    Client (Maybe RemoteMember) -> Sem r (Maybe RemoteMember)
forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r) =>
Client a -> Sem r a
embedClient (Client (Maybe RemoteMember) -> Sem r (Maybe RemoteMember))
-> Client (Maybe RemoteMember) -> Sem r (Maybe RemoteMember)
forall a b. (a -> b) -> a -> b
$ ConvId -> Domain -> UserId -> Client (Maybe RemoteMember)
lookupRemoteMember ConvId
cid (Remote UserId -> Domain
forall (t :: QTag) a. QualifiedWithTag t a -> Domain
tDomain Remote UserId
uid) (Remote UserId -> UserId
forall (t :: QTag) a. QualifiedWithTag t a -> a
tUnqualified Remote UserId
uid)
  GetRemoteMembers ConvId
rcid -> do
    ByteString -> Sem r ()
forall (r :: EffectRow). Member TinyLog r => ByteString -> Sem r ()
logEffect ByteString
"MemberStore.GetRemoteMembers"
    Client [RemoteMember] -> Sem r [RemoteMember]
forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r) =>
Client a -> Sem r a
embedClient (Client [RemoteMember] -> Sem r [RemoteMember])
-> Client [RemoteMember] -> Sem r [RemoteMember]
forall a b. (a -> b) -> a -> b
$ ConvId -> Client [RemoteMember]
lookupRemoteMembers ConvId
rcid
  CheckLocalMemberRemoteConv UserId
uid Remote ConvId
rcnv -> do
    ByteString -> Sem r ()
forall (r :: EffectRow). Member TinyLog r => ByteString -> Sem r ()
logEffect ByteString
"MemberStore.CheckLocalMemberRemoteConv"
    (Maybe UserId -> x) -> Sem r (Maybe UserId) -> Sem r x
forall a b. (a -> b) -> Sem r a -> Sem r b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Bool -> x
Bool -> Bool
not (Bool -> x) -> (Maybe UserId -> Bool) -> Maybe UserId -> x
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe UserId -> Bool
forall a. Maybe a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null) (Sem r (Maybe UserId) -> Sem r x)
-> Sem r (Maybe UserId) -> Sem r x
forall a b. (a -> b) -> a -> b
$ Client (Maybe UserId) -> Sem r (Maybe UserId)
forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r) =>
Client a -> Sem r a
embedClient (Client (Maybe UserId) -> Sem r (Maybe UserId))
-> Client (Maybe UserId) -> Sem r (Maybe UserId)
forall a b. (a -> b) -> a -> b
$ UserId -> Remote ConvId -> Client (Maybe UserId)
lookupLocalMemberRemoteConv UserId
uid Remote ConvId
rcnv
  SelectRemoteMembers [UserId]
uids Remote ConvId
rcnv -> do
    ByteString -> Sem r ()
forall (r :: EffectRow). Member TinyLog r => ByteString -> Sem r ()
logEffect ByteString
"MemberStore.SelectRemoteMembers"
    Client ([UserId], Bool) -> Sem r ([UserId], Bool)
forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r) =>
Client a -> Sem r a
embedClient (Client ([UserId], Bool) -> Sem r ([UserId], Bool))
-> Client ([UserId], Bool) -> Sem r ([UserId], Bool)
forall a b. (a -> b) -> a -> b
$ [UserId] -> Remote ConvId -> Client ([UserId], Bool)
filterRemoteConvMembers [UserId]
uids Remote ConvId
rcnv
  SetSelfMember Qualified ConvId
qcid Local UserId
luid MemberUpdate
upd -> do
    ByteString -> Sem r ()
forall (r :: EffectRow). Member TinyLog r => ByteString -> Sem r ()
logEffect ByteString
"MemberStore.SetSelfMember"
    Client () -> Sem r ()
forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r) =>
Client a -> Sem r a
embedClient (Client () -> Sem r ()) -> Client () -> Sem r ()
forall a b. (a -> b) -> a -> b
$ Qualified ConvId -> Local UserId -> MemberUpdate -> Client ()
updateSelfMember Qualified ConvId
qcid Local UserId
luid MemberUpdate
upd
  SetOtherMember Local ConvId
lcid Qualified UserId
quid OtherMemberUpdate
upd -> do
    ByteString -> Sem r ()
forall (r :: EffectRow). Member TinyLog r => ByteString -> Sem r ()
logEffect ByteString
"MemberStore.SetOtherMember"
    Client () -> Sem r ()
forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r) =>
Client a -> Sem r a
embedClient (Client () -> Sem r ()) -> Client () -> Sem r ()
forall a b. (a -> b) -> a -> b
$ Local ConvId -> Qualified UserId -> OtherMemberUpdate -> Client ()
updateOtherMemberLocalConv Local ConvId
lcid Qualified UserId
quid OtherMemberUpdate
upd
  DeleteMembers ConvId
cnv UserList UserId
ul -> do
    ByteString -> Sem r ()
forall (r :: EffectRow). Member TinyLog r => ByteString -> Sem r ()
logEffect ByteString
"MemberStore.DeleteMembers"
    Client () -> Sem r ()
forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r) =>
Client a -> Sem r a
embedClient (Client () -> Sem r ()) -> Client () -> Sem r ()
forall a b. (a -> b) -> a -> b
$ ConvId -> UserList UserId -> Client ()
removeMembersFromLocalConv ConvId
cnv UserList UserId
ul
  DeleteMembersInRemoteConversation Remote ConvId
rcnv [UserId]
uids -> do
    ByteString -> Sem r ()
forall (r :: EffectRow). Member TinyLog r => ByteString -> Sem r ()
logEffect ByteString
"MemberStore.DeleteMembersInRemoteConversation"
    Client () -> Sem r ()
forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r) =>
Client a -> Sem r a
embedClient (Client () -> Sem r ()) -> Client () -> Sem r ()
forall a b. (a -> b) -> a -> b
$
      Remote ConvId -> [UserId] -> Client ()
removeLocalMembersFromRemoteConv Remote ConvId
rcnv [UserId]
uids
  AddMLSClients GroupId
lcnv Qualified UserId
quid Set (ClientId, LeafIndex)
cs -> do
    ByteString -> Sem r ()
forall (r :: EffectRow). Member TinyLog r => ByteString -> Sem r ()
logEffect ByteString
"MemberStore.AddMLSClients"
    Client () -> Sem r ()
forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r) =>
Client a -> Sem r a
embedClient (Client () -> Sem r ()) -> Client () -> Sem r ()
forall a b. (a -> b) -> a -> b
$ GroupId
-> Qualified UserId -> Set (ClientId, LeafIndex) -> Client ()
addMLSClients GroupId
lcnv Qualified UserId
quid Set (ClientId, LeafIndex)
cs
  PlanClientRemoval GroupId
lcnv f ClientIdentity
cids -> do
    ByteString -> Sem r ()
forall (r :: EffectRow). Member TinyLog r => ByteString -> Sem r ()
logEffect ByteString
"MemberStore.PlanClientRemoval"
    Client () -> Sem r ()
forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r) =>
Client a -> Sem r a
embedClient (Client () -> Sem r ()) -> Client () -> Sem r ()
forall a b. (a -> b) -> a -> b
$ GroupId -> f ClientIdentity -> Client ()
forall (f :: * -> *).
Foldable f =>
GroupId -> f ClientIdentity -> Client ()
planMLSClientRemoval GroupId
lcnv f ClientIdentity
cids
  RemoveMLSClients GroupId
lcnv Qualified UserId
quid Set ClientId
cs -> do
    ByteString -> Sem r ()
forall (r :: EffectRow). Member TinyLog r => ByteString -> Sem r ()
logEffect ByteString
"MemberStore.RemoveMLSClients"
    Client () -> Sem r ()
forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r) =>
Client a -> Sem r a
embedClient (Client () -> Sem r ()) -> Client () -> Sem r ()
forall a b. (a -> b) -> a -> b
$ GroupId -> Qualified UserId -> Set ClientId -> Client ()
removeMLSClients GroupId
lcnv Qualified UserId
quid Set ClientId
cs
  RemoveAllMLSClients GroupId
gid -> do
    ByteString -> Sem r ()
forall (r :: EffectRow). Member TinyLog r => ByteString -> Sem r ()
logEffect ByteString
"MemberStore.RemoveAllMLSClients"
    Client () -> Sem r ()
forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r) =>
Client a -> Sem r a
embedClient (Client () -> Sem r ()) -> Client () -> Sem r ()
forall a b. (a -> b) -> a -> b
$ GroupId -> Client ()
removeAllMLSClients GroupId
gid
  LookupMLSClients GroupId
lcnv -> do
    ByteString -> Sem r ()
forall (r :: EffectRow). Member TinyLog r => ByteString -> Sem r ()
logEffect ByteString
"MemberStore.LookupMLSClients"
    Client (Map (Qualified UserId) (Map ClientId LeafIndex))
-> Sem r (Map (Qualified UserId) (Map ClientId LeafIndex))
forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r) =>
Client a -> Sem r a
embedClient (Client (Map (Qualified UserId) (Map ClientId LeafIndex))
 -> Sem r (Map (Qualified UserId) (Map ClientId LeafIndex)))
-> Client (Map (Qualified UserId) (Map ClientId LeafIndex))
-> Sem r (Map (Qualified UserId) (Map ClientId LeafIndex))
forall a b. (a -> b) -> a -> b
$ GroupId -> Client (Map (Qualified UserId) (Map ClientId LeafIndex))
lookupMLSClients GroupId
lcnv
  LookupMLSClientLeafIndices GroupId
lcnv -> do
    ByteString -> Sem r ()
forall (r :: EffectRow). Member TinyLog r => ByteString -> Sem r ()
logEffect ByteString
"MemberStore.LookupMLSClientLeafIndices"
    Client (Map (Qualified UserId) (Map ClientId LeafIndex), IndexMap)
-> Sem
     r (Map (Qualified UserId) (Map ClientId LeafIndex), IndexMap)
forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r) =>
Client a -> Sem r a
embedClient (Client (Map (Qualified UserId) (Map ClientId LeafIndex), IndexMap)
 -> Sem
      r (Map (Qualified UserId) (Map ClientId LeafIndex), IndexMap))
-> Client
     (Map (Qualified UserId) (Map ClientId LeafIndex), IndexMap)
-> Sem
     r (Map (Qualified UserId) (Map ClientId LeafIndex), IndexMap)
forall a b. (a -> b) -> a -> b
$ GroupId
-> Client
     (Map (Qualified UserId) (Map ClientId LeafIndex), IndexMap)
lookupMLSClientLeafIndices GroupId
lcnv
  GetRemoteMembersByDomain Domain
dom -> do
    ByteString -> Sem r ()
forall (r :: EffectRow). Member TinyLog r => ByteString -> Sem r ()
logEffect ByteString
"MemberStore.GetRemoteMembersByDomain"
    Client [(ConvId, RemoteMember)] -> Sem r [(ConvId, RemoteMember)]
forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r) =>
Client a -> Sem r a
embedClient (Client [(ConvId, RemoteMember)] -> Sem r [(ConvId, RemoteMember)])
-> Client [(ConvId, RemoteMember)]
-> Sem r [(ConvId, RemoteMember)]
forall a b. (a -> b) -> a -> b
$ Domain -> Client [(ConvId, RemoteMember)]
lookupRemoteMembersByDomain Domain
dom
  GetLocalMembersByDomain Domain
dom -> do
    ByteString -> Sem r ()
forall (r :: EffectRow). Member TinyLog r => ByteString -> Sem r ()
logEffect ByteString
"MemberStore.GetLocalMembersByDomain"
    Client [(ConvId, UserId)] -> Sem r [(ConvId, UserId)]
forall (r :: EffectRow) a.
(Member (Embed IO) r, Member (Input ClientState) r) =>
Client a -> Sem r a
embedClient (Client [(ConvId, UserId)] -> Sem r [(ConvId, UserId)])
-> Client [(ConvId, UserId)] -> Sem r [(ConvId, UserId)]
forall a b. (a -> b) -> a -> b
$ Domain -> Client [(ConvId, UserId)]
lookupLocalMembersByDomain Domain
dom