Skip to content

Commit 1bc6cf9

Browse files
committed
Merge remote-tracking branch 'origin/develop' into SQSERVICES-1627-check-remaining-time-of-an-activated-a-feature-in-back-office
2 parents d3747dc + 18d469e commit 1bc6cf9

File tree

13 files changed

+148
-19
lines changed

13 files changed

+148
-19
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add shellcheck, libstdc++ to nix env; handle emacs auto-save files better
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add internal endpoint in Brig to update clients' key package refs in DB upon committing.
2+
Brig should be deployed before Galley.

hack/bin/cabal-fmt.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,22 @@ format_single() {
2727
cabal-fmt -i "$cabal_file"
2828
}
2929

30+
handle_emacs_autosave() {
31+
hs_autosave_files="$(cd "$TOP_LEVEL"; find . -not \( -path ./dist-newstyle -prune \) -not \( -path ./charts -prune \) -name "*.hs~")"
32+
33+
if [ -n "${hs_autosave_files}" ]; then
34+
if [ "${WIRE_FORCE_RM_EMACS_AUTOSAVE_FILES-}" == "1" ]; then
35+
# shellcheck disable=SC2086
36+
rm ${hs_autosave_files}
37+
else
38+
echo -e "\nautosave files are breaking cabal-fmt:\n\n${hs_autosave_files}\n\nto remove, run with 'WIRE_FORCE_RM_EMACS_AUTOSAVE_FILES=1'.\n"
39+
exit 1
40+
fi
41+
fi
42+
}
43+
44+
handle_emacs_autosave
45+
3046
if [ "$1" = "all" ]; then
3147
format_all
3248
else

libs/wire-api/src/Wire/API/MLS/Commit.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ instance ParseMLS Commit where
3131
parseMLS = Commit <$> parseMLSVector @Word32 parseMLS <*> parseMLSOptional parseMLS
3232

3333
data UpdatePath = UpdatePath
34-
{ upLeaf :: KeyPackage,
34+
{ upLeaf :: RawMLS KeyPackage,
3535
upNodes :: [UpdatePathNode]
3636
}
3737

libs/wire-api/src/Wire/API/MLS/KeyPackage.hs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ module Wire.API.MLS.KeyPackage
3333
kpRef',
3434
KeyPackageTBS (..),
3535
KeyPackageRef (..),
36+
KeyPackageUpdate (..),
3637
)
3738
where
3839

@@ -114,6 +115,7 @@ instance ToSchema KeyPackageCount where
114115
newtype KeyPackageRef = KeyPackageRef {unKeyPackageRef :: ByteString}
115116
deriving stock (Eq, Ord, Show)
116117
deriving (FromHttpApiData, ToHttpApiData, S.ToParamSchema) via Base64ByteString
118+
deriving (ToJSON, FromJSON, S.ToSchema) via (Schema KeyPackageRef)
117119

118120
instance ToSchema KeyPackageRef where
119121
schema = named "KeyPackageRef" $ unKeyPackageRef .= fmap KeyPackageRef base64Schema
@@ -191,3 +193,10 @@ instance ParseMLS KeyPackage where
191193
KeyPackage
192194
<$> parseRawMLS parseMLS
193195
<*> parseMLSBytes @Word16
196+
197+
--------------------------------------------------------------------------------
198+
199+
data KeyPackageUpdate = KeyPackageUpdate
200+
{ kpupPrevious :: KeyPackageRef,
201+
kpupNext :: KeyPackageRef
202+
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,16 @@ type MLSAPI =
198198
'[RespondEmpty 201 "Key package ref mapping created"]
199199
()
200200
)
201+
:<|> Named
202+
"post-key-package-ref"
203+
( Summary "Update a KeyPackageRef in mapping"
204+
:> ReqBody '[Servant.JSON] KeyPackageRef
205+
:> MultiVerb
206+
'POST
207+
'[Servant.JSON]
208+
'[RespondEmpty 201 "Key package ref mapping updated"]
209+
()
210+
)
201211
)
202212
)
203213
:<|> GetMLSClients

