diff --git a/app/app.go b/app/app.go index f7d2654253..40ba029672 100644 --- a/app/app.go +++ b/app/app.go @@ -94,6 +94,7 @@ func (a *App) InitServer() { if a.Srv().runEssentialJobs { a.Srv().Go(func() { runLicenseExpirationCheckJob(a) + runCheckAdminSupportStatusJob(a) }) a.srv.runJobs() } @@ -326,6 +327,9 @@ func (a *App) getWarnMetricStatusAndDisplayTextsForId(warnMetricId string, T i18 warnMetricDisplayTexts.EmailBody = T("api.server.warn_metric.number_of_posts_2M.contact_us.email_body") warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_posts_2M.notification_body") } + case model.SYSTEM_METRIC_SUPPORT_EMAIL_NOT_CONFIGURED: + warnMetricDisplayTexts.BotTitle = T("api.server.warn_metric.support_email_not_configured.notification_title") + warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.support_email_not_configured.start_trial.notification_body") default: mlog.Debug("Invalid metric id", mlog.String("id", warnMetricId)) return nil, nil @@ -378,6 +382,11 @@ func (a *App) notifyAdminsOfWarnMetricStatus(warnMetricId string, isE0Edition bo return err } + warnMetric, ok := model.WarnMetricsTable[warnMetricId] + if !ok { + return model.NewAppError("NotifyAdminsOfWarnMetricStatus", "app.system.warn_metric.notification.invalid_metric.app_error", nil, "", http.StatusInternalServerError) + } + for _, sysAdmin := range sysAdmins { T := i18n.GetUserTranslations(sysAdmin.Locale) bot.DisplayName = T("app.system.warn_metric.bot_displayname") @@ -442,8 +451,12 @@ func (a *App) notifyAdminsOfWarnMetricStatus(warnMetricId string, isE0Edition bo AuthorName: "", Title: warnMetricDisplayTexts.BotTitle, Text: warnMetricDisplayTexts.BotMessageBody, - Actions: actions, }} + + if !warnMetric.SkipAction { + attachments[0].Actions = actions + } + model.ParseSlackAttachment(botPost, attachments) mlog.Debug("Post admin advisory for metric", mlog.String("warnMetricId", warnMetricId), mlog.String("userid", botPost.UserId)) diff --git a/app/server.go b/app/server.go index 1c279ec92b..c8dc9adb84 100644 --- a/app/server.go +++ b/app/server.go @@ -1422,6 +1422,13 @@ func runCheckWarnMetricStatusJob(a *App) { }, time.Hour*model.WARN_METRIC_JOB_INTERVAL) } +func runCheckAdminSupportStatusJob(a *App) { + doCheckAdminSupportStatus(a) + model.CreateRecurringTask("Check Admin Support Status Job", func() { + doCheckAdminSupportStatus(a) + }, time.Hour*model.WARN_METRIC_JOB_INTERVAL) +} + func doSecurity(s *Server) { s.DoSecurityUpdateCheck() } @@ -1586,6 +1593,16 @@ func doCheckWarnMetricStatus(a *App) { } } +func doCheckAdminSupportStatus(a *App) { + isE0Edition := model.BuildEnterpriseReady == "true" + + if strings.TrimSpace(*a.Config().SupportSettings.SupportEmail) == model.SUPPORT_SETTINGS_DEFAULT_SUPPORT_EMAIL { + if err := a.notifyAdminsOfWarnMetricStatus(model.SYSTEM_METRIC_SUPPORT_EMAIL_NOT_CONFIGURED, isE0Edition); err != nil { + mlog.Error("Failed to send notifications to admin users.", mlog.Err(err)) + } + } +} + func (s *Server) StopMetricsServer() { s.metricsLock.Lock() defer s.metricsLock.Unlock() diff --git a/app/server_test.go b/app/server_test.go index 0c07ed8442..df19ea6246 100644 --- a/app/server_test.go +++ b/app/server_test.go @@ -695,3 +695,61 @@ func TestSentry(t *testing.T) { } }) } + +func TestAdminAdvisor(t *testing.T) { + th := Setup(t) + defer th.TearDown() + + // creating a system user to whole admin advisor will send post + user := model.User{ + Email: strings.ToLower(model.NewId()) + "success+test@example.com", + Nickname: "Darth Vader", + Username: "vader" + model.NewId(), + Password: "passwd1", + AuthService: "", + Roles: model.SYSTEM_ADMIN_ROLE_ID, + } + ruser, err := th.App.CreateUser(&user) + assert.Nil(t, err, "User should be created") + defer th.App.PermanentDeleteUser(&user) + + t.Run("Should notify admin of un-configured support email", func(t *testing.T) { + doCheckAdminSupportStatus(th.App) + + bot, err := th.App.GetUserByUsername(model.BOT_WARN_METRIC_BOT_USERNAME) + assert.NotNil(t, bot, "Bot should have been created now") + assert.Nil(t, err, "No error should be generated") + + channel, err := th.App.getDirectChannel(bot.Id, ruser.Id) + assert.NotNil(t, channel, "DM channel should exist between Admin Advisor and system admin") + assert.Nil(t, err, "No error should be generated") + }) + + t.Run("Should NOT notify admin when support email is configured", func(t *testing.T) { + th.App.UpdateConfig(func(m *model.Config) { + email := "success+test@example.com" + m.SupportSettings.SupportEmail = &email + }) + + bot, err := th.App.GetUserByUsername(model.BOT_WARN_METRIC_BOT_USERNAME) + assert.NotNil(t, bot, "Bot should be already created") + assert.Nil(t, err, "No error should be generated") + + channel, err := th.App.getDirectChannel(bot.Id, ruser.Id) + assert.NotNil(t, channel, "DM channel should already exist") + assert.Nil(t, err, "No error should be generated") + + err = th.App.PermanentDeleteChannel(channel) + assert.Nil(t, err, "No error should be generated") + + doCheckAdminSupportStatus(th.App) + + channel, err = th.App.getDirectChannel(bot.Id, ruser.Id) + assert.NotNil(t, channel, "DM channel should exist between Admin Advisor and system admin") + assert.Nil(t, err, "No error should be generated") + + posts, err := th.App.GetPosts(channel.Id, 0, 100) + assert.Nil(t, err, "No error should be generated") + assert.Equal(t, 0, len(posts.Posts)) + }) +} diff --git a/i18n/en.json b/i18n/en.json index 53b4dc4624..ff9f4aff91 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -2754,6 +2754,14 @@ "id": "api.server.warn_metric.starting_trial", "translation": "Getting Trial" }, + { + "id": "api.server.warn_metric.support_email_not_configured.notification_title", + "translation": "Set Your Support Email Address" + }, + { + "id": "api.server.warn_metric.support_email_not_configured.start_trial.notification_body", + "translation": "Please go to **System Console > Site Configuration > Customization** to set the [Support Email](https://docs.mattermost.com/administration/config-settings.html#support-email) as your organization's internal IT Support Desk email address for end user feedback, email notifications, and support requests." + }, { "id": "api.slackimport.slack_add_bot_user.email_pwd", "translation": "The Integration/Slack Bot user with email {{.Email}} and password {{.Password}} has been imported.\r\n" diff --git a/model/config.go b/model/config.go index 83501dd7c1..553c74862e 100644 --- a/model/config.go +++ b/model/config.go @@ -134,7 +134,7 @@ const ( SUPPORT_SETTINGS_DEFAULT_ABOUT_LINK = "https://about.mattermost.com/default-about/" SUPPORT_SETTINGS_DEFAULT_HELP_LINK = "https://about.mattermost.com/default-help/" SUPPORT_SETTINGS_DEFAULT_REPORT_A_PROBLEM_LINK = "https://about.mattermost.com/default-report-a-problem/" - SUPPORT_SETTINGS_DEFAULT_SUPPORT_EMAIL = "feedback@mattermost.com" + SUPPORT_SETTINGS_DEFAULT_SUPPORT_EMAIL = "" SUPPORT_SETTINGS_DEFAULT_RE_ACCEPTANCE_PERIOD = 365 LDAP_SETTINGS_DEFAULT_FIRST_NAME_ATTRIBUTE = "" diff --git a/model/system.go b/model/system.go index 088990b3eb..b7cda1ef01 100644 --- a/model/system.go +++ b/model/system.go @@ -32,6 +32,7 @@ const ( SYSTEM_WARN_METRIC_NUMBER_OF_ACTIVE_USERS_500 = "warn_metric_number_of_active_users_500" SYSTEM_WARN_METRIC_NUMBER_OF_POSTS_2M = "warn_metric_number_of_posts_2M" SYSTEM_WARN_METRIC_LAST_RUN_TIMESTAMP_KEY = "LastWarnMetricRunTimestamp" + SYSTEM_METRIC_SUPPORT_EMAIL_NOT_CONFIGURED = "warn_metric_support_email_not_configured" SYSTEM_FIRST_ADMIN_VISIT_MARKETPLACE = "FirstAdminVisitMarketplace" AWS_METERING_REPORT_INTERVAL = 1 AWS_METERING_DIMENSION_USAGE_HRS = "UsageHrs" @@ -170,13 +171,21 @@ var WarnMetricsTable = map[string]WarnMetric{ IsBotOnly: false, IsRunOnce: true, }, + SYSTEM_METRIC_SUPPORT_EMAIL_NOT_CONFIGURED: { + Id: SYSTEM_METRIC_SUPPORT_EMAIL_NOT_CONFIGURED, + Limit: -1, + IsBotOnly: true, + IsRunOnce: false, + SkipAction: true, + }, } type WarnMetric struct { - Id string - Limit int64 - IsBotOnly bool - IsRunOnce bool + Id string + Limit int64 + IsBotOnly bool + IsRunOnce bool + SkipAction bool } type WarnMetricDisplayTexts struct { diff --git a/templates/email_info.html b/templates/email_info.html index 6b83db76ee..bbd0d4935b 100644 --- a/templates/email_info.html +++ b/templates/email_info.html @@ -1,7 +1,9 @@ {{define "email_info"}} +{{if .Props.SupportEmail}}