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 }