github.com/haalcala/mattermost-server-change-repo/v5@v5.33.2/app/app.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package app
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"html/template"
    10  	"net/http"
    11  	"strconv"
    12  	"strings"
    13  	"time"
    14  
    15  	"github.com/mattermost/go-i18n/i18n"
    16  	goi18n "github.com/mattermost/go-i18n/i18n"
    17  
    18  	"github.com/mattermost/mattermost-server/v5/einterfaces"
    19  	"github.com/mattermost/mattermost-server/v5/mlog"
    20  	"github.com/mattermost/mattermost-server/v5/model"
    21  	"github.com/mattermost/mattermost-server/v5/services/httpservice"
    22  	"github.com/mattermost/mattermost-server/v5/services/imageproxy"
    23  	"github.com/mattermost/mattermost-server/v5/services/mailservice"
    24  	"github.com/mattermost/mattermost-server/v5/services/searchengine"
    25  	"github.com/mattermost/mattermost-server/v5/services/timezones"
    26  	"github.com/mattermost/mattermost-server/v5/utils"
    27  )
    28  
    29  type App struct {
    30  	srv *Server
    31  
    32  	// XXX: This is required because removing this needs BleveEngine
    33  	// to be registered in (h *MainHelper) setupStore, but that creates
    34  	// a cyclic dependency as bleve tests themselves import testlib.
    35  	searchEngine *searchengine.Broker
    36  
    37  	t              goi18n.TranslateFunc
    38  	session        model.Session
    39  	requestId      string
    40  	ipAddress      string
    41  	path           string
    42  	userAgent      string
    43  	acceptLanguage string
    44  
    45  	context context.Context
    46  }
    47  
    48  func New(options ...AppOption) *App {
    49  	app := &App{}
    50  
    51  	for _, option := range options {
    52  		option(app)
    53  	}
    54  
    55  	return app
    56  }
    57  
    58  func (a *App) InitServer() {
    59  	a.srv.AppInitializedOnce.Do(func() {
    60  		a.initEnterprise()
    61  
    62  		a.AddConfigListener(func(oldConfig *model.Config, newConfig *model.Config) {
    63  			if *oldConfig.GuestAccountsSettings.Enable && !*newConfig.GuestAccountsSettings.Enable {
    64  				if appErr := a.DeactivateGuests(); appErr != nil {
    65  					mlog.Error("Unable to deactivate guest accounts", mlog.Err(appErr))
    66  				}
    67  			}
    68  		})
    69  
    70  		// Disable active guest accounts on first run if guest accounts are disabled
    71  		if !*a.Config().GuestAccountsSettings.Enable {
    72  			if appErr := a.DeactivateGuests(); appErr != nil {
    73  				mlog.Error("Unable to deactivate guest accounts", mlog.Err(appErr))
    74  			}
    75  		}
    76  
    77  		// Scheduler must be started before cluster.
    78  		a.initJobs()
    79  
    80  		if a.srv.joinCluster && a.srv.Cluster != nil {
    81  			a.registerAllClusterMessageHandlers()
    82  		}
    83  
    84  		a.DoAppMigrations()
    85  
    86  		a.InitPostMetadata()
    87  
    88  		a.InitPlugins(*a.Config().PluginSettings.Directory, *a.Config().PluginSettings.ClientDirectory)
    89  		a.AddConfigListener(func(prevCfg, cfg *model.Config) {
    90  			if *cfg.PluginSettings.Enable {
    91  				a.InitPlugins(*cfg.PluginSettings.Directory, *a.Config().PluginSettings.ClientDirectory)
    92  			} else {
    93  				a.srv.ShutDownPlugins()
    94  			}
    95  		})
    96  		if a.Srv().runjobs {
    97  			a.Srv().Go(func() {
    98  				runLicenseExpirationCheckJob(a)
    99  				runCheckWarnMetricStatusJob(a)
   100  			})
   101  		}
   102  		a.srv.RunJobs()
   103  	})
   104  }
   105  
   106  func (a *App) initJobs() {
   107  	if jobsLdapSyncInterface != nil {
   108  		a.srv.Jobs.LdapSync = jobsLdapSyncInterface(a)
   109  	}
   110  	if jobsPluginsInterface != nil {
   111  		a.srv.Jobs.Plugins = jobsPluginsInterface(a)
   112  	}
   113  	if jobsExpiryNotifyInterface != nil {
   114  		a.srv.Jobs.ExpiryNotify = jobsExpiryNotifyInterface(a)
   115  	}
   116  	if productNoticesJobInterface != nil {
   117  		a.srv.Jobs.ProductNotices = productNoticesJobInterface(a)
   118  	}
   119  	if jobsImportProcessInterface != nil {
   120  		a.srv.Jobs.ImportProcess = jobsImportProcessInterface(a)
   121  	}
   122  	if jobsImportDeleteInterface != nil {
   123  		a.srv.Jobs.ImportDelete = jobsImportDeleteInterface(a)
   124  	}
   125  	if jobsExportDeleteInterface != nil {
   126  		a.srv.Jobs.ExportDelete = jobsExportDeleteInterface(a)
   127  	}
   128  
   129  	if jobsExportProcessInterface != nil {
   130  		a.srv.Jobs.ExportProcess = jobsExportProcessInterface(a)
   131  	}
   132  
   133  	if jobsExportProcessInterface != nil {
   134  		a.srv.Jobs.ExportProcess = jobsExportProcessInterface(a)
   135  	}
   136  
   137  	if jobsActiveUsersInterface != nil {
   138  		a.srv.Jobs.ActiveUsers = jobsActiveUsersInterface(a)
   139  	}
   140  
   141  	if jobsCloudInterface != nil {
   142  		a.srv.Jobs.Cloud = jobsCloudInterface(a.srv)
   143  	}
   144  
   145  	a.srv.Jobs.Workers = a.srv.Jobs.InitWorkers()
   146  	a.srv.Jobs.Schedulers = a.srv.Jobs.InitSchedulers()
   147  }
   148  
   149  func (a *App) TelemetryId() string {
   150  	return a.Srv().TelemetryId()
   151  }
   152  
   153  func (s *Server) HTMLTemplates() *template.Template {
   154  	if s.htmlTemplateWatcher != nil {
   155  		return s.htmlTemplateWatcher.Templates()
   156  	}
   157  
   158  	return nil
   159  }
   160  
   161  func (a *App) Handle404(w http.ResponseWriter, r *http.Request) {
   162  	ipAddress := utils.GetIpAddress(r, a.Config().ServiceSettings.TrustedProxyIPHeader)
   163  	mlog.Debug("not found handler triggered", mlog.String("path", r.URL.Path), mlog.Int("code", 404), mlog.String("ip", ipAddress))
   164  
   165  	if *a.Config().ServiceSettings.WebserverMode == "disabled" {
   166  		http.NotFound(w, r)
   167  		return
   168  	}
   169  
   170  	utils.RenderWebAppError(a.Config(), w, r, model.NewAppError("Handle404", "api.context.404.app_error", nil, "", http.StatusNotFound), a.AsymmetricSigningKey())
   171  }
   172  
   173  func (s *Server) getSystemInstallDate() (int64, *model.AppError) {
   174  	systemData, err := s.Store.System().GetByName(model.SYSTEM_INSTALLATION_DATE_KEY)
   175  	if err != nil {
   176  		return 0, model.NewAppError("getSystemInstallDate", "app.system.get_by_name.app_error", nil, err.Error(), http.StatusInternalServerError)
   177  	}
   178  	value, err := strconv.ParseInt(systemData.Value, 10, 64)
   179  	if err != nil {
   180  		return 0, model.NewAppError("getSystemInstallDate", "app.system_install_date.parse_int.app_error", nil, err.Error(), http.StatusInternalServerError)
   181  	}
   182  	return value, nil
   183  }
   184  
   185  func (s *Server) getFirstServerRunTimestamp() (int64, *model.AppError) {
   186  	systemData, err := s.Store.System().GetByName(model.SYSTEM_FIRST_SERVER_RUN_TIMESTAMP_KEY)
   187  	if err != nil {
   188  		return 0, model.NewAppError("getFirstServerRunTimestamp", "app.system.get_by_name.app_error", nil, err.Error(), http.StatusInternalServerError)
   189  	}
   190  	value, err := strconv.ParseInt(systemData.Value, 10, 64)
   191  	if err != nil {
   192  		return 0, model.NewAppError("getFirstServerRunTimestamp", "app.system_install_date.parse_int.app_error", nil, err.Error(), http.StatusInternalServerError)
   193  	}
   194  	return value, nil
   195  }
   196  
   197  func (s *Server) getLastWarnMetricTimestamp() (int64, *model.AppError) {
   198  	systemData, err := s.Store.System().GetByName(model.SYSTEM_WARN_METRIC_LAST_RUN_TIMESTAMP_KEY)
   199  	if err != nil {
   200  		return 0, model.NewAppError("getLastWarnMetricTimestamp", "app.system.get_by_name.app_error", nil, err.Error(), http.StatusInternalServerError)
   201  	}
   202  	value, err := strconv.ParseInt(systemData.Value, 10, 64)
   203  	if err != nil {
   204  		return 0, model.NewAppError("getLastWarnMetricTimestamp", "app.system_install_date.parse_int.app_error", nil, err.Error(), http.StatusInternalServerError)
   205  	}
   206  	return value, nil
   207  }
   208  
   209  func (a *App) GetWarnMetricsStatus() (map[string]*model.WarnMetricStatus, *model.AppError) {
   210  	systemDataList, nErr := a.Srv().Store.System().Get()
   211  	if nErr != nil {
   212  		return nil, model.NewAppError("GetWarnMetricsStatus", "app.system.get.app_error", nil, nErr.Error(), http.StatusInternalServerError)
   213  	}
   214  
   215  	isE0Edition := model.BuildEnterpriseReady == "true" // license == nil was already validated upstream
   216  
   217  	result := map[string]*model.WarnMetricStatus{}
   218  	for key, value := range systemDataList {
   219  		if strings.HasPrefix(key, model.WARN_METRIC_STATUS_STORE_PREFIX) {
   220  			if warnMetric, ok := model.WarnMetricsTable[key]; ok {
   221  				if !warnMetric.IsBotOnly && (value == model.WARN_METRIC_STATUS_RUNONCE || value == model.WARN_METRIC_STATUS_LIMIT_REACHED) {
   222  					result[key], _ = a.getWarnMetricStatusAndDisplayTextsForId(key, nil, isE0Edition)
   223  				}
   224  			}
   225  		}
   226  	}
   227  
   228  	return result, nil
   229  }
   230  
   231  func (a *App) getWarnMetricStatusAndDisplayTextsForId(warnMetricId string, T i18n.TranslateFunc, isE0Edition bool) (*model.WarnMetricStatus, *model.WarnMetricDisplayTexts) {
   232  	var warnMetricStatus *model.WarnMetricStatus
   233  	var warnMetricDisplayTexts = &model.WarnMetricDisplayTexts{}
   234  
   235  	if warnMetric, ok := model.WarnMetricsTable[warnMetricId]; ok {
   236  		warnMetricStatus = &model.WarnMetricStatus{
   237  			Id:    warnMetric.Id,
   238  			Limit: warnMetric.Limit,
   239  			Acked: false,
   240  		}
   241  
   242  		if T == nil {
   243  			mlog.Debug("No translation function")
   244  			return warnMetricStatus, nil
   245  		}
   246  
   247  		warnMetricDisplayTexts.BotSuccessMessage = T("api.server.warn_metric.bot_response.notification_success.message")
   248  
   249  		switch warnMetricId {
   250  		case model.SYSTEM_WARN_METRIC_NUMBER_OF_TEAMS_5:
   251  			warnMetricDisplayTexts.BotTitle = T("api.server.warn_metric.number_of_teams_5.notification_title")
   252  			if isE0Edition {
   253  				warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_teams_5.start_trial.notification_body")
   254  				warnMetricDisplayTexts.BotSuccessMessage = T("api.server.warn_metric.number_of_teams_5.start_trial_notification_success.message")
   255  			} else {
   256  				warnMetricDisplayTexts.EmailBody = T("api.server.warn_metric.number_of_teams_5.contact_us.email_body")
   257  				warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_teams_5.notification_body")
   258  			}
   259  		case model.SYSTEM_WARN_METRIC_MFA:
   260  			warnMetricDisplayTexts.BotTitle = T("api.server.warn_metric.mfa.notification_title")
   261  			if isE0Edition {
   262  				warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.mfa.start_trial.notification_body")
   263  				warnMetricDisplayTexts.BotSuccessMessage = T("api.server.warn_metric.mfa.start_trial_notification_success.message")
   264  			} else {
   265  				warnMetricDisplayTexts.EmailBody = T("api.server.warn_metric.mfa.contact_us.email_body")
   266  				warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.mfa.notification_body")
   267  			}
   268  		case model.SYSTEM_WARN_METRIC_EMAIL_DOMAIN:
   269  			warnMetricDisplayTexts.BotTitle = T("api.server.warn_metric.email_domain.notification_title")
   270  			if isE0Edition {
   271  				warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.email_domain.start_trial.notification_body")
   272  				warnMetricDisplayTexts.BotSuccessMessage = T("api.server.warn_metric.email_domain.start_trial_notification_success.message")
   273  			} else {
   274  				warnMetricDisplayTexts.EmailBody = T("api.server.warn_metric.email_domain.contact_us.email_body")
   275  				warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.email_domain.notification_body")
   276  			}
   277  		case model.SYSTEM_WARN_METRIC_NUMBER_OF_CHANNELS_50:
   278  			warnMetricDisplayTexts.BotTitle = T("api.server.warn_metric.number_of_channels_50.notification_title")
   279  			if isE0Edition {
   280  				warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_channels_50.start_trial.notification_body")
   281  				warnMetricDisplayTexts.BotSuccessMessage = T("api.server.warn_metric.number_of_channels_50.start_trial.notification_success.message")
   282  			} else {
   283  				warnMetricDisplayTexts.EmailBody = T("api.server.warn_metric.number_of_channels_50.contact_us.email_body")
   284  				warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_channels_50.notification_body")
   285  			}
   286  		case model.SYSTEM_WARN_METRIC_NUMBER_OF_ACTIVE_USERS_100:
   287  			warnMetricDisplayTexts.BotTitle = T("api.server.warn_metric.number_of_active_users_100.notification_title")
   288  			if isE0Edition {
   289  				warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_active_users_100.start_trial.notification_body")
   290  				warnMetricDisplayTexts.BotSuccessMessage = T("api.server.warn_metric.number_of_active_users_100.start_trial.notification_success.message")
   291  			} else {
   292  				warnMetricDisplayTexts.EmailBody = T("api.server.warn_metric.number_of_active_users_100.contact_us.email_body")
   293  				warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_active_users_100.notification_body")
   294  			}
   295  		case model.SYSTEM_WARN_METRIC_NUMBER_OF_ACTIVE_USERS_200:
   296  			warnMetricDisplayTexts.BotTitle = T("api.server.warn_metric.number_of_active_users_200.notification_title")
   297  			if isE0Edition {
   298  				warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_active_users_200.start_trial.notification_body")
   299  				warnMetricDisplayTexts.BotSuccessMessage = T("api.server.warn_metric.number_of_active_users_200.start_trial.notification_success.message")
   300  			} else {
   301  				warnMetricDisplayTexts.EmailBody = T("api.server.warn_metric.number_of_active_users_200.contact_us.email_body")
   302  				warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_active_users_200.notification_body")
   303  			}
   304  		case model.SYSTEM_WARN_METRIC_NUMBER_OF_ACTIVE_USERS_300:
   305  			warnMetricDisplayTexts.BotTitle = T("api.server.warn_metric.number_of_active_users_300.start_trial.notification_title")
   306  			if isE0Edition {
   307  				warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_active_users_300.start_trial.notification_body")
   308  				warnMetricDisplayTexts.BotSuccessMessage = T("api.server.warn_metric.number_of_active_users_300.start_trial.notification_success.message")
   309  			} else {
   310  				warnMetricDisplayTexts.EmailBody = T("api.server.warn_metric.number_of_active_users_300.contact_us.email_body")
   311  				warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_active_users_300.notification_body")
   312  			}
   313  		case model.SYSTEM_WARN_METRIC_NUMBER_OF_ACTIVE_USERS_500:
   314  			warnMetricDisplayTexts.BotTitle = T("api.server.warn_metric.number_of_active_users_500.notification_title")
   315  			if isE0Edition {
   316  				warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_active_users_500.start_trial.notification_body")
   317  				warnMetricDisplayTexts.BotSuccessMessage = T("api.server.warn_metric.number_of_active_users_500.start_trial.notification_success.message")
   318  			} else {
   319  				warnMetricDisplayTexts.EmailBody = T("api.server.warn_metric.number_of_active_users_500.contact_us.email_body")
   320  				warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_active_users_500.notification_body")
   321  			}
   322  		case model.SYSTEM_WARN_METRIC_NUMBER_OF_POSTS_2M:
   323  			warnMetricDisplayTexts.BotTitle = T("api.server.warn_metric.number_of_posts_2M.notification_title")
   324  			if isE0Edition {
   325  				warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_posts_2M.start_trial.notification_body")
   326  				warnMetricDisplayTexts.BotSuccessMessage = T("api.server.warn_metric.number_of_posts_2M.start_trial.notification_success.message")
   327  			} else {
   328  				warnMetricDisplayTexts.EmailBody = T("api.server.warn_metric.number_of_posts_2M.contact_us.email_body")
   329  				warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_posts_2M.notification_body")
   330  			}
   331  		default:
   332  			mlog.Debug("Invalid metric id", mlog.String("id", warnMetricId))
   333  			return nil, nil
   334  		}
   335  
   336  		return warnMetricStatus, warnMetricDisplayTexts
   337  	}
   338  	return nil, nil
   339  }
   340  
   341  func (a *App) notifyAdminsOfWarnMetricStatus(warnMetricId string, isE0Edition bool) *model.AppError {
   342  	perPage := 25
   343  	userOptions := &model.UserGetOptions{
   344  		Page:     0,
   345  		PerPage:  perPage,
   346  		Role:     model.SYSTEM_ADMIN_ROLE_ID,
   347  		Inactive: false,
   348  	}
   349  
   350  	// get sysadmins
   351  	var sysAdmins []*model.User
   352  	for {
   353  		sysAdminsList, err := a.GetUsers(userOptions)
   354  		if err != nil {
   355  			return err
   356  		}
   357  
   358  		if len(sysAdminsList) == 0 {
   359  			return model.NewAppError("NotifyAdminsOfWarnMetricStatus", "app.system.warn_metric.notification.empty_admin_list.app_error", nil, "", http.StatusInternalServerError)
   360  		}
   361  		sysAdmins = append(sysAdmins, sysAdminsList...)
   362  
   363  		if len(sysAdminsList) < perPage {
   364  			mlog.Debug("Number of system admins is less than page limit", mlog.Int("count", len(sysAdminsList)))
   365  			break
   366  		}
   367  	}
   368  
   369  	T := utils.GetUserTranslations(sysAdmins[0].Locale)
   370  	warnMetricsBot := &model.Bot{
   371  		Username:    model.BOT_WARN_METRIC_BOT_USERNAME,
   372  		DisplayName: T("app.system.warn_metric.bot_displayname"),
   373  		Description: "",
   374  		OwnerId:     sysAdmins[0].Id,
   375  	}
   376  
   377  	bot, err := a.getOrCreateWarnMetricsBot(warnMetricsBot)
   378  	if err != nil {
   379  		return err
   380  	}
   381  
   382  	for _, sysAdmin := range sysAdmins {
   383  		T := utils.GetUserTranslations(sysAdmin.Locale)
   384  		bot.DisplayName = T("app.system.warn_metric.bot_displayname")
   385  		bot.Description = T("app.system.warn_metric.bot_description")
   386  
   387  		channel, appErr := a.GetOrCreateDirectChannel(bot.UserId, sysAdmin.Id)
   388  		if appErr != nil {
   389  			return appErr
   390  		}
   391  
   392  		warnMetricStatus, warnMetricDisplayTexts := a.getWarnMetricStatusAndDisplayTextsForId(warnMetricId, T, isE0Edition)
   393  		if warnMetricStatus == nil {
   394  			return model.NewAppError("NotifyAdminsOfWarnMetricStatus", "app.system.warn_metric.notification.invalid_metric.app_error", nil, "", http.StatusInternalServerError)
   395  		}
   396  
   397  		botPost := &model.Post{
   398  			UserId:    bot.UserId,
   399  			ChannelId: channel.Id,
   400  			Type:      model.POST_SYSTEM_WARN_METRIC_STATUS,
   401  			Message:   "",
   402  		}
   403  
   404  		actionId := "contactUs"
   405  		actionName := T("api.server.warn_metric.contact_us")
   406  		postActionValue := T("api.server.warn_metric.contacting_us")
   407  		postActionUrl := fmt.Sprintf("/warn_metrics/ack/%s", warnMetricId)
   408  
   409  		if isE0Edition {
   410  			actionId = "startTrial"
   411  			actionName = T("api.server.warn_metric.start_trial")
   412  			postActionValue = T("api.server.warn_metric.starting_trial")
   413  			postActionUrl = fmt.Sprintf("/warn_metrics/trial-license-ack/%s", warnMetricId)
   414  		}
   415  
   416  		actions := []*model.PostAction{}
   417  		actions = append(actions,
   418  			&model.PostAction{
   419  				Id:   actionId,
   420  				Name: actionName,
   421  				Type: model.POST_ACTION_TYPE_BUTTON,
   422  				Options: []*model.PostActionOptions{
   423  					{
   424  						Text:  "TrackEventId",
   425  						Value: warnMetricId,
   426  					},
   427  					{
   428  						Text:  "ActionExecutingMessage",
   429  						Value: postActionValue,
   430  					},
   431  				},
   432  				Integration: &model.PostActionIntegration{
   433  					Context: model.StringInterface{
   434  						"bot_user_id": bot.UserId,
   435  						"force_ack":   false,
   436  					},
   437  					URL: postActionUrl,
   438  				},
   439  			},
   440  		)
   441  
   442  		attachments := []*model.SlackAttachment{{
   443  			AuthorName: "",
   444  			Title:      warnMetricDisplayTexts.BotTitle,
   445  			Text:       warnMetricDisplayTexts.BotMessageBody,
   446  			Actions:    actions,
   447  		}}
   448  		model.ParseSlackAttachment(botPost, attachments)
   449  
   450  		mlog.Debug("Post admin advisory for metric", mlog.String("warnMetricId", warnMetricId), mlog.String("userid", botPost.UserId))
   451  		if _, err := a.CreatePostAsUser(botPost, a.Session().Id, true); err != nil {
   452  			return err
   453  		}
   454  	}
   455  
   456  	return nil
   457  }
   458  
   459  func (a *App) NotifyAndSetWarnMetricAck(warnMetricId string, sender *model.User, forceAck bool, isBot bool) *model.AppError {
   460  	if warnMetric, ok := model.WarnMetricsTable[warnMetricId]; ok {
   461  		data, nErr := a.Srv().Store.System().GetByName(warnMetric.Id)
   462  		if nErr == nil && data != nil && data.Value == model.WARN_METRIC_STATUS_ACK {
   463  			mlog.Debug("This metric warning has already been acknowledged", mlog.String("id", warnMetric.Id))
   464  			return nil
   465  		}
   466  
   467  		if !forceAck {
   468  			if *a.Config().EmailSettings.SMTPServer == "" {
   469  				return model.NewAppError("NotifyAndSetWarnMetricAck", "api.email.send_warn_metric_ack.missing_server.app_error", nil, utils.T("api.context.invalid_param.app_error", map[string]interface{}{"Name": "SMTPServer"}), http.StatusInternalServerError)
   470  			}
   471  			T := utils.GetUserTranslations(sender.Locale)
   472  			bodyPage := a.Srv().EmailService.newEmailTemplate("warn_metric_ack", sender.Locale)
   473  			bodyPage.Props["ContactNameHeader"] = T("api.templates.warn_metric_ack.body.contact_name_header")
   474  			bodyPage.Props["ContactNameValue"] = sender.GetFullName()
   475  			bodyPage.Props["ContactEmailHeader"] = T("api.templates.warn_metric_ack.body.contact_email_header")
   476  			bodyPage.Props["ContactEmailValue"] = sender.Email
   477  
   478  			//same definition as the active users count metric displayed in the SystemConsole Analytics section
   479  			registeredUsersCount, cerr := a.Srv().Store.User().Count(model.UserCountOptions{})
   480  			if cerr != nil {
   481  				mlog.Warn("Error retrieving the number of registered users", mlog.Err(cerr))
   482  			} else {
   483  				bodyPage.Props["RegisteredUsersHeader"] = T("api.templates.warn_metric_ack.body.registered_users_header")
   484  				bodyPage.Props["RegisteredUsersValue"] = registeredUsersCount
   485  			}
   486  			bodyPage.Props["SiteURLHeader"] = T("api.templates.warn_metric_ack.body.site_url_header")
   487  			bodyPage.Props["SiteURL"] = a.GetSiteURL()
   488  			bodyPage.Props["TelemetryIdHeader"] = T("api.templates.warn_metric_ack.body.diagnostic_id_header")
   489  			bodyPage.Props["TelemetryIdValue"] = a.TelemetryId()
   490  			bodyPage.Props["Footer"] = T("api.templates.warn_metric_ack.footer")
   491  
   492  			warnMetricStatus, warnMetricDisplayTexts := a.getWarnMetricStatusAndDisplayTextsForId(warnMetricId, T, false)
   493  			if warnMetricStatus == nil {
   494  				return model.NewAppError("NotifyAndSetWarnMetricAck", "api.email.send_warn_metric_ack.invalid_warn_metric.app_error", nil, "", http.StatusInternalServerError)
   495  			}
   496  
   497  			subject := T("api.templates.warn_metric_ack.subject")
   498  			bodyPage.Props["Title"] = warnMetricDisplayTexts.EmailBody
   499  
   500  			mailConfig := a.Srv().MailServiceConfig()
   501  			if err := mailservice.SendMailUsingConfig(model.MM_SUPPORT_ADVISOR_ADDRESS, subject, bodyPage.Render(), mailConfig, false, sender.Email); err != nil {
   502  				return model.NewAppError("NotifyAndSetWarnMetricAck", "api.email.send_warn_metric_ack.failure.app_error", map[string]interface{}{"Error": err.Error()}, "", http.StatusInternalServerError)
   503  			}
   504  		}
   505  
   506  		if err := a.setWarnMetricsStatusAndNotify(warnMetric.Id); err != nil {
   507  			return err
   508  		}
   509  	}
   510  	return nil
   511  }
   512  
   513  func (a *App) setWarnMetricsStatusAndNotify(warnMetricId string) *model.AppError {
   514  	// Ack all metric warnings on the server
   515  	if err := a.setWarnMetricsStatus(model.WARN_METRIC_STATUS_ACK); err != nil {
   516  		return err
   517  	}
   518  
   519  	// Inform client that this metric warning has been acked
   520  	message := model.NewWebSocketEvent(model.WEBSOCKET_WARN_METRIC_STATUS_REMOVED, "", "", "", nil)
   521  	message.Add("warnMetricId", warnMetricId)
   522  	a.Publish(message)
   523  
   524  	return nil
   525  }
   526  
   527  func (a *App) setWarnMetricsStatus(status string) *model.AppError {
   528  	mlog.Debug("Set monitoring status for all warn metrics", mlog.String("status", status))
   529  	for _, warnMetric := range model.WarnMetricsTable {
   530  		if err := a.setWarnMetricsStatusForId(warnMetric.Id, status); err != nil {
   531  			return err
   532  		}
   533  	}
   534  	return nil
   535  }
   536  
   537  func (a *App) setWarnMetricsStatusForId(warnMetricId string, status string) *model.AppError {
   538  	mlog.Debug("Store status for warn metric", mlog.String("warnMetricId", warnMetricId), mlog.String("status", status))
   539  	if err := a.Srv().Store.System().SaveOrUpdateWithWarnMetricHandling(&model.System{
   540  		Name:  warnMetricId,
   541  		Value: status,
   542  	}); err != nil {
   543  		return model.NewAppError("setWarnMetricsStatusForId", "app.system.warn_metric.store.app_error", map[string]interface{}{"WarnMetricName": warnMetricId}, err.Error(), http.StatusInternalServerError)
   544  	}
   545  	return nil
   546  }
   547  
   548  func (a *App) RequestLicenseAndAckWarnMetric(warnMetricId string, isBot bool) *model.AppError {
   549  	if *a.Config().ExperimentalSettings.RestrictSystemAdmin {
   550  		return model.NewAppError("RequestLicenseAndAckWarnMetric", "api.restricted_system_admin", nil, "", http.StatusForbidden)
   551  	}
   552  
   553  	currentUser, appErr := a.GetUser(a.Session().UserId)
   554  	if appErr != nil {
   555  		return appErr
   556  	}
   557  
   558  	registeredUsersCount, err := a.Srv().Store.User().Count(model.UserCountOptions{})
   559  	if err != nil {
   560  		return model.NewAppError("RequestLicenseAndAckWarnMetric", "api.license.request_trial_license.fail_get_user_count.app_error", nil, err.Error(), http.StatusBadRequest)
   561  	}
   562  
   563  	trialLicenseRequest := &model.TrialLicenseRequest{
   564  		ServerID:              a.TelemetryId(),
   565  		Name:                  currentUser.GetDisplayName(model.SHOW_FULLNAME),
   566  		Email:                 currentUser.Email,
   567  		SiteName:              *a.Config().TeamSettings.SiteName,
   568  		SiteURL:               *a.Config().ServiceSettings.SiteURL,
   569  		Users:                 int(registeredUsersCount),
   570  		TermsAccepted:         true,
   571  		ReceiveEmailsAccepted: true,
   572  	}
   573  
   574  	if trialLicenseRequest.SiteURL == "" {
   575  		return model.NewAppError("RequestLicenseAndAckWarnMetric", "api.license.request_trial_license.no-site-url.app_error", nil, "", http.StatusBadRequest)
   576  	}
   577  
   578  	if err := a.Srv().RequestTrialLicense(trialLicenseRequest); err != nil {
   579  		// turn off warn metric warning even in case of StartTrial failure
   580  		if nerr := a.setWarnMetricsStatusAndNotify(warnMetricId); nerr != nil {
   581  			return nerr
   582  		}
   583  
   584  		return err
   585  	}
   586  
   587  	if appErr = a.NotifyAndSetWarnMetricAck(warnMetricId, currentUser, true, isBot); appErr != nil {
   588  		return appErr
   589  	}
   590  
   591  	return nil
   592  }
   593  
   594  func (a *App) Srv() *Server {
   595  	return a.srv
   596  }
   597  func (a *App) Log() *mlog.Logger {
   598  	return a.srv.Log
   599  }
   600  func (a *App) NotificationsLog() *mlog.Logger {
   601  	return a.srv.NotificationsLog
   602  }
   603  func (a *App) T(translationID string, args ...interface{}) string {
   604  	return a.t(translationID, args...)
   605  }
   606  func (a *App) Session() *model.Session {
   607  	return &a.session
   608  }
   609  func (a *App) RequestId() string {
   610  	return a.requestId
   611  }
   612  func (a *App) IpAddress() string {
   613  	return a.ipAddress
   614  }
   615  func (a *App) Path() string {
   616  	return a.path
   617  }
   618  func (a *App) UserAgent() string {
   619  	return a.userAgent
   620  }
   621  func (a *App) AcceptLanguage() string {
   622  	return a.acceptLanguage
   623  }
   624  func (a *App) AccountMigration() einterfaces.AccountMigrationInterface {
   625  	return a.srv.AccountMigration
   626  }
   627  func (a *App) Cluster() einterfaces.ClusterInterface {
   628  	return a.srv.Cluster
   629  }
   630  func (a *App) Compliance() einterfaces.ComplianceInterface {
   631  	return a.srv.Compliance
   632  }
   633  func (a *App) DataRetention() einterfaces.DataRetentionInterface {
   634  	return a.srv.DataRetention
   635  }
   636  func (a *App) SearchEngine() *searchengine.Broker {
   637  	return a.searchEngine
   638  }
   639  func (a *App) Ldap() einterfaces.LdapInterface {
   640  	return a.srv.Ldap
   641  }
   642  func (a *App) MessageExport() einterfaces.MessageExportInterface {
   643  	return a.srv.MessageExport
   644  }
   645  func (a *App) Metrics() einterfaces.MetricsInterface {
   646  	return a.srv.Metrics
   647  }
   648  func (a *App) Notification() einterfaces.NotificationInterface {
   649  	return a.srv.Notification
   650  }
   651  func (a *App) Saml() einterfaces.SamlInterface {
   652  	return a.srv.Saml
   653  }
   654  func (a *App) Cloud() einterfaces.CloudInterface {
   655  	return a.srv.Cloud
   656  }
   657  func (a *App) HTTPService() httpservice.HTTPService {
   658  	return a.srv.HTTPService
   659  }
   660  func (a *App) ImageProxy() *imageproxy.ImageProxy {
   661  	return a.srv.ImageProxy
   662  }
   663  func (a *App) Timezones() *timezones.Timezones {
   664  	return a.srv.timezones
   665  }
   666  func (a *App) Context() context.Context {
   667  	return a.context
   668  }
   669  
   670  func (a *App) SetSession(s *model.Session) {
   671  	a.session = *s
   672  }
   673  
   674  func (a *App) SetT(t goi18n.TranslateFunc) {
   675  	a.t = t
   676  }
   677  func (a *App) SetRequestId(s string) {
   678  	a.requestId = s
   679  }
   680  func (a *App) SetIpAddress(s string) {
   681  	a.ipAddress = s
   682  }
   683  func (a *App) SetUserAgent(s string) {
   684  	a.userAgent = s
   685  }
   686  func (a *App) SetAcceptLanguage(s string) {
   687  	a.acceptLanguage = s
   688  }
   689  func (a *App) SetPath(s string) {
   690  	a.path = s
   691  }
   692  func (a *App) SetContext(c context.Context) {
   693  	a.context = c
   694  }
   695  func (a *App) SetServer(srv *Server) {
   696  	a.srv = srv
   697  }
   698  func (a *App) GetT() goi18n.TranslateFunc {
   699  	return a.t
   700  }
   701  
   702  func (a *App) DBHealthCheckWrite() error {
   703  	currentTime := strconv.FormatInt(time.Now().Unix(), 10)
   704  
   705  	return a.Srv().Store.System().SaveOrUpdate(&model.System{
   706  		Name:  a.dbHealthCheckKey(),
   707  		Value: currentTime,
   708  	})
   709  }
   710  
   711  func (a *App) DBHealthCheckDelete() error {
   712  	_, err := a.Srv().Store.System().PermanentDeleteByName(a.dbHealthCheckKey())
   713  	return err
   714  }
   715  
   716  func (a *App) dbHealthCheckKey() string {
   717  	return fmt.Sprintf("health_check_%s", a.GetClusterId())
   718  }