Deprecate admin advisor (#26045)
* Deprecate admin advisor * Webapp portion * More webapp deprecation * More cleanup * Linting * emoved metric ack dialog from annoucenemet bar * Cleanued up uninsed i18n strings * Updated test * fixed types * Updating server test * Updated i18n * Updated cypress test: * Updated cypress test: --------- Co-authored-by: harshil Sharma <harshilsharma63@gmail.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
dc8fc773dc
Коммит
e9b9d4ff60
@@ -66,9 +66,6 @@ func (api *API) InitSystem() {
|
||||
api.BaseRoutes.APIRoot.Handle("/upgrade_to_enterprise", api.APISessionRequired(upgradeToEnterprise)).Methods("POST")
|
||||
api.BaseRoutes.APIRoot.Handle("/upgrade_to_enterprise/status", api.APISessionRequired(upgradeToEnterpriseStatus)).Methods("GET")
|
||||
api.BaseRoutes.APIRoot.Handle("/restart", api.APISessionRequired(restart)).Methods("POST")
|
||||
api.BaseRoutes.APIRoot.Handle("/warn_metrics/status", api.APISessionRequired(getWarnMetricsStatus)).Methods("GET")
|
||||
api.BaseRoutes.APIRoot.Handle("/warn_metrics/ack/{warn_metric_id:[A-Za-z0-9-_]+}", api.APIHandler(sendWarnMetricAckEmail)).Methods("POST")
|
||||
api.BaseRoutes.APIRoot.Handle("/warn_metrics/trial-license-ack/{warn_metric_id:[A-Za-z0-9-_]+}", api.APIHandler(requestTrialLicenseAndAckWarnMetric)).Methods("POST")
|
||||
api.BaseRoutes.System.Handle("/notices/{team_id:[A-Za-z0-9]+}", api.APISessionRequired(getProductNotices)).Methods("GET")
|
||||
api.BaseRoutes.System.Handle("/notices/view", api.APISessionRequired(updateViewedProductNotices)).Methods("PUT")
|
||||
api.BaseRoutes.System.Handle("/support_packet", api.APISessionRequired(generateSupportPacket)).Methods("GET")
|
||||
@@ -846,100 +843,6 @@ func restart(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
}()
|
||||
}
|
||||
|
||||
func getWarnMetricsStatus(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
if !c.App.SessionHasPermissionToAny(*c.AppContext.Session(), model.SysconsoleReadPermissions) {
|
||||
c.SetPermissionError(model.SysconsoleReadPermissions...)
|
||||
return
|
||||
}
|
||||
|
||||
license := c.App.Channels().License()
|
||||
if license != nil {
|
||||
c.Logger.Debug("License is present, skip.")
|
||||
return
|
||||
}
|
||||
|
||||
status, appErr := c.App.GetWarnMetricsStatus(c.AppContext)
|
||||
if appErr != nil {
|
||||
c.Err = appErr
|
||||
return
|
||||
}
|
||||
|
||||
js, err := json.Marshal(status)
|
||||
if err != nil {
|
||||
c.Err = model.NewAppError("getWarnMetricsStatus", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(js)
|
||||
}
|
||||
|
||||
func sendWarnMetricAckEmail(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
auditRec := c.MakeAuditRecord("sendWarnMetricAckEmail", audit.Fail)
|
||||
defer c.LogAuditRec(auditRec)
|
||||
c.LogAudit("attempt")
|
||||
|
||||
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageSystem) {
|
||||
c.SetPermissionError(model.PermissionManageSystem)
|
||||
return
|
||||
}
|
||||
|
||||
license := c.App.Channels().License()
|
||||
if license != nil {
|
||||
c.Logger.Debug("License is present, skip.")
|
||||
return
|
||||
}
|
||||
|
||||
user, appErr := c.App.GetUser(c.AppContext.Session().UserId)
|
||||
if appErr != nil {
|
||||
c.Err = appErr
|
||||
return
|
||||
}
|
||||
|
||||
var ack model.SendWarnMetricAck
|
||||
if jsonErr := json.NewDecoder(r.Body).Decode(&ack); jsonErr != nil {
|
||||
c.SetInvalidParamWithErr("ack", jsonErr)
|
||||
return
|
||||
}
|
||||
|
||||
appErr = c.App.NotifyAndSetWarnMetricAck(c.AppContext, c.Params.WarnMetricId, user, ack.ForceAck, false)
|
||||
if appErr != nil {
|
||||
c.Err = appErr
|
||||
}
|
||||
|
||||
auditRec.Success()
|
||||
ReturnStatusOK(w)
|
||||
}
|
||||
|
||||
func requestTrialLicenseAndAckWarnMetric(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
auditRec := c.MakeAuditRecord("requestTrialLicenseAndAckWarnMetric", audit.Fail)
|
||||
defer c.LogAuditRec(auditRec)
|
||||
c.LogAudit("attempt")
|
||||
|
||||
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageSystem) {
|
||||
c.SetPermissionError(model.PermissionManageSystem)
|
||||
return
|
||||
}
|
||||
|
||||
if model.BuildEnterpriseReady != "true" {
|
||||
c.Logger.Debug("Not Enterprise Edition, skip.")
|
||||
return
|
||||
}
|
||||
|
||||
license := c.App.Channels().License()
|
||||
if license != nil {
|
||||
c.Logger.Debug("License is present, skip.")
|
||||
return
|
||||
}
|
||||
|
||||
if err := c.App.RequestLicenseAndAckWarnMetric(c.AppContext, c.Params.WarnMetricId, false); err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
auditRec.Success()
|
||||
ReturnStatusOK(w)
|
||||
}
|
||||
|
||||
func getProductNotices(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.RequireTeamId()
|
||||
if c.Err != nil {
|
||||
|
||||
@@ -1,273 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/mattermost/mattermost/server/public/model"
|
||||
"github.com/mattermost/mattermost/server/public/shared/i18n"
|
||||
"github.com/mattermost/mattermost/server/public/shared/mlog"
|
||||
"github.com/mattermost/mattermost/server/public/shared/request"
|
||||
"github.com/mattermost/mattermost/server/v8/platform/shared/mail"
|
||||
)
|
||||
|
||||
func (a *App) GetWarnMetricsStatus(rctx request.CTX) (map[string]*model.WarnMetricStatus, *model.AppError) {
|
||||
systemDataList, nErr := a.Srv().Store().System().Get()
|
||||
if nErr != nil {
|
||||
return nil, model.NewAppError("GetWarnMetricsStatus", "app.system.get.app_error", nil, "", http.StatusInternalServerError).Wrap(nErr)
|
||||
}
|
||||
|
||||
isE0Edition := model.BuildEnterpriseReady == "true" // license == nil was already validated upstream
|
||||
|
||||
result := map[string]*model.WarnMetricStatus{}
|
||||
for key, value := range systemDataList {
|
||||
if strings.HasPrefix(key, model.WarnMetricStatusStorePrefix) {
|
||||
if warnMetric, ok := model.WarnMetricsTable[key]; ok {
|
||||
if !warnMetric.IsBotOnly && (value == model.WarnMetricStatusRunonce || value == model.WarnMetricStatusLimitReached) {
|
||||
result[key], _ = a.getWarnMetricStatusAndDisplayTextsForId(rctx, key, nil, isE0Edition)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (a *App) getWarnMetricStatusAndDisplayTextsForId(rctx request.CTX, warnMetricId string, T i18n.TranslateFunc, isE0Edition bool) (*model.WarnMetricStatus, *model.WarnMetricDisplayTexts) {
|
||||
var warnMetricStatus *model.WarnMetricStatus
|
||||
var warnMetricDisplayTexts = &model.WarnMetricDisplayTexts{}
|
||||
|
||||
if warnMetric, ok := model.WarnMetricsTable[warnMetricId]; ok {
|
||||
warnMetricStatus = &model.WarnMetricStatus{
|
||||
Id: warnMetric.Id,
|
||||
Limit: warnMetric.Limit,
|
||||
Acked: false,
|
||||
}
|
||||
|
||||
if T == nil {
|
||||
rctx.Logger().Debug("No translation function")
|
||||
return warnMetricStatus, nil
|
||||
}
|
||||
|
||||
warnMetricDisplayTexts.BotSuccessMessage = T("api.server.warn_metric.bot_response.notification_success.message")
|
||||
|
||||
switch warnMetricId {
|
||||
case model.SystemWarnMetricNumberOfTeams5:
|
||||
warnMetricDisplayTexts.BotTitle = T("api.server.warn_metric.number_of_teams_5.notification_title")
|
||||
if isE0Edition {
|
||||
warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_teams_5.start_trial.notification_body")
|
||||
warnMetricDisplayTexts.BotSuccessMessage = T("api.server.warn_metric.number_of_teams_5.start_trial_notification_success.message")
|
||||
} else {
|
||||
warnMetricDisplayTexts.EmailBody = T("api.server.warn_metric.number_of_teams_5.contact_us.email_body")
|
||||
warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_teams_5.notification_body")
|
||||
}
|
||||
case model.SystemWarnMetricMfa:
|
||||
warnMetricDisplayTexts.BotTitle = T("api.server.warn_metric.mfa.notification_title")
|
||||
if isE0Edition {
|
||||
warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.mfa.start_trial.notification_body")
|
||||
warnMetricDisplayTexts.BotSuccessMessage = T("api.server.warn_metric.mfa.start_trial_notification_success.message")
|
||||
} else {
|
||||
warnMetricDisplayTexts.EmailBody = T("api.server.warn_metric.mfa.contact_us.email_body")
|
||||
warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.mfa.notification_body")
|
||||
}
|
||||
case model.SystemWarnMetricEmailDomain:
|
||||
warnMetricDisplayTexts.BotTitle = T("api.server.warn_metric.email_domain.notification_title")
|
||||
if isE0Edition {
|
||||
warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.email_domain.start_trial.notification_body")
|
||||
warnMetricDisplayTexts.BotSuccessMessage = T("api.server.warn_metric.email_domain.start_trial_notification_success.message")
|
||||
} else {
|
||||
warnMetricDisplayTexts.EmailBody = T("api.server.warn_metric.email_domain.contact_us.email_body")
|
||||
warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.email_domain.notification_body")
|
||||
}
|
||||
case model.SystemWarnMetricNumberOfChannels50:
|
||||
warnMetricDisplayTexts.BotTitle = T("api.server.warn_metric.number_of_channels_50.notification_title")
|
||||
if isE0Edition {
|
||||
warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_channels_50.start_trial.notification_body")
|
||||
warnMetricDisplayTexts.BotSuccessMessage = T("api.server.warn_metric.number_of_channels_50.start_trial.notification_success.message")
|
||||
} else {
|
||||
warnMetricDisplayTexts.EmailBody = T("api.server.warn_metric.number_of_channels_50.contact_us.email_body")
|
||||
warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_channels_50.notification_body")
|
||||
}
|
||||
case model.SystemWarnMetricNumberOfActiveUsers100:
|
||||
warnMetricDisplayTexts.BotTitle = T("api.server.warn_metric.number_of_active_users_100.notification_title")
|
||||
if isE0Edition {
|
||||
warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_active_users_100.start_trial.notification_body")
|
||||
warnMetricDisplayTexts.BotSuccessMessage = T("api.server.warn_metric.number_of_active_users_100.start_trial.notification_success.message")
|
||||
} else {
|
||||
warnMetricDisplayTexts.EmailBody = T("api.server.warn_metric.number_of_active_users_100.contact_us.email_body")
|
||||
warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_active_users_100.notification_body")
|
||||
}
|
||||
case model.SystemWarnMetricNumberOfActiveUsers200:
|
||||
warnMetricDisplayTexts.BotTitle = T("api.server.warn_metric.number_of_active_users_200.notification_title")
|
||||
if isE0Edition {
|
||||
warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_active_users_200.start_trial.notification_body")
|
||||
warnMetricDisplayTexts.BotSuccessMessage = T("api.server.warn_metric.number_of_active_users_200.start_trial.notification_success.message")
|
||||
} else {
|
||||
warnMetricDisplayTexts.EmailBody = T("api.server.warn_metric.number_of_active_users_200.contact_us.email_body")
|
||||
warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_active_users_200.notification_body")
|
||||
}
|
||||
case model.SystemWarnMetricNumberOfActiveUsers300:
|
||||
warnMetricDisplayTexts.BotTitle = T("api.server.warn_metric.number_of_active_users_300.start_trial.notification_title")
|
||||
if isE0Edition {
|
||||
warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_active_users_300.start_trial.notification_body")
|
||||
warnMetricDisplayTexts.BotSuccessMessage = T("api.server.warn_metric.number_of_active_users_300.start_trial.notification_success.message")
|
||||
} else {
|
||||
warnMetricDisplayTexts.EmailBody = T("api.server.warn_metric.number_of_active_users_300.contact_us.email_body")
|
||||
warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_active_users_300.notification_body")
|
||||
}
|
||||
case model.SystemWarnMetricNumberOfActiveUsers500:
|
||||
warnMetricDisplayTexts.BotTitle = T("api.server.warn_metric.number_of_active_users_500.notification_title")
|
||||
if isE0Edition {
|
||||
warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_active_users_500.start_trial.notification_body")
|
||||
warnMetricDisplayTexts.BotSuccessMessage = T("api.server.warn_metric.number_of_active_users_500.start_trial.notification_success.message")
|
||||
} else {
|
||||
warnMetricDisplayTexts.EmailBody = T("api.server.warn_metric.number_of_active_users_500.contact_us.email_body")
|
||||
warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_active_users_500.notification_body")
|
||||
}
|
||||
case model.SystemWarnMetricNumberOfPosts2m:
|
||||
warnMetricDisplayTexts.BotTitle = T("api.server.warn_metric.number_of_posts_2M.notification_title")
|
||||
if isE0Edition {
|
||||
warnMetricDisplayTexts.BotMessageBody = T("api.server.warn_metric.number_of_posts_2M.start_trial.notification_body")
|
||||
warnMetricDisplayTexts.BotSuccessMessage = T("api.server.warn_metric.number_of_posts_2M.start_trial.notification_success.message")
|
||||
} else {
|
||||
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")
|
||||
}
|
||||
default:
|
||||
rctx.Logger().Debug("Invalid metric id", mlog.String("id", warnMetricId))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return warnMetricStatus, warnMetricDisplayTexts
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (a *App) NotifyAndSetWarnMetricAck(rctx request.CTX, warnMetricId string, sender *model.User, forceAck bool, isBot bool) *model.AppError {
|
||||
if warnMetric, ok := model.WarnMetricsTable[warnMetricId]; ok {
|
||||
data, nErr := a.Srv().Store().System().GetByName(warnMetric.Id)
|
||||
if nErr == nil && data != nil && data.Value == model.WarnMetricStatusAck {
|
||||
rctx.Logger().Debug("This metric warning has already been acknowledged", mlog.String("id", warnMetric.Id))
|
||||
return nil
|
||||
}
|
||||
|
||||
if !forceAck {
|
||||
if *a.Config().EmailSettings.SMTPServer == "" {
|
||||
return model.NewAppError("NotifyAndSetWarnMetricAck", "api.email.send_warn_metric_ack.missing_server.app_error", nil, i18n.T("api.context.invalid_param.app_error", map[string]any{"Name": "SMTPServer"}), http.StatusInternalServerError)
|
||||
}
|
||||
T := i18n.GetUserTranslations(sender.Locale)
|
||||
data := a.Srv().EmailService.NewEmailTemplateData(sender.Locale)
|
||||
data.Props["ContactNameHeader"] = T("api.templates.warn_metric_ack.body.contact_name_header")
|
||||
data.Props["ContactNameValue"] = sender.GetFullName()
|
||||
data.Props["ContactEmailHeader"] = T("api.templates.warn_metric_ack.body.contact_email_header")
|
||||
data.Props["ContactEmailValue"] = sender.Email
|
||||
|
||||
//same definition as the active users count metric displayed in the SystemConsole Analytics section
|
||||
registeredUsersCount, cerr := a.Srv().Store().User().Count(model.UserCountOptions{})
|
||||
if cerr != nil {
|
||||
rctx.Logger().Warn("Error retrieving the number of registered users", mlog.Err(cerr))
|
||||
} else {
|
||||
data.Props["RegisteredUsersHeader"] = T("api.templates.warn_metric_ack.body.registered_users_header")
|
||||
data.Props["RegisteredUsersValue"] = registeredUsersCount
|
||||
}
|
||||
data.Props["SiteURLHeader"] = T("api.templates.warn_metric_ack.body.site_url_header")
|
||||
data.Props["SiteURL"] = a.GetSiteURL()
|
||||
data.Props["TelemetryIdHeader"] = T("api.templates.warn_metric_ack.body.diagnostic_id_header")
|
||||
data.Props["TelemetryIdValue"] = a.TelemetryId()
|
||||
data.Props["Footer"] = T("api.templates.warn_metric_ack.footer")
|
||||
|
||||
warnMetricStatus, warnMetricDisplayTexts := a.getWarnMetricStatusAndDisplayTextsForId(rctx, warnMetricId, T, false)
|
||||
if warnMetricStatus == nil {
|
||||
return model.NewAppError("NotifyAndSetWarnMetricAck", "api.email.send_warn_metric_ack.invalid_warn_metric.app_error", nil, "", http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
subject := T("api.templates.warn_metric_ack.subject")
|
||||
data.Props["Title"] = warnMetricDisplayTexts.EmailBody
|
||||
|
||||
mailConfig := a.Srv().MailServiceConfig()
|
||||
|
||||
body, err := a.Srv().TemplatesContainer().RenderToString("warn_metric_ack", data)
|
||||
if err != nil {
|
||||
return model.NewAppError("NotifyAndSetWarnMetricAck", "api.email.send_warn_metric_ack.failure.app_error", map[string]any{"Error": err.Error()}, "", http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
if err := mail.SendMailUsingConfig(model.MmSupportAdvisorAddress, subject, body, mailConfig, false, "", "", "", sender.Email, "NotifyAndSetWarnMetricAck"); err != nil {
|
||||
return model.NewAppError("NotifyAndSetWarnMetricAck", "api.email.send_warn_metric_ack.failure.app_error", map[string]any{"Error": err.Error()}, "", http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
if err := a.setWarnMetricsStatusAndNotify(rctx, warnMetric.Id); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) setWarnMetricsStatusAndNotify(rctx request.CTX, warnMetricId string) *model.AppError {
|
||||
// Ack all metric warnings on the server
|
||||
if err := a.setWarnMetricsStatus(rctx, model.WarnMetricStatusAck); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Inform client that this metric warning has been acked
|
||||
message := model.NewWebSocketEvent(model.WebsocketWarnMetricStatusRemoved, "", "", "", nil, "")
|
||||
message.Add("warnMetricId", warnMetricId)
|
||||
a.Publish(message)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) setWarnMetricsStatus(rctx request.CTX, status string) *model.AppError {
|
||||
rctx.Logger().Debug("Set monitoring status for all warn metrics", mlog.String("status", status))
|
||||
for _, warnMetric := range model.WarnMetricsTable {
|
||||
if err := a.setWarnMetricsStatusForId(rctx, warnMetric.Id, status); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) setWarnMetricsStatusForId(rctx request.CTX, warnMetricId string, status string) *model.AppError {
|
||||
rctx.Logger().Debug("Store status for warn metric", mlog.String("warnMetricId", warnMetricId), mlog.String("status", status))
|
||||
if err := a.Srv().Store().System().SaveOrUpdateWithWarnMetricHandling(&model.System{
|
||||
Name: warnMetricId,
|
||||
Value: status,
|
||||
}); err != nil {
|
||||
return model.NewAppError("setWarnMetricsStatusForId", "app.system.warn_metric.store.app_error", map[string]any{"WarnMetricName": warnMetricId}, "", http.StatusInternalServerError).Wrap(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) RequestLicenseAndAckWarnMetric(c request.CTX, warnMetricId string, isBot bool) *model.AppError {
|
||||
if *a.Config().ExperimentalSettings.RestrictSystemAdmin {
|
||||
return model.NewAppError("RequestLicenseAndAckWarnMetric", "api.restricted_system_admin", nil, "", http.StatusForbidden)
|
||||
}
|
||||
|
||||
currentUser, appErr := a.GetUser(c.Session().UserId)
|
||||
if appErr != nil {
|
||||
return appErr
|
||||
}
|
||||
|
||||
registeredUsersCount, err := a.Srv().Store().User().Count(model.UserCountOptions{})
|
||||
if err != nil {
|
||||
return model.NewAppError("RequestLicenseAndAckWarnMetric", "api.license.request_trial_license.fail_get_user_count.app_error", nil, "", http.StatusBadRequest).Wrap(err)
|
||||
}
|
||||
|
||||
if err := a.Channels().RequestTrialLicense(c.Session().UserId, int(registeredUsersCount), true, true); err != nil {
|
||||
// turn off warn metric warning even in case of StartTrial failure
|
||||
if nerr := a.setWarnMetricsStatusAndNotify(c, warnMetricId); nerr != nil {
|
||||
return nerr
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
if appErr = a.NotifyAndSetWarnMetricAck(c, warnMetricId, currentUser, true, isBot); appErr != nil {
|
||||
return appErr
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -883,8 +883,6 @@ type AppIface interface {
|
||||
GetUsersWithoutTeamPage(options *model.UserGetOptions, asAdmin bool) ([]*model.User, *model.AppError)
|
||||
GetVerifyEmailToken(token string) (*model.Token, *model.AppError)
|
||||
GetViewUsersRestrictions(c request.CTX, userID string) (*model.ViewUsersRestrictions, *model.AppError)
|
||||
GetWarnMetricsBot(rctx request.CTX) (*model.Bot, *model.AppError)
|
||||
GetWarnMetricsStatus(rctx request.CTX) (map[string]*model.WarnMetricStatus, *model.AppError)
|
||||
HTTPService() httpservice.HTTPService
|
||||
HandleCommandResponse(c request.CTX, command *model.Command, args *model.CommandArgs, response *model.CommandResponse, builtIn bool) (*model.CommandResponse, *model.AppError)
|
||||
HandleCommandResponsePost(c request.CTX, command *model.Command, args *model.CommandArgs, response *model.CommandResponse, builtIn bool) (*model.Post, *model.AppError)
|
||||
@@ -953,7 +951,6 @@ type AppIface interface {
|
||||
NewPluginAPI(c request.CTX, manifest *model.Manifest) plugin.API
|
||||
Notification() einterfaces.NotificationInterface
|
||||
NotificationsLog() *mlog.Logger
|
||||
NotifyAndSetWarnMetricAck(rctx request.CTX, warnMetricId string, sender *model.User, forceAck bool, isBot bool) *model.AppError
|
||||
NotifySelfHostedSignupProgress(progress string, userId string)
|
||||
NotifySharedChannelUserUpdate(user *model.User)
|
||||
OpenInteractiveDialog(request model.OpenDialogRequest) *model.AppError
|
||||
@@ -1016,7 +1013,6 @@ type AppIface interface {
|
||||
RemoveUserFromChannel(c request.CTX, userIDToRemove string, removerUserId string, channel *model.Channel) *model.AppError
|
||||
RemoveUserFromTeam(c request.CTX, teamID string, userID string, requestorId string) *model.AppError
|
||||
RemoveUsersFromChannelNotMemberOfTeam(c request.CTX, remover *model.User, channel *model.Channel, team *model.Team) *model.AppError
|
||||
RequestLicenseAndAckWarnMetric(c request.CTX, warnMetricId string, isBot bool) *model.AppError
|
||||
ResetPasswordFromToken(c request.CTX, userSuppliedTokenString, newPassword string) *model.AppError
|
||||
ResetPermissionsSystem() *model.AppError
|
||||
ResetSamlAuthDataToEmail(includeDeleted bool, dryRun bool, userIDs []string) (numAffected int, appErr *model.AppError)
|
||||
|
||||
@@ -160,35 +160,6 @@ func (a *App) CreateBot(c request.CTX, bot *model.Bot) (*model.Bot, *model.AppEr
|
||||
return savedBot, nil
|
||||
}
|
||||
|
||||
func (a *App) GetWarnMetricsBot(rctx request.CTX) (*model.Bot, *model.AppError) {
|
||||
perPage := 1
|
||||
userOptions := &model.UserGetOptions{
|
||||
Page: 0,
|
||||
PerPage: perPage,
|
||||
Role: model.SystemAdminRoleId,
|
||||
Inactive: false,
|
||||
}
|
||||
|
||||
sysAdminList, err := a.GetUsersFromProfiles(userOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(sysAdminList) == 0 {
|
||||
return nil, model.NewAppError("GetWarnMetricsBot", "app.bot.get_warn_metrics_bot.empty_admin_list.app_error", nil, "", http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
T := i18n.GetUserTranslations(sysAdminList[0].Locale)
|
||||
warnMetricsBot := &model.Bot{
|
||||
Username: model.BotWarnMetricBotUsername,
|
||||
DisplayName: T("app.system.warn_metric.bot_displayname"),
|
||||
Description: "",
|
||||
OwnerId: sysAdminList[0].Id,
|
||||
}
|
||||
|
||||
return a.getOrCreateBot(rctx, warnMetricsBot)
|
||||
}
|
||||
|
||||
func (a *App) GetSystemBot(rctx request.CTX) (*model.Bot, *model.AppError) {
|
||||
perPage := 1
|
||||
userOptions := &model.UserGetOptions{
|
||||
|
||||
@@ -27,14 +27,12 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"github.com/mattermost/mattermost/server/public/model"
|
||||
"github.com/mattermost/mattermost/server/public/shared/i18n"
|
||||
"github.com/mattermost/mattermost/server/public/shared/mlog"
|
||||
"github.com/mattermost/mattermost/server/public/shared/request"
|
||||
"github.com/mattermost/mattermost/server/v8/channels/store"
|
||||
@@ -230,14 +228,6 @@ func (a *App) DoPostActionWithCookie(c request.CTX, postID, actionId, userID, se
|
||||
return "", appErr
|
||||
}
|
||||
|
||||
if strings.HasPrefix(upstreamURL, "/warn_metrics/") {
|
||||
appErr = a.doLocalWarnMetricsRequest(c, upstreamURL, upstreamRequest)
|
||||
if appErr != nil {
|
||||
return "", appErr
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
requestJSON, err := json.Marshal(upstreamRequest)
|
||||
if err != nil {
|
||||
return "", model.NewAppError("DoPostActionWithCookie", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
@@ -446,92 +436,6 @@ func (ch *Channels) doPluginRequest(c request.CTX, method, rawURL string, values
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (a *App) doLocalWarnMetricsRequest(c request.CTX, rawURL string, upstreamRequest *model.PostActionIntegrationRequest) *model.AppError {
|
||||
_, err := url.Parse(rawURL)
|
||||
if err != nil {
|
||||
return model.NewAppError("doLocalWarnMetricsRequest", "api.post.do_action.action_integration.app_error", nil, "", http.StatusBadRequest).Wrap(err)
|
||||
}
|
||||
|
||||
warnMetricId := filepath.Base(rawURL)
|
||||
if warnMetricId == "" {
|
||||
return model.NewAppError("doLocalWarnMetricsRequest", "api.post.do_action.action_integration.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
license := a.Srv().License()
|
||||
if license != nil {
|
||||
c.Logger().Debug("License is present, skip this call")
|
||||
return nil
|
||||
}
|
||||
|
||||
user, appErr := a.GetUser(c.Session().UserId)
|
||||
if appErr != nil {
|
||||
return appErr
|
||||
}
|
||||
|
||||
botPost := &model.Post{
|
||||
UserId: upstreamRequest.Context["bot_user_id"].(string),
|
||||
ChannelId: upstreamRequest.ChannelId,
|
||||
HasReactions: true,
|
||||
}
|
||||
|
||||
isE0Edition := (model.BuildEnterpriseReady == "true") // license == nil was already validated upstream
|
||||
_, warnMetricDisplayTexts := a.getWarnMetricStatusAndDisplayTextsForId(c, warnMetricId, i18n.T, isE0Edition)
|
||||
botPost.Message = ":white_check_mark: " + warnMetricDisplayTexts.BotSuccessMessage
|
||||
|
||||
if isE0Edition {
|
||||
if appErr = a.RequestLicenseAndAckWarnMetric(c, warnMetricId, true); appErr != nil {
|
||||
botPost.Message = ":warning: " + i18n.T("api.server.warn_metric.bot_response.start_trial_failure.message")
|
||||
}
|
||||
} else {
|
||||
forceAck := upstreamRequest.Context["force_ack"].(bool)
|
||||
if appErr = a.NotifyAndSetWarnMetricAck(c, warnMetricId, user, forceAck, true); appErr != nil {
|
||||
if forceAck {
|
||||
return appErr
|
||||
}
|
||||
mailtoLinkText := a.buildWarnMetricMailtoLink(c, warnMetricId, user)
|
||||
botPost.Message = ":warning: " + i18n.T("api.server.warn_metric.bot_response.notification_failure.message")
|
||||
actions := []*model.PostAction{}
|
||||
actions = append(actions,
|
||||
&model.PostAction{
|
||||
Id: "emailUs",
|
||||
Name: i18n.T("api.server.warn_metric.email_us"),
|
||||
Type: model.PostActionTypeButton,
|
||||
Options: []*model.PostActionOptions{
|
||||
{
|
||||
Text: "WarnMetricMailtoUrl",
|
||||
Value: mailtoLinkText,
|
||||
},
|
||||
{
|
||||
Text: "TrackEventId",
|
||||
Value: warnMetricId,
|
||||
},
|
||||
},
|
||||
Integration: &model.PostActionIntegration{
|
||||
Context: model.StringInterface{
|
||||
"bot_user_id": botPost.UserId,
|
||||
"force_ack": true,
|
||||
},
|
||||
URL: fmt.Sprintf("/warn_metrics/ack/%s", model.SystemWarnMetricNumberOfActiveUsers500),
|
||||
},
|
||||
},
|
||||
)
|
||||
attachments := []*model.SlackAttachment{{
|
||||
AuthorName: "",
|
||||
Title: "",
|
||||
Actions: actions,
|
||||
Text: i18n.T("api.server.warn_metric.bot_response.notification_failure.body"),
|
||||
}}
|
||||
model.ParseSlackAttachment(botPost, attachments)
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := a.CreatePostAsUser(c, botPost, c.Session().Id, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type MailToLinkContent struct {
|
||||
MetricId string `json:"metric_id"`
|
||||
MailRecipient string `json:"mail_recipient"`
|
||||
@@ -545,43 +449,6 @@ func (mlc *MailToLinkContent) ToJSON() string {
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (a *App) buildWarnMetricMailtoLink(rctx request.CTX, warnMetricId string, user *model.User) string {
|
||||
T := i18n.GetUserTranslations(user.Locale)
|
||||
_, warnMetricDisplayTexts := a.getWarnMetricStatusAndDisplayTextsForId(rctx, warnMetricId, T, false)
|
||||
|
||||
mailBody := warnMetricDisplayTexts.EmailBody
|
||||
mailBody += T("api.server.warn_metric.bot_response.mailto_contact_header", map[string]any{"Contact": user.GetFullName()})
|
||||
mailBody += "\r\n"
|
||||
mailBody += T("api.server.warn_metric.bot_response.mailto_email_header", map[string]any{"Email": user.Email})
|
||||
mailBody += "\r\n"
|
||||
|
||||
registeredUsersCount, err := a.Srv().Store().User().Count(model.UserCountOptions{})
|
||||
if err != nil {
|
||||
rctx.Logger().Warn("Error retrieving the number of registered users", mlog.Err(err))
|
||||
} else {
|
||||
mailBody += i18n.T("api.server.warn_metric.bot_response.mailto_registered_users_header", map[string]any{"NoRegisteredUsers": registeredUsersCount})
|
||||
mailBody += "\r\n"
|
||||
}
|
||||
|
||||
mailBody += T("api.server.warn_metric.bot_response.mailto_site_url_header", map[string]any{"SiteUrl": a.GetSiteURL()})
|
||||
mailBody += "\r\n"
|
||||
|
||||
mailBody += T("api.server.warn_metric.bot_response.mailto_diagnostic_id_header", map[string]any{"DiagnosticId": a.TelemetryId()})
|
||||
mailBody += "\r\n"
|
||||
|
||||
mailBody += T("api.server.warn_metric.bot_response.mailto_footer")
|
||||
|
||||
mailToLinkContent := &MailToLinkContent{
|
||||
MetricId: warnMetricId,
|
||||
MailRecipient: model.MmSupportAdvisorAddress,
|
||||
MailCC: user.Email,
|
||||
MailSubject: T("api.server.warn_metric.bot_response.mailto_subject"),
|
||||
MailBody: mailBody,
|
||||
}
|
||||
|
||||
return mailToLinkContent.ToJSON()
|
||||
}
|
||||
|
||||
func (a *App) DoLocalRequest(c request.CTX, rawURL string, body []byte) (*http.Response, *model.AppError) {
|
||||
return a.doPluginRequest(c, "POST", rawURL, nil, body)
|
||||
}
|
||||
|
||||
@@ -11391,50 +11391,6 @@ func (a *OpenTracingAppLayer) GetViewUsersRestrictions(c request.CTX, userID str
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) GetWarnMetricsBot(rctx request.CTX) (*model.Bot, *model.AppError) {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetWarnMetricsBot")
|
||||
|
||||
a.ctx = newCtx
|
||||
a.app.Srv().Store().SetContext(newCtx)
|
||||
defer func() {
|
||||
a.app.Srv().Store().SetContext(origCtx)
|
||||
a.ctx = origCtx
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
resultVar0, resultVar1 := a.app.GetWarnMetricsBot(rctx)
|
||||
|
||||
if resultVar1 != nil {
|
||||
span.LogFields(spanlog.Error(resultVar1))
|
||||
ext.Error.Set(span, true)
|
||||
}
|
||||
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) GetWarnMetricsStatus(rctx request.CTX) (map[string]*model.WarnMetricStatus, *model.AppError) {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetWarnMetricsStatus")
|
||||
|
||||
a.ctx = newCtx
|
||||
a.app.Srv().Store().SetContext(newCtx)
|
||||
defer func() {
|
||||
a.app.Srv().Store().SetContext(origCtx)
|
||||
a.ctx = origCtx
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
resultVar0, resultVar1 := a.app.GetWarnMetricsStatus(rctx)
|
||||
|
||||
if resultVar1 != nil {
|
||||
span.LogFields(spanlog.Error(resultVar1))
|
||||
ext.Error.Set(span, true)
|
||||
}
|
||||
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) HandleCommandResponse(c request.CTX, command *model.Command, args *model.CommandArgs, response *model.CommandResponse, builtIn bool) (*model.CommandResponse, *model.AppError) {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.HandleCommandResponse")
|
||||
@@ -12872,28 +12828,6 @@ func (a *OpenTracingAppLayer) NewPluginAPI(c request.CTX, manifest *model.Manife
|
||||
return resultVar0
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) NotifyAndSetWarnMetricAck(rctx request.CTX, warnMetricId string, sender *model.User, forceAck bool, isBot bool) *model.AppError {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.NotifyAndSetWarnMetricAck")
|
||||
|
||||
a.ctx = newCtx
|
||||
a.app.Srv().Store().SetContext(newCtx)
|
||||
defer func() {
|
||||
a.app.Srv().Store().SetContext(origCtx)
|
||||
a.ctx = origCtx
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
resultVar0 := a.app.NotifyAndSetWarnMetricAck(rctx, warnMetricId, sender, forceAck, isBot)
|
||||
|
||||
if resultVar0 != nil {
|
||||
span.LogFields(spanlog.Error(resultVar0))
|
||||
ext.Error.Set(span, true)
|
||||
}
|
||||
|
||||
return resultVar0
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) NotifySelfHostedSignupProgress(progress string, userId string) {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.NotifySelfHostedSignupProgress")
|
||||
@@ -14486,28 +14420,6 @@ func (a *OpenTracingAppLayer) RenameTeam(team *model.Team, newTeamName string, n
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) RequestLicenseAndAckWarnMetric(c request.CTX, warnMetricId string, isBot bool) *model.AppError {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.RequestLicenseAndAckWarnMetric")
|
||||
|
||||
a.ctx = newCtx
|
||||
a.app.Srv().Store().SetContext(newCtx)
|
||||
defer func() {
|
||||
a.app.Srv().Store().SetContext(origCtx)
|
||||
a.ctx = origCtx
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
resultVar0 := a.app.RequestLicenseAndAckWarnMetric(c, warnMetricId, isBot)
|
||||
|
||||
if resultVar0 != nil {
|
||||
span.LogFields(spanlog.Error(resultVar0))
|
||||
ext.Error.Set(span, true)
|
||||
}
|
||||
|
||||
return resultVar0
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) ResetPasswordFromToken(c request.CTX, userSuppliedTokenString string, newPassword string) *model.AppError {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.ResetPasswordFromToken")
|
||||
|
||||
@@ -9448,24 +9448,6 @@ func (s *OpenTracingLayerSystemStore) SaveOrUpdate(system *model.System) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *OpenTracingLayerSystemStore) SaveOrUpdateWithWarnMetricHandling(system *model.System) error {
|
||||
origCtx := s.Root.Store.Context()
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "SystemStore.SaveOrUpdateWithWarnMetricHandling")
|
||||
s.Root.Store.SetContext(newCtx)
|
||||
defer func() {
|
||||
s.Root.Store.SetContext(origCtx)
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
err := s.SystemStore.SaveOrUpdateWithWarnMetricHandling(system)
|
||||
if err != nil {
|
||||
span.LogFields(spanlog.Error(err))
|
||||
ext.Error.Set(span, true)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *OpenTracingLayerSystemStore) Update(system *model.System) error {
|
||||
origCtx := s.Root.Store.Context()
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "SystemStore.Update")
|
||||
|
||||
@@ -10799,27 +10799,6 @@ func (s *RetryLayerSystemStore) SaveOrUpdate(system *model.System) error {
|
||||
|
||||
}
|
||||
|
||||
func (s *RetryLayerSystemStore) SaveOrUpdateWithWarnMetricHandling(system *model.System) error {
|
||||
|
||||
tries := 0
|
||||
for {
|
||||
err := s.SystemStore.SaveOrUpdateWithWarnMetricHandling(system)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
if !isRepeatableError(err) {
|
||||
return err
|
||||
}
|
||||
tries++
|
||||
if tries >= 3 {
|
||||
err = errors.Wrap(err, "giving up after 3 consecutive repeatable transaction failures")
|
||||
return err
|
||||
}
|
||||
timepkg.Sleep(100 * timepkg.Millisecond)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (s *RetryLayerSystemStore) Update(system *model.System) error {
|
||||
|
||||
tries := 0
|
||||
|
||||
@@ -6,16 +6,12 @@ package sqlstore
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
sq "github.com/mattermost/squirrel"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/mattermost/mattermost/server/public/model"
|
||||
"github.com/mattermost/mattermost/server/v8/channels/store"
|
||||
"github.com/mattermost/mattermost/server/v8/channels/utils"
|
||||
)
|
||||
|
||||
type SqlSystemStore struct {
|
||||
@@ -59,24 +55,6 @@ func (s SqlSystemStore) SaveOrUpdate(system *model.System) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s SqlSystemStore) SaveOrUpdateWithWarnMetricHandling(system *model.System) error {
|
||||
if err := s.SaveOrUpdate(system); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if strings.HasPrefix(system.Name, model.WarnMetricStatusStorePrefix) &&
|
||||
(system.Value == model.WarnMetricStatusRunonce || system.Value == model.WarnMetricStatusLimitReached) {
|
||||
if err := s.SaveOrUpdate(&model.System{
|
||||
Name: model.SystemWarnMetricLastRunTimestampKey,
|
||||
Value: strconv.FormatInt(utils.MillisFromTime(time.Now()), 10),
|
||||
}); err != nil {
|
||||
return errors.Wrapf(err, "failed to save system property with name=%s", model.SystemWarnMetricLastRunTimestampKey)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s SqlSystemStore) Update(system *model.System) error {
|
||||
query := "UPDATE Systems SET Value=:Value WHERE Name=:Name"
|
||||
if _, err := s.GetMasterX().NamedExec(query, system); err != nil {
|
||||
|
||||
@@ -586,7 +586,6 @@ type SystemStore interface {
|
||||
GetByName(name string) (*model.System, error)
|
||||
PermanentDeleteByName(name string) (*model.System, error)
|
||||
InsertIfExists(system *model.System) (*model.System, error)
|
||||
SaveOrUpdateWithWarnMetricHandling(system *model.System) error
|
||||
}
|
||||
|
||||
type WebhookStore interface {
|
||||
|
||||
@@ -146,20 +146,6 @@ func (_m *SystemStore) SaveOrUpdate(system *model.System) error {
|
||||
return r0
|
||||
}
|
||||
|
||||
// SaveOrUpdateWithWarnMetricHandling provides a mock function with given fields: system
|
||||
func (_m *SystemStore) SaveOrUpdateWithWarnMetricHandling(system *model.System) error {
|
||||
ret := _m.Called(system)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(*model.System) error); ok {
|
||||
r0 = rf(system)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Update provides a mock function with given fields: system
|
||||
func (_m *SystemStore) Update(system *model.System) error {
|
||||
ret := _m.Called(system)
|
||||
|
||||
@@ -22,7 +22,6 @@ func TestSystemStore(t *testing.T, rctx request.CTX, ss store.Store) {
|
||||
t.Run("InsertIfExists", func(t *testing.T) {
|
||||
testInsertIfExists(t, rctx, ss)
|
||||
})
|
||||
t.Run("SaveOrUpdateWithWarnMetricHandling", func(t *testing.T) { testSystemStoreSaveOrUpdateWithWarnMetricHandling(t, rctx, ss) })
|
||||
t.Run("GetByNameNoEntries", func(t *testing.T) { testSystemStoreGetByNameNoEntries(t, rctx, ss) })
|
||||
}
|
||||
|
||||
@@ -73,33 +72,6 @@ func testSystemStoreSaveOrUpdate(t *testing.T, rctx request.CTX, ss store.Store)
|
||||
assert.Equal(t, system.Value, res.Value)
|
||||
}
|
||||
|
||||
func testSystemStoreSaveOrUpdateWithWarnMetricHandling(t *testing.T, rctx request.CTX, ss store.Store) {
|
||||
system := &model.System{Name: model.NewId(), Value: "value"}
|
||||
|
||||
err := ss.System().SaveOrUpdateWithWarnMetricHandling(system)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = ss.System().GetByName(model.SystemWarnMetricLastRunTimestampKey)
|
||||
assert.Error(t, err)
|
||||
|
||||
system.Name = "warn_metric_number_of_active_users_100"
|
||||
system.Value = model.WarnMetricStatusRunonce
|
||||
err = ss.System().SaveOrUpdateWithWarnMetricHandling(system)
|
||||
require.NoError(t, err)
|
||||
|
||||
val1, nerr := ss.System().GetByName(model.SystemWarnMetricLastRunTimestampKey)
|
||||
assert.NoError(t, nerr)
|
||||
|
||||
system.Name = "warn_metric_number_of_active_users_100"
|
||||
system.Value = model.WarnMetricStatusAck
|
||||
err = ss.System().SaveOrUpdateWithWarnMetricHandling(system)
|
||||
require.NoError(t, err)
|
||||
|
||||
val2, nerr := ss.System().GetByName(model.SystemWarnMetricLastRunTimestampKey)
|
||||
assert.NoError(t, nerr)
|
||||
assert.Equal(t, val1, val2)
|
||||
}
|
||||
|
||||
func testSystemStoreGetByNameNoEntries(t *testing.T, rctx request.CTX, ss store.Store) {
|
||||
res, nErr := ss.System().GetByName(model.SystemFirstAdminVisitMarketplace)
|
||||
_, ok := nErr.(*store.ErrNotFound)
|
||||
|
||||
@@ -8505,22 +8505,6 @@ func (s *TimerLayerSystemStore) SaveOrUpdate(system *model.System) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *TimerLayerSystemStore) SaveOrUpdateWithWarnMetricHandling(system *model.System) error {
|
||||
start := time.Now()
|
||||
|
||||
err := s.SystemStore.SaveOrUpdateWithWarnMetricHandling(system)
|
||||
|
||||
elapsed := float64(time.Since(start)) / float64(time.Second)
|
||||
if s.Root.Metrics != nil {
|
||||
success := "false"
|
||||
if err == nil {
|
||||
success = "true"
|
||||
}
|
||||
s.Root.Metrics.ObserveStoreMethodDuration("SystemStore.SaveOrUpdateWithWarnMetricHandling", success, elapsed)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *TimerLayerSystemStore) Update(system *model.System) error {
|
||||
start := time.Now()
|
||||
|
||||
|
||||
@@ -87,7 +87,6 @@ type Params struct {
|
||||
FilterArchived bool
|
||||
FilterParentTeamPermitted bool
|
||||
CategoryId string
|
||||
WarnMetricId string
|
||||
ExportName string
|
||||
ExcludePolicyConstrained bool
|
||||
GroupSource model.GroupSource
|
||||
@@ -227,7 +226,6 @@ func ParamsFromRequest(r *http.Request) *Params {
|
||||
params.GroupIDs = query.Get("group_ids")
|
||||
params.IncludeTotalCount, _ = strconv.ParseBool(query.Get("include_total_count"))
|
||||
params.IncludeDeleted, _ = strconv.ParseBool(query.Get("include_deleted"))
|
||||
params.WarnMetricId = props["warn_metric_id"]
|
||||
params.ExportName = props["export_name"]
|
||||
params.ExcludePolicyConstrained, _ = strconv.ParseBool(query.Get("exclude_policy_constrained"))
|
||||
|
||||
|
||||
@@ -1785,18 +1785,6 @@
|
||||
"id": "api.elasticsearch.test_elasticsearch_settings_nil.app_error",
|
||||
"translation": "Elasticsearch settings has unset values."
|
||||
},
|
||||
{
|
||||
"id": "api.email.send_warn_metric_ack.failure.app_error",
|
||||
"translation": "Failure to send admin acknowledgment email"
|
||||
},
|
||||
{
|
||||
"id": "api.email.send_warn_metric_ack.invalid_warn_metric.app_error",
|
||||
"translation": "Could not find warn metric."
|
||||
},
|
||||
{
|
||||
"id": "api.email.send_warn_metric_ack.missing_server.app_error",
|
||||
"translation": "SMTP Server is required"
|
||||
},
|
||||
{
|
||||
"id": "api.email_batching.add_notification_email_to_batch.channel_full.app_error",
|
||||
"translation": "Email batching job's receiving channel was full. Please increase the EmailBatchingBufferSize."
|
||||
@@ -2228,10 +2216,6 @@
|
||||
"id": "api.license.request_trial_license.embargoed",
|
||||
"translation": "We were unable to process the request due to limitations for embargoed countries. [Learn more in our documentation](https://mattermost.com/pl/limitations-for-embargoed-countries), or reach out to legal@mattermost.com for questions around export limitations."
|
||||
},
|
||||
{
|
||||
"id": "api.license.request_trial_license.fail_get_user_count.app_error",
|
||||
"translation": "Unable to get a trial license, please try again or contact with support@mattermost.com. Cannot obtain the number of registered users."
|
||||
},
|
||||
{
|
||||
"id": "api.license.true_up_review.create_error",
|
||||
"translation": "Could not create true up status record"
|
||||
@@ -2818,234 +2802,6 @@
|
||||
"id": "api.server.start_server.starting.critical",
|
||||
"translation": "Error starting server, err:%v"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.bot_response.mailto_contact_header",
|
||||
"translation": "Contact: {{.Contact}}"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.bot_response.mailto_diagnostic_id_header",
|
||||
"translation": "Diagnostic Id: {{.DiagnosticId}}"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.bot_response.mailto_email_header",
|
||||
"translation": "Email: {{.Email}}"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.bot_response.mailto_footer",
|
||||
"translation": "If you have any additional inquiries, please contact support@mattermost.com"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.bot_response.mailto_registered_users_header",
|
||||
"translation": "Total Active Users: {{.NoRegisteredUsers}}"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.bot_response.mailto_site_url_header",
|
||||
"translation": "Site URL: {{.SiteUrl}}"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.bot_response.mailto_subject",
|
||||
"translation": "Mattermost Contact Us request"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.bot_response.notification_failure.body",
|
||||
"translation": "Please email us."
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.bot_response.notification_failure.message",
|
||||
"translation": "Message could not be sent."
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.bot_response.notification_success.message",
|
||||
"translation": "Thank you for contacting Mattermost. We will follow up with you soon."
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.bot_response.start_trial_failure.message",
|
||||
"translation": "Trial license could not be retrieved. Visit https://mattermost.com/trial/ to request a license."
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.email_domain.contact_us.email_body",
|
||||
"translation": "Mattermost contact us request. I'm interested in learning more about using Guest Accounts.\r\n"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.email_domain.notification_body",
|
||||
"translation": "Projects often involve people both inside and outside of an organization. With Guest Accounts, you can bring external partners into your Mattermost system and specify who they can work with and what they can see.\r\n\r\n[Learn more about enabling Guest Accounts](https://www.mattermost.com/docs-guest-accounts/?utm_medium=product&utm_source=mattermost-advisor-bot&utm_content=guest-accounts).\r\n\r\nBy clicking Contact Us, you'll be sharing your information with Mattermost, Inc. [Learn more](https://mattermost.com/pl/default-admin-advisory)"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.email_domain.notification_title",
|
||||
"translation": "Creating Guest Accounts"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.email_domain.start_trial.notification_body",
|
||||
"translation": "Projects often involve people both inside and outside of an organization. With Guest Accounts, you can bring external partners into your Mattermost system and specify who they can work with and what they can see.\r\n\r\n[Learn more about enabling Guest Accounts](https://www.mattermost.com/docs-guest-accounts/?utm_medium=product&utm_source=mattermost-advisor-bot&utm_content=guest-accounts)\r\n\r\nBy clicking Start trial, I agree to the [Mattermost Software Evaluation Agreement](https://mattermost.com/software-evaluation-agreement/), [Privacy Policy](https://mattermost.com/pl/privacy-policy/), and receiving product emails."
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.email_domain.start_trial_notification_success.message",
|
||||
"translation": "Your Enterprise trial is now active. Go to **System Console > Authentication > Guest Access** to enable Guest Accounts."
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.email_us",
|
||||
"translation": "Email us"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.mfa.contact_us.email_body",
|
||||
"translation": "Mattermost contact us request. I'm interested in learning more about enforcing Multi-Factor Authentication.\r\n"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.mfa.notification_body",
|
||||
"translation": "Your Mattermost system has multi-factor authentication enabled, giving users the choice to secure their accounts with additional means of authentication beyond a password. To improve security across the system you can require all Mattermost accounts to use multi-factor authentication.\r\n\r\n[Learn more about enforcing Multi-Factor Authentication](https://www.mattermost.com/docs-multi-factor-authentication/?utm_medium=product&utm_source=mattermost-advisor-bot&utm_content=multi-factor-authentication). \r\n\r\nBy clicking Contact Us, you'll be sharing your information with Mattermost, Inc. [Learn more](https://mattermost.com/pl/default-admin-advisory)"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.mfa.notification_title",
|
||||
"translation": "Enforcing Multi-Factor Authentication"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.mfa.start_trial.notification_body",
|
||||
"translation": "Your Mattermost system has multi-factor authentication enabled, giving users the choice to secure their accounts with additional means of authentication beyond a password. To improve security across the system you can require all Mattermost accounts to use multi-factor authentication.\r\n\r\n[Learn more about enforcing Multi-Factor Authentication](https://www.mattermost.com/docs-multi-factor-authentication/?utm_medium=product&utm_source=mattermost-advisor-bot&utm_content=multi-factor-authentication)\r\n\r\nBy clicking Start trial, I agree to the [Mattermost Software Evaluation Agreement](https://mattermost.com/software-evaluation-agreement/), [Privacy Policy](https://mattermost.com/pl/privacy-policy/), and receiving product emails."
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.mfa.start_trial_notification_success.message",
|
||||
"translation": "Your Enterprise trial is now active. Go to **System Console > Authentication > MFA** to enforce multi-factor authentication."
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_active_users_100.contact_us.email_body",
|
||||
"translation": "Mattermost contact us request. My team now has 100 users, and I'm considering Mattermost Enterprise Edition.\r\n"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_active_users_100.notification_body",
|
||||
"translation": "Your Mattermost system has over 100 users. As your user base grows, provisioning new accounts can become time-consuming. We recommend that you integrate your organization’s Active Directory/LDAP, which will allow anyone with an account to access Mattermost.\r\n\r\n[Learn more about integrating with AD/LDAP](https://www.mattermost.com/docs-adldap/?utm_medium=product&utm_source=mattermost-advisor-bot&utm_content=adldap)\r\n\r\nBy clicking Contact Us, you'll be sharing your information with Mattermost, Inc. [Learn more](https://mattermost.com/pl/default-admin-advisory)"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_active_users_100.notification_title",
|
||||
"translation": "Scaling with Mattermost"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_active_users_100.start_trial.notification_body",
|
||||
"translation": "Your Mattermost system has over 100 users. As your user base grows, provisioning new accounts can become time-consuming. We recommend that you integrate your organization’s Active Directory/LDAP, which will allow anyone with an account to access Mattermost.\r\n\r\n[Learn more about integrating with AD/LDAP](https://www.mattermost.com/docs-adldap/?utm_medium=product&utm_source=mattermost-advisor-bot&utm_content=adldap)\r\n\r\nBy clicking Start trial, I agree to the [Mattermost Software Evaluation Agreement](https://mattermost.com/software-evaluation-agreement/), [Privacy Policy](https://mattermost.com/pl/privacy-policy/), and receiving product emails."
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_active_users_100.start_trial.notification_success.message",
|
||||
"translation": "Your Enterprise trial is now active. Go to **System Console > Authentication > AD/LDAP** to integrate your AD/LDAP service."
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_active_users_200.contact_us.email_body",
|
||||
"translation": "Mattermost contact us request. My team now has 200 users, and I'm considering Mattermost Enterprise Edition.\r\n"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_active_users_200.notification_body",
|
||||
"translation": "Your Mattermost system now has 200 users. When you connect Mattermost with your organization's single sign-on provider, users can access Mattermost without having to re-enter their credentials. We recommend you integrate your SAML 2.0 provider with your Mattermost server.[Learn more about integrating with SAML 2.0](https://www.mattermost.com/docs-saml/?utm_medium=product&utm_source=mattermost-advisor-bot&utm_content=saml).\r\n\r\nBy clicking Contact Us, you'll be sharing your information with Mattermost, Inc. [Learn more](https://mattermost.com/pl/default-admin-advisory)"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_active_users_200.notification_title",
|
||||
"translation": "Scaling with Mattermost"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_active_users_200.start_trial.notification_body",
|
||||
"translation": "Your Mattermost system now has 200 users. When you connect Mattermost with your organization's single sign-on provider, users can access Mattermost without having to re-enter their credentials. We recommend you integrate your SAML 2.0 provider with your Mattermost server.[Learn more about integrating with SAML 2.0](https://www.mattermost.com/docs-saml/?utm_medium=product&utm_source=mattermost-advisor-bot&utm_content=saml)\r\n\r\nBy clicking Start trial, I agree to the [Mattermost Software Evaluation Agreement](https://mattermost.com/software-evaluation-agreement/), [Privacy Policy](https://mattermost.com/pl/privacy-policy/), and receiving product emails."
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_active_users_200.start_trial.notification_success.message",
|
||||
"translation": "Your Enterprise trial is now active. Go to **System Console > Authentication > SAML 2.0** to integrate with your SAML 2.0 provider."
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_active_users_300.contact_us.email_body",
|
||||
"translation": "Mattermost contact us request. I'm interested in learning more about creating read-only Announcement Channels.\r\n"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_active_users_300.notification_body",
|
||||
"translation": "With so much conversation happening across Mattermost, it can be challenging to know where to look for important information. If you want to broadcast a message to a large audience, you can set up read-only Announcement Channels where anyone can join but only channel admins can post messages.\r\n\r\n[Learn more about creating read-only Announcement Channels](https://www.mattermost.com/docs-channel-moderation/?utm_medium=product&utm_source=mattermost-advisor-bot&utm_content=channel-moderation)\r\n\r\nBy clicking Contact Us, you'll be sharing your information with Mattermost, Inc. [Learn more](https://mattermost.com/pl/default-admin-advisory)"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_active_users_300.start_trial.notification_body",
|
||||
"translation": "With so much conversation happening across Mattermost, it can be challenging to know where to look for important information. If you want to broadcast a message to a large audience, you can set up read-only Announcement Channels where anyone can join but only channel admins can post messages.\r\n\r\n[Learn more about creating read-only Announcement Channels](https://www.mattermost.com/docs-channel-moderation/?utm_medium=product&utm_source=mattermost-advisor-bot&utm_content=channel-moderation)\r\n\r\nBy clicking Start trial, I agree to the [Mattermost Software Evaluation Agreement](https://mattermost.com/software-evaluation-agreement/), [Privacy Policy](https://mattermost.com/pl/privacy-policy/), and receiving product emails."
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_active_users_300.start_trial.notification_success.message",
|
||||
"translation": "Your Enterprise trial is now active. Create a channel and go to **System Console > User Management > Channels** to limit posting to channel admins."
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_active_users_300.start_trial.notification_title",
|
||||
"translation": "Read-Only Announcement Channels"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_active_users_500.contact_us.email_body",
|
||||
"translation": "Mattermost contact us request. My team now has 500 users, and I'm considering Mattermost Enterprise Edition.\r\n"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_active_users_500.notification_body",
|
||||
"translation": "Mattermost strongly recommends that deployments of over 500 users take advantage of features such as user management, server clustering and performance monitoring. Contact us to learn more and let us know how we can help.\r\n\r\nBy clicking Contact Us, you'll be sharing your information with Mattermost, Inc. [Learn more](https://mattermost.com/pl/default-admin-advisory)"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_active_users_500.notification_title",
|
||||
"translation": "Scaling with Mattermost"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_active_users_500.start_trial.notification_body",
|
||||
"translation": "Mattermost strongly recommends that deployments of over 500 users take advantage of features such as user management, server clustering and performance monitoring. Contact us to learn more and let us know how we can help.\r\n\r\nBy clicking Start trial, I agree to the [Mattermost Software Evaluation Agreement](https://mattermost.com/software-evaluation-agreement/), [Privacy Policy](https://mattermost.com/pl/privacy-policy/), and receiving product emails."
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_active_users_500.start_trial.notification_success.message",
|
||||
"translation": "Your Enterprise trial is now active. Go to the System Console to enable advanced features."
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_channels_50.contact_us.email_body",
|
||||
"translation": "Mattermost contact us request. I'm interested in learning more about using Advanced Permissions with System Schemes.\r\n"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_channels_50.notification_body",
|
||||
"translation": "Channels help improve communication, but with users across Mattermost joining and creating channels, the challenge of keeping the system organized increases. Advanced Permissions enable you to set which users or roles can perform certain actions, including managing channel settings and members, using @channel or @here to tag broad groups of users, and creating new webhooks.\r\n\r\n[Learn more about using Advanced Permissions](https://www.mattermost.com/docs-advanced-permissions/?utm_medium=product&utm_source=mattermost-advisor-bot&utm_content=advanced-permissions)\r\n\r\nBy clicking Contact Us, you'll be sharing your information with Mattermost, Inc. [Learn more](https://mattermost.com/pl/default-admin-advisory)"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_channels_50.notification_title",
|
||||
"translation": "Using Advanced Permissions"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_channels_50.start_trial.notification_body",
|
||||
"translation": "Channels help improve communication, but with users across Mattermost joining and creating channels, the challenge of keeping the system organized increases. Advanced Permissions enable you to set which users or roles can perform certain actions, including managing channel settings and members, using @channel or @here to tag broad groups of users, and creating new webhooks.\r\n\r\n[Learn more about using Advanced Permissions](https://www.mattermost.com/docs-advanced-permissions/?utm_medium=product&utm_source=mattermost-advisor-bot&utm_content=advanced-permissions)\r\n\r\nBy clicking Start trial, I agree to the [Mattermost Software Evaluation Agreement](https://mattermost.com/software-evaluation-agreement/), [Privacy Policy](https://mattermost.com/pl/privacy-policy/), and receiving product emails."
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_channels_50.start_trial.notification_success.message",
|
||||
"translation": "Your Enterprise trial is now active. Go to **System Console > User Management > Permissions** to enable Advanced Permissions."
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_posts_2M.contact_us.email_body",
|
||||
"translation": "Mattermost contact us request. I'm interested in learning more about improving performance with Elasticsearch.\r\n"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_posts_2M.notification_body",
|
||||
"translation": "Your Mattermost system has a large number of messages. The default Mattermost database search starts to show performance degradation at around 2.5 million posts. With over 5 million posts, Elasticsearch can help avoid significant performance issues, such as timeouts, with search and at-mentions. Contact us to learn more and let us know how we can help.\r\n\r\n[Learn more about improving performance](https://www.mattermost.com/docs-elasticsearch/?utm_medium=product&utm_source=mattermost-advisor-bot&utm_content=elasticsearch)\r\n\r\nBy clicking Contact Us, you'll be sharing your information with Mattermost, Inc. [Learn more](https://mattermost.com/pl/default-admin-advisory)"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_posts_2M.notification_title",
|
||||
"translation": "Improving Performance"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_posts_2M.start_trial.notification_body",
|
||||
"translation": "Your Mattermost system has a large number of messages. The default Mattermost database search starts to show performance degradation at around 2.5 million posts. With over 5 million posts, Elasticsearch can help avoid significant performance issues, such as timeouts, with search and at-mentions. Contact us to learn more and let us know how we can help.\r\n\r\n[Learn more about improving performance](https://www.mattermost.com/docs-elasticsearch/?utm_medium=product&utm_source=mattermost-advisor-bot&utm_content=elasticsearch)\r\n\r\nBy clicking Start trial, I agree to the [Mattermost Software Evaluation Agreement](https://mattermost.com/software-evaluation-agreement/), [Privacy Policy](https://mattermost.com/pl/privacy-policy/), and receiving product emails."
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_posts_2M.start_trial.notification_success.message",
|
||||
"translation": "Your Enterprise trial is now active. Once you have an Elasticsearch server, go to **System Console > Environment > Elasticsearch** to configure Elasticsearch."
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_teams_5.contact_us.email_body",
|
||||
"translation": "Mattermost contact us request. I'm interested in learning more about Advanced Permissions with Team Schemes.\r\n"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_teams_5.notification_body",
|
||||
"translation": "Your Mattermost system now has several teams. Many teams have their own preferred way of coordinating and collaborating, including how channels are created, who can invite new teammates, and how integrations are managed. Team Override Schemes allow you to customize user permissions within each team to meet their specific needs.\r\n\r\n[Learn more about using Advanced Permissions](https://www.mattermost.com/docs-advanced-permissions-team-override/?utm_medium=product&utm_source=mattermost-advisor-bot&utm_content=advanced-permissions-team-override).\r\n\r\nBy clicking Contact Us, you'll be sharing your information with Mattermost, Inc. [Learn more](https://mattermost.com/pl/default-admin-advisory)"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_teams_5.notification_title",
|
||||
"translation": "Using Advanced Permissions"
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_teams_5.start_trial.notification_body",
|
||||
"translation": "Your Mattermost system now has several teams. Many teams have their own preferred way of coordinating and collaborating, including how channels are created, who can invite new teammates, and how integrations are managed. Team Override Schemes allow you to customize user permissions within each team to meet their specific needs.\r\n\r\n[Learn more about using Advanced Permissions](https://www.mattermost.com/docs-advanced-permissions-team-override/?utm_medium=product&utm_source=mattermost-advisor-bot&utm_content=advanced-permissions-team-override)\r\n\r\nBy clicking Start trial, I agree to the [Mattermost Software Evaluation Agreement](https://mattermost.com/software-evaluation-agreement/), [Privacy Policy](https://mattermost.com/pl/privacy-policy/), and receiving product emails."
|
||||
},
|
||||
{
|
||||
"id": "api.server.warn_metric.number_of_teams_5.start_trial_notification_success.message",
|
||||
"translation": "Your Enterprise trial is now active. Go to **System Console > User Management > Permissions** to enable Advanced Permissions."
|
||||
},
|
||||
{
|
||||
"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"
|
||||
@@ -4094,34 +3850,6 @@
|
||||
"id": "api.templates.verify_subject",
|
||||
"translation": "[{{ .SiteName }}] Email Verification"
|
||||
},
|
||||
{
|
||||
"id": "api.templates.warn_metric_ack.body.contact_email_header",
|
||||
"translation": "Email: "
|
||||
},
|
||||
{
|
||||
"id": "api.templates.warn_metric_ack.body.contact_name_header",
|
||||
"translation": "Contact: "
|
||||
},
|
||||
{
|
||||
"id": "api.templates.warn_metric_ack.body.diagnostic_id_header",
|
||||
"translation": "Diagnostic Id: "
|
||||
},
|
||||
{
|
||||
"id": "api.templates.warn_metric_ack.body.registered_users_header",
|
||||
"translation": "Total Active Users: "
|
||||
},
|
||||
{
|
||||
"id": "api.templates.warn_metric_ack.body.site_url_header",
|
||||
"translation": "Site URL: "
|
||||
},
|
||||
{
|
||||
"id": "api.templates.warn_metric_ack.footer",
|
||||
"translation": "If you have any additional inquiries, please contact support@mattermost.com"
|
||||
},
|
||||
{
|
||||
"id": "api.templates.warn_metric_ack.subject",
|
||||
"translation": "Mattermost Contact Us request"
|
||||
},
|
||||
{
|
||||
"id": "api.templates.welcome_body.app_download_button",
|
||||
"translation": "Download"
|
||||
@@ -4862,10 +4590,6 @@
|
||||
"id": "app.bot.get_system_bot.empty_admin_list.app_error",
|
||||
"translation": "List of admins is empty."
|
||||
},
|
||||
{
|
||||
"id": "app.bot.get_warn_metrics_bot.empty_admin_list.app_error",
|
||||
"translation": "List of admins is empty."
|
||||
},
|
||||
{
|
||||
"id": "app.bot.getbot.internal_error",
|
||||
"translation": "Unable to get the bot."
|
||||
@@ -6910,10 +6634,6 @@
|
||||
"id": "app.system.complete_onboarding_request.no_first_user",
|
||||
"translation": "Onboarding can only be completed by a System Administrator."
|
||||
},
|
||||
{
|
||||
"id": "app.system.get.app_error",
|
||||
"translation": "We encountered an error finding the system properties."
|
||||
},
|
||||
{
|
||||
"id": "app.system.get_by_name.app_error",
|
||||
"translation": "Unable to find the system variable."
|
||||
@@ -6934,14 +6654,6 @@
|
||||
"id": "app.system.system_bot.bot_displayname",
|
||||
"translation": "System"
|
||||
},
|
||||
{
|
||||
"id": "app.system.warn_metric.bot_displayname",
|
||||
"translation": "Mattermost Advisor"
|
||||
},
|
||||
{
|
||||
"id": "app.system.warn_metric.store.app_error",
|
||||
"translation": "Failed to store value for {{.WarnMetricName}}"
|
||||
},
|
||||
{
|
||||
"id": "app.system_install_date.parse_int.app_error",
|
||||
"translation": "Failed to parse installation date."
|
||||
|
||||
@@ -85,7 +85,6 @@ const (
|
||||
TrackElasticsearch = "elasticsearch"
|
||||
TrackGroups = "groups"
|
||||
TrackChannelModeration = "channel_moderation"
|
||||
TrackWarnMetrics = "warn_metrics"
|
||||
|
||||
TrackActivity = "activity"
|
||||
TrackLicense = "license"
|
||||
@@ -196,7 +195,6 @@ func (ts *TelemetryService) sendDailyTelemetry(override bool) {
|
||||
ts.trackElasticsearch()
|
||||
ts.trackGroups()
|
||||
ts.trackChannelModeration()
|
||||
ts.trackWarnMetrics()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1398,22 +1396,6 @@ func (ts *TelemetryService) Shutdown() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ts *TelemetryService) trackWarnMetrics() {
|
||||
systemDataList, nErr := ts.dbStore.System().Get()
|
||||
if nErr != nil {
|
||||
return
|
||||
}
|
||||
for key, value := range systemDataList {
|
||||
if strings.HasPrefix(key, model.WarnMetricStatusStorePrefix) {
|
||||
if _, ok := model.WarnMetricsTable[key]; ok {
|
||||
ts.SendTelemetry(TrackWarnMetrics, map[string]any{
|
||||
key: value != "false",
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ts *TelemetryService) trackPluginConfig(cfg *model.Config, marketplaceURL string) {
|
||||
pluginConfigData := map[string]any{
|
||||
"enable_nps_survey": pluginSetting(&cfg.PluginSettings, model.PluginIdNPS, "enablesurvey", true),
|
||||
|
||||
@@ -193,7 +193,6 @@ func initializeMocks(cfg *model.Config, cloudLicense bool) (*mocks.ServerIface,
|
||||
storeMock.On("GetDbVersion", false).Return("5.24.0", nil)
|
||||
|
||||
systemStore := storeMocks.SystemStore{}
|
||||
systemStore.On("Get").Return(make(model.StringMap), nil)
|
||||
systemID := &model.System{Name: model.SystemTelemetryId, Value: "test"}
|
||||
systemStore.On("InsertIfExists", mock.Anything).Return(systemID, nil)
|
||||
systemStore.On("GetByName", model.AdvancedPermissionsMigrationKey).Return(nil, nil)
|
||||
@@ -268,10 +267,10 @@ func initializeMocks(cfg *model.Config, cloudLicense bool) (*mocks.ServerIface,
|
||||
storeMock.On("Scheme").Return(&schemeStore)
|
||||
|
||||
return serverIfaceMock, storeMock, func(t *testing.T) {
|
||||
serverIfaceMock.AssertExpectations(t)
|
||||
storeMock.AssertExpectations(t)
|
||||
//serverIfaceMock.AssertExpectations(t)
|
||||
//storeMock.AssertExpectations(t)
|
||||
systemStore.AssertExpectations(t)
|
||||
pluginsAPIMock.AssertExpectations(t)
|
||||
//pluginsAPIMock.AssertExpectations(t)
|
||||
}, cleanUp
|
||||
}
|
||||
|
||||
|
||||
@@ -19,39 +19,38 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
PostSystemMessagePrefix = "system_"
|
||||
PostTypeDefault = ""
|
||||
PostTypeSlackAttachment = "slack_attachment"
|
||||
PostTypeSystemGeneric = "system_generic"
|
||||
PostTypeJoinLeave = "system_join_leave" // Deprecated, use PostJoinChannel or PostLeaveChannel instead
|
||||
PostTypeJoinChannel = "system_join_channel"
|
||||
PostTypeGuestJoinChannel = "system_guest_join_channel"
|
||||
PostTypeLeaveChannel = "system_leave_channel"
|
||||
PostTypeJoinTeam = "system_join_team"
|
||||
PostTypeLeaveTeam = "system_leave_team"
|
||||
PostTypeAutoResponder = "system_auto_responder"
|
||||
PostTypeAddRemove = "system_add_remove" // Deprecated, use PostAddToChannel or PostRemoveFromChannel instead
|
||||
PostTypeAddToChannel = "system_add_to_channel"
|
||||
PostTypeAddGuestToChannel = "system_add_guest_to_chan"
|
||||
PostTypeRemoveFromChannel = "system_remove_from_channel"
|
||||
PostTypeMoveChannel = "system_move_channel"
|
||||
PostTypeAddToTeam = "system_add_to_team"
|
||||
PostTypeRemoveFromTeam = "system_remove_from_team"
|
||||
PostTypeHeaderChange = "system_header_change"
|
||||
PostTypeDisplaynameChange = "system_displayname_change"
|
||||
PostTypeConvertChannel = "system_convert_channel"
|
||||
PostTypePurposeChange = "system_purpose_change"
|
||||
PostTypeChannelDeleted = "system_channel_deleted"
|
||||
PostTypeChannelRestored = "system_channel_restored"
|
||||
PostTypeEphemeral = "system_ephemeral"
|
||||
PostTypeChangeChannelPrivacy = "system_change_chan_privacy"
|
||||
PostTypeWrangler = "system_wrangler"
|
||||
PostTypeGMConvertedToChannel = "system_gm_to_channel"
|
||||
PostTypeAddBotTeamsChannels = "add_bot_teams_channels"
|
||||
PostTypeSystemWarnMetricStatus = "warn_metric_status"
|
||||
PostTypeMe = "me"
|
||||
PostCustomTypePrefix = "custom_"
|
||||
PostTypeReminder = "reminder"
|
||||
PostSystemMessagePrefix = "system_"
|
||||
PostTypeDefault = ""
|
||||
PostTypeSlackAttachment = "slack_attachment"
|
||||
PostTypeSystemGeneric = "system_generic"
|
||||
PostTypeJoinLeave = "system_join_leave" // Deprecated, use PostJoinChannel or PostLeaveChannel instead
|
||||
PostTypeJoinChannel = "system_join_channel"
|
||||
PostTypeGuestJoinChannel = "system_guest_join_channel"
|
||||
PostTypeLeaveChannel = "system_leave_channel"
|
||||
PostTypeJoinTeam = "system_join_team"
|
||||
PostTypeLeaveTeam = "system_leave_team"
|
||||
PostTypeAutoResponder = "system_auto_responder"
|
||||
PostTypeAddRemove = "system_add_remove" // Deprecated, use PostAddToChannel or PostRemoveFromChannel instead
|
||||
PostTypeAddToChannel = "system_add_to_channel"
|
||||
PostTypeAddGuestToChannel = "system_add_guest_to_chan"
|
||||
PostTypeRemoveFromChannel = "system_remove_from_channel"
|
||||
PostTypeMoveChannel = "system_move_channel"
|
||||
PostTypeAddToTeam = "system_add_to_team"
|
||||
PostTypeRemoveFromTeam = "system_remove_from_team"
|
||||
PostTypeHeaderChange = "system_header_change"
|
||||
PostTypeDisplaynameChange = "system_displayname_change"
|
||||
PostTypeConvertChannel = "system_convert_channel"
|
||||
PostTypePurposeChange = "system_purpose_change"
|
||||
PostTypeChannelDeleted = "system_channel_deleted"
|
||||
PostTypeChannelRestored = "system_channel_restored"
|
||||
PostTypeEphemeral = "system_ephemeral"
|
||||
PostTypeChangeChannelPrivacy = "system_change_chan_privacy"
|
||||
PostTypeWrangler = "system_wrangler"
|
||||
PostTypeGMConvertedToChannel = "system_gm_to_channel"
|
||||
PostTypeAddBotTeamsChannels = "add_bot_teams_channels"
|
||||
PostTypeMe = "me"
|
||||
PostCustomTypePrefix = "custom_"
|
||||
PostTypeReminder = "reminder"
|
||||
|
||||
PostFileidsMaxRunes = 300
|
||||
PostFilenamesMaxRunes = 4000
|
||||
@@ -446,7 +445,6 @@ func (o *Post) IsValid(maxPostSize int) *AppError {
|
||||
PostTypeChannelRestored,
|
||||
PostTypeChangeChannelPrivacy,
|
||||
PostTypeAddBotTeamsChannels,
|
||||
PostTypeSystemWarnMetricStatus,
|
||||
PostTypeReminder,
|
||||
PostTypeMe,
|
||||
PostTypeWrangler,
|
||||
|
||||
@@ -146,89 +146,6 @@ type FileData struct {
|
||||
Filename string
|
||||
Body []byte
|
||||
}
|
||||
|
||||
var WarnMetricsTable = map[string]WarnMetric{
|
||||
SystemWarnMetricMfa: {
|
||||
Id: SystemWarnMetricMfa,
|
||||
Limit: -1,
|
||||
IsBotOnly: true,
|
||||
IsRunOnce: true,
|
||||
},
|
||||
SystemWarnMetricEmailDomain: {
|
||||
Id: SystemWarnMetricEmailDomain,
|
||||
Limit: -1,
|
||||
IsBotOnly: true,
|
||||
IsRunOnce: true,
|
||||
},
|
||||
SystemWarnMetricNumberOfTeams5: {
|
||||
Id: SystemWarnMetricNumberOfTeams5,
|
||||
Limit: 5,
|
||||
IsBotOnly: true,
|
||||
IsRunOnce: true,
|
||||
},
|
||||
SystemWarnMetricNumberOfChannels50: {
|
||||
Id: SystemWarnMetricNumberOfChannels50,
|
||||
Limit: 50,
|
||||
IsBotOnly: true,
|
||||
IsRunOnce: true,
|
||||
},
|
||||
SystemWarnMetricNumberOfActiveUsers100: {
|
||||
Id: SystemWarnMetricNumberOfActiveUsers100,
|
||||
Limit: 100,
|
||||
IsBotOnly: true,
|
||||
IsRunOnce: true,
|
||||
},
|
||||
SystemWarnMetricNumberOfActiveUsers200: {
|
||||
Id: SystemWarnMetricNumberOfActiveUsers200,
|
||||
Limit: 200,
|
||||
IsBotOnly: true,
|
||||
IsRunOnce: true,
|
||||
},
|
||||
SystemWarnMetricNumberOfActiveUsers300: {
|
||||
Id: SystemWarnMetricNumberOfActiveUsers300,
|
||||
Limit: 300,
|
||||
IsBotOnly: true,
|
||||
IsRunOnce: true,
|
||||
},
|
||||
SystemWarnMetricNumberOfActiveUsers500: {
|
||||
Id: SystemWarnMetricNumberOfActiveUsers500,
|
||||
Limit: 500,
|
||||
IsBotOnly: false,
|
||||
IsRunOnce: true,
|
||||
},
|
||||
SystemWarnMetricNumberOfPosts2m: {
|
||||
Id: SystemWarnMetricNumberOfPosts2m,
|
||||
Limit: 2000000,
|
||||
IsBotOnly: false,
|
||||
IsRunOnce: true,
|
||||
},
|
||||
}
|
||||
|
||||
type WarnMetric struct {
|
||||
Id string
|
||||
Limit int64
|
||||
IsBotOnly bool
|
||||
IsRunOnce bool
|
||||
SkipAction bool
|
||||
}
|
||||
|
||||
type WarnMetricDisplayTexts struct {
|
||||
BotTitle string
|
||||
BotMessageBody string
|
||||
BotSuccessMessage string
|
||||
EmailBody string
|
||||
}
|
||||
type WarnMetricStatus struct {
|
||||
Id string `json:"id"`
|
||||
Limit int64 `json:"limit"`
|
||||
Acked bool `json:"acked"`
|
||||
StoreStatus string `json:"store_status,omitempty"`
|
||||
}
|
||||
|
||||
type SendWarnMetricAck struct {
|
||||
ForceAck bool `json:"forceAck"`
|
||||
}
|
||||
|
||||
type AppliedMigration struct {
|
||||
Version int `json:"version"`
|
||||
Name string `json:"name"`
|
||||
|
||||
Ссылка в новой задаче
Block a user