Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cabal.project
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ packages:
, libs/wire-api/
, libs/wire-api-federation/
, libs/wire-message-proto-lens/
, libs/wire-subsystems/
, libs/zauth/
, services/background-worker/
, services/brig/
Expand Down Expand Up @@ -162,6 +163,8 @@ package wire-api-federation
ghc-options: -Werror
package wire-message-proto-lens
ghc-options: -Werror
package wire-subsystems
ghc-options: -Werror
package zauth
ghc-options: -Werror
package fedcalls
Expand Down
1 change: 1 addition & 0 deletions changelog.d/3-bug-fixes/wpb-6144-messaging-blocked-user
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Do not deliver MLS one-to-one conversation messages to a user that blocked the sender
1 change: 1 addition & 0 deletions changelog.d/5-internal/notification-subsystem
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Start refactoring code into subsystems, first subsystem being the NotificationSubsystem.
47 changes: 47 additions & 0 deletions integration/test/Test/MLS/One2One.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

module Test.MLS.One2One where

import API.Brig
import API.Galley
import qualified Data.ByteString.Base64 as Base64
import qualified Data.ByteString.Char8 as B8
Expand Down Expand Up @@ -54,6 +55,52 @@ testGetMLSOne2OneUnconnected otherDomain = do
bindResponse (getMLSOne2OneConversation alice bob) $ \resp ->
resp.status `shouldMatchInt` 403

testMLSOne2OneBlocked :: HasCallStack => Domain -> App ()
testMLSOne2OneBlocked otherDomain = do
[alice, bob] <- for [OwnDomain, otherDomain] $ flip randomUser def
void $ postConnection bob alice >>= getBody 201
void $ putConnection alice bob "blocked" >>= getBody 200
void $ getMLSOne2OneConversation alice bob >>= getJSON 403
void $ getMLSOne2OneConversation bob alice >>= getJSON 403

-- | Alice and Bob are initially connected, but then Alice blocks Bob.
testMLSOne2OneBlockedAfterConnected :: HasCallStack => One2OneScenario -> App ()
testMLSOne2OneBlockedAfterConnected scenario = do
alice <- randomUser OwnDomain def
let otherDomain = one2OneScenarioDomain scenario
convDomain = one2OneScenarioConvDomain scenario
bob <- createMLSOne2OnePartner otherDomain alice convDomain
conv <- getMLSOne2OneConversation alice bob >>= getJSON 200
convId <- conv %. "qualified_id"
do
bobConv <- getMLSOne2OneConversation bob alice >>= getJSON 200
convId `shouldMatch` (bobConv %. "qualified_id")

[alice1, bob1] <- traverse (createMLSClient def) [alice, bob]
traverse_ uploadNewKeyPackage [bob1]
resetGroup alice1 conv
commit <- createAddCommit alice1 [bob]
withWebSocket bob1 $ \ws -> do
void $ sendAndConsumeCommitBundle commit
let isMessage n = nPayload n %. "type" `isEqual` "conversation.mls-welcome"
n <- awaitMatch isMessage ws
nPayload n %. "data" `shouldMatch` B8.unpack (Base64.encode (fold commit.welcome))

withWebSocket bob1 $ \ws -> do
-- Alice blocks Bob
void $ putConnection alice bob "blocked" >>= getBody 200
-- There is also a proteus 1-to-1 conversation. Neither it nor the MLS
-- 1-to-1 conversation should get any events.
awaitAnyEvent 2 ws `shouldMatch` (Nothing :: Maybe Value)
-- Alice is not in the MLS 1-to-1 conversation given that she has blocked
-- Bob.
void $ getMLSOne2OneConversation alice bob >>= getJSON 403

mp <- createApplicationMessage bob1 "hello, world, again"
withWebSocket alice1 $ \ws -> do
void $ postMLSMessage mp.sender mp.message >>= getJSON 201
awaitAnyEvent 2 ws `shouldMatch` (Nothing :: Maybe Value)

