diff --git a/changelog.d/5-internal/brig-upa-store-effect b/changelog.d/5-internal/brig-upa-store-effect new file mode 100644 index 00000000000..2c968c67dd3 --- /dev/null +++ b/changelog.d/5-internal/brig-upa-store-effect @@ -0,0 +1 @@ +Brig Polysemy: Port UserPendingActivationStore to polysemy diff --git a/services/brig/brig.cabal b/services/brig/brig.cabal index 8a4fac52941..70cf4076c81 100644 --- a/services/brig/brig.cabal +++ b/services/brig/brig.cabal @@ -54,7 +54,6 @@ library Brig.Data.Types Brig.Data.User Brig.Data.UserKey - Brig.Data.UserPendingActivation Brig.Effects.BlacklistPhonePrefixStore Brig.Effects.BlacklistPhonePrefixStore.Cassandra Brig.Effects.BlacklistStore @@ -90,6 +89,8 @@ library Brig.Sem.CodeStore.Cassandra Brig.Sem.PasswordResetStore Brig.Sem.PasswordResetStore.CodeStore + Brig.Sem.UserPendingActivationStore + Brig.Sem.UserPendingActivationStore.Cassandra Brig.SMTP Brig.Team.API Brig.Team.DB @@ -167,7 +168,7 @@ library ghc-options: -O2 -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates -Wpartial-fields -fwarn-tabs -optP-Wno-nonportable-include-path - -funbox-strict-fields + -funbox-strict-fields -fplugin=Polysemy.Plugin build-depends: aeson >=2.0.1.0 @@ -240,6 +241,7 @@ library , optparse-applicative >=0.11 , pem >=0.2 , polysemy + , polysemy-plugin , polysemy-wire-zoo , proto-lens >=0.1 , random-shuffle >=0.0.3 @@ -541,6 +543,7 @@ executable brig-integration , optparse-applicative , pem , polysemy + , polysemy-wire-zoo , process , proto-lens , QuickCheck diff --git a/services/brig/src/Brig/API.hs b/services/brig/src/Brig/API.hs index 61483fc0bb1..d724135c50f 100644 --- a/services/brig/src/Brig/API.hs +++ b/services/brig/src/Brig/API.hs @@ -27,16 +27,19 @@ import Brig.Effects.BlacklistPhonePrefixStore (BlacklistPhonePrefixStore) import Brig.Effects.BlacklistStore (BlacklistStore) import Brig.Sem.CodeStore import Brig.Sem.PasswordResetStore (PasswordResetStore) +import Brig.Sem.UserPendingActivationStore (UserPendingActivationStore) import qualified Data.Swagger.Build.Api as Doc import Network.Wai.Routing (Routes) import Polysemy sitemap :: + forall r p. Members '[ CodeStore, PasswordResetStore, BlacklistStore, - BlacklistPhonePrefixStore + BlacklistPhonePrefixStore, + UserPendingActivationStore p ] r => Routes Doc.ApiBuilder (Handler r) () diff --git a/services/brig/src/Brig/API/Internal.hs b/services/brig/src/Brig/API/Internal.hs index c2e871490f4..b180513c1eb 100644 --- a/services/brig/src/Brig/API/Internal.hs +++ b/services/brig/src/Brig/API/Internal.hs @@ -46,6 +46,7 @@ import Brig.Options hiding (internalEvents, sesQueue) import qualified Brig.Provider.API as Provider import Brig.Sem.CodeStore (CodeStore) import Brig.Sem.PasswordResetStore (PasswordResetStore) +import Brig.Sem.UserPendingActivationStore (UserPendingActivationStore) import qualified Brig.Team.API as Team import Brig.Team.DB (lookupInvitationByEmail) import Brig.Types.Connection @@ -100,7 +101,13 @@ import Wire.API.User.RichInfo --------------------------------------------------------------------------- -- Sitemap (servant) -servantSitemap :: Members '[BlacklistStore] r => ServerT BrigIRoutes.API (Handler r) +servantSitemap :: + Members + '[ BlacklistStore, + UserPendingActivationStore p + ] + r => + ServerT BrigIRoutes.API (Handler r) servantSitemap = ejpdAPI :<|> accountAPI :<|> mlsAPI :<|> getVerificationCode :<|> teamsAPI :<|> userAPI ejpdAPI :: ServerT BrigIRoutes.EJPD_API (Handler r) @@ -125,7 +132,13 @@ mlsAPI = :<|> getMLSClients :<|> mapKeyPackageRefsInternal -accountAPI :: Member BlacklistStore r => ServerT BrigIRoutes.AccountAPI (Handler r) +accountAPI :: + Members + '[ BlacklistStore, + UserPendingActivationStore p + ] + r => + ServerT BrigIRoutes.AccountAPI (Handler r) accountAPI = Named @"createUserNoVerify" createUserNoVerify :<|> Named @"createUserNoVerifySpar" createUserNoVerifySpar @@ -214,7 +227,8 @@ sitemap :: '[ CodeStore, PasswordResetStore, BlacklistStore, - BlacklistPhonePrefixStore + BlacklistPhonePrefixStore, + UserPendingActivationStore p ] r => Routes a (Handler r) () @@ -420,7 +434,14 @@ internalListFullClients :: UserSet -> (AppT r) UserClientsFull internalListFullClients (UserSet usrs) = UserClientsFull <$> wrapClient (Data.lookupClientsBulk (Set.toList usrs)) -createUserNoVerify :: Member BlacklistStore r => NewUser -> (Handler r) (Either RegisterError SelfProfile) +createUserNoVerify :: + Members + '[ BlacklistStore, + UserPendingActivationStore p + ] + r => + NewUser -> + (Handler r) (Either RegisterError SelfProfile) createUserNoVerify uData = lift . runExceptT $ do result <- API.createUser uData let acc = createdAccount result diff --git a/services/brig/src/Brig/API/Public.hs b/services/brig/src/Brig/API/Public.hs index 00b29d92d65..1b66269cfbc 100644 --- a/services/brig/src/Brig/API/Public.hs +++ b/services/brig/src/Brig/API/Public.hs @@ -51,6 +51,7 @@ import Brig.Options hiding (internalEvents, sesQueue) import qualified Brig.Provider.API as Provider import Brig.Sem.CodeStore (CodeStore) import Brig.Sem.PasswordResetStore (PasswordResetStore) +import Brig.Sem.UserPendingActivationStore (UserPendingActivationStore) import qualified Brig.Team.API as Team import qualified Brig.Team.Email as Team import Brig.Types.Activation (ActivationPair) @@ -185,10 +186,11 @@ swaggerDocsAPI (Just V1) = swaggerDocsAPI Nothing = swaggerDocsAPI (Just maxBound) servantSitemap :: - forall r. + forall r p. Members '[ BlacklistStore, - BlacklistPhonePrefixStore + BlacklistPhonePrefixStore, + UserPendingActivationStore p ] r => ServerT BrigAPI (Handler r) @@ -625,7 +627,14 @@ newNonce _ = do pure nonce -- | docs/reference/user/registration.md {#RefRegistration} -createUser :: Member BlacklistStore r => Public.NewUserPublic -> (Handler r) (Either Public.RegisterError Public.RegisterSuccess) +createUser :: + Members + '[ BlacklistStore, + UserPendingActivationStore p + ] + r => + Public.NewUserPublic -> + (Handler r) (Either Public.RegisterError Public.RegisterSuccess) createUser (Public.NewUserPublic new) = lift . runExceptT $ do API.checkRestrictedUserCreation new for_ (Public.newUserEmail new) $ mapExceptT wrapHttp . checkWhitelistWithError RegisterErrorWhitelistError . Left diff --git a/services/brig/src/Brig/API/User.hs b/services/brig/src/Brig/API/User.hs index ba48a0d9a93..afd82173ec9 100644 --- a/services/brig/src/Brig/API/User.hs +++ b/services/brig/src/Brig/API/User.hs @@ -106,8 +106,6 @@ import Brig.Data.User import qualified Brig.Data.User as Data import Brig.Data.UserKey import qualified Brig.Data.UserKey as Data -import Brig.Data.UserPendingActivation -import qualified Brig.Data.UserPendingActivation as Data import Brig.Effects.BlacklistPhonePrefixStore (BlacklistPhonePrefixStore) import qualified Brig.Effects.BlacklistPhonePrefixStore as BlacklistPhonePrefixStore import Brig.Effects.BlacklistStore (BlacklistStore) @@ -122,6 +120,8 @@ import Brig.Sem.CodeStore (CodeStore) import qualified Brig.Sem.CodeStore as E import Brig.Sem.PasswordResetStore (PasswordResetStore) import qualified Brig.Sem.PasswordResetStore as E +import Brig.Sem.UserPendingActivationStore (UserPendingActivation (..), UserPendingActivationStore) +import qualified Brig.Sem.UserPendingActivationStore as UserPendingActivationStore import qualified Brig.Team.DB as Team import Brig.Types.Activation (ActivationPair) import Brig.Types.Connection @@ -277,7 +277,15 @@ createUserSpar new = do pure $ CreateUserTeam tid nm -- docs/reference/user/registration.md {#RefRegistration} -createUser :: forall r. Member BlacklistStore r => NewUser -> ExceptT RegisterError (AppT r) CreateUserResult +createUser :: + forall r p. + Members + '[ BlacklistStore, + UserPendingActivationStore p + ] + r => + NewUser -> + ExceptT RegisterError (AppT r) CreateUserResult createUser new = do (email, phone) <- validateEmailAndPhone new @@ -448,8 +456,8 @@ createUser new = do field "user" (toByteString uid) . field "team" (toByteString $ Team.iiTeam ii) . msg (val "Accepting invitation") + liftSem $ UserPendingActivationStore.remove uid wrapClient $ do - Data.usersPendingActivationRemove uid Team.deleteInvitation (Team.inTeam inv) (Team.inInvitation inv) addUserToTeamSSO :: UserAccount -> TeamId -> UserIdentity -> ExceptT RegisterError (AppT r) CreateUserTeam @@ -512,7 +520,15 @@ initAccountFeatureConfig uid = do -- | 'createUser' is becoming hard to maintian, and instead of adding more case distinctions -- all over the place there, we add a new function that handles just the one new flow where -- users are invited to the team via scim. -createUserInviteViaScim :: Member BlacklistStore r => UserId -> NewUserScimInvitation -> ExceptT Error.Error (AppT r) UserAccount +createUserInviteViaScim :: + Members + '[ BlacklistStore, + UserPendingActivationStore p + ] + r => + UserId -> + NewUserScimInvitation -> + ExceptT Error.Error (AppT r) UserAccount createUserInviteViaScim uid (NewUserScimInvitation tid loc name rawEmail) = do email <- either (const . throwE . Error.StdError $ errorToWai @'E.InvalidEmail) pure (validateEmail rawEmail) let emKey = userEmailKey email @@ -526,7 +542,7 @@ createUserInviteViaScim uid (NewUserScimInvitation tid loc name rawEmail) = do ttl <- setTeamInvitationTimeout <$> view settings now <- liftIO =<< view currentTime pure $ addUTCTime (realToFrac ttl) now - lift . wrapClient $ Data.usersPendingActivationAdd (UserPendingActivation uid expiresAt) + lift . liftSem $ UserPendingActivationStore.add (UserPendingActivation uid expiresAt) let activated = -- treating 'PendingActivation' as 'Active', but then 'Brig.Data.User.toIdentity' diff --git a/services/brig/src/Brig/CanonicalInterpreter.hs b/services/brig/src/Brig/CanonicalInterpreter.hs index 72ae9ee2cb9..6460a79c42f 100644 --- a/services/brig/src/Brig/CanonicalInterpreter.hs +++ b/services/brig/src/Brig/CanonicalInterpreter.hs @@ -9,17 +9,21 @@ import Brig.Sem.CodeStore (CodeStore) import Brig.Sem.CodeStore.Cassandra (codeStoreToCassandra, interpretClientToIO) import Brig.Sem.PasswordResetStore (PasswordResetStore) import Brig.Sem.PasswordResetStore.CodeStore (passwordResetStoreToCodeStore) +import Brig.Sem.UserPendingActivationStore (UserPendingActivationStore) +import Brig.Sem.UserPendingActivationStore.Cassandra (userPendingActivationStoreToCassandra) import qualified Cassandra as Cas import Control.Lens ((^.)) import Imports import Polysemy (Embed, Final, embedToFinal, runFinal) import Wire.Sem.Now (Now) import Wire.Sem.Now.IO (nowToIOAction) +import Wire.Sem.Paging.Cassandra (InternalPaging) type BrigCanonicalEffects = '[ BlacklistPhonePrefixStore, BlacklistStore, PasswordResetStore, + UserPendingActivationStore InternalPaging, Now, CodeStore, Embed Cas.Client, @@ -34,6 +38,7 @@ runBrigToIO e (AppT ma) = . interpretClientToIO (e ^. casClient) . codeStoreToCassandra @Cas.Client . nowToIOAction (e ^. currentTime) + . userPendingActivationStoreToCassandra . passwordResetStoreToCodeStore . interpretBlacklistStoreToCassandra @Cas.Client . interpretBlacklistPhonePrefixStoreToCassandra @Cas.Client diff --git a/services/brig/src/Brig/Data/UserPendingActivation.hs b/services/brig/src/Brig/Data/UserPendingActivation.hs deleted file mode 100644 index 23a56684281..00000000000 --- a/services/brig/src/Brig/Data/UserPendingActivation.hs +++ /dev/null @@ -1,62 +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 Brig.Data.UserPendingActivation - ( usersPendingActivationAdd, - usersPendingActivationList, - usersPendingActivationRemove, - usersPendingActivationRemoveMultiple, - UserPendingActivation (..), - ) -where - -import Cassandra -import Data.Id (UserId) -import Data.Time (UTCTime) -import Imports - -data UserPendingActivation = UserPendingActivation - { upaUserId :: !UserId, - upaDay :: !UTCTime - } - deriving stock (Eq, Show, Ord) - -usersPendingActivationAdd :: MonadClient m => UserPendingActivation -> m () -usersPendingActivationAdd (UserPendingActivation uid expiresAt) = do - retry x5 . write insertExpiration . params LocalQuorum $ (uid, expiresAt) - where - insertExpiration :: PrepQuery W (UserId, UTCTime) () - insertExpiration = "INSERT INTO users_pending_activation (user, expires_at) VALUES (?, ?)" - -usersPendingActivationList :: MonadClient m => m (Page UserPendingActivation) -usersPendingActivationList = do - uncurry UserPendingActivation <$$> retry x1 (paginate selectExpired (params LocalQuorum ())) - where - selectExpired :: PrepQuery R () (UserId, UTCTime) - selectExpired = - "SELECT user, expires_at FROM users_pending_activation" - -usersPendingActivationRemove :: MonadClient m => UserId -> m () -usersPendingActivationRemove uid = usersPendingActivationRemoveMultiple [uid] - -usersPendingActivationRemoveMultiple :: MonadClient m => [UserId] -> m () -usersPendingActivationRemoveMultiple uids = - retry x5 . write deleteExpired . params LocalQuorum $ Identity uids - where - deleteExpired :: PrepQuery W (Identity [UserId]) () - deleteExpired = - "DELETE FROM users_pending_activation WHERE user IN ?" diff --git a/services/brig/src/Brig/Run.hs b/services/brig/src/Brig/Run.hs index 3e20d9fddf8..8a5eba0a1c3 100644 --- a/services/brig/src/Brig/Run.hs +++ b/services/brig/src/Brig/Run.hs @@ -36,13 +36,13 @@ import qualified Brig.AWS.SesNotification as SesNotification import Brig.App import qualified Brig.Calling as Calling import Brig.CanonicalInterpreter -import Brig.Data.UserPendingActivation (UserPendingActivation (..), usersPendingActivationList, usersPendingActivationRemoveMultiple) import qualified Brig.InternalEvent.Process as Internal import Brig.Options hiding (internalEvents, sesQueue) import qualified Brig.Queue as Queue +import Brig.Sem.UserPendingActivationStore (UserPendingActivation (UserPendingActivation), UserPendingActivationStore) +import qualified Brig.Sem.UserPendingActivationStore as UsersPendingActivationStore import Brig.Types.Intra (AccountStatus (PendingInvitation)) import Brig.Version -import Cassandra (Page (Page)) import qualified Control.Concurrent.Async as Async import Control.Exception.Safe (catchAny) import Control.Lens (view, (.~), (^.)) @@ -67,6 +67,7 @@ import Network.Wai.Routing.Route (App) import Network.Wai.Utilities (lookupRequestId) import Network.Wai.Utilities.Server import qualified Network.Wai.Utilities.Server as Server +import Polysemy (Members) import Servant (Context ((:.)), (:<|>) (..)) import qualified Servant import System.Logger (msg, val, (.=), (~~)) @@ -76,6 +77,7 @@ import Wire.API.Routes.API import Wire.API.Routes.Public.Brig import Wire.API.Routes.Version import Wire.API.Routes.Version.Wai +import qualified Wire.Sem.Paging as P -- FUTUREWORK: If any of these async threads die, we will have no clue about it -- and brig could start misbehaving. We should ensure that brig dies whenever a @@ -180,7 +182,7 @@ bodyParserErrorFormatter _ _ errMsg = Servant.errHeaders = [(HTTP.hContentType, HTTPMedia.renderHeader (Servant.contentType (Proxy @Servant.JSON)))] } -pendingActivationCleanup :: forall r. AppT r () +pendingActivationCleanup :: forall r p. (P.Paging p, Members '[UserPendingActivationStore p] r) => AppT r () pendingActivationCleanup = do safeForever "pendingActivationCleanup" $ do now <- liftIO =<< view currentTime @@ -200,7 +202,7 @@ pendingActivationCleanup = do if isExpired && isPendingInvitation then Just uid else Nothing ) - wrapClient . usersPendingActivationRemoveMultiple $ + liftSem . UsersPendingActivationStore.removeMultiple $ catMaybes ( uids <&> \(isExpired, _isPendingInvitation, uid) -> if isExpired then Just uid else Nothing @@ -218,13 +220,13 @@ pendingActivationCleanup = do forExpirationsPaged :: ([UserPendingActivation] -> (AppT r) ()) -> (AppT r) () forExpirationsPaged f = do - go =<< wrapClient usersPendingActivationList + go =<< liftSem (UsersPendingActivationStore.list Nothing) where - go :: Page UserPendingActivation -> (AppT r) () - go (Page hasMore result nextPage) = do - f result - when hasMore $ - go =<< wrapClient (lift nextPage) + go :: P.Page p UserPendingActivation -> (AppT r) () + go p = do + f (P.pageItems p) + when (P.pageHasMore p) $ do + go =<< liftSem (UsersPendingActivationStore.list $ Just $ P.pageState p) threadDelayRandom :: (AppT r) () threadDelayRandom = do diff --git a/services/brig/src/Brig/Sem/UserPendingActivationStore.hs b/services/brig/src/Brig/Sem/UserPendingActivationStore.hs new file mode 100644 index 00000000000..a23f1d5a878 --- /dev/null +++ b/services/brig/src/Brig/Sem/UserPendingActivationStore.hs @@ -0,0 +1,27 @@ +{-# LANGUAGE TemplateHaskell #-} + +module Brig.Sem.UserPendingActivationStore where + +import Data.Id +import Data.Time.Clock +import Imports +import Polysemy +import Wire.Sem.Paging + +data UserPendingActivation = UserPendingActivation + { upaUserId :: !UserId, + upaDay :: !UTCTime + } + deriving stock (Eq, Show, Ord) + +data UserPendingActivationStore p m a where + Add :: UserPendingActivation -> UserPendingActivationStore p m () + List :: + Maybe (PagingState p UserPendingActivation) -> + UserPendingActivationStore p m (Page p UserPendingActivation) + RemoveMultiple :: [UserId] -> UserPendingActivationStore p m () + +makeSem ''UserPendingActivationStore + +remove :: forall p r. Member (UserPendingActivationStore p) r => UserId -> Sem r () +remove uid = removeMultiple [uid] diff --git a/services/brig/src/Brig/Sem/UserPendingActivationStore/Cassandra.hs b/services/brig/src/Brig/Sem/UserPendingActivationStore/Cassandra.hs new file mode 100644 index 00000000000..9521af20d44 --- /dev/null +++ b/services/brig/src/Brig/Sem/UserPendingActivationStore/Cassandra.hs @@ -0,0 +1,49 @@ +module Brig.Sem.UserPendingActivationStore.Cassandra + ( userPendingActivationStoreToCassandra, + ) +where + +import Brig.Sem.UserPendingActivationStore +import Cassandra +import Data.Id (UserId) +import Data.Time (UTCTime) +import Imports +import Polysemy +import Polysemy.Internal.Tactics +import qualified Wire.Sem.Paging.Cassandra as PC + +userPendingActivationStoreToCassandra :: + forall r a. + (Member (Embed Client) r) => + Sem (UserPendingActivationStore PC.InternalPaging ': r) a -> + Sem r a +userPendingActivationStoreToCassandra = + interpretH $ + liftT . embed @Client . \case + Add upa -> usersPendingActivationAdd upa + List Nothing -> (flip PC.mkInternalPage pure) =<< usersPendingActivationList + List (Just ps) -> PC.ipNext ps + RemoveMultiple uids -> usersPendingActivationRemoveMultiple uids + +usersPendingActivationAdd :: MonadClient m => UserPendingActivation -> m () +usersPendingActivationAdd (UserPendingActivation uid expiresAt) = do + retry x5 . write insertExpiration . params LocalQuorum $ (uid, expiresAt) + where + insertExpiration :: PrepQuery W (UserId, UTCTime) () + insertExpiration = "INSERT INTO users_pending_activation (user, expires_at) VALUES (?, ?)" + +usersPendingActivationList :: MonadClient m => m (Page UserPendingActivation) +usersPendingActivationList = do + uncurry UserPendingActivation <$$> retry x1 (paginate selectExpired (params LocalQuorum ())) + where + selectExpired :: PrepQuery R () (UserId, UTCTime) + selectExpired = + "SELECT user, expires_at FROM users_pending_activation" + +usersPendingActivationRemoveMultiple :: MonadClient m => [UserId] -> m () +usersPendingActivationRemoveMultiple uids = + retry x5 . write deleteExpired . params LocalQuorum $ Identity uids + where + deleteExpired :: PrepQuery W (Identity [UserId]) () + deleteExpired = + "DELETE FROM users_pending_activation WHERE user IN ?" diff --git a/services/brig/src/Brig/Team/API.hs b/services/brig/src/Brig/Team/API.hs index a8fefecf984..9afa8b0a361 100644 --- a/services/brig/src/Brig/Team/API.hs +++ b/services/brig/src/Brig/Team/API.hs @@ -35,6 +35,7 @@ import qualified Brig.Email as Email import qualified Brig.IO.Intra as Intra import Brig.Options (setMaxTeamSize, setTeamInvitationTimeout) import qualified Brig.Phone as Phone +import Brig.Sem.UserPendingActivationStore (UserPendingActivationStore) import qualified Brig.Team.DB as DB import Brig.Team.Email import Brig.Team.Util (ensurePermissionToAddUser, ensurePermissions) @@ -60,7 +61,7 @@ import Network.Wai.Routing import Network.Wai.Utilities hiding (code, message) import Network.Wai.Utilities.Swagger (document) import qualified Network.Wai.Utilities.Swagger as Doc -import Polysemy (Member) +import Polysemy (Member, Members) import System.Logger (Msg) import qualified System.Logger.Class as Log import Util.Logging (logFunction, logTeam) @@ -188,7 +189,13 @@ routesPublic = do Doc.response 200 "Invitation successful." Doc.end Doc.response 403 "No permission (not admin or owner of this team)." Doc.end -routesInternal :: Member BlacklistStore r => Routes a (Handler r) () +routesInternal :: + Members + '[ BlacklistStore, + UserPendingActivationStore p + ] + r => + Routes a (Handler r) () routesInternal = do get "/i/teams/invitations/by-email" (continue getInvitationByEmailH) $ accept "application" "json" @@ -280,12 +287,26 @@ createInvitationPublic uid tid body = do context (createInvitation' tid inviteeRole (Just (inviterUid inviter)) (inviterEmail inviter) body) -createInvitationViaScimH :: Member BlacklistStore r => JSON ::: JsonRequest NewUserScimInvitation -> (Handler r) Response +createInvitationViaScimH :: + Members + '[ BlacklistStore, + UserPendingActivationStore p + ] + r => + JSON ::: JsonRequest NewUserScimInvitation -> + (Handler r) Response createInvitationViaScimH (_ ::: req) = do body <- parseJsonBody req setStatus status201 . json <$> createInvitationViaScim body -createInvitationViaScim :: Member BlacklistStore r => NewUserScimInvitation -> (Handler r) UserAccount +createInvitationViaScim :: + Members + '[ BlacklistStore, + UserPendingActivationStore p + ] + r => + NewUserScimInvitation -> + (Handler r) UserAccount createInvitationViaScim newUser@(NewUserScimInvitation tid loc name email) = do env <- ask let inviteeRole = defaultRole diff --git a/services/brig/test/integration/Main.hs b/services/brig/test/integration/Main.hs index 7321ee93d3c..3e51716247c 100644 --- a/services/brig/test/integration/Main.hs +++ b/services/brig/test/integration/Main.hs @@ -61,6 +61,7 @@ import Util import Util.Options import Util.Test import Wire.API.Federation.API +import Wire.Sem.Paging.Cassandra (InternalPaging) data BackendConf = BackendConf { remoteBrig :: Endpoint, @@ -157,7 +158,7 @@ runTests iConf brigOpts otherArgs = do assertEqual "inconcistent sitemap" mempty - (pathsConsistencyCheck . treeToPaths . compile $ Brig.API.sitemap @BrigCanonicalEffects), + (pathsConsistencyCheck . treeToPaths . compile $ Brig.API.sitemap @BrigCanonicalEffects @InternalPaging), userApi, providerApi, searchApis,