nix/default.nix

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ let
3333
compile-deps = pkgs.buildEnv {
3434
name = "wire-server-compile-deps";
3535
paths = [
36+
pkgs.stdenv.cc.cc.lib
37+
3638
pkgs.bash
3739
pkgs.coreutils
3840
pkgs.gnused
@@ -96,6 +98,7 @@ let
9698
pkgs.netcat
9799
pkgs.niv
98100
pkgs.ormolu
101+
pkgs.shellcheck
99102
pkgs.python3
100103
pkgs.rsync
101104
pkgs.shellcheck

services/brig/src/Brig/API/Internal.hs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ mlsAPI =
120120
:<|> Named @"get-conversation-by-key-package-ref" (getConvIdByKeyPackageRef ref)
121121
)
122122
:<|> Named @"put-key-package-ref" (putKeyPackageRef ref)
123+
:<|> Named @"post-key-package-ref" (postKeyPackageRef ref)
123124
)
124125
:<|> getMLSClients
125126
:<|> mapKeyPackageRefsInternal
@@ -161,6 +162,10 @@ putKeyPackageRef ref = lift . wrapClient . Data.addKeyPackageRef ref
161162
getConvIdByKeyPackageRef :: KeyPackageRef -> Handler r (Maybe (Qualified ConvId))
162163
getConvIdByKeyPackageRef = runMaybeT . mapMaybeT wrapClientE . Data.keyPackageRefConvId
163164

165+
-- Used by galley to update key packages in mls_key_package_ref on commits with update_path
166+
postKeyPackageRef :: KeyPackageRef -> KeyPackageRef -> Handler r ()
167+
postKeyPackageRef ref = lift . wrapClient . Data.updateKeyPackageRef ref
168+
164169
getMLSClients :: UserId -> SignatureSchemeTag -> Handler r (Set ClientId)
165170
getMLSClients usr ss = do
166171
results <- lift (wrapClient (API.lookupUsersClientIds (pure usr))) >>= getResult

services/brig/src/Brig/Data/MLS/KeyPackage.hs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ module Brig.Data.MLS.KeyPackage
2424
keyPackageRefConvId,
2525
keyPackageRefSetConvId,
2626
addKeyPackageRef,
27+
updateKeyPackageRef,
2728
)
2829
where
2930

@@ -194,9 +195,48 @@ addKeyPackageRef ref nkpr = do
194195
q :: PrepQuery W (ClientId, ConvId, Domain, Domain, UserId, KeyPackageRef) x
195196
q = "UPDATE mls_key_package_refs SET client = ?, conv = ?, conv_domain = ?, domain = ?, user = ? WHERE ref = ?"
196197

198+
-- | Update key package ref, used in Galley when commit reveals key package ref update for the sender.
199+
-- Nothing is changed if the previous key package ref is not found in the table.
200+
-- Updating amounts to INSERT the new key package ref, followed by DELETE the
201+
-- previous one.
202+
--
203+
-- FUTUREWORK: this function has to be extended if a table mapping (client,
204+
-- conversation) to key package ref is added, for instance, when implementing
205+
-- external delete proposals.
206+
updateKeyPackageRef :: MonadClient m => KeyPackageRef -> KeyPackageRef -> m ()
207+
updateKeyPackageRef prevRef newRef =
208+
void . runMaybeT $ do
209+
backup <- backupKeyPackageMeta prevRef
210+
lift $ restoreKeyPackageMeta newRef backup >> deleteKeyPackage prevRef
211+
197212
--------------------------------------------------------------------------------
198213
-- Utilities
199214

215+
backupKeyPackageMeta :: MonadClient m => KeyPackageRef -> MaybeT m (ClientId, Qualified ConvId, Qualified UserId)
216+
backupKeyPackageMeta ref = do
217+
(clientId, convId, convDomain, userDomain, userId) <- MaybeT . retry x1 $ query1 q (params LocalQuorum (Identity ref))
218+
pure (clientId, Qualified convId convDomain, Qualified userId userDomain)
219+
where
220+
q :: PrepQuery R (Identity KeyPackageRef) (ClientId, ConvId, Domain, Domain, UserId)
221+
q = "SELECT client, conv, conv_domain, domain, user FROM mls_key_package_refs WHERE ref = ?"
222+
223+
restoreKeyPackageMeta :: MonadClient m => KeyPackageRef -> (ClientId, Qualified ConvId, Qualified UserId) -> m ()
224+
restoreKeyPackageMeta ref (clientId, convId, userId) = do
225+
write q (params LocalQuorum (ref, clientId, qUnqualified convId, qDomain convId, qDomain userId, qUnqualified userId))
226+
where
227+
q :: PrepQuery W (KeyPackageRef, ClientId, ConvId, Domain, Domain, UserId) ()
228+
q = "INSERT INTO mls_key_package_refs (ref, client, conv, conv_domain, domain, user) VALUES (?, ?, ?, ?, ?, ?)"
229+
230+
deleteKeyPackage :: MonadClient m => KeyPackageRef -> m ()
231+
deleteKeyPackage ref =
232+
retry x5 $
233+
write
234+
q
235+
(params LocalQuorum (Identity ref))
236+
where
237+
q :: PrepQuery W (Identity KeyPackageRef) x
238+
q = "DELETE FROM mls_key_package_refs WHERE ref = ?"
239+
200240
pick :: [a] -> IO (Maybe a)
201241
pick [] = pure Nothing
202242
pick xs = do