testGetMLSOne2OneSameTeam :: App ()
testGetMLSOne2OneSameTeam = do
(alice, _, _) <- createTeam OwnDomain 1
Expand Down
3 changes: 2 additions & 1 deletion integration/test/Testlib/Cannon.hs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ module Testlib.Cannon
awaitNMatchesResult,
awaitNMatches,
awaitMatch,
awaitAnyEvent,
awaitAtLeastNMatchesResult,
awaitAtLeastNMatches,
awaitNToMMatchesResult,
Expand Down Expand Up @@ -282,7 +283,7 @@ printAwaitResult = prettyAwaitResult >=> liftIO . putStrLn
printAwaitAtLeastResult :: AwaitAtLeastResult -> App ()
printAwaitAtLeastResult = prettyAwaitAtLeastResult >=> liftIO . putStrLn

awaitAnyEvent :: MonadIO m => Int -> WebSocket -> m (Maybe Value)
awaitAnyEvent :: Int -> WebSocket -> App (Maybe Value)
awaitAnyEvent tSecs = liftIO . timeout (tSecs * 1000 * 1000) . atomically . readTChan . wsChan

-- | 'await' an expected number of notification events on the websocket that
Expand Down
2 changes: 2 additions & 0 deletions libs/extended/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
, servant-server
, temporary
, text
, time
, tinylog
, unliftio
, wai
Expand Down Expand Up @@ -63,6 +64,7 @@ mkDerivation {
servant-openapi3
servant-server
text
time
tinylog
unliftio
wai
Expand Down
2 changes: 2 additions & 0 deletions libs/extended/extended.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ build-type: Simple
library
-- cabal-fmt: expand src
exposed-modules:
Data.Time.Clock.DiffTime
Network.AMQP.Extended
Network.RabbitMqAdmin
Options.Applicative.Extended
Expand Down Expand Up @@ -101,6 +102,7 @@ library
, servant-openapi3
, servant-server
, text
, time
, tinylog
, unliftio
, wai
Expand Down
43 changes: 43 additions & 0 deletions libs/extended/src/Data/Time/Clock/DiffTime.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
module Data.Time.Clock.DiffTime
( DiffTime,
weeksToDiffTime,
daysToDiffTime,
hoursToDiffTime,
minutesToDiffTime,
secondsToDiffTime,
millisecondsToDiffTime,
microsecondsToDiffTime,
nanosecondsToDiffTime,
picosecondsToDiffTime,
diffTimeToFullMicroseconds,
diffTimeToPicoseconds,
)
where

import Data.Time
import Imports

weeksToDiffTime,
daysToDiffTime,
hoursToDiffTime,
minutesToDiffTime,
millisecondsToDiffTime,
microsecondsToDiffTime,
nanosecondsToDiffTime ::
Integer -> DiffTime
weeksToDiffTime = daysToDiffTime . (7 *)
daysToDiffTime = hoursToDiffTime . (24 *)
hoursToDiffTime = minutesToDiffTime . (60 *)
minutesToDiffTime = secondsToDiffTime . (60 *)
millisecondsToDiffTime = picosecondsToDiffTime . (e9 *)
microsecondsToDiffTime = picosecondsToDiffTime . (e6 *)
nanosecondsToDiffTime = picosecondsToDiffTime . (e3 *)

-- | Rounds down. Useful for 'threadDelay', 'timeout', etc.
diffTimeToFullMicroseconds :: DiffTime -> Int
diffTimeToFullMicroseconds = fromInteger . (`div` e6) . diffTimeToPicoseconds

e3, e6, e9 :: Integer
e3 = 1_000
e6 = 1_000_000
e9 = 1_000_000_000
10 changes: 6 additions & 4 deletions libs/gundeck-types/src/Gundeck/Types/Push/V2.hs
Original file line number Diff line number Diff line change
Expand Up @@ -171,14 +171,15 @@ instance ToJSON RecipientClients where
-- ApsData

newtype ApsSound = ApsSound {fromSound :: Text}
deriving (Eq, Show, ToJSON, FromJSON)
deriving (Eq, Show, ToJSON, FromJSON, Arbitrary)

newtype ApsLocKey = ApsLocKey {fromLocKey :: Text}
deriving (Eq, Show, ToJSON, FromJSON)
deriving (Eq, Show, ToJSON, FromJSON, Arbitrary)

data ApsPreference
= ApsStdPreference
deriving (Eq, Show)
deriving (Eq, Show, Generic)
deriving (Arbitrary) via GenericUniform ApsPreference

instance ToJSON ApsPreference where
toJSON ApsStdPreference = "std"
Expand All @@ -195,7 +196,8 @@ data ApsData = ApsData
_apsPreference :: !(Maybe ApsPreference),
_apsBadge :: !Bool
}
deriving (Eq, Show)
deriving (Eq, Show, Generic)
deriving (Arbitrary) via GenericUniform ApsData

