From fc9e266fd6fdbc455201c68cd0ee761b379f79c9 Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Tue, 17 Dec 2024 11:53:49 +0100 Subject: [PATCH 1/3] Delete backend-notification queues from federation-v0 and federation-v1 after running tests (#4374) This ensures that the queues don't accumulate in the statically deployed instances over time. https://wearezeta.atlassian.net/browse/WPB-11810 Co-authored-by: Akshay Mankar --- .envrc | 13 ++++-- changelog.d/5-internal/WPB-11810 | 1 + charts/integration/templates/configmap.yaml | 14 ++++++ .../templates/integration-integration.yaml | 14 ++++++ hack/bin/integration-test.sh | 6 +++ integration/test/Test/Events.hs | 5 +- integration/test/Testlib/Env.hs | 2 + integration/test/Testlib/ResourcePool.hs | 9 ++-- integration/test/Testlib/Run.hs | 46 +++++++++++++++++++ integration/test/Testlib/Types.hs | 12 ++++- libs/extended/src/Network/AMQP/Extended.hs | 9 ++-- libs/extended/src/Network/RabbitMqAdmin.hs | 30 +++++++++--- .../src/Wire/BackendNotificationPusher.hs | 16 ++++--- .../Wire/BackendNotificationPusherSpec.hs | 12 +++-- services/integration.yaml | 14 ++++++ 15 files changed, 173 insertions(+), 30 deletions(-) create mode 100644 changelog.d/5-internal/WPB-11810 diff --git a/.envrc b/.envrc index 6fd34b70988..0d35f22e533 100644 --- a/.envrc +++ b/.envrc @@ -17,16 +17,16 @@ export NIX_CONFIG='extra-experimental-features = nix-command' [[ -d "$layout_dir" ]] || mkdir -p "$layout_dir" -if [[ ! -d "$env_dir" || ! -f "$layout_dir/nix-rebuild" || "$store_paths" != $(< "$layout_dir/nix-rebuild" ) ]]; then +if [[ ! -d "$env_dir" || ! -f "$layout_dir/nix-rebuild" || "$store_paths" != $(<"$layout_dir/nix-rebuild") ]]; then bcmd=nix - if command -v nom &> /dev/null; then + if command -v nom &>/dev/null; then if [[ "${USE_NOM}" != "0" ]]; then bcmd=nom fi fi echo "🔧 Building environment" $bcmd build -f nix wireServer.devEnv -Lv --out-link ./.env - echo "$store_paths" > "$layout_dir/nix-rebuild" + echo "$store_paths" >"$layout_dir/nix-rebuild" fi PATH_add "./.env/bin" @@ -49,8 +49,13 @@ export LANG=en_US.UTF-8 export RABBITMQ_USERNAME=guest export RABBITMQ_PASSWORD=alpaca-grapefruit -# Redis +export RABBITMQ_USERNAME_V0=guest +export RABBITMQ_PASSWORD_V0=alpaca-grapefruit + +export RABBITMQ_USERNAME_V1=guest +export RABBITMQ_PASSWORD_V1=alpaca-grapefruit +# Redis export REDIS_PASSWORD=very-secure-redis-cluster-password export REDIS_ADDITIONAL_WRITE_PASSWORD=very-secure-redis-master-password diff --git a/changelog.d/5-internal/WPB-11810 b/changelog.d/5-internal/WPB-11810 new file mode 100644 index 00000000000..060a9fc7df3 --- /dev/null +++ b/changelog.d/5-internal/WPB-11810 @@ -0,0 +1 @@ +Delete federation V0 and V1 queues after integration tests diff --git a/charts/integration/templates/configmap.yaml b/charts/integration/templates/configmap.yaml index ae450fe9a7a..6dc88682c80 100644 --- a/charts/integration/templates/configmap.yaml +++ b/charts/integration/templates/configmap.yaml @@ -70,6 +70,20 @@ data: rabbitmq: host: rabbitmq adminPort: 15671 + tls: true + vHost: / + + rabbitmq-v0: + host: rabbitmq.wire-federation-v0.svc.cluster.local + adminPort: 15672 + tls: false + vHost: / + + rabbitmq-v1: + host: rabbitmq.wire-federation-v1.svc.cluster.local + adminPort: 15672 + tls: false + vHost: / backendTwo: diff --git a/charts/integration/templates/integration-integration.yaml b/charts/integration/templates/integration-integration.yaml index 454a3fa151e..dc132746797 100644 --- a/charts/integration/templates/integration-integration.yaml +++ b/charts/integration/templates/integration-integration.yaml @@ -310,6 +310,20 @@ spec: secretKeyRef: name: brig key: rabbitmqPassword + - name: RABBITMQ_USERNAME_V0 + value: "wire-server" + - name: RABBITMQ_PASSWORD_V0 + valueFrom: + secretKeyRef: + name: rabbitmq-v0 + key: rabbitmq-password + - name: RABBITMQ_USERNAME_V1 + value: "wire-server" + - name: RABBITMQ_PASSWORD_V1 + valueFrom: + secretKeyRef: + name: rabbitmq-v1 + key: rabbitmq-password {{- if hasKey .Values.secrets "redisUsername" }} - name: REDIS_USERNAME valueFrom: diff --git a/hack/bin/integration-test.sh b/hack/bin/integration-test.sh index 0667ebeac28..d1f1c02931d 100755 --- a/hack/bin/integration-test.sh +++ b/hack/bin/integration-test.sh @@ -50,6 +50,12 @@ summary() { done } +# Copy the secrets from the wire-federation-v0 namespace to the current namespace to be able to delete RabbitMQ queues that are created by the integration tests to avoid overflows +kubectl -n "$NAMESPACE" delete --force secret rabbitmq-v0 || true +kubectl -n wire-federation-v0 get secrets rabbitmq -ojson | jq 'del(.metadata.namespace) | del(.metadata.resourceVersion) | del(.metadata.uid) | .metadata.name="rabbitmq-v0"' | kubectl -n "$NAMESPACE" apply -f - +kubectl -n "$NAMESPACE" delete --force secret rabbitmq-v1 || true +kubectl -n wire-federation-v1 get secrets rabbitmq -ojson | jq 'del(.metadata.namespace) | del(.metadata.resourceVersion) | del(.metadata.uid) | .metadata.name="rabbitmq-v1"' | kubectl -n "$NAMESPACE" apply -f - + # Run tests in parallel using GNU parallel (see https://www.gnu.org/software/parallel/) # The below commands are a little convoluted, but we wish to: # - run integration tests. If they fail, keep track of this, but still go and get logs, so we see what failed diff --git a/integration/test/Test/Events.hs b/integration/test/Test/Events.hs index 2bd9fd5b6ba..97aeb660fb6 100644 --- a/integration/test/Test/Events.hs +++ b/integration/test/Test/Events.hs @@ -570,7 +570,10 @@ killConnection backend = do port = 0, adminPort = fromIntegral rc.adminPort, vHost = Text.pack backend.berVHost, - tls = Just $ RabbitMqTlsOpts Nothing True + tls = + if rc.tls + then Just $ RabbitMqTlsOpts Nothing True + else Nothing } servantClient <- liftIO $ mkRabbitMqAdminClientEnv opts name <- do diff --git a/integration/test/Testlib/Env.hs b/integration/test/Testlib/Env.hs index f276f624c52..401332e4a0b 100644 --- a/integration/test/Testlib/Env.hs +++ b/integration/test/Testlib/Env.hs @@ -109,6 +109,8 @@ mkGlobalEnv cfgFile = do gServicesCwdBase = devEnvProjectRoot <&> ( "services"), gBackendResourcePool = resourcePool, gRabbitMQConfig = intConfig.rabbitmq, + gRabbitMQConfigV0 = intConfig.rabbitmqV0, + gRabbitMQConfigV1 = intConfig.rabbitmqV1, gTempDir = tempDir, gTimeOutSeconds = timeOutSeconds } diff --git a/integration/test/Testlib/ResourcePool.hs b/integration/test/Testlib/ResourcePool.hs index 610d951bca7..8a262cfccf1 100644 --- a/integration/test/Testlib/ResourcePool.hs +++ b/integration/test/Testlib/ResourcePool.hs @@ -21,7 +21,6 @@ import Data.Functor import Data.IORef import qualified Data.Set as Set import Data.String -import qualified Data.Text as T import Data.Tuple import Database.CQL.IO import GHC.Stack (HasCallStack) @@ -86,13 +85,13 @@ deleteAllRabbitMQQueues rc resource = do { host = rc.host, port = 0, adminPort = fromIntegral rc.adminPort, - vHost = T.pack resource.berVHost, + vHost = fromString resource.berVHost, tls = Just $ RabbitMqTlsOpts Nothing True } client <- mkRabbitMqAdminClientEnv opts - queues <- listQueuesByVHost client (T.pack resource.berVHost) Nothing Nothing - for_ queues $ \queue -> - deleteQueue client (T.pack resource.berVHost) queue.name + queuesPage <- listQueuesByVHost client (fromString resource.berVHost) (fromString "") False 100 1 + for_ queuesPage.items $ \queue -> + deleteQueue client (fromString resource.berVHost) queue.name deleteAllDynamicBackendConfigs :: BackendResource -> Client () deleteAllDynamicBackendConfigs resource = write cql (defQueryParams LocalQuorum ()) diff --git a/integration/test/Testlib/Run.hs b/integration/test/Testlib/Run.hs index 29a501c03da..d7d533060c7 100644 --- a/integration/test/Testlib/Run.hs +++ b/integration/test/Testlib/Run.hs @@ -9,7 +9,13 @@ import Data.Foldable import Data.Function import Data.Functor import Data.List +import Data.Maybe (fromMaybe) +import Data.String (IsString (fromString)) +import Data.Text (Text) +import qualified Data.Text as T import Data.Time.Clock +import Network.AMQP.Extended +import Network.RabbitMqAdmin import RunAllTests import System.Directory import System.Environment @@ -133,11 +139,51 @@ runTests tests mXMLOutput cfg = do pure (TestSuiteReport [TestCaseReport qname TestSuccess tm]) writeChan output Nothing wait displayThread + deleteFederationV0AndV1Queues genv printReport report mapM_ (saveXMLReport report) mXMLOutput when (any (\testCase -> testCase.result /= TestSuccess) report.cases) $ exitFailure +deleteFederationV0AndV1Queues :: GlobalEnv -> IO () +deleteFederationV0AndV1Queues env = do + let testDomains = env.gDomain1 : env.gDomain2 : env.gDynamicDomains + putStrLn "Attempting to delete federation V0 queues..." + (mV0User, mV0Pass) <- readCredsFromEnvWithSuffix "V0" + fromMaybe (putStrLn "No or incomplete credentials for fed V0 RabbitMQ") $ + deleteFederationQueues testDomains env.gRabbitMQConfigV0 <$> mV0User <*> mV0Pass + + putStrLn "Attempting to delete federation V1 queues..." + (mV1User, mV1Pass) <- readCredsFromEnvWithSuffix "V1" + fromMaybe (putStrLn "No or incomplete credentials for fed V1 RabbitMQ") $ + deleteFederationQueues testDomains env.gRabbitMQConfigV1 <$> mV1User <*> mV1Pass + where + readCredsFromEnvWithSuffix :: String -> IO (Maybe Text, Maybe Text) + readCredsFromEnvWithSuffix suffix = + (,) + <$> (fmap fromString <$> lookupEnv ("RABBITMQ_USERNAME_" <> suffix)) + <*> (fmap fromString <$> lookupEnv ("RABBITMQ_PASSWORD_" <> suffix)) + +deleteFederationQueues :: [String] -> RabbitMQConfig -> Text -> Text -> IO () +deleteFederationQueues testDomains rc username password = do + let opts = + RabbitMqAdminOpts + { host = rc.host, + port = 0, + adminPort = fromIntegral rc.adminPort, + vHost = fromString rc.vHost, + tls = + if rc.tls + then Just (RabbitMqTlsOpts Nothing True) + else Nothing + } + client <- mkRabbitMqAdminClientEnvWithCreds opts username password + for_ testDomains $ \domain -> do + page <- client.listQueuesByVHost (fromString rc.vHost) (fromString $ "^backend-notifications\\." <> domain <> "$") True 100 1 + for_ page.items $ \queue -> do + putStrLn $ "Deleting queue " <> T.unpack queue.name + void $ deleteQueue client (fromString rc.vHost) queue.name + doListTests :: [(String, String, String, x)] -> IO () doListTests tests = for_ tests $ \(qname, _desc, _full, _) -> do putStrLn qname diff --git a/integration/test/Testlib/Types.hs b/integration/test/Testlib/Types.hs index f9189116cb1..d5c95021afa 100644 --- a/integration/test/Testlib/Types.hs +++ b/integration/test/Testlib/Types.hs @@ -90,7 +90,9 @@ instance FromJSON DynamicBackendConfig data RabbitMQConfig = RabbitMQConfig { host :: String, - adminPort :: Word16 + adminPort :: Word16, + tls :: Bool, + vHost :: String } deriving (Show) @@ -100,6 +102,8 @@ instance FromJSON RabbitMQConfig where RabbitMQConfig <$> ob .: fromString "host" <*> ob .: fromString "adminPort" + <*> ob .: fromString "tls" + <*> ob .: fromString "vHost" -- | Initialised once per testsuite. data GlobalEnv = GlobalEnv @@ -115,6 +119,8 @@ data GlobalEnv = GlobalEnv gServicesCwdBase :: Maybe FilePath, gBackendResourcePool :: ResourcePool BackendResource, gRabbitMQConfig :: RabbitMQConfig, + gRabbitMQConfigV0 :: RabbitMQConfig, + gRabbitMQConfigV1 :: RabbitMQConfig, gTempDir :: FilePath, gTimeOutSeconds :: Int } @@ -127,6 +133,8 @@ data IntegrationConfig = IntegrationConfig integrationTestHostName :: String, dynamicBackends :: Map String DynamicBackendConfig, rabbitmq :: RabbitMQConfig, + rabbitmqV0 :: RabbitMQConfig, + rabbitmqV1 :: RabbitMQConfig, cassandra :: CassandraConfig } deriving (Show, Generic) @@ -142,6 +150,8 @@ instance FromJSON IntegrationConfig where <*> o .: fromString "integrationTestHostName" <*> o .: fromString "dynamicBackends" <*> o .: fromString "rabbitmq" + <*> o .: fromString "rabbitmq-v0" + <*> o .: fromString "rabbitmq-v1" <*> o .: fromString "cassandra" data ServiceMap = ServiceMap diff --git a/libs/extended/src/Network/AMQP/Extended.hs b/libs/extended/src/Network/AMQP/Extended.hs index 1453f3909e4..bed28040c09 100644 --- a/libs/extended/src/Network/AMQP/Extended.hs +++ b/libs/extended/src/Network/AMQP/Extended.hs @@ -7,6 +7,7 @@ module Network.AMQP.Extended withConnection, openConnectionWithRetries, mkRabbitMqAdminClientEnv, + mkRabbitMqAdminClientEnvWithCreds, mkRabbitMqChannelMVar, demoteOpts, RabbitMqTlsOpts (..), @@ -91,9 +92,8 @@ instance FromJSON RabbitMqAdminOpts where <*> parseTlsJson v <*> v .: "adminPort" -mkRabbitMqAdminClientEnv :: RabbitMqAdminOpts -> IO (AdminAPI (AsClientT IO)) -mkRabbitMqAdminClientEnv opts = do - (username, password) <- readCredsFromEnv +mkRabbitMqAdminClientEnvWithCreds :: RabbitMqAdminOpts -> Text -> Text -> IO (AdminAPI (AsClientT IO)) +mkRabbitMqAdminClientEnvWithCreds opts username password = do mTlsSettings <- traverse (mkTLSSettings opts.host) opts.tls let (protocol, managerSettings) = case mTlsSettings of Nothing -> (Servant.Http, HTTP.defaultManagerSettings) @@ -107,6 +107,9 @@ mkRabbitMqAdminClientEnv opts = do (either throwM pure <=< flip runClientM clientEnv) (toServant $ adminClient basicAuthData) +mkRabbitMqAdminClientEnv :: RabbitMqAdminOpts -> IO (AdminAPI (AsClientT IO)) +mkRabbitMqAdminClientEnv opts = readCredsFromEnv >>= uncurry (mkRabbitMqAdminClientEnvWithCreds opts) + -- | When admin opts are needed use `AmqpEndpoint Identity`, otherwise use -- `AmqpEndpoint NoAdmin`. data AmqpEndpoint = AmqpEndpoint diff --git a/libs/extended/src/Network/RabbitMqAdmin.hs b/libs/extended/src/Network/RabbitMqAdmin.hs index acc6bf8c920..0ed9a359f22 100644 --- a/libs/extended/src/Network/RabbitMqAdmin.hs +++ b/libs/extended/src/Network/RabbitMqAdmin.hs @@ -13,20 +13,36 @@ type VHost = Text type QueueName = Text +data Page a = Page {items :: [a], page :: Int, pageCount :: Int} + deriving (Show, Eq, Generic) + +instance (FromJSON a) => FromJSON (Page a) where + parseJSON = + genericParseJSON $ + defaultOptions + { fieldLabelModifier = camelTo2 '_' + } + +instance (ToJSON a) => ToJSON (Page a) where + toJSON = + genericToJSON $ + defaultOptions + { fieldLabelModifier = camelTo2 '_' + } + -- | Upstream Docs: -- https://rawcdn.githack.com/rabbitmq/rabbitmq-server/v3.12.0/deps/rabbitmq_management/priv/www/api/index.html data AdminAPI route = AdminAPI - { -- | NOTE: This endpoint can be made paginated, but that complicates - -- consumer code a little. This might be needed for performance tuning - -- later, but perhaps not. - listQueuesByVHost :: + { listQueuesByVHost :: route :- "api" :> "queues" :> Capture "vhost" VHost - :> QueryParam "name" Text - :> QueryParam "use_regex" Bool - :> Get '[JSON] [Queue], + :> QueryParam' '[Required, Strict] "name" Text + :> QueryParam' '[Required, Strict] "use_regex" Bool + :> QueryParam' '[Required, Strict] "page_size" Int + :> QueryParam' '[Required, Strict] "page" Int + :> Get '[JSON] (Page Queue), deleteQueue :: route :- "api" diff --git a/services/background-worker/src/Wire/BackendNotificationPusher.hs b/services/background-worker/src/Wire/BackendNotificationPusher.hs index 68f9e25dd54..92c9880efbc 100644 --- a/services/background-worker/src/Wire/BackendNotificationPusher.hs +++ b/services/background-worker/src/Wire/BackendNotificationPusher.hs @@ -277,14 +277,18 @@ getRemoteDomains adminClient = do handlers = skipAsyncExceptions <> [logRetries (const $ pure True) logErrr] - recovering policy handlers $ const go + recovering policy handlers $ const $ go [] 1 where - go :: AppT IO [Domain] - go = do + go :: [Domain] -> Int -> AppT IO [Domain] + go domains pageNumber = do vhost <- asks rabbitmqVHost - queues <- liftIO $ listQueuesByVHost adminClient vhost (Just "backend-notifications\\..*") (Just True) - let notifQueuesSuffixes = mapMaybe (\q -> Text.stripPrefix "backend-notifications." q.name) queues - catMaybes <$> traverse (\d -> either (\e -> logInvalidDomain d e >> pure Nothing) (pure . Just) $ mkDomain d) notifQueuesSuffixes + queuesPage <- liftIO $ listQueuesByVHost adminClient vhost "^backend-notifications\\..*" True 100 pageNumber + let notifQueuesSuffixes = mapMaybe (\q -> Text.stripPrefix "backend-notifications." q.name) queuesPage.items + newDomains <- catMaybes <$> traverse (\d -> either (\e -> logInvalidDomain d e >> pure Nothing) (pure . Just) $ mkDomain d) notifQueuesSuffixes + let domainsSoFar = newDomains <> domains + if queuesPage.page >= queuesPage.pageCount + then pure domainsSoFar + else go domainsSoFar (pageNumber + 1) logInvalidDomain d e = Log.warn $ Log.msg (Log.val "Found invalid domain in a backend notifications queue name") diff --git a/services/background-worker/test/Test/Wire/BackendNotificationPusherSpec.hs b/services/background-worker/test/Test/Wire/BackendNotificationPusherSpec.hs index 7e63fb10f44..b06c2a6e614 100644 --- a/services/background-worker/test/Test/Wire/BackendNotificationPusherSpec.hs +++ b/services/background-worker/test/Test/Wire/BackendNotificationPusherSpec.hs @@ -353,12 +353,18 @@ mockApi mockAdmin = deleteConnection = mockDeleteConnection mockAdmin } -mockListQueuesByVHost :: MockRabbitMqAdmin -> Text -> Maybe Text -> Maybe Bool -> Servant.Handler [Queue] -mockListQueuesByVHost MockRabbitMqAdmin {..} vhost _ _ = do +mockListQueuesByVHost :: MockRabbitMqAdmin -> Text -> Text -> Bool -> Int -> Int -> Servant.Handler (Page Queue) +mockListQueuesByVHost MockRabbitMqAdmin {..} vhost _ _ _ _ = do atomically $ modifyTVar listQueuesVHostCalls (<> [vhost]) readTVarIO broken >>= \case True -> throwError $ Servant.err500 - False -> pure $ map (\n -> Queue n vhost) queues + False -> + pure + Page + { items = map (\n -> Queue n vhost) queues, + pageCount = 1, + page = 1 + } mockListDeleteQueue :: MockRabbitMqAdmin -> Text -> Text -> Servant.Handler NoContent mockListDeleteQueue _ _ _ = do diff --git a/services/integration.yaml b/services/integration.yaml index 43ac98a343c..ffcff1f945a 100644 --- a/services/integration.yaml +++ b/services/integration.yaml @@ -164,6 +164,20 @@ dynamicBackends: rabbitmq: host: localhost adminPort: 15671 + tls: true + vHost: / + +rabbitmq-v0: + host: localhost + adminPort: 15672 + tls: false + vHost: federation-v0 + +rabbitmq-v1: + host: localhost + adminPort: 15672 + tls: false + vHost: federation-v1 cassandra: host: 127.0.0.1 From 5a260a03c871723eb910caf0d29e5fed46d72fab Mon Sep 17 00:00:00 2001 From: Stefan Berthold Date: Tue, 17 Dec 2024 13:59:32 +0100 Subject: [PATCH 2/3] Add profile name to new team owner welcome mail (#4378) --- changelog.d/3-bug-fixes/WPB-15085 | 1 + .../src/Wire/EmailSubsystem/Template.hs | 10 ---------- services/brig/src/Brig/API/User.hs | 1 + services/brig/src/Brig/Team/Email.hs | 11 ++++++----- services/brig/src/Brig/Team/Template.hs | 8 -------- 5 files changed, 8 insertions(+), 23 deletions(-) create mode 100644 changelog.d/3-bug-fixes/WPB-15085 diff --git a/changelog.d/3-bug-fixes/WPB-15085 b/changelog.d/3-bug-fixes/WPB-15085 new file mode 100644 index 00000000000..1fa867f5fe9 --- /dev/null +++ b/changelog.d/3-bug-fixes/WPB-15085 @@ -0,0 +1 @@ +Add profile name to new team owner welcome mail diff --git a/libs/wire-subsystems/src/Wire/EmailSubsystem/Template.hs b/libs/wire-subsystems/src/Wire/EmailSubsystem/Template.hs index 7c209b2972a..15a31a04eba 100644 --- a/libs/wire-subsystems/src/Wire/EmailSubsystem/Template.hs +++ b/libs/wire-subsystems/src/Wire/EmailSubsystem/Template.hs @@ -210,15 +210,6 @@ data MemberWelcomeEmailTemplate = MemberWelcomeEmailTemplate memberWelcomeEmailSenderName :: !Text } -data PersonalUserMemberWelcomeEmailTemplate = PersonalUserMemberWelcomeEmailTemplate - { personalUserMemberWelcomeEmailUrl :: !Text, - personalUserMemberWelcomeEmailSubject :: !Template, - personalUserMemberWelcomeEmailBodyText :: !Template, - personalUserMemberWelcomeEmailBodyHtml :: !Template, - personalUserMemberWelcomeEmailSender :: !EmailAddress, - personalUserMemberWelcomeEmailSenderName :: !Text - } - data NewTeamOwnerWelcomeEmailTemplate = NewTeamOwnerWelcomeEmailTemplate { newTeamOwnerWelcomeEmailUrl :: !Text, newTeamOwnerWelcomeEmailSubject :: !Template, @@ -233,6 +224,5 @@ data TeamTemplates = TeamTemplates existingUserInvitationEmail :: !InvitationEmailTemplate, creatorWelcomeEmail :: !CreatorWelcomeEmailTemplate, memberWelcomeEmail :: !MemberWelcomeEmailTemplate, - personalUserMemberWelcomeEmail :: !PersonalUserMemberWelcomeEmailTemplate, newTeamOwnerWelcomeEmail :: !NewTeamOwnerWelcomeEmailTemplate } diff --git a/services/brig/src/Brig/API/User.hs b/services/brig/src/Brig/API/User.hs index 92d260f6d2f..c6adbf99ffd 100644 --- a/services/brig/src/Brig/API/User.hs +++ b/services/brig/src/Brig/API/User.hs @@ -302,6 +302,7 @@ upgradePersonalToTeam luid bNewTeam = do tid bNewTeam.bnuTeam.newTeamName.fromRange (Just user.userLocale) + user.userDisplayName pure $! createUserTeam diff --git a/services/brig/src/Brig/Team/Email.hs b/services/brig/src/Brig/Team/Email.hs index e9c22b1f82a..90dc3519483 100644 --- a/services/brig/src/Brig/Team/Email.hs +++ b/services/brig/src/Brig/Team/Email.hs @@ -40,11 +40,11 @@ sendMemberWelcomeMail to tid teamName loc = do branding <- asks (.templateBranding) liftSem $ sendMail $ renderMemberWelcomeMail to tid teamName tpl branding -sendNewTeamOwnerWelcomeEmail :: (Member EmailSending r) => EmailAddress -> TeamId -> Text -> Maybe Locale -> (AppT r) () -sendNewTeamOwnerWelcomeEmail to tid teamName loc = do +sendNewTeamOwnerWelcomeEmail :: (Member EmailSending r) => EmailAddress -> TeamId -> Text -> Maybe Locale -> Name -> (AppT r) () +sendNewTeamOwnerWelcomeEmail to tid teamName loc profileName = do tpl <- newTeamOwnerWelcomeEmail . snd <$> teamTemplatesWithLocale loc branding <- asks (.templateBranding) - liftSem $ sendMail $ renderNewTeamOwnerWelcomeEmail to tid teamName tpl branding + liftSem $ sendMail $ renderNewTeamOwnerWelcomeEmail to tid teamName profileName tpl branding ------------------------------------------------------------------------------- -- Member Welcome Email @@ -74,8 +74,8 @@ renderMemberWelcomeMail emailTo tid teamName MemberWelcomeEmailTemplate {..} bra ------------------------------------------------------------------------------- -- New Team Owner Welcome Email -renderNewTeamOwnerWelcomeEmail :: EmailAddress -> TeamId -> Text -> NewTeamOwnerWelcomeEmailTemplate -> TemplateBranding -> Mail -renderNewTeamOwnerWelcomeEmail emailTo tid teamName NewTeamOwnerWelcomeEmailTemplate {..} branding = +renderNewTeamOwnerWelcomeEmail :: EmailAddress -> TeamId -> Text -> Name -> NewTeamOwnerWelcomeEmailTemplate -> TemplateBranding -> Mail +renderNewTeamOwnerWelcomeEmail emailTo tid teamName profileName NewTeamOwnerWelcomeEmailTemplate {..} branding = (emptyMail from) { mailTo = [to], mailHeaders = @@ -94,4 +94,5 @@ renderNewTeamOwnerWelcomeEmail emailTo tid teamName NewTeamOwnerWelcomeEmailTemp replace "email" = fromEmail emailTo replace "team_id" = idToText tid replace "team_name" = teamName + replace "name" = profileName.fromName replace x = x diff --git a/services/brig/src/Brig/Team/Template.hs b/services/brig/src/Brig/Team/Template.hs index 713c1555a6f..4ca5feccfdf 100644 --- a/services/brig/src/Brig/Team/Template.hs +++ b/services/brig/src/Brig/Team/Template.hs @@ -63,14 +63,6 @@ loadTeamTemplates o = readLocalesDir defLocale (templateDir gOptions) "team" $ \ <*> pure (emailSender gOptions) <*> readText fp "email/sender.txt" ) - <*> ( PersonalUserMemberWelcomeEmailTemplate - "" - (template "") - (template "") - (template "") - (emailSender gOptions) - <$> readText fp "email/sender.txt" - ) <*> ( NewTeamOwnerWelcomeEmailTemplate (tCreatorWelcomeUrl tOptions) <$> readTemplate fp "email/new-team-owner-welcome-subject.txt" <*> readTemplate fp "email/new-team-owner-welcome.txt" From 0a966e1a6c2b517127863efa9eb08154f00dd75f Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Tue, 17 Dec 2024 16:53:07 +0100 Subject: [PATCH 3/3] WPB-15072 team activated is not sent to ibis when a personal user creates a new team (#4380) --- changelog.d/3-bug-fixes/WPB-15072 | 1 + integration/test/API/GalleyInternal.hs | 5 +++++ integration/test/Test/Teams.hs | 8 ++++++-- services/brig/src/Brig/API/User.hs | 1 + 4 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 changelog.d/3-bug-fixes/WPB-15072 diff --git a/changelog.d/3-bug-fixes/WPB-15072 b/changelog.d/3-bug-fixes/WPB-15072 new file mode 100644 index 00000000000..60dbbe6f537 --- /dev/null +++ b/changelog.d/3-bug-fixes/WPB-15072 @@ -0,0 +1 @@ +Send team active event in personal user to team flow diff --git a/integration/test/API/GalleyInternal.hs b/integration/test/API/GalleyInternal.hs index bb8a471ce36..65592f37108 100644 --- a/integration/test/API/GalleyInternal.hs +++ b/integration/test/API/GalleyInternal.hs @@ -119,3 +119,8 @@ patchTeamFeature domain team featureName payload = do tid <- asString team req <- baseRequest domain Galley Unversioned $ joinHttpPath ["i", "teams", tid, "features", featureName] submit "PATCH" $ req & addJSON payload + +getTeam :: (HasCallStack, MakesValue domain) => domain -> String -> App Response +getTeam domain tid = do + req <- baseRequest domain Galley Unversioned $ joinHttpPath ["i", "teams", tid] + submit "GET" $ req diff --git a/integration/test/Test/Teams.hs b/integration/test/Test/Teams.hs index 2d566527c0e..ed834c4c169 100644 --- a/integration/test/Test/Teams.hs +++ b/integration/test/Test/Teams.hs @@ -22,7 +22,7 @@ import API.Brig import qualified API.BrigInternal as I import API.Common import API.Galley (getTeam, getTeamMembers, getTeamMembersCsv, getTeamNotifications) -import API.GalleyInternal (setTeamFeatureStatus) +import qualified API.GalleyInternal as I import API.Gundeck import qualified API.Nginz as Nginz import Control.Monad.Codensity (Codensity (runCodensity)) @@ -58,7 +58,7 @@ testInvitePersonalUserToTeam = do resp.json %. "invitations" `shouldMatch` ([] :: [()]) ownerId <- owner %. "id" & asString - setTeamFeatureStatus domain tid "exposeInvitationURLsToTeamAdmin" "enabled" >>= assertSuccess + I.setTeamFeatureStatus domain tid "exposeInvitationURLsToTeamAdmin" "enabled" >>= assertSuccess user <- I.createUser domain def >>= getJSON 201 uid <- user %. "id" >>= asString email <- user %. "email" >>= asString @@ -289,6 +289,10 @@ testUpgradePersonalToTeam = do team <- getTeam alice tid >>= getJSON 200 team %. "name" `shouldMatch` teamName + iTeam <- asString tid >>= I.getTeam alice >>= getJSON 200 + iTeam %. "team.name" `shouldMatch` teamName + iTeam %. "status" `shouldMatch` "active" + bindResponse (getTeamMembers alice tid) $ \resp -> do resp.status `shouldMatchInt` 200 owner <- asList (resp.json %. "members") >>= assertOne diff --git a/services/brig/src/Brig/API/User.hs b/services/brig/src/Brig/API/User.hs index c6adbf99ffd..4d16684d9b1 100644 --- a/services/brig/src/Brig/API/User.hs +++ b/services/brig/src/Brig/API/User.hs @@ -289,6 +289,7 @@ upgradePersonalToTeam luid bNewTeam = do liftSem $ GalleyAPIAccess.createTeam uid (bnuTeam bNewTeam) tid let newTeam = bNewTeam.bnuTeam pure $ CreateUserTeam tid (fromRange newTeam.newTeamName) + liftSem $ GalleyAPIAccess.changeTeamStatus tid Team.Active bNewTeam.bnuCurrency liftSem $ updateUserTeam uid tid liftSem $ User.internalUpdateSearchIndex uid