services/galley/src/Galley/API/MLS/Message.hs

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ processCommit ::
328328
Member (ErrorS 'MissingLegalholdConsent) r,
329329
Member (Input (Local ())) r,
330330
Member ProposalStore r,
331+
Member BrigAccess r,
331332
Member Resource r
332333
) =>
333334
Qualified UserId ->
@@ -353,24 +354,47 @@ processCommit qusr con lconv epoch sender commit = do
353354
let ttlSeconds :: Int = 600 -- 10 minutes
354355
withCommitLock groupId epoch (fromIntegral ttlSeconds) $ do
355356
checkEpoch epoch (tUnqualified lconv)
356-
when (epoch == Epoch 0) $ do
357-
-- this is a newly created conversation, and it should contain exactly one
358-
-- client (the creator)
359-
case (sender, first (toList . lmMLSClients) self) of
360-
(MemberSender ref, Left [creatorClient]) -> do
361-
-- register the creator client
362-
addKeyPackageRef
363-
ref
364-
qusr
365-
creatorClient
366-
(qUntagged (fmap Data.convId lconv))
367-
-- remote clients cannot send the first commit
368-
(_, Right _) -> throwS @'MLSStaleMessage
369-
-- uninitialised conversations should contain exactly one client
370-
(MemberSender _, _) ->
371-
throw (InternalErrorWithDescription "Unexpected creator client set")
372-
-- the sender of the first commit must be a member
373-
_ -> throw (mlsProtocolError "Unexpected sender")
357+
postponedKeyPackageRefUpdate <-
358+
if epoch == Epoch 0
359+
then do
360+
-- this is a newly created conversation, and it should contain exactly one
361+
-- client (the creator)
362+
case (sender, first (toList . lmMLSClients) self) of
363+
(MemberSender currentRef, Left [creatorClient]) -> do
364+
-- use update path as sender reference and if not existing fall back to sender
365+
senderRef <-
366+
maybe
367+
(pure currentRef)
368+
( (& note (mlsProtocolError "Could not compute key package ref"))
369+
. kpRef'
370+
. upLeaf
371+
)
372+
$ cPath commit
373+
-- register the creator client
374+
addKeyPackageRef
375+
senderRef
376+
qusr
377+
creatorClient
378+
(qUntagged (fmap Data.convId lconv))
379+
-- remote clients cannot send the first commit
380+
(_, Right _) -> throwS @'MLSStaleMessage
381+
-- uninitialised conversations should contain exactly one client
382+
(MemberSender _, _) ->
383+
throw (InternalErrorWithDescription "Unexpected creator client set")
384+
-- the sender of the first commit must be a member
385+
_ -> throw (mlsProtocolError "Unexpected sender")
386+
pure $ pure () -- no key package ref update necessary
387+
else case (sender, upLeaf <$> cPath commit) of
388+
(MemberSender senderRef, Just updatedKeyPackage) -> do
389+
updatedRef <- kpRef' updatedKeyPackage & note (mlsProtocolError "Could not compute key package ref")
390+
-- postpone key package ref update until other checks/processing passed
391+
pure . updateKeyPackageRef $
392+
KeyPackageUpdate
393+
{ kpupPrevious = senderRef,
394+
kpupNext = updatedRef
395+
}
396+
(_, Nothing) -> pure $ pure () -- ignore commits without update path
397+
_ -> throw (mlsProtocolError "Unexpected sender")
374398

375399
-- check all pending proposals are referenced in the commit
376400
allPendingProposals <- getAllPendingProposals groupId epoch
@@ -382,6 +406,8 @@ processCommit qusr con lconv epoch sender commit = do
382406
action <- foldMap (applyProposalRef (tUnqualified lconv) groupId epoch) (cProposals commit)
383407
updates <- executeProposalAction qusr con lconv action
384408

409+
-- update key package ref if necessary
410+
postponedKeyPackageRefUpdate
385411
-- increment epoch number
386412
setConversationEpoch (Data.convId (tUnqualified lconv)) (succ epoch)
387413

0 commit comments

Comments
 (0)