makeLenses ''ApsData

Expand Down
1 change: 1 addition & 0 deletions libs/polysemy-wire-zoo/polysemy-wire-zoo.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ library
Wire.Sem.Concurrency
Wire.Sem.Concurrency.IO
Wire.Sem.Concurrency.Sequential
Wire.Sem.Delay
Wire.Sem.FromUTC
Wire.Sem.Jwk
Wire.Sem.Logger
Expand Down
58 changes: 58 additions & 0 deletions libs/polysemy-wire-zoo/src/Wire/Sem/Concurrency.hs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,32 @@ unsafePooledMapConcurrentlyN_ n f as =
(UnsafePooledMapConcurrentlyN_ n f as :: Concurrency 'Unsafe (Sem r) ())
{-# INLINEABLE unsafePooledMapConcurrentlyN_ #-}

unsafePooledForConcurrentlyN ::
forall r t a b.
(Member (Concurrency 'Unsafe) r, Foldable t) =>
-- | Max. number of threads. Should not be less than 1.
Int ->
t a ->
(a -> Sem r b) ->
Sem r [b]
unsafePooledForConcurrentlyN n as f =
send
(UnsafePooledMapConcurrentlyN n f as :: Concurrency 'Unsafe (Sem r) [b])
{-# INLINEABLE unsafePooledForConcurrentlyN #-}

unsafePooledForConcurrentlyN_ ::
forall r t a b.
(Member (Concurrency 'Unsafe) r, Foldable t) =>
-- | Max. number of threads. Should not be less than 1.
Int ->
t a ->
(a -> Sem r b) ->
Sem r ()
unsafePooledForConcurrentlyN_ n as f =
send
(UnsafePooledMapConcurrentlyN_ n f as :: Concurrency 'Unsafe (Sem r) ())
{-# INLINEABLE unsafePooledForConcurrentlyN_ #-}

pooledMapConcurrentlyN ::
forall r' r t a b.
r' ~ '[Final IO] =>
Expand Down Expand Up @@ -111,3 +137,35 @@ pooledMapConcurrentlyN_ n f as =
Concurrency 'Safe (Sem r) ()
)
{-# INLINEABLE pooledMapConcurrentlyN_ #-}

pooledForConcurrentlyN ::
forall r' r t a b.
r' ~ '[Final IO] =>
(Member (Concurrency 'Safe) r, Subsume r' r, Foldable t) =>
-- | Max. number of threads. Should not be less than 1.
Int ->
t a ->
(a -> Sem r' b) ->
Sem r [b]
pooledForConcurrentlyN n as f =
send
( UnsafePooledMapConcurrentlyN n (subsume_ @r' @r . f) as ::
Concurrency 'Safe (Sem r) [b]
)
{-# INLINEABLE pooledForConcurrentlyN #-}

pooledForConcurrentlyN_ ::
forall r' r t a b.
r' ~ '[Final IO] =>
(Member (Concurrency 'Safe) r, Subsume r' r, Foldable t) =>
-- | Max. number of threads. Should not be less than 1.
Int ->
t a ->
(a -> Sem r' b) ->
Sem r ()
pooledForConcurrentlyN_ n as f =
send
( UnsafePooledMapConcurrentlyN_ n (subsume_ @r' @r . f) as ::
Concurrency 'Safe (Sem r) ()
)
{-# INLINEABLE pooledForConcurrentlyN_ #-}
32 changes: 32 additions & 0 deletions libs/polysemy-wire-zoo/src/Wire/Sem/Delay.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{-# LANGUAGE TemplateHaskell #-}

module Wire.Sem.Delay where

import Imports
import Polysemy

data Delay m a where
Delay :: Int -> Delay m ()

makeSem ''Delay

runDelay :: Member (Embed IO) r => Sem (Delay ': r) a -> Sem r a
runDelay = interpret $ \case
Delay i -> threadDelay i

runControlledDelay :: forall r a. (Member (Embed IO) r) => MVar Int -> Sem (Delay : r) a -> Sem r a
runControlledDelay tickSource = interpret $ \case
Delay n -> waitForTicks n
where
waitForTicks :: Int -> Sem r ()
waitForTicks 0 = pure ()
waitForTicks remaining0 = do
passedTicks <- takeMVar tickSource
let remaining = remaining0 - passedTicks
if remaining <= 0
then pure ()
else waitForTicks remaining

runDelayInstantly :: Sem (Delay : r) a -> Sem r a
runDelayInstantly = interpret $ \case
Delay _ -> pure ()
15 changes: 15 additions & 0 deletions libs/polysemy-wire-zoo/src/Wire/Sem/Logger/TinyLog.hs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{-# LANGUAGE RecordWildCards #-}

-- This file is part of the Wire Server implementation.
--
-- Copyright (C) 2022 Wire Swiss GmbH <opensource@wire.com>
Expand All @@ -21,12 +23,16 @@ module Wire.Sem.Logger.TinyLog
stringLoggerToTinyLog,
discardTinyLogs,
module Wire.Sem.Logger.Level,
LogRecorder (..),
newLogRecorder,
recordLogs,
)
where

import Data.Id
import Imports
import Polysemy
import Polysemy.TinyLog (TinyLog)
import qualified System.Logger as Log
import Wire.Sem.Logger
import Wire.Sem.Logger.Level
Expand Down Expand Up @@ -58,3 +64,12 @@ stringLoggerToTinyLog = mapLogger @String Log.msg

discardTinyLogs :: Sem (Logger (Log.Msg -> Log.Msg) ': r) a -> Sem r a
discardTinyLogs = discardLogs

newtype LogRecorder = LogRecorder {recordedLogs :: IORef [(Level, LByteString)]}

newLogRecorder :: IO LogRecorder
newLogRecorder = LogRecorder <$> newIORef []

recordLogs :: Member (Embed IO) r => LogRecorder -> Sem (TinyLog ': r) a -> Sem r a
recordLogs LogRecorder {..} = interpret $ \(Log lvl msg) ->
modifyIORef' recordedLogs (++ [(lvl, Log.render (Log.renderDefault ", ") msg)])
3 changes: 3 additions & 0 deletions libs/types-common/src/Data/Range.hs
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,9 @@ genRange pack_ gc =
instance (KnownNat n, KnownNat m, n <= m) => Arbitrary (Range n m Integer) where
arbitrary = genIntegral

instance (KnownNat n, KnownNat m, n <= m) => Arbitrary (Range n m Int32) where
arbitrary = genIntegral

instance (KnownNat n, KnownNat m, n <= m) => Arbitrary (Range n m Word) where
arbitrary = genIntegral

Expand Down
Loading