diff --git a/libs/wire-api/src/Wire/API/Conversation.hs b/libs/wire-api/src/Wire/API/Conversation.hs index 2f0b26ec0b..b6de69fce2 100644 --- a/libs/wire-api/src/Wire/API/Conversation.hs +++ b/libs/wire-api/src/Wire/API/Conversation.hs @@ -531,11 +531,11 @@ defRole = activatedAccessRole maybeRole :: ConvType -> Maybe (Set AccessRole) -> Set AccessRole maybeRole SelfConv _ = privateAccessRole -maybeRole GlobalTeamConv _ = teamAccessRole maybeRole ConnectConv _ = privateAccessRole maybeRole One2OneConv _ = privateAccessRole maybeRole RegularConv Nothing = defRole maybeRole RegularConv (Just r) = r +maybeRole GlobalTeamConv _ = teamAccessRole data AccessRole = TeamMemberAccessRole diff --git a/libs/wire-api/src/Wire/API/MLS/GlobalTeamConversation.hs b/libs/wire-api/src/Wire/API/MLS/GlobalTeamConversation.hs deleted file mode 100644 index f9f1096860..0000000000 --- a/libs/wire-api/src/Wire/API/MLS/GlobalTeamConversation.hs +++ /dev/null @@ -1,63 +0,0 @@ --- This file is part of the Wire Server implementation. --- --- Copyright (C) 2022 Wire Swiss GmbH --- --- 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 . - -module Wire.API.MLS.GlobalTeamConversation where - -import Control.Lens ((?~)) -import Data.Aeson (FromJSON, ToJSON) -import Data.Id -import Data.Qualified -import Data.Schema -import qualified Data.Swagger as S -import Imports -import Wire.API.Conversation hiding (Conversation) -import Wire.API.Conversation.Protocol -import Wire.Arbitrary (Arbitrary (..), GenericUniform (..)) - --- | Public-facing global team conversation. --- Membership is implicit. Every member of a team is part of it. --- Protocol is also implicit: it's always MLS. -data GlobalTeamConversation = GlobalTeamConversation - { gtcId :: Qualified ConvId, - gtcMlsMetadata :: ConversationMLSData, - gtcCreator :: Maybe UserId, - gtcAccess :: [Access], - gtcName :: Text, - gtcTeam :: TeamId - } - deriving stock (Eq, Show, Generic) - deriving (Arbitrary) via (GenericUniform GlobalTeamConversation) - deriving (FromJSON, ToJSON, S.ToSchema) via Schema GlobalTeamConversation - -instance ToSchema GlobalTeamConversation where - schema = - objectWithDocModifier - "GlobalTeamConversation" - (description ?~ "The global team conversation object as returned from the server") - $ GlobalTeamConversation - <$> gtcId .= field "qualified_id" schema - <*> gtcMlsMetadata .= mlsDataSchema - <*> gtcCreator - .= maybe_ - ( optFieldWithDocModifier - "creator" - (description ?~ "The creator's user ID") - schema - ) - <*> gtcAccess .= field "access" (array schema) - <*> gtcName .= field "name" schema - <*> gtcTeam .= field "team" schema diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Galley/Conversation.hs b/libs/wire-api/src/Wire/API/Routes/Public/Galley/Conversation.hs index 7105e47611..9f0332d107 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Galley/Conversation.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Galley/Conversation.hs @@ -130,18 +130,6 @@ type ConversationAPI = :> QualifiedCapture "cnv" ConvId :> Get '[Servant.JSON] Conversation ) - -- :<|> Named - -- "get-global-team-conversation" - -- ( Summary "Get the global conversation for a given team ID" - -- :> CanThrow 'ConvNotFound - -- :> CanThrow 'NotATeamMember - -- :> ZLocalUser - -- :> "teams" - -- :> Capture "tid" TeamId - -- :> "conversations" - -- :> "global" - -- :> Get '[Servant.JSON] GlobalTeamConversation - -- ) :<|> Named "get-conversation-roles" ( Summary "Get existing roles available for the given conversation" diff --git a/libs/wire-api/wire-api.cabal b/libs/wire-api/wire-api.cabal index bf841e4d75..ed7e1bb8eb 100644 --- a/libs/wire-api/wire-api.cabal +++ b/libs/wire-api/wire-api.cabal @@ -48,7 +48,6 @@ library Wire.API.MLS.Credential Wire.API.MLS.Epoch Wire.API.MLS.Extension - Wire.API.MLS.GlobalTeamConversation Wire.API.MLS.Group Wire.API.MLS.GroupInfoBundle Wire.API.MLS.KeyPackage diff --git a/services/galley/src/Galley/API/Action.hs b/services/galley/src/Galley/API/Action.hs index 44e9d9d433..35310f3d80 100644 --- a/services/galley/src/Galley/API/Action.hs +++ b/services/galley/src/Galley/API/Action.hs @@ -277,13 +277,8 @@ ensureAllowed tag loc action conv origUser = do -- not a team conv, so one of the other access roles has to allow this. when (Set.null $ cupAccessRoles action Set.\\ Set.fromList [TeamMemberAccessRole]) $ throwS @'InvalidTargetAccess - SConversationSelfInviteTag -> - unless - (convType conv == GlobalTeamConv) - $ throwS @'InvalidOperation - SConversationLeaveTag -> - when (convType conv == GlobalTeamConv) $ - throwS @'InvalidOperation + SConversationSelfInviteTag -> pure () + SConversationLeaveTag -> pure () _ -> pure () -- | Returns additional members that resulted from the action (e.g. ConversationJoin) @@ -634,10 +629,7 @@ updateLocalConversationUnchecked lconv qusr con action = do conv = tUnqualified lconv -- retrieve member - self <- - if (cnvmType . convMetadata . tUnqualified $ lconv) == GlobalTeamConv - then pure $ Left $ localMemberFromUser (qUnqualified qusr) - else noteS @'ConvNotFound $ getConvMember lconv conv qusr + self <- noteS @'ConvNotFound $ getConvMember lconv conv qusr -- perform checks ensureConversationActionAllowed (sing @tag) lcnv action conv self @@ -657,23 +649,6 @@ updateLocalConversationUnchecked lconv qusr con action = do -- -------------------------------------------------------------------------------- -- -- Utilities -localMemberFromUser :: UserId -> LocalMember -localMemberFromUser uid = - LocalMember - { lmId = uid, - lmStatus = - MemberStatus - { msOtrMutedStatus = Nothing, - msOtrMutedRef = Nothing, - msOtrArchived = False, - msOtrArchivedRef = Nothing, - msHidden = False, - msHiddenRef = Nothing - }, - lmService = Nothing, - lmConvRoleName = roleToRoleName convRoleWireMember - } - ensureConversationActionAllowed :: forall tag mem x r. ( IsConvMember mem, diff --git a/services/galley/src/Galley/API/Internal.hs b/services/galley/src/Galley/API/Internal.hs index 730aabd767..3ca5a2e3fd 100644 --- a/services/galley/src/Galley/API/Internal.hs +++ b/services/galley/src/Galley/API/Internal.hs @@ -729,7 +729,6 @@ rmUser lusr conn = do deleteMembers (Data.convId c) (UserList [tUnqualified lusr] []) for_ (bucketRemote (fmap rmId (Data.convRemoteMembers c))) $ notifyRemoteMembers now qUser (Data.convId c) pure Nothing - pp <- for cc $ \c -> case Data.convType c of SelfConv -> pure Nothing One2OneConv -> deleteMembers (Data.convId c) (UserList [tUnqualified lusr] []) $> Nothing diff --git a/services/galley/src/Galley/API/MLS/Message.hs b/services/galley/src/Galley/API/MLS/Message.hs index 7080b94941..44be340f59 100644 --- a/services/galley/src/Galley/API/MLS/Message.hs +++ b/services/galley/src/Galley/API/MLS/Message.hs @@ -866,25 +866,6 @@ processInternalCommit qusr senderClient con lconv mlsMeta cm epoch action sender -- this is a newly created conversation, and it should contain exactly one -- client (the creator) throwS @'MLSUnexpectedSenderClient - (Left _, GlobalTeamConv, []) -> do - creatorClient <- noteS @'MLSMissingSenderClient senderClient - creatorRef <- - maybe - (pure senderRef) - ( note (mlsProtocolError "Could not compute key package ref") - . kpRef' - . upLeaf - ) - $ cPath commit - -- add user to global conv as a member as well - lusr <- qualifyLocal (qUnqualified qusr) - void $ createMember (convId <$> lconv) lusr - addMLSClients - (cnvmlsGroupId mlsMeta) - qusr - (Set.singleton (creatorClient, creatorRef)) - (Left _, GlobalTeamConv, _) -> - throwS @'MLSUnexpectedSenderClient (Left lm, _, [(qu, (creatorClient, _))]) | qu == qUntagged (qualifyAs lconv (lmId lm)) -> do -- use update path as sender reference and if not existing fall back to sender diff --git a/services/galley/src/Galley/API/MLS/Util.hs b/services/galley/src/Galley/API/MLS/Util.hs index 9738b5b046..d1d22026cf 100644 --- a/services/galley/src/Galley/API/MLS/Util.hs +++ b/services/galley/src/Galley/API/MLS/Util.hs @@ -26,7 +26,6 @@ import Galley.Effects import Galley.Effects.ConversationStore import Galley.Effects.MemberStore import Galley.Effects.ProposalStore -import Galley.Types.Conversations.Members import Imports import Polysemy import Polysemy.TinyLog (TinyLog) @@ -36,7 +35,6 @@ import Wire.API.Conversation hiding (Conversation) import Wire.API.Conversation.Protocol import Wire.API.Error import Wire.API.Error.Galley -import Wire.API.MLS.GlobalTeamConversation import Wire.API.MLS.KeyPackage import Wire.API.MLS.Proposal import Wire.API.MLS.Serialisation @@ -52,13 +50,7 @@ getLocalConvForUser :: Local ConvId -> Sem r Data.Conversation getLocalConvForUser qusr lcnv = do - gtc <- getGlobalTeamConversationById lcnv - conv <- case gtc of - Just conv -> do - localMembers <- getLocalMembers (qUnqualified . gtcId $ conv) - pure $ gtcToConv conv (qUnqualified qusr) localMembers - Nothing -> do - getConversation (tUnqualified lcnv) >>= noteS @'ConvNotFound + conv <- getConversation (tUnqualified lcnv) >>= noteS @'ConvNotFound -- check that sender is part of conversation isMember' <- @@ -90,29 +82,3 @@ getPendingBackendRemoveProposals gid epoch = do TinyLog.warn $ Log.msg ("found pending proposal without origin, ignoring" :: ByteString) pure Nothing ) - -gtcToConv :: - GlobalTeamConversation -> - UserId -> - [LocalMember] -> - Conversation -gtcToConv gtc usr lm = - let mlsData = gtcMlsMetadata gtc - in Conversation - { convId = qUnqualified $ gtcId gtc, - convLocalMembers = lm, - convRemoteMembers = mempty, - convDeleted = False, - convMetadata = - ConversationMetadata - { cnvmType = GlobalTeamConv, - cnvmCreator = usr, - cnvmAccess = [SelfInviteAccess], - cnvmAccessRoles = mempty, - cnvmName = Just $ gtcName gtc, - cnvmTeam = Just $ gtcTeam gtc, - cnvmMessageTimer = Nothing, - cnvmReceiptMode = Nothing - }, - convProtocol = ProtocolMLS mlsData - } diff --git a/services/galley/src/Galley/API/Public/Conversation.hs b/services/galley/src/Galley/API/Public/Conversation.hs index fc00eaceff..f14ee73397 100644 --- a/services/galley/src/Galley/API/Public/Conversation.hs +++ b/services/galley/src/Galley/API/Public/Conversation.hs @@ -32,7 +32,6 @@ conversationAPI = mkNamedAPI @"get-unqualified-conversation" getUnqualifiedConversation <@> mkNamedAPI @"get-unqualified-conversation-legalhold-alias" getUnqualifiedConversation <@> mkNamedAPI @"get-conversation" getConversation - -- <@> mkNamedAPI @"get-global-team-conversation" getGlobalTeamConversation <@> mkNamedAPI @"get-conversation-roles" getConversationRoles <@> mkNamedAPI @"get-group-info" getGroupInfo <@> mkNamedAPI @"list-conversation-ids-unqualified" conversationIdsPageFromUnqualified diff --git a/services/galley/src/Galley/API/Query.hs b/services/galley/src/Galley/API/Query.hs index aefb08a810..1df1e373a4 100644 --- a/services/galley/src/Galley/API/Query.hs +++ b/services/galley/src/Galley/API/Query.hs @@ -21,7 +21,6 @@ module Galley.API.Query ( getBotConversationH, getUnqualifiedConversation, getConversation, - getGlobalTeamConversation, getConversationRoles, conversationIdsPageFromUnqualified, conversationIdsPageFromV2, @@ -53,7 +52,6 @@ import Data.Proxy import Data.Qualified import Data.Range import qualified Data.Set as Set -import Data.Tagged import Galley.API.Error import Galley.API.MLS.Keys import Galley.API.MLS.Types @@ -69,7 +67,6 @@ import qualified Galley.Effects.ListItems as E import qualified Galley.Effects.MemberStore as E import Galley.Effects.TeamFeatureStore (FeaturePersistentConstraint) import qualified Galley.Effects.TeamFeatureStore as TeamFeatures -import qualified Galley.Effects.TeamStore as E import Galley.Env import Galley.Options import Galley.Types.Conversations.Members @@ -94,7 +91,6 @@ import Wire.API.Error.Galley import Wire.API.Federation.API import Wire.API.Federation.API.Galley import Wire.API.Federation.Error -import qualified Wire.API.MLS.GlobalTeamConversation as Public import qualified Wire.API.Provider.Bot as Public import qualified Wire.API.Routes.MultiTablePaging as Public import Wire.API.Team.Feature as Public hiding (setStatus) @@ -146,25 +142,6 @@ getUnqualifiedConversation lusr cnv = do c <- getConversationAndCheckMembership (tUnqualified lusr) (qualifyAs lusr cnv) Mapping.conversationView lusr c -getGlobalTeamConversation :: - Members - '[ ConversationStore, - ErrorS 'NotATeamMember, - MemberStore, - TeamStore - ] - r => - Local UserId -> - TeamId -> - Sem r Public.GlobalTeamConversation -getGlobalTeamConversation lusr tid = do - let ltid = qualifyAs lusr tid - void $ noteS @'NotATeamMember =<< E.getTeamMember tid (tUnqualified lusr) - E.getGlobalTeamConversation ltid >>= \case - Nothing -> - E.createGlobalTeamConversation (qualifyAs lusr tid) - Just conv -> pure conv - getConversation :: forall r. Members @@ -316,12 +293,6 @@ conversationIdsPageFromUnqualified :: Maybe (Range 1 1000 Int32) -> Sem r (Public.ConversationList ConvId) conversationIdsPageFromUnqualified lusr start msize = do - void $ - E.getUserTeams (tUnqualified lusr) >>= \tids -> - runError @InternalError $ - runError @(Tagged 'NotATeamMember ()) - (for_ tids $ \tid -> getGlobalTeamConversation lusr tid) - let size = fromMaybe (toRange (Proxy @1000)) msize ids <- E.listItems (tUnqualified lusr) start size pure $ diff --git a/services/galley/src/Galley/API/Util.hs b/services/galley/src/Galley/API/Util.hs index 835560e5f4..215c32567b 100644 --- a/services/galley/src/Galley/API/Util.hs +++ b/services/galley/src/Galley/API/Util.hs @@ -36,7 +36,6 @@ import Data.Singletons import qualified Data.Text as T import Data.Time import Galley.API.Error -import Galley.API.MLS.Util import Galley.API.Mapping import qualified Galley.Data.Conversation as Data import Galley.Data.Services (BotMember, newBotMember) @@ -193,7 +192,7 @@ ensureActionAllowed action self = case isActionAllowed (fromSing action) (convMe ensureGroupConversation :: Member (ErrorS 'InvalidOperation) r => Data.Conversation -> Sem r () ensureGroupConversation conv = do let ty = Data.convType conv - unless (ty `elem` [RegularConv, GlobalTeamConv]) $ throwS @'InvalidOperation + unless (ty == RegularConv) $ throwS @'InvalidOperation -- | Ensure that the set of actions provided are not "greater" than the user's -- own. This is used to ensure users cannot "elevate" allowed actions @@ -520,13 +519,9 @@ getConversationWithError :: Local ConvId -> UserId -> Sem r Data.Conversation -getConversationWithError lcnv uid = +getConversationWithError lcnv _uid = let cid = tUnqualified lcnv - in getConversation cid >>= \case - Just c -> pure c - Nothing -> do - gtc <- noteS @'ConvNotFound =<< getGlobalTeamConversationById lcnv - pure $ gtcToConv gtc uid mempty + in noteS @'ConvNotFound =<< getConversation cid getConversationAndMemberWithError :: forall e uid mem r. diff --git a/services/galley/src/Galley/Cassandra/Conversation.hs b/services/galley/src/Galley/Cassandra/Conversation.hs index 10a87ff2c8..1ae40fa1d6 100644 --- a/services/galley/src/Galley/Cassandra/Conversation.hs +++ b/services/galley/src/Galley/Cassandra/Conversation.hs @@ -19,7 +19,6 @@ module Galley.Cassandra.Conversation ( createConversation, deleteConversation, interpretConversationStoreToCassandra, - getGlobalTeamConversationById, ) where @@ -55,7 +54,6 @@ import qualified UnliftIO import Wire.API.Conversation hiding (Conversation, Member) import Wire.API.Conversation.Protocol import Wire.API.MLS.CipherSuite -import Wire.API.MLS.GlobalTeamConversation import Wire.API.MLS.Group import Wire.API.MLS.PublicGroupState @@ -190,10 +188,13 @@ conversationMeta conv = <$> retry x1 (query1 Cql.selectConv (params LocalQuorum (Identity conv))) where toConvMeta (t, mc, a, r, r', n, i, _, mt, rm, _, _, _, _) = do - c <- mc - let mbAccessRolesV2 = Set.fromList . Cql.fromSet <$> r' - accessRoles = maybeRole t $ parseAccessRoles r mbAccessRolesV2 - pure $ ConversationMetadata t c (defAccess t a) accessRoles n i mt rm + if t == GlobalTeamConv + then Nothing + else do + c <- mc + let mbAccessRolesV2 = Set.fromList . Cql.fromSet <$> r' + accessRoles = maybeRole t $ parseAccessRoles r mbAccessRolesV2 + pure $ ConversationMetadata t c (defAccess t a) accessRoles n i mt rm getPublicGroupState :: ConvId -> Client (Maybe OpaquePublicGroupState) getPublicGroupState cid = do @@ -252,71 +253,6 @@ getConversation conv = do <*> UnliftIO.wait cdata runMaybeT $ conversationGC =<< maybe mzero pure mbConv -getGlobalTeamConversation :: - Local TeamId -> - Client (Maybe GlobalTeamConversation) -getGlobalTeamConversation qtid = - let cid = qualifyAs qtid (globalTeamConv (tUnqualified qtid)) - in getGlobalTeamConversationById cid - -getGlobalTeamConversationById :: - Local ConvId -> - Client (Maybe GlobalTeamConversation) -getGlobalTeamConversationById lconv = do - let cid = tUnqualified lconv - mconv <- retry x1 (query1 Cql.selectGlobalTeamConv (params LocalQuorum (Identity cid))) - pure $ toGlobalConv mconv - where - toGlobalConv mconv = do - (muid, mname, mtid, mty, mgid, mepoch, mcs) <- mconv - guard (mty == Just GlobalTeamConv) - tid <- mtid - name <- mname - mlsData <- ConversationMLSData <$> mgid <*> (mepoch <|> Just (Epoch 0)) <*> mcs - - pure $ - GlobalTeamConversation - (qUntagged lconv) - mlsData - muid - [SelfInviteAccess] - name - tid - -createGlobalTeamConversation :: - Local TeamId -> - Client GlobalTeamConversation -createGlobalTeamConversation tid = do - let lconv = qualifyAs tid (globalTeamConv $ tUnqualified tid) - gid = convToGroupId lconv - cs = MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519 - retry x5 . batch $ do - setType BatchLogged - setConsistency LocalQuorum - addPrepQuery - Cql.insertGlobalTeamConv - ( tUnqualified lconv, - Cql.Set [SelfInviteAccess], - "Global team conversation", - tUnqualified tid, - Just gid, - Just cs - ) - addPrepQuery Cql.insertTeamConv (tUnqualified tid, tUnqualified lconv) - addPrepQuery Cql.insertGroupId (gid, tUnqualified lconv, tDomain lconv) - pure $ - GlobalTeamConversation - (qUntagged lconv) - ( ConversationMLSData - gid - (Epoch 0) - cs - ) - Nothing - [SelfInviteAccess] - "Global team conversation" - (tUnqualified tid) - -- | "Garbage collect" a 'Conversation', i.e. if the conversation is -- marked as deleted, actually remove it from the database and return -- 'Nothing'. @@ -408,29 +344,32 @@ toConv :: Maybe Conversation toConv cid ms remoteMems mconv = do (cty, muid, acc, role, roleV2, nme, ti, del, timer, rm, ptag, mgid, mep, mcs) <- mconv - uid <- muid - let mbAccessRolesV2 = Set.fromList . Cql.fromSet <$> roleV2 - accessRoles = maybeRole cty $ parseAccessRoles role mbAccessRolesV2 - proto <- toProtocol ptag mgid mep mcs - pure - Conversation - { convId = cid, - convDeleted = fromMaybe False del, - convLocalMembers = ms, - convRemoteMembers = remoteMems, - convProtocol = proto, - convMetadata = - ConversationMetadata - { cnvmType = cty, - cnvmCreator = uid, - cnvmAccess = defAccess cty acc, - cnvmAccessRoles = accessRoles, - cnvmName = nme, - cnvmTeam = ti, - cnvmMessageTimer = timer, - cnvmReceiptMode = rm - } - } + if cty == GlobalTeamConv + then Nothing + else do + uid <- muid + let mbAccessRolesV2 = Set.fromList . Cql.fromSet <$> roleV2 + accessRoles = maybeRole cty $ parseAccessRoles role mbAccessRolesV2 + proto <- toProtocol ptag mgid mep mcs + pure + Conversation + { convId = cid, + convDeleted = fromMaybe False del, + convLocalMembers = ms, + convRemoteMembers = remoteMems, + convProtocol = proto, + convMetadata = + ConversationMetadata + { cnvmType = cty, + cnvmCreator = uid, + cnvmAccess = defAccess cty acc, + cnvmAccessRoles = accessRoles, + cnvmName = nme, + cnvmTeam = ti, + cnvmMessageTimer = timer, + cnvmReceiptMode = rm + } + } mapGroupId :: GroupId -> Qualified ConvId -> Client () mapGroupId gId conv = @@ -449,9 +388,6 @@ interpretConversationStoreToCassandra = interpret $ \case CreateConversation loc nc -> embedClient $ createConversation loc nc CreateMLSSelfConversation lusr -> embedClient $ createMLSSelfConversation lusr GetConversation cid -> embedClient $ getConversation cid - GetGlobalTeamConversation tid -> embedClient $ getGlobalTeamConversation tid - GetGlobalTeamConversationById lconv -> embedClient $ getGlobalTeamConversationById lconv - CreateGlobalTeamConversation tid -> embedClient $ createGlobalTeamConversation tid GetConversationIdByGroupId gId -> embedClient $ lookupGroupId gId GetConversations cids -> localConversations cids GetConversationMetadata cid -> embedClient $ conversationMeta cid diff --git a/services/galley/src/Galley/Cassandra/Conversation/Members.hs b/services/galley/src/Galley/Cassandra/Conversation/Members.hs index 85b37b634e..25eb9c4058 100644 --- a/services/galley/src/Galley/Cassandra/Conversation/Members.hs +++ b/services/galley/src/Galley/Cassandra/Conversation/Members.hs @@ -118,31 +118,8 @@ removeRemoteMembersFromLocalConv cnv victims = do members :: ConvId -> Client [LocalMember] members conv = do - mconv <- retry x1 $ query1 Cql.selectConv (params LocalQuorum (Identity conv)) - case mconv of - Just (GlobalTeamConv, _, _, _, _, _, Just tid, _, _, _, _, _, _, _) -> do - res <- - retry x1 $ - query - Cql.selectTeamMembers - (params LocalQuorum (Identity tid)) - let uids = mapMaybe fst' $ res - pure $ mapMaybe toMemberFromId uids - _ -> - fmap (mapMaybe toMember) . retry x1 $ - query Cql.selectMembers (params LocalQuorum (Identity conv)) - where - fst' (a, _, _, _, _) = Just a - -toMemberFromId :: UserId -> Maybe LocalMember -toMemberFromId usr = - Just $ - LocalMember - { lmId = usr, - lmService = Nothing, - lmStatus = toMemberStatus (Nothing, Nothing, Nothing, Nothing, Nothing, Nothing), - lmConvRoleName = roleNameWireMember - } + fmap (mapMaybe toMember) . retry x1 $ + query Cql.selectMembers (params LocalQuorum (Identity conv)) toMemberStatus :: ( -- otr muted @@ -226,14 +203,9 @@ member :: UserId -> Client (Maybe LocalMember) member conv usr = do - mconv <- retry x1 $ query1 Cql.selectConv (params LocalQuorum (Identity conv)) - case mconv of - Just (GlobalTeamConv, _, _, _, _, _, _, _, _, _, _, _, _, _) -> - pure $ toMemberFromId usr - _ -> do - fmap (toMember =<<) $ - retry x1 $ - query1 Cql.selectMember (params LocalQuorum (conv, usr)) + fmap (toMember =<<) $ + retry x1 $ + query1 Cql.selectMember (params LocalQuorum (conv, 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 diff --git a/services/galley/src/Galley/Cassandra/Instances.hs b/services/galley/src/Galley/Cassandra/Instances.hs index e0ceb40255..1370bf6af6 100644 --- a/services/galley/src/Galley/Cassandra/Instances.hs +++ b/services/galley/src/Galley/Cassandra/Instances.hs @@ -52,6 +52,7 @@ deriving instance Cql ReceiptMode instance Cql ConvType where ctype = Tagged IntColumn + -- FUTUREWORK: rely on bounded enum typeclass instead of by hand? toCql RegularConv = CqlInt 0 toCql SelfConv = CqlInt 1 toCql One2OneConv = CqlInt 2 @@ -63,7 +64,6 @@ instance Cql ConvType where 1 -> pure SelfConv 2 -> pure One2OneConv 3 -> pure ConnectConv - 4 -> pure GlobalTeamConv n -> Left $ "unexpected conversation-type: " ++ show n fromCql _ = Left "conv-type: int expected" diff --git a/services/galley/src/Galley/Cassandra/Queries.hs b/services/galley/src/Galley/Cassandra/Queries.hs index 0be8fc57b4..5cdac44f74 100644 --- a/services/galley/src/Galley/Cassandra/Queries.hs +++ b/services/galley/src/Galley/Cassandra/Queries.hs @@ -219,20 +219,6 @@ selectConv :: ) selectConv = "select type, creator, access, access_role, access_roles_v2, name, team, deleted, message_timer, receipt_mode, protocol, group_id, epoch, cipher_suite from conversation where conv = ?" -selectGlobalTeamConv :: - PrepQuery - R - (Identity ConvId) - ( Maybe UserId, - Maybe Text, - Maybe TeamId, - Maybe ConvType, - Maybe GroupId, - Maybe Epoch, - Maybe CipherSuiteTag - ) -selectGlobalTeamConv = "select creator, name, team, type, group_id, epoch, cipher_suite from conversation where conv = ?" - selectReceiptMode :: PrepQuery R (Identity ConvId) (Identity (Maybe ReceiptMode)) selectReceiptMode = "select receipt_mode from conversation where conv = ?" @@ -267,12 +253,6 @@ insertMLSSelfConv = <> show (fromEnum ProtocolMLSTag) <> ", ?, ?)" -insertGlobalTeamConv :: PrepQuery W (ConvId, C.Set Access, Text, TeamId, Maybe GroupId, Maybe CipherSuiteTag) () -insertGlobalTeamConv = "insert into conversation (conv, type, access, name, team, group_id, cipher_suite) values (?, 4, ?, ?, ?, ?, ?)" - -setGlobalTeamConvCreator :: PrepQuery W (UserId, ConvId) () -setGlobalTeamConvCreator = "update conversation set creator = ? where conv = ?" - updateConvAccess :: PrepQuery W (C.Set Access, C.Set AccessRole, ConvId) () updateConvAccess = "update conversation set access = ?, access_roles_v2 = ? where conv = ?" diff --git a/services/galley/src/Galley/Data/Conversation.hs b/services/galley/src/Galley/Data/Conversation.hs index 378262560f..519e8608a6 100644 --- a/services/galley/src/Galley/Data/Conversation.hs +++ b/services/galley/src/Galley/Data/Conversation.hs @@ -23,7 +23,6 @@ module Galley.Data.Conversation -- * Utilities isConvDeleted, selfConv, - globalTeamConv, localOne2OneConvId, convAccess, convAccessData, @@ -59,9 +58,6 @@ isConvDeleted = convDeleted selfConv :: UserId -> ConvId selfConv uid = Id (toUUID uid) -globalTeamConv :: TeamId -> ConvId -globalTeamConv tid = Id (toUUID tid) - -- | We deduce the conversation ID by adding the 4 components of the V4 UUID -- together pairwise, and then setting the version bits (v4) and variant bits -- (variant 2). This means that we always know what the UUID is for a diff --git a/services/galley/src/Galley/Effects/ConversationStore.hs b/services/galley/src/Galley/Effects/ConversationStore.hs index f1d9f37495..1660c2f689 100644 --- a/services/galley/src/Galley/Effects/ConversationStore.hs +++ b/services/galley/src/Galley/Effects/ConversationStore.hs @@ -28,9 +28,6 @@ module Galley.Effects.ConversationStore -- * Read conversation getConversation, - getGlobalTeamConversation, - getGlobalTeamConversationById, - createGlobalTeamConversation, getConversationIdByGroupId, getConversations, getConversationMetadata, @@ -71,7 +68,6 @@ import Imports import Polysemy import Wire.API.Conversation hiding (Conversation, Member) import Wire.API.MLS.Epoch -import Wire.API.MLS.GlobalTeamConversation import Wire.API.MLS.PublicGroupState data ConversationStore m a where @@ -82,9 +78,6 @@ data ConversationStore m a where ConversationStore m Conversation DeleteConversation :: ConvId -> ConversationStore m () GetConversation :: ConvId -> ConversationStore m (Maybe Conversation) - GetGlobalTeamConversation :: Local TeamId -> ConversationStore m (Maybe GlobalTeamConversation) - GetGlobalTeamConversationById :: Local ConvId -> ConversationStore m (Maybe GlobalTeamConversation) - CreateGlobalTeamConversation :: Local TeamId -> ConversationStore m GlobalTeamConversation GetConversationIdByGroupId :: GroupId -> ConversationStore m (Maybe (Qualified ConvId)) GetConversations :: [ConvId] -> ConversationStore m [Conversation] GetConversationMetadata :: ConvId -> ConversationStore m (Maybe ConversationMetadata) diff --git a/services/galley/test/integration/API/MLS.hs b/services/galley/test/integration/API/MLS.hs index 1928d98eea..8100c90b36 100644 --- a/services/galley/test/integration/API/MLS.hs +++ b/services/galley/test/integration/API/MLS.hs @@ -191,17 +191,6 @@ tests s = test s "remote user posts commit bundle" testRemoteUserPostsCommitBundle, test s "add user with a commit bundle and a team conv" testAddTeamUserWithBundle ], - -- testGroup - -- "GlobalTeamConv" - -- [ test s "Non-existing team returns 403" testGetGlobalTeamConvNonExistant, - -- test s "Non member of team returns 403" testGetGlobalTeamConvNonMember, - -- test s "Global team conversation is created on get if not present" (testGetGlobalTeamConv s), - -- test s "Can't leave global team conversation" testGlobalTeamConversationLeave, - -- test s "Send message in global team conversation" testGlobalTeamConversationMessage, - -- test s "Listing convs includes global team conversation" testConvListIncludesGlobal, - -- test s "Listing convs includes global team conversation for new users" testConvListIncludesGlobalForNewUsers, - -- test s "Listing convs before calling GET on global team conversation still includes it" testConvListIncludesGlobalBeforeGet - -- ], testGroup "Self conversation" [ test s "create a self conversation" testSelfConversation, @@ -2146,213 +2135,6 @@ testRemoteUserPostsCommitBundle = do pure () --- testGetGlobalTeamConvNonExistant :: TestM () --- testGetGlobalTeamConvNonExistant = do --- uid <- randomUser --- tid <- randomId --- -- authorisation fails b/c not a team member --- getGlobalTeamConv uid tid !!! const 403 === statusCode --- --- testGetGlobalTeamConvNonMember :: TestM () --- testGetGlobalTeamConvNonMember = do --- owner <- randomUser --- tid <- createBindingTeamInternal "sample-team" owner --- team <- getTeam owner tid --- assertQueue "create team" tActivate --- liftIO $ assertEqual "owner" owner (team ^. teamCreator) --- assertQueueEmpty --- --- -- authorisation fails b/c not a team member --- uid <- randomUser --- getGlobalTeamConv uid tid !!! const 403 === statusCode --- --- testGetGlobalTeamConv :: IO TestSetup -> TestM () --- testGetGlobalTeamConv setup = do --- owner <- randomUser --- tid <- createBindingTeamInternal "sample-team" owner --- team <- getTeam owner tid --- assertQueue "create team" tActivate --- liftIO $ assertEqual "owner" owner (team ^. teamCreator) --- assertQueueEmpty --- --- s <- liftIO setup --- let domain = s ^. tsGConf . optSettings . setFederationDomain --- --- let response = getGlobalTeamConv owner tid response --- let convoId = globalTeamConv tid --- lconv = toLocalUnsafe domain convoId --- expected = --- GlobalTeamConversation --- (qUntagged lconv) --- ( ConversationMLSData --- (convToGroupId lconv) --- (Epoch 0) --- MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519 --- ) --- Nothing --- [SelfInviteAccess] --- "Global team conversation" --- tid --- --- let cm = Aeson.decode rs :: Maybe GlobalTeamConversation --- liftIO $ assertEqual "conversation metadata" cm (Just expected) --- --- testConvListIncludesGlobal :: TestM () --- testConvListIncludesGlobal = do --- aliceQ <- randomQualifiedUser --- let alice = qUnqualified aliceQ --- tid <- createBindingTeamInternal "sample-team" alice --- team <- getTeam alice tid --- assertQueue "create team" tActivate --- liftIO $ assertEqual "alice" alice (team ^. teamCreator) --- assertQueueEmpty --- --- -- global team conv doesn't yet include user --- let paginationOpts = GetPaginatedConversationIds Nothing (toRange (Proxy @5)) --- listConvIds alice paginationOpts !!! do --- const 200 === statusCode --- const (Just [globalTeamConv tid]) =/~= (hush . (<$$>) qUnqualified . decodeQualifiedConvIdList) --- --- -- add user to conv --- runMLSTest $ do --- alice1 <- createMLSClient aliceQ --- --- let response = getGlobalTeamConv alice tid response --- let (Just gtc) = Aeson.decode rs :: Maybe GlobalTeamConversation --- gid = cnvmlsGroupId $ gtcMlsMetadata gtc --- --- void $ uploadNewKeyPackage alice1 --- --- -- create mls group --- createGroup alice1 gid --- void $ createAddCommit alice1 [] >>= sendAndConsumeCommitBundle --- --- -- Now we should have the user as part of that conversation also in the backend --- listConvIds alice paginationOpts !!! do --- const 200 === statusCode --- const (Just [globalTeamConv tid]) =~= (hush . (<$$>) qUnqualified . decodeQualifiedConvIdList) --- --- testConvListIncludesGlobalBeforeGet :: TestM () --- testConvListIncludesGlobalBeforeGet = do --- (tid, alice, []) <- Util.createBindingTeamWithMembers 1 --- let paginationOpts = GetPaginatedConversationIds Nothing (toRange (Proxy @5)) --- listConvIds alice paginationOpts !!! do --- const 200 === statusCode --- const (Just [globalTeamConv tid]) =~= (hush . (<$$>) qUnqualified . decodeQualifiedConvIdList) --- --- testConvListIncludesGlobalForNewUsers :: TestM () --- testConvListIncludesGlobalForNewUsers = do --- localDomain <- viewFederationDomain --- -- c <- view tsCannon --- (tid, alice, [bob]) <- Util.createBindingTeamWithMembers 2 --- let aliceQ = Qualified alice localDomain --- bobQ = Qualified bob localDomain --- --- runMLSTest $ do --- [alice1, bob1] <- traverse createMLSClient [aliceQ, bobQ] --- void $ uploadNewKeyPackage bob1 --- --- void $ setupMLSGroup alice1 --- void $ createAddCommit alice1 [bobQ] >>= sendAndConsumeCommitBundle --- --- let paginationOpts = GetPaginatedConversationIds Nothing (toRange (Proxy @5)) --- listConvIds alice paginationOpts !!! do --- const 200 === statusCode --- const (Just [globalTeamConv tid]) =~= (hush . (<$$>) qUnqualified . decodeQualifiedConvIdList) --- --- listConvIds bob paginationOpts !!! do --- const 200 === statusCode --- const (Just [globalTeamConv tid]) =~= (hush . (<$$>) qUnqualified . decodeQualifiedConvIdList) --- --- testGlobalTeamConversationMessage :: TestM () --- testGlobalTeamConversationMessage = do --- alice <- randomQualifiedUser --- let aliceUnq = qUnqualified alice --- --- tid <- createBindingTeamInternal "sample-team" aliceUnq --- team <- getTeam aliceUnq tid --- assertQueue "create team" tActivate --- liftIO $ assertEqual "owner" aliceUnq (team ^. teamCreator) --- assertQueueEmpty --- --- runMLSTest $ do --- clients@[alice1, alice2, alice3] <- traverse createMLSClient (replicate 3 alice) --- --- let response = getGlobalTeamConv aliceUnq tid response --- let (Just gtc) = Aeson.decode rs :: Maybe GlobalTeamConversation --- qcnv = gtcId gtc --- gid = cnvmlsGroupId $ gtcMlsMetadata gtc --- --- traverse_ uploadNewKeyPackage clients --- --- createGroup alice1 gid --- void $ createAddCommit alice1 [] >>= sendAndConsumeCommitBundle --- --- pgs <- --- LBS.toStrict . fromJust . responseBody --- <$> getGroupInfo (ciUser alice1) qcnv --- void $ createExternalCommit alice2 (Just pgs) qcnv >>= sendAndConsumeCommitBundle --- --- -- FUTUREWORK: add tests for race conditions when adding two commits with same epoch? --- -- TODO(elland): test racing conditions for get global team conv --- pgs' <- --- LBS.toStrict . fromJust . responseBody --- <$> getGroupInfo (ciUser alice1) qcnv --- void $ createExternalCommit alice3 (Just pgs') qcnv >>= sendAndConsumeCommitBundle --- --- do --- message <- createApplicationMessage alice1 "some text" --- --- mlsBracket [alice2, alice3] $ \wss -> do --- events <- sendAndConsumeMessage message --- liftIO $ events @?= [] --- liftIO $ --- WS.assertMatchN_ (5 # WS.Second) wss $ --- wsAssertMLSMessage qcnv alice (mpMessage message) --- --- do --- message <- createApplicationMessage alice2 "some text new" --- --- mlsBracket [alice1, alice3] $ \wss -> do --- events <- sendAndConsumeMessage message --- liftIO $ events @?= [] --- liftIO $ --- WS.assertMatchN_ (5 # WS.Second) wss $ --- wsAssertMLSMessage qcnv alice (mpMessage message) --- --- testGlobalTeamConversationLeave :: TestM () --- testGlobalTeamConversationLeave = do --- alice <- randomQualifiedUser --- let aliceUnq = qUnqualified alice --- --- tid <- createBindingTeamInternal "sample-team" aliceUnq --- team <- getTeam aliceUnq tid --- assertQueue "create team" tActivate --- liftIO $ assertEqual "owner" aliceUnq (team ^. teamCreator) --- assertQueueEmpty --- --- runMLSTest $ do --- alice1 <- createMLSClient alice --- --- let response = getGlobalTeamConv aliceUnq tid response --- let (Just gtc) = Aeson.decode rs :: Maybe GlobalTeamConversation --- gid = cnvmlsGroupId $ gtcMlsMetadata gtc --- --- void $ uploadNewKeyPackage alice1 --- createGroup alice1 gid --- void $ createAddCommit alice1 [] >>= sendAndConsumeCommitBundle --- mlsBracket [alice1] $ \wss -> do --- liftTest $ --- deleteMemberQualified (qUnqualified alice) alice (gtcId gtc) --- !!! do --- const 403 === statusCode --- const (Just "invalid-op") === fmap Wai.label . responseJsonError --- WS.assertNoEvent (1 # WS.Second) wss - testSelfConversation :: TestM () testSelfConversation = do alice <- randomQualifiedUser diff --git a/services/galley/test/integration/API/Util.hs b/services/galley/test/integration/API/Util.hs index 3654f4a17c..6ac32f4c00 100644 --- a/services/galley/test/integration/API/Util.hs +++ b/services/galley/test/integration/API/Util.hs @@ -1113,20 +1113,6 @@ getConv u c = do . zConn "conn" . zType "access" -getGlobalTeamConv :: - (MonadIO m, MonadHttp m, HasGalley m, HasCallStack) => - UserId -> - TeamId -> - m ResponseLBS -getGlobalTeamConv u tid = do - g <- viewGalley - get $ - g - . paths ["teams", toByteString' tid, "conversations", "global"] - . zUser u - . zConn "conn" - . zType "access" - getConvQualified :: (MonadIO m, MonadHttp m, HasGalley m, HasCallStack) => UserId -> Qualified ConvId -> m ResponseLBS getConvQualified u (Qualified conv domain) = do g <- viewGalley