From 27a702e29a69816a92e003d0666c9715a00617bc Mon Sep 17 00:00:00 2001 From: Michel Engelen <32863416+michelengelen@users.noreply.github.com> Date: Mon, 9 Jan 2023 16:50:43 +0100 Subject: [PATCH 01/41] Contribute/wysiwyg (#22020) * add feature flag for WYSIWYG editor * Empty-Commit-test * added missing default value * removed duplicate line * Empty-Commit-test Co-authored-by: Jason Frerich Co-authored-by: Mattermost Build --- model/feature_flags.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/model/feature_flags.go b/model/feature_flags.go index 47dd10378d..4864a660c1 100644 --- a/model/feature_flags.go +++ b/model/feature_flags.go @@ -63,6 +63,9 @@ type FeatureFlags struct { PostPriority bool + // Enable WYSIWYG text editor + WysiwygEditor bool + PeopleProduct bool AnnualSubscription bool @@ -101,6 +104,7 @@ func (f *FeatureFlags) SetDefaults() { f.ReduceOnBoardingTaskList = false f.ThreadsEverywhere = false f.GlobalDrafts = true + f.WysiwygEditor = false } func (f *FeatureFlags) Plugins() map[string]string { From d27d7bc8f75326b690e63530ab783fea78224ee5 Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Mon, 9 Jan 2023 21:53:07 +0530 Subject: [PATCH 02/41] MM-49485: Set BoardsProduct FF to on by default (#22006) https://mattermost.atlassian.net/browse/MM-49485 ```release-note Boards will be served as an in-built product from within Mattermost server instead of a plugin. If you want to disable this, please set the MM_FEATUREFLAGS_BoardsProduct env var to "false" (without the quotes). In this mode, the boards plugin will remain disabled. ``` --- config/diff_test.go | 6 +++--- model/config.go | 4 ++-- model/config_test.go | 4 ++-- model/feature_flags.go | 2 +- scripts/test.sh | 1 + 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/config/diff_test.go b/config/diff_test.go index 15ec6f41f7..427045dae7 100644 --- a/config/diff_test.go +++ b/config/diff_test.go @@ -808,7 +808,7 @@ func TestDiff(t *testing.T) { Enable: !defaultConfigGen().PluginSettings.PluginStates["com.mattermost.nps"].Enable, }, "focalboard": { - Enable: true, + Enable: false, }, "playbooks": { Enable: true, @@ -846,7 +846,7 @@ func TestDiff(t *testing.T) { Enable: true, }, "focalboard": { - Enable: true, + Enable: false, }, "playbooks": { Enable: true, @@ -876,7 +876,7 @@ func TestDiff(t *testing.T) { BaseVal: defaultConfigGen().PluginSettings.PluginStates, ActualVal: map[string]*model.PluginState{ "focalboard": { - Enable: true, + Enable: false, }, "playbooks": { Enable: true, diff --git a/model/config.go b/model/config.go index ad169fcbbf..ef948375cf 100644 --- a/model/config.go +++ b/model/config.go @@ -2867,8 +2867,8 @@ func (s *PluginSettings) SetDefaults(ls LogSettings) { } if s.PluginStates[PluginIdFocalboard] == nil { - // Enable the focalboard plugin by default - s.PluginStates[PluginIdFocalboard] = &PluginState{Enable: true} + // Disable the focalboard plugin by default + s.PluginStates[PluginIdFocalboard] = &PluginState{Enable: false} } if s.PluginStates[PluginIdApps] == nil { diff --git a/model/config_test.go b/model/config_test.go index cedffbcb08..752ace1547 100644 --- a/model/config_test.go +++ b/model/config_test.go @@ -387,11 +387,11 @@ func TestConfigDefaultChannelExportPluginState(t *testing.T) { } func TestConfigDefaultFocalboardPluginState(t *testing.T) { - t.Run("should enable Focalboard plugin by default", func(t *testing.T) { + t.Run("should not enable Focalboard plugin by default", func(t *testing.T) { c1 := Config{} c1.SetDefaults() - assert.True(t, c1.PluginSettings.PluginStates["focalboard"].Enable) + assert.False(t, c1.PluginSettings.PluginStates["focalboard"].Enable) }) t.Run("should not re-enable focalboard plugin after it has been disabled", func(t *testing.T) { diff --git a/model/feature_flags.go b/model/feature_flags.go index 4864a660c1..449a04b5bc 100644 --- a/model/feature_flags.go +++ b/model/feature_flags.go @@ -95,7 +95,7 @@ func (f *FeatureFlags) SetDefaults() { f.InsightsEnabled = true f.CommandPalette = false f.CallsEnabled = true - f.BoardsProduct = false + f.BoardsProduct = true f.SendWelcomePost = true f.PostPriority = true f.PeopleProduct = false diff --git a/scripts/test.sh b/scripts/test.sh index 63f89fc785..f13d9244c5 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -14,6 +14,7 @@ COVERMODE=$8 PACKAGES_COMMA=$(echo $PACKAGES | tr ' ' ',') export MM_SERVER_PATH=$PWD +export MM_FEATUREFLAGS_BoardsProduct=false echo "Packages to test: $PACKAGES" echo "GOFLAGS: $GOFLAGS" From 079f752478becc2e00df49c49aafd880608bdc34 Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Mon, 9 Jan 2023 22:25:29 +0530 Subject: [PATCH 03/41] MM-49546: Sentry crash: fix nil pointer dereference (#22018) We return a store error always to be handled correctly at the app layer. https://mattermost.atlassian.net/browse/MM-49546 ```release-note NONE ``` Co-authored-by: Mattermost Build --- app/post_test.go | 7 +++++++ store/sqlstore/thread_store.go | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/post_test.go b/app/post_test.go index 4630eb75af..3e6b090419 100644 --- a/app/post_test.go +++ b/app/post_test.go @@ -2409,10 +2409,17 @@ func TestFollowThreadSkipsParticipants(t *testing.T) { require.True(t, p.Id == sysadmin.Id || p.Id == user.Id) } + oldID := threadMembership.PostId threadMembership.PostId = "notfound" _, err = th.App.GetThreadForUser(threadMembership, false) require.NotNil(t, err) assert.Equal(t, http.StatusNotFound, err.StatusCode) + + threadMembership.Following = false + threadMembership.PostId = oldID + _, err = th.App.GetThreadForUser(threadMembership, false) + require.NotNil(t, err) + assert.Equal(t, http.StatusNotFound, err.StatusCode) } func TestAutofollowBasedOnRootPost(t *testing.T) { diff --git a/store/sqlstore/thread_store.go b/store/sqlstore/thread_store.go index 0de9c5db45..f4c81ed450 100644 --- a/store/sqlstore/thread_store.go +++ b/store/sqlstore/thread_store.go @@ -503,7 +503,7 @@ func (s *SqlThreadStore) GetThreadFollowers(threadID string, fetchOnlyActive boo func (s *SqlThreadStore) GetThreadForUser(threadMembership *model.ThreadMembership, extended, postPriorityEnabled bool) (*model.ThreadResponse, error) { if !threadMembership.Following { - return nil, nil // in case the thread is not followed anymore - return nil error to be interpreted as 404 + return nil, store.NewErrNotFound("ThreadMembership", "") } unreadRepliesQuery := sq. From 4b04b0957fa13989cc796261c292c1e313f01a04 Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Mon, 9 Jan 2023 10:08:39 -0700 Subject: [PATCH 04/41] update pre-package boards to v7.7.0 (#21980) Co-authored-by: Mattermost Build --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7c8de4311b..b7fe3ab357 100644 --- a/Makefile +++ b/Makefile @@ -163,7 +163,7 @@ PLUGIN_PACKAGES += mattermost-plugin-nps-v1.3.1 PLUGIN_PACKAGES += mattermost-plugin-todo-v0.6.1 PLUGIN_PACKAGES += mattermost-plugin-welcomebot-v1.2.0 PLUGIN_PACKAGES += mattermost-plugin-zoom-v1.6.0 -PLUGIN_PACKAGES += focalboard-v7.5.4 +PLUGIN_PACKAGES += focalboard-v7.7.0 PLUGIN_PACKAGES += mattermost-plugin-apps-v1.1.0 # Prepares the enterprise build if exists. The IGNORE stuff is a hack to get the Makefile to execute the commands outside a target From a3dcaee066dd10b38f62502d8afba3fc4311877d Mon Sep 17 00:00:00 2001 From: Konstantinos Pittas Date: Mon, 9 Jan 2023 20:02:45 +0200 Subject: [PATCH 05/41] [MM-42652] Re-enable test (#21986) --- api4/channel_category_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/api4/channel_category_test.go b/api4/channel_category_test.go index e58a557ee6..af3e9b2319 100644 --- a/api4/channel_category_test.go +++ b/api4/channel_category_test.go @@ -103,7 +103,6 @@ func TestCreateCategoryForTeamForUser(t *testing.T) { }) t.Run("should publish expected WS payload", func(t *testing.T) { - t.Skip("MM-42652") userWSClient, err := th.CreateWebSocketClient() require.NoError(t, err) defer userWSClient.Close() From 699b0d675c2b1d475a0ec919a0cdb95a3633844b Mon Sep 17 00:00:00 2001 From: Ben Schumacher Date: Mon, 9 Jan 2023 22:03:13 +0100 Subject: [PATCH 06/41] [MM-49530] Update prepackaged version of Apps Plugin to v1.2.0 (#22013) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b7fe3ab357..6d9f8a6b64 100644 --- a/Makefile +++ b/Makefile @@ -164,7 +164,7 @@ PLUGIN_PACKAGES += mattermost-plugin-todo-v0.6.1 PLUGIN_PACKAGES += mattermost-plugin-welcomebot-v1.2.0 PLUGIN_PACKAGES += mattermost-plugin-zoom-v1.6.0 PLUGIN_PACKAGES += focalboard-v7.7.0 -PLUGIN_PACKAGES += mattermost-plugin-apps-v1.1.0 +PLUGIN_PACKAGES += mattermost-plugin-apps-v1.2.0 # Prepares the enterprise build if exists. The IGNORE stuff is a hack to get the Makefile to execute the commands outside a target ifeq ($(BUILD_ENTERPRISE_READY),true) From 02ffa107e15222b51c886e92d3186cc9db7d5f70 Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Tue, 10 Jan 2023 09:57:02 +0530 Subject: [PATCH 07/41] MM-49374: Update job metadata for bulk export (#21983) If a bulk export is triggered via a job, then we update the metadata field of the job as it progresses through the records. https://mattermost.atlassian.net/browse/MM-49374 ```release-note Now you can monitor the progress of the bulk export job via its metadata field. It is available at `mmctl export job show `. ``` Co-authored-by: Mattermod --- app/app_iface.go | 2 +- app/export.go | 67 +++++++++++++++++++++------- app/export_test.go | 24 +++++----- app/opentracing/opentracing_layer.go | 4 +- cmd/mattermost/commands/export.go | 2 +- jobs/base_workers.go | 15 ++++++- jobs/export_process/worker.go | 4 +- 7 files changed, 84 insertions(+), 34 deletions(-) diff --git a/app/app_iface.go b/app/app_iface.go index f10ca2d8b9..8c10cb16fc 100644 --- a/app/app_iface.go +++ b/app/app_iface.go @@ -435,7 +435,7 @@ type AppIface interface { BuildPostReactions(ctx request.CTX, postID string) (*[]ReactionImportData, *model.AppError) BuildPushNotificationMessage(c request.CTX, contentsConfig string, post *model.Post, user *model.User, channel *model.Channel, channelName string, senderName string, explicitMention bool, channelWideMention bool, replyToThreadType string) (*model.PushNotification, *model.AppError) BuildSamlMetadataObject(idpMetadata []byte) (*model.SamlMetadataResponse, *model.AppError) - BulkExport(ctx request.CTX, writer io.Writer, outPath string, opts model.BulkExportOpts) *model.AppError + BulkExport(ctx request.CTX, writer io.Writer, outPath string, job *model.Job, opts model.BulkExportOpts) *model.AppError BulkImport(c *request.Context, jsonlReader io.Reader, attachmentsReader *zip.Reader, dryRun bool, workers int) (*model.AppError, int) BulkImportWithPath(c *request.Context, jsonlReader io.Reader, attachmentsReader *zip.Reader, dryRun bool, workers int, importPath string) (*model.AppError, int) CanNotifyAdmin(trial bool) bool diff --git a/app/export.go b/app/export.go index 8e52fa74e7..ee427b6936 100644 --- a/app/export.go +++ b/app/export.go @@ -12,6 +12,7 @@ import ( "net/http" "os" "path/filepath" + "strconv" "strings" "time" @@ -65,7 +66,7 @@ var exportablePreferences = map[imports.ComparablePreference]string{{ }: "EmailInterval", } -func (a *App) BulkExport(ctx request.CTX, writer io.Writer, outPath string, opts model.BulkExportOpts) *model.AppError { +func (a *App) BulkExport(ctx request.CTX, writer io.Writer, outPath string, job *model.Job, opts model.BulkExportOpts) *model.AppError { var zipWr *zip.Writer if opts.CreateArchive { var err error @@ -78,46 +79,50 @@ func (a *App) BulkExport(ctx request.CTX, writer io.Writer, outPath string, opts } } + if job != nil && job.Data == nil { + job.Data = make(model.StringMap) + } + ctx.Logger().Info("Bulk export: exporting version") if err := a.exportVersion(writer); err != nil { return err } ctx.Logger().Info("Bulk export: exporting teams") - teamNames, err := a.exportAllTeams(writer) + teamNames, err := a.exportAllTeams(ctx, job, writer) if err != nil { return err } ctx.Logger().Info("Bulk export: exporting channels") - if err = a.exportAllChannels(writer, teamNames); err != nil { + if err = a.exportAllChannels(ctx, job, writer, teamNames); err != nil { return err } ctx.Logger().Info("Bulk export: exporting users") - if err = a.exportAllUsers(writer); err != nil { + if err = a.exportAllUsers(ctx, job, writer); err != nil { return err } ctx.Logger().Info("Bulk export: exporting posts") - attachments, err := a.exportAllPosts(ctx, writer, opts.IncludeAttachments) + attachments, err := a.exportAllPosts(ctx, job, writer, opts.IncludeAttachments) if err != nil { return err } ctx.Logger().Info("Bulk export: exporting emoji") - emojiPaths, err := a.exportCustomEmoji(ctx, writer, outPath, "exported_emoji", !opts.CreateArchive) + emojiPaths, err := a.exportCustomEmoji(ctx, job, writer, outPath, "exported_emoji", !opts.CreateArchive) if err != nil { return err } ctx.Logger().Info("Bulk export: exporting direct channels") - if err = a.exportAllDirectChannels(writer); err != nil { + if err = a.exportAllDirectChannels(ctx, job, writer); err != nil { return err } ctx.Logger().Info("Bulk export: exporting direct posts") - directAttachments, err := a.exportAllDirectPosts(ctx, writer, opts.IncludeAttachments) + directAttachments, err := a.exportAllDirectPosts(ctx, job, writer, opts.IncludeAttachments) if err != nil { return err } @@ -139,6 +144,8 @@ func (a *App) BulkExport(ctx request.CTX, writer io.Writer, outPath string, opts return err } } + + updateJobProgress(ctx.Logger(), a.Srv().Store(), job, "attachments_exported", len(attachments)+len(directAttachments)+len(emojiPaths)) } return nil @@ -175,9 +182,10 @@ func (a *App) exportVersion(writer io.Writer) *model.AppError { return a.exportWriteLine(writer, versionLine) } -func (a *App) exportAllTeams(writer io.Writer) (map[string]bool, *model.AppError) { +func (a *App) exportAllTeams(ctx request.CTX, job *model.Job, writer io.Writer) (map[string]bool, *model.AppError) { afterId := strings.Repeat("0", 26) teamNames := make(map[string]bool) + cnt := 0 for { teams, err := a.Srv().Store().Team().GetAllForExportAfter(1000, afterId) if err != nil { @@ -187,6 +195,8 @@ func (a *App) exportAllTeams(writer io.Writer) (map[string]bool, *model.AppError if len(teams) == 0 { break } + cnt += len(teams) + updateJobProgress(ctx.Logger(), a.Srv().Store(), job, "teams_exported", cnt) for _, team := range teams { afterId = team.Id @@ -207,8 +217,9 @@ func (a *App) exportAllTeams(writer io.Writer) (map[string]bool, *model.AppError return teamNames, nil } -func (a *App) exportAllChannels(writer io.Writer, teamNames map[string]bool) *model.AppError { +func (a *App) exportAllChannels(ctx request.CTX, job *model.Job, writer io.Writer, teamNames map[string]bool) *model.AppError { afterId := strings.Repeat("0", 26) + cnt := 0 for { channels, err := a.Srv().Store().Channel().GetAllChannelsForExportAfter(1000, afterId) @@ -219,6 +230,8 @@ func (a *App) exportAllChannels(writer io.Writer, teamNames map[string]bool) *mo if len(channels) == 0 { break } + cnt += len(channels) + updateJobProgress(ctx.Logger(), a.Srv().Store(), job, "channels_exported", cnt) for _, channel := range channels { afterId = channel.Id @@ -242,8 +255,9 @@ func (a *App) exportAllChannels(writer io.Writer, teamNames map[string]bool) *mo return nil } -func (a *App) exportAllUsers(writer io.Writer) *model.AppError { +func (a *App) exportAllUsers(ctx request.CTX, job *model.Job, writer io.Writer) *model.AppError { afterId := strings.Repeat("0", 26) + cnt := 0 for { users, err := a.Srv().Store().User().GetAllAfter(1000, afterId) @@ -254,6 +268,8 @@ func (a *App) exportAllUsers(writer io.Writer) *model.AppError { if len(users) == 0 { break } + cnt += len(users) + updateJobProgress(ctx.Logger(), a.Srv().Store(), job, "users_exported", cnt) for _, user := range users { afterId = user.Id @@ -395,12 +411,13 @@ func (a *App) buildUserNotifyProps(notifyProps model.StringMap) *imports.UserNot } } -func (a *App) exportAllPosts(ctx request.CTX, writer io.Writer, withAttachments bool) ([]imports.AttachmentImportData, *model.AppError) { +func (a *App) exportAllPosts(ctx request.CTX, job *model.Job, writer io.Writer, withAttachments bool) ([]imports.AttachmentImportData, *model.AppError) { var attachments []imports.AttachmentImportData afterId := strings.Repeat("0", 26) var postProcessCount uint64 logCheckpoint := time.Now() + cnt := 0 for { if time.Since(logCheckpoint) > 5*time.Minute { ctx.Logger().Debug(fmt.Sprintf("Bulk Export: processed %d posts", postProcessCount)) @@ -415,6 +432,8 @@ func (a *App) exportAllPosts(ctx request.CTX, writer io.Writer, withAttachments if len(posts) == 0 { return attachments, nil } + cnt += len(posts) + updateJobProgress(ctx.Logger(), a.Srv().Store(), job, "posts_exported", cnt) for _, post := range posts { afterId = post.Id @@ -538,9 +557,10 @@ func (a *App) buildPostAttachments(postID string) ([]imports.AttachmentImportDat return attachments, nil } -func (a *App) exportCustomEmoji(c request.CTX, writer io.Writer, outPath, exportDir string, exportFiles bool) ([]string, *model.AppError) { +func (a *App) exportCustomEmoji(c request.CTX, job *model.Job, writer io.Writer, outPath, exportDir string, exportFiles bool) ([]string, *model.AppError) { var emojiPaths []string pageNumber := 0 + cnt := 0 for { customEmojiList, err := a.GetEmojiList(c, pageNumber, 100, model.EmojiSortByName) @@ -551,6 +571,8 @@ func (a *App) exportCustomEmoji(c request.CTX, writer io.Writer, outPath, export if len(customEmojiList) == 0 { break } + cnt += len(customEmojiList) + updateJobProgress(c.Logger(), a.Srv().Store(), job, "emojis_exported", cnt) pageNumber++ @@ -619,8 +641,9 @@ func (a *App) copyEmojiImages(emojiId string, emojiImagePath string, pathToDir s return nil } -func (a *App) exportAllDirectChannels(writer io.Writer) *model.AppError { +func (a *App) exportAllDirectChannels(ctx request.CTX, job *model.Job, writer io.Writer) *model.AppError { afterId := strings.Repeat("0", 26) + cnt := 0 for { channels, err := a.Srv().Store().Channel().GetAllDirectChannelsForExportAfter(1000, afterId) if err != nil { @@ -630,6 +653,8 @@ func (a *App) exportAllDirectChannels(writer io.Writer) *model.AppError { if len(channels) == 0 { break } + cnt += len(channels) + updateJobProgress(ctx.Logger(), a.Srv().Store(), job, "direct_channels_exported", cnt) for _, channel := range channels { afterId = channel.Id @@ -682,12 +707,13 @@ func (a *App) buildFavoritedByList(channelID string) ([]string, *model.AppError) return userIDs, nil } -func (a *App) exportAllDirectPosts(ctx request.CTX, writer io.Writer, withAttachments bool) ([]imports.AttachmentImportData, *model.AppError) { +func (a *App) exportAllDirectPosts(ctx request.CTX, job *model.Job, writer io.Writer, withAttachments bool) ([]imports.AttachmentImportData, *model.AppError) { var attachments []imports.AttachmentImportData afterId := strings.Repeat("0", 26) var postProcessCount uint64 logCheckpoint := time.Now() + cnt := 0 for { if time.Since(logCheckpoint) > 5*time.Minute { ctx.Logger().Debug(fmt.Sprintf("Bulk Export: processed %d direct posts", postProcessCount)) @@ -702,6 +728,8 @@ func (a *App) exportAllDirectPosts(ctx request.CTX, writer io.Writer, withAttach if len(posts) == 0 { break } + cnt += len(posts) + updateJobProgress(ctx.Logger(), a.Srv().Store(), job, "direct_posts_exported", cnt) for _, post := range posts { afterId = post.Id @@ -815,3 +843,12 @@ func (a *App) DeleteExport(name string) *model.AppError { return a.RemoveFile(filePath) } + +func updateJobProgress(logger mlog.LoggerIFace, store store.Store, job *model.Job, key string, value int) { + if job != nil { + job.Data[key] = strconv.Itoa(value) + if _, err2 := store.Job().UpdateOptimistically(job, model.JobStatusInProgress); err2 != nil { + logger.Warn("Failed to update job status", mlog.Err(err2)) + } + } +} diff --git a/app/export_test.go b/app/export_test.go index 7dbaa984b7..e839e1dc13 100644 --- a/app/export_test.go +++ b/app/export_test.go @@ -164,7 +164,7 @@ func TestExportCustomEmoji(t *testing.T) { outPath, err := filepath.Abs(filePath) require.NoError(t, err) - _, appErr := th.App.exportCustomEmoji(th.Context, fileWriter, outPath, dirNameToExportEmoji, false) + _, appErr := th.App.exportCustomEmoji(th.Context, nil, fileWriter, outPath, dirNameToExportEmoji, false) require.Nil(t, appErr, "should not have failed") } @@ -178,7 +178,7 @@ func TestExportAllUsers(t *testing.T) { require.Nil(t, err) var b bytes.Buffer - err = th1.App.BulkExport(th1.Context, &b, "somePath", model.BulkExportOpts{}) + err = th1.App.BulkExport(th1.Context, &b, "somePath", nil, model.BulkExportOpts{}) require.Nil(t, err) th2 := Setup(t) @@ -235,7 +235,7 @@ func TestExportDMChannel(t *testing.T) { }) var b bytes.Buffer - err := th1.App.BulkExport(th1.Context, &b, "somePath", model.BulkExportOpts{}) + err := th1.App.BulkExport(th1.Context, &b, "somePath", nil, model.BulkExportOpts{}) require.Nil(t, err) channels, nErr := th1.App.Srv().Store().Channel().GetAllDirectChannelsForExportAfter(1000, "00000000") @@ -282,7 +282,7 @@ func TestExportDMChannel(t *testing.T) { th1.App.PermanentDeleteUser(th1.Context, th1.BasicUser) var b bytes.Buffer - err := th1.App.BulkExport(th1.Context, &b, "somePath", model.BulkExportOpts{}) + err := th1.App.BulkExport(th1.Context, &b, "somePath", nil, model.BulkExportOpts{}) require.Nil(t, err) th2 := Setup(t).InitBasic() @@ -306,7 +306,7 @@ func TestExportDMChannelToSelf(t *testing.T) { th1.CreateDmChannel(th1.BasicUser) var b bytes.Buffer - err := th1.App.BulkExport(th1.Context, &b, "somePath", model.BulkExportOpts{}) + err := th1.App.BulkExport(th1.Context, &b, "somePath", nil, model.BulkExportOpts{}) require.Nil(t, err) channels, nErr := th1.App.Srv().Store().Channel().GetAllDirectChannelsForExportAfter(1000, "00000000") @@ -344,7 +344,7 @@ func TestExportGMChannel(t *testing.T) { th1.CreateGroupChannel(th1.Context, user1, user2) var b bytes.Buffer - err := th1.App.BulkExport(th1.Context, &b, "somePath", model.BulkExportOpts{}) + err := th1.App.BulkExport(th1.Context, &b, "somePath", nil, model.BulkExportOpts{}) require.Nil(t, err) channels, nErr := th1.App.Srv().Store().Channel().GetAllDirectChannelsForExportAfter(1000, "00000000") @@ -376,7 +376,7 @@ func TestExportGMandDMChannels(t *testing.T) { th1.CreateGroupChannel(th1.Context, user1, user2) var b bytes.Buffer - err := th1.App.BulkExport(th1.Context, &b, "somePath", model.BulkExportOpts{}) + err := th1.App.BulkExport(th1.Context, &b, "somePath", nil, model.BulkExportOpts{}) require.Nil(t, err) channels, nErr := th1.App.Srv().Store().Channel().GetAllDirectChannelsForExportAfter(1000, "00000000") @@ -459,7 +459,7 @@ func TestExportDMandGMPost(t *testing.T) { assert.Equal(t, 4, len(posts)) var b bytes.Buffer - appErr := th1.App.BulkExport(th1.Context, &b, "somePath", model.BulkExportOpts{}) + appErr := th1.App.BulkExport(th1.Context, &b, "somePath", nil, model.BulkExportOpts{}) require.Nil(t, appErr) th1.TearDown() @@ -534,7 +534,7 @@ func TestExportPostWithProps(t *testing.T) { require.NotEmpty(t, posts[1].Props) var b bytes.Buffer - appErr := th1.App.BulkExport(th1.Context, &b, "somePath", model.BulkExportOpts{}) + appErr := th1.App.BulkExport(th1.Context, &b, "somePath", nil, model.BulkExportOpts{}) require.Nil(t, appErr) th1.TearDown() @@ -572,7 +572,7 @@ func TestExportDMPostWithSelf(t *testing.T) { th1.CreatePost(dmChannel) var b bytes.Buffer - err := th1.App.BulkExport(th1.Context, &b, "somePath", model.BulkExportOpts{}) + err := th1.App.BulkExport(th1.Context, &b, "somePath", nil, model.BulkExportOpts{}) require.Nil(t, err) posts, nErr := th1.App.Srv().Store().Post().GetDirectPostParentsForExportAfter(1000, "0000000") @@ -640,7 +640,7 @@ func TestBulkExport(t *testing.T) { IncludeAttachments: true, CreateArchive: true, } - appErr = th.App.BulkExport(th.Context, exportFile, dir, opts) + appErr = th.App.BulkExport(th.Context, exportFile, dir, nil, opts) require.Nil(t, appErr) th.TearDown() @@ -731,7 +731,7 @@ func TestExportDeletedTeams(t *testing.T) { require.Nil(t, err) var b bytes.Buffer - err = th1.App.BulkExport(th1.Context, &b, "somePath", model.BulkExportOpts{}) + err = th1.App.BulkExport(th1.Context, &b, "somePath", nil, model.BulkExportOpts{}) require.Nil(t, err) th2 := Setup(t) diff --git a/app/opentracing/opentracing_layer.go b/app/opentracing/opentracing_layer.go index 367d98ec39..608d007d7d 100644 --- a/app/opentracing/opentracing_layer.go +++ b/app/opentracing/opentracing_layer.go @@ -974,7 +974,7 @@ func (a *OpenTracingAppLayer) BuildSamlMetadataObject(idpMetadata []byte) (*mode return resultVar0, resultVar1 } -func (a *OpenTracingAppLayer) BulkExport(ctx request.CTX, writer io.Writer, outPath string, opts model.BulkExportOpts) *model.AppError { +func (a *OpenTracingAppLayer) BulkExport(ctx request.CTX, writer io.Writer, outPath string, job *model.Job, opts model.BulkExportOpts) *model.AppError { origCtx := a.ctx span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.BulkExport") @@ -986,7 +986,7 @@ func (a *OpenTracingAppLayer) BulkExport(ctx request.CTX, writer io.Writer, outP }() defer span.Finish() - resultVar0 := a.app.BulkExport(ctx, writer, outPath, opts) + resultVar0 := a.app.BulkExport(ctx, writer, outPath, job, opts) if resultVar0 != nil { span.LogFields(spanlog.Error(resultVar0)) diff --git a/cmd/mattermost/commands/export.go b/cmd/mattermost/commands/export.go index d5573ee975..21ff04162e 100644 --- a/cmd/mattermost/commands/export.go +++ b/cmd/mattermost/commands/export.go @@ -240,7 +240,7 @@ func bulkExportCmdF(command *cobra.Command, args []string) error { var opts model.BulkExportOpts opts.IncludeAttachments = attachments opts.CreateArchive = archive - if err := a.BulkExport(request.EmptyContext(a.Log()), fileWriter, filepath.Dir(outPath), opts); err != nil { + if err := a.BulkExport(request.EmptyContext(a.Log()), fileWriter, filepath.Dir(outPath), nil /* nil job since it's spawned from CLI */, opts); err != nil { CommandPrintErrorln(err.Error()) return err } diff --git a/jobs/base_workers.go b/jobs/base_workers.go index 58bdc98ba7..71c360690f 100644 --- a/jobs/base_workers.go +++ b/jobs/base_workers.go @@ -78,6 +78,14 @@ func (worker *SimpleWorker) DoJob(job *model.Job) { return } + var appErr *model.AppError + // We get the job again because ClaimJob changes the job status. + job, appErr = worker.jobServer.GetJob(job.Id) + if appErr != nil { + mlog.Error("SimpleWorker: job execution error", mlog.String("worker", worker.name), mlog.String("job_id", job.Id), mlog.Err(appErr)) + worker.setJobError(job, appErr) + } + err := worker.execute(job) if err != nil { mlog.Error("SimpleWorker: job execution error", mlog.String("worker", worker.name), mlog.String("job_id", job.Id), mlog.Err(err)) @@ -90,8 +98,13 @@ func (worker *SimpleWorker) DoJob(job *model.Job) { } func (worker *SimpleWorker) setJobSuccess(job *model.Job) { + if err := worker.jobServer.SetJobProgress(job, 100); err != nil { + mlog.Error("Worker: Failed to update progress for job", mlog.String("worker", worker.name), mlog.String("job_id", job.Id), mlog.Err(err)) + worker.setJobError(job, err) + } + if err := worker.jobServer.SetJobSuccess(job); err != nil { - mlog.Error("SimpleWorker: Failed to set success for job", mlog.String("worker", worker.name), mlog.String("job_id", job.Id), mlog.String("error", err.Error())) + mlog.Error("SimpleWorker: Failed to set success for job", mlog.String("worker", worker.name), mlog.String("job_id", job.Id), mlog.Err(err)) worker.setJobError(job, err) } } diff --git a/jobs/export_process/worker.go b/jobs/export_process/worker.go index 7f80ac1950..48605b8fb6 100644 --- a/jobs/export_process/worker.go +++ b/jobs/export_process/worker.go @@ -21,7 +21,7 @@ type AppIface interface { configservice.ConfigService WriteFile(fr io.Reader, path string) (int64, *model.AppError) WriteFileContext(ctx context.Context, fr io.Reader, path string) (int64, *model.AppError) - BulkExport(ctx request.CTX, writer io.Writer, outPath string, opts model.BulkExportOpts) *model.AppError + BulkExport(ctx request.CTX, writer io.Writer, outPath string, job *model.Job, opts model.BulkExportOpts) *model.AppError Log() *mlog.Logger } @@ -56,7 +56,7 @@ func MakeWorker(jobServer *jobs.JobServer, app AppIface) model.Worker { }() logger := app.Log().With(mlog.String("job_id", job.Id)) - appErr := app.BulkExport(request.EmptyContext(logger), wr, outPath, opts) + appErr := app.BulkExport(request.EmptyContext(logger), wr, outPath, job, opts) wr.Close() // Close never returns an error if appErr != nil { From 3ed9381acaba3d0a447beb791c3afcd9a11301b5 Mon Sep 17 00:00:00 2001 From: Christopher Poile Date: Tue, 10 Jan 2023 08:37:23 -0500 Subject: [PATCH 08/41] Prepackage Calls version v0.12.0 (#22033) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6d9f8a6b64..63bb84e727 100644 --- a/Makefile +++ b/Makefile @@ -149,7 +149,7 @@ TEMPLATES_DIR=templates PLUGIN_PACKAGES ?= mattermost-plugin-antivirus-v0.1.2 PLUGIN_PACKAGES += mattermost-plugin-autolink-v1.2.2 PLUGIN_PACKAGES += mattermost-plugin-aws-SNS-v1.2.0 -PLUGIN_PACKAGES += mattermost-plugin-calls-v0.11.0 +PLUGIN_PACKAGES += mattermost-plugin-calls-v0.12.0 PLUGIN_PACKAGES += mattermost-plugin-channel-export-v1.0.0 PLUGIN_PACKAGES += mattermost-plugin-confluence-v1.3.0 PLUGIN_PACKAGES += mattermost-plugin-custom-attributes-v1.3.1 From 41c028e346c455a4b256522ca4053a606e6204c3 Mon Sep 17 00:00:00 2001 From: Jesse Hallam Date: Tue, 10 Jan 2023 13:45:17 -0400 Subject: [PATCH 09/41] Fix plugin /public handling for subpaths (#21886) * Fix plugin /public handling for subpaths Plugins support a `public` folder in the bundle automatically being accessible at `/plugins/ Co-authored-by: Mattermost Build --- app/plugin_requests.go | 10 ++- app/plugin_requests_test.go | 125 +++++++++++++++++++++++++++++++++++- tests/README.md | 15 +++-- tests/testplugin.tar.gz | Bin 72989 -> 73039 bytes tests/testplugin.tar.gz.asc | 22 +++---- tests/testplugin.tar.gz.sig | Bin 438 -> 438 bytes 6 files changed, 149 insertions(+), 23 deletions(-) diff --git a/app/plugin_requests.go b/app/plugin_requests.go index 1ccc966822..2670cbae12 100644 --- a/app/plugin_requests.go +++ b/app/plugin_requests.go @@ -5,7 +5,6 @@ package app import ( "bytes" - "fmt" "io" "net/http" "path" @@ -93,7 +92,7 @@ func (ch *Channels) ServePluginPublicRequest(w http.ResponseWriter, r *http.Requ return } - // Should be in the form of /$PLUGIN_ID/public/{anything} by the time we get here + // Should be in the form of /(subpath/)?/plugins/{plugin_id}/public/* by the time we get here vars := mux.Vars(r) pluginID := vars["plugin_id"] @@ -111,8 +110,13 @@ func (ch *Channels) ServePluginPublicRequest(w http.ResponseWriter, r *http.Requ return } + subpath, err := utils.GetSubpathFromConfig(ch.cfgSvc.Config()) + if err != nil { + http.Error(w, "Internal Server Error", http.StatusInternalServerError) + } + publicFilePath := path.Clean(r.URL.Path) - prefix := fmt.Sprintf("/plugins/%s/public/", pluginID) + prefix := path.Join(subpath, "plugins", pluginID, "public") if !strings.HasPrefix(publicFilePath, prefix) { http.NotFound(w, r) return diff --git a/app/plugin_requests_test.go b/app/plugin_requests_test.go index c41c70be6d..d5796a975f 100644 --- a/app/plugin_requests_test.go +++ b/app/plugin_requests_test.go @@ -4,23 +4,65 @@ package app import ( + "fmt" + "io" "net/http" "net/http/httptest" + "os" + "path/filepath" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/mattermost/mattermost-server/v6/model" + "github.com/mattermost/mattermost-server/v6/utils/fileutils" ) func TestServePluginPublicRequest(t *testing.T) { + installPlugin := func(t *testing.T, th *TestHelper, pluginID string) { + t.Helper() + + path, _ := fileutils.FindDir("tests") + fileReader, err := os.Open(filepath.Join(path, fmt.Sprintf("%s.tar.gz", pluginID))) + require.NoError(t, err) + defer fileReader.Close() + + _, appErr := th.App.WriteFile(fileReader, getBundleStorePath(pluginID)) + checkNoError(t, appErr) + + appErr = th.App.SyncPlugins() + checkNoError(t, appErr) + + env := th.App.GetPluginsEnvironment() + require.NotNil(t, env) + + // Check if installed + pluginStatus, err := env.Statuses() + require.NoError(t, err) + found := false + for _, pluginStatus := range pluginStatus { + if pluginStatus.PluginId == pluginID { + found = true + } + } + require.True(t, found, "failed to find plugin %s in plugin statuses", pluginID) + + appErr = th.App.EnablePlugin(pluginID) + checkNoError(t, appErr) + + t.Cleanup(func() { + appErr = th.App.ch.RemovePlugin(pluginID) + checkNoError(t, appErr) + }) + } + t.Run("returns not found when plugins environment is nil", func(t *testing.T) { th := Setup(t) - defer th.TearDown() + t.Cleanup(th.TearDown) th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PluginSettings.Enable = true }) - req, err := http.NewRequest("GET", "/plugins", nil) + req, err := http.NewRequest("GET", "/plugins/plugin_id/public/file.txt", nil) require.NoError(t, err) rr := httptest.NewRecorder() @@ -29,4 +71,83 @@ func TestServePluginPublicRequest(t *testing.T) { assert.Equal(t, http.StatusNotFound, rr.Code) }) + + t.Run("resolves path for valid plugin", func(t *testing.T) { + th := Setup(t) + t.Cleanup(th.TearDown) + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PluginSettings.Enable = true }) + + path, _ := fileutils.FindDir("tests") + fileReader, err := os.Open(filepath.Join(path, "testplugin.tar.gz")) + require.NoError(t, err) + defer fileReader.Close() + + installPlugin(t, th, "testplugin") + + req, err := http.NewRequest("GET", "/plugins/testplugin/public/file.txt", nil) + require.NoError(t, err) + + rr := httptest.NewRecorder() + th.App.ch.srv.Router.ServeHTTP(rr, req) + + assert.Equal(t, http.StatusOK, rr.Code) + body, err := io.ReadAll(rr.Body) + require.NoError(t, err) + require.Equal(t, "Hello World!", string(body)) + }) + + t.Run("resolves path for valid plugin when subpath configured", func(t *testing.T) { + os.Setenv("MM_SERVICESETTINGS_SITEURL", "http://localhost:8065/subpath") + defer os.Unsetenv("MM_SERVICESETTINGS_SITEURL") + + th := Setup(t) + t.Cleanup(th.TearDown) + + installPlugin(t, th, "testplugin") + + req, err := http.NewRequest("GET", "/subpath/plugins/testplugin/public/file.txt", nil) + require.NoError(t, err) + + rr := httptest.NewRecorder() + th.App.ch.srv.RootRouter.ServeHTTP(rr, req) + + assert.Equal(t, http.StatusOK, rr.Code) + body, err := io.ReadAll(rr.Body) + require.NoError(t, err) + assert.Equal(t, "Hello World!", string(body)) + }) + + t.Run("fails for invalid plugin", func(t *testing.T) { + th := Setup(t) + t.Cleanup(th.TearDown) + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PluginSettings.Enable = true }) + + req, err := http.NewRequest("GET", "/plugins/invalidplugin/public/file.txt", nil) + require.NoError(t, err) + + rr := httptest.NewRecorder() + th.App.ch.srv.Router.ServeHTTP(rr, req) + + assert.Equal(t, http.StatusNotFound, rr.Code) + }) + + t.Run("fails attempting to break out of path", func(t *testing.T) { + os.Setenv("MM_SERVICESETTINGS_SITEURL", "http://localhost:8065/subpath") + defer os.Unsetenv("MM_SERVICESETTINGS_SITEURL") + + th := Setup(t) + t.Cleanup(th.TearDown) + + installPlugin(t, th, "testplugin") + installPlugin(t, th, "testplugin2") + + req, err := http.NewRequest("GET", "/subpath/plugins/testplugin/public/../../testplugin2/file.txt", nil) + require.NoError(t, err) + + rr := httptest.NewRecorder() + th.App.ch.srv.RootRouter.ServeHTTP(rr, req) + + require.Equal(t, http.StatusMovedPermanently, rr.Code) + assert.Equal(t, "/subpath/plugins/testplugin2/file.txt", rr.Header()["Location"][0]) + }) } diff --git a/tests/README.md b/tests/README.md index 3a464bf033..d259132da5 100644 --- a/tests/README.md +++ b/tests/README.md @@ -22,18 +22,19 @@ It is possible to manually test specific sections of any test, instead of using There are two test plugins: `testplugin.tar.gz` and `testplugin2.tar.gz`. These are use in some integration tests in the `api4` package. Any changes to the plugin bundles require updating the corresponding signatures. First, import the public and private development key: -``` -$ gpg --import ./development-public-key.gpg -$ gpg --import ./development-private-key.asc +```sh +gpg --import ./development-public-key.gpg +gpg --import ./development-private-key.asc ``` This has to be done only once. Then update the signatures: +```sh +gpg -u F3FACE45E0DE642C8BD6A8E64C7C6562C192CC1F --verbose --personal-digest-preferences SHA256 --detach-sign testplugin.tar.gz +gpg -u F3FACE45E0DE642C8BD6A8E64C7C6562C192CC1F --verbose --personal-digest-preferences SHA256 --detach-sign --armor testplugin.tar.gz +gpg -u F3FACE45E0DE642C8BD6A8E64C7C6562C192CC1F --verbose --personal-digest-preferences SHA256 --detach-sign testplugin2.tar.gz +gpg -u F3FACE45E0DE642C8BD6A8E64C7C6562C192CC1F --verbose --personal-digest-preferences SHA256 --detach-sign --armor testplugin2.tar.gz ``` -$ gpg -u F3FACE45E0DE642C8BD6A8E64C7C6562C192CC1F --verbose --personal-digest-preferences SHA256 --detach-sign testplugin.tar.gz -$ gpg -u F3FACE45E0DE642C8BD6A8E64C7C6562C192CC1F --verbose --personal-digest-preferences SHA256 --detach-sign --armor testplugin.tar.gz -$ gpg -u F3FACE45E0DE642C8BD6A8E64C7C6562C192CC1F --verbose --personal-digest-preferences SHA256 --detach-sign testplugin2.tar.gz -$ gpg -u F3FACE45E0DE642C8BD6A8E64C7C6562C192CC1F --verbose --personal-digest-preferences SHA256 --detach-sign --armor testplugin2.tar.gz Finally, include the updates bundles and signatures in your commit. diff --git a/tests/testplugin.tar.gz b/tests/testplugin.tar.gz index da716bbee32bc88ccb6cfc531091606be93bdd56..456276f917c373b457ad99aba20e5f2636a26e91 100644 GIT binary patch literal 73039 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

y_wL7~OTdu0SvY20 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 z z*9*phq_U1ujo%*Hw1>QLs1!OkC5yBil`H~f)QZi>`1Fyrb zhIgL0PKKKt*84sK`f&D*X35;DU9Y%CmS?YQlNu#-Y0_?1Hn#k>rgwD(vt(~mv?*oV zx{|zCRonWP`hrp;$4F6c6fv zJAK%*Y~*~Y0Y3serXPksnRUw{4KT@F2y;IfQQ!hTlM}C7VE54N!!bJDH8{7Cwd&rp z?gl)?0NjsFY=fpGdbe}ynUqr~Cz` zk0mp&T*}O%7#7Spt<^M@qW)JClC=(>Jh6yKnz|=SY(s+@zKS%i<;W<|Jr0@z_`tnF8Ez;MBbiKjmo~sm)(6u& z^mm?&6g~>eL7xWAz9P!kgl!TtGv}sBwk=QoXp&uMBQ;VAi39Id5lt>xyTky7J*d!U zJ7Q3N3*hL6l|?g$5-BXEC}5l|gJipqa@>^@c%=&D45v~BqU*PIQA_i2tZmy>m>Q_0 zXG8`Uw5N+#tu*r5vIW|8;?fV%fQtVBJPH4qsv{$lC#(i{vuGP#6 zE*5kwEjc@cRoW&`l^@Z3))^dyHnHI+JJZbpc5TNDKq1RZpT`q5}ObU-#v*OB0s zRE?SjoNCaH{p@$d_8}U#8b!6u#+i@j*JZ|hfMHK$p~e*2ac56Om9X}oJeuwHJsxj$ z-`@&X$y0qr$9J_b_yDx7)$BG|zD+9@@l`kU8P+}7(Zf9HtDL+#M1_Nc3PZ2m;XNg1 zKLA$LxZ1iusueLhenFIwoa3frofS)NEo%{({=d~)#{-~AZ-+%ZadO?ex8kC3`ka(! z#?=O+r+M3^Q&oj1kSw~U=SQS{J^1uaIaMf3ucdk1dNPqadN79%lw7F<&{R@VNO*56 zkqKgIs0g@ZT*&RybI6KT#$x6^<7Rzn{y-~WfyOf7#KMUcfAj6awop- zbULF*SMW*u$je@HsKX!UW=Z*-(qTFQWc94zpjs*%aaawkv?EOQt8J9Vc}j_;xv|?4 zD)o^CPxI0v0i=yhKb`%!$8+r!_@@pC+b*^Ns`IQ55=%gsBg5N(Sci)eT~@)ku|#kA zQL=yEV{xm>mfi6#TfM6O87E%3%5tuy0L?mk`iRWtj+M-{cw)3Y8$IbRmeYtnXwL3L z75Qqj(1FNfYQA!sS&65hSOYlFF-1ippJMdQMvvl=rClF_DDCMZI&$76Mo`B5=P#4=qdM^DpZ%6C%At81KTZwhjD^nz$=PDKzJ3-g zF9p4|vv74~B|KYOU0q)3FP|-KZS*#mw^o){dt1G5eG#WUI1e+fo2A{wPN$F2emfo2 ztp8gkQ*nR>5i~-b(=1$(X+*C8EN({_axSSfRaVhnqNDNh;k^{oxeBw%2FeZ`7DUQTIWfm3|D2;eDj0T*d!MNq4g^cVtgXG+~In-A-hj?aH>%(wt+Lald zNW29AA^wIqmG(VHD|se;16`LgV^QX;V0@AJ>{70nA3!?i;PO2_HMH&zIm$2DSF#5A0D+0(ZGEq@{&*bWD8YR%D>ks-Kf*ZVh`?GG)j_^KK z8Ax)^)H0PeiggB*fIgoHqls^jGm>X%ol5=WwP5$6p9}C4Wa9=fD)y9XZS$`m={rBz z<}}KpN+qD`iQOQ*Jt+vKm`)WK$tO=6FY&FFT2{u`CRY<4obm7aK0}ZF;wED!#^RK% z*v6A5s{Nu8RB<`X0JN7{?he#VLC%G37gmP%AshgcppBJe;&bCvLkmZhz2iMFyacAM zS}@PVz0ZK7GjWL#hMQLw;e83LNk_mvuB4WuoS-X-VfuA1Cx|?0XC&p{Lgsp@H$9g; zaRT^FF$q?AcWS4~ji~^%iE+Yl!W*Y5W3tV5$W=)ZmLkiVGlgXH&~QyBoK>_u+cH{) zb+jz&Xc<<+vbB&9#PYWMGC7r8)6;+b6-!QPbY%lOc=MiVW*}Z>C@7qvJ zX0=T(ZnkliPMdI^FU#-M>Rp7%)+9$3#xlqXTfBAdMFpx4y!c39#9?NrtaajLKKh}Z z|FHZ$hL*MuD6LX<@LlIvpUHQg;~cU)rz$mU04j}eu5x{;S(sym&W6U31&31gT5VYD z4!LF_!>hG~njBaM+sQaKanyZlV_ygNk++38vw+#*imf_E7IENDgXDI_F>&s?A%Kvf z*BgZue7|^tcV5Ag@2z6xE;Zb8(^jk`pZxc%RMkKI$_}iqGScxHwijiK7iBRCowYC> z%a+;Xaap>nT++~Gj-6P-wNJl5%$u@0OjYUWl&HbIS2t<6)UgrSZ8rgX)o``#;wG_n zzpNQ|CNYq4(||czDUq!=@+GH{nJS|zWhz`~De$#ixoM!egsz~%0x3^o1;LOVrtr~w zvUO+G48$$V0Om0Ww5CmWF_?fxK^)Y+9FMMnDUDk4LH4ap&Pgh(%c!kV*p3H$#g=b^kOKvxKfEeZl17DUTX%W#d8n6R&NZQHL*4s%U#rX70ss z_HS>0Pr8Ht6)Lv6s@~wx3%R#0&^sj(fM%XnbdHL)$tYWb@cRWLDs-?c;A(x1hFkin z)oRr9x}tl{I2UrfGDlS}x~w&tUM;9dD5=11pm=c8@B?&U*#MjrO(kphJLdvw0rhck zh6j=;;$rxL0BvXsgXkk>NmwCUJHED*PNbP%HYKG&CK2naf}5|kH~~X0kriIT(Ali? zCbd8zv7@*oOP&y5?O(NqUzP(8Bf_f$*UlcCBR}XVy+T9tq1@p`mlTt69BP})3#F9! zpoX%`*`xV?CvoH|LO(WC^b#h-s$wcK(*=5UR|Rr!%$kE}U!<(cw04`S^C*u=hPkS2 zd8*kg9IMDa980}4c9bfeOHNfmhYE@NM|I7wxlR>EzLC@d+{4>tZjZ1o!33j@6yoU;nBb=63(S z_m4yTK9CO{M3PIu&+W~S`oaF zVC-xIlKmrAA<}q?6qQrjCw^toKD||aP|>uH<;97HX|zEF9;#_Vs!MrIV&4e@t?@ne z9$VvnYCyIvI5nw9JAsz3HPj%!*74s6y||Om!BdSda*Y#TwG91JU2Ush3J@oK$jB7b z)bsP!#w75Pm(eE)8z+*#XQ?kzSs{*D2MhY?X!iV3*ZK&mJAPhQ78dj2c}9vB?h8) zR+YxC1h%5WMuWD*X+@eAn|18ix<5n+fBv0$K+`iE{l-^0YCv>?d3`DKY0)F}QBjNe z$<-d~m8p>ItW0B{w-(71hNNJN7KMW`iW7{4vy1C_lCBzTVt#F5{Ls@nb7^>Kbqamf zb8BB4JPFMbOW&YYb-iJA2h*+xZG4gCEU=Z5xae zpODVTI<)TRGQQg0?W{tkMEN4(X400ev8oDgL%M?SiMHldwpxsRRahqbv)G=c!>;l9 zvHHpzWJ61V3eUu4q$(MfwMzl{fQx8Zmw)}YuxqH_FTEd1=eVJEcGaVt>MgHJMd4tgy^uQ^}gcOR=$fUhqZ)vOoB)02fOACelI_-ai%pLb(>hWxhFFXs@g zyx+F^Ox;K1nl6^3_kKs52EAJbz02jLOoR*9-IR8Q2eQ%feNaBs!

(_R4b>p0yTKPt1}yFv*y;!I+JL2f5RPT!_^J+m*#Bn-8pKe{;out;o2*81YXX zJgNHyMeN8bXqrl{vTUIsXa$;e*>R$>n3=Tq zOX@*q;6B#66s+QHbxtmV1JD{03O+sFF+}AFl~G(zAQ1+}cRD^w=tPtl6AYb$MnbfC zcz+T8KqAqczFCw z@cti`S>xOKzdcP6EyY`o_?Ok;$^)jyxC|;&B$XZqt78!g`lIVquBgqa;>S$M#E7#2 z6-shzS$C9x#y)ZB9RB0=^MhB$o2M$(oJuOE>`zK+dHL-9|Jx}-bIwgDX9&k16!4hm z-KQAqNcbL5he~dW6RsWCBnhvUyHw0ZNA860@ho#;uB738*wF06lMBIgFzxoNrgPKD4>p zK38w%RuZ?OM$}{F#BM_6OLpO_w+c8Q5VVft+MDnyt2JwHFFtTDoih60G|0Rg&n>Hm%m-PA2KG@e==!EpJsd@!iowX>*L zG!N}7H-=G@7=X^^0j%fHCpm{9((06JxD-f(@zR}S<78;BQUw&&-b-M-k^{=Y5-+7! zQT*|ibyTs8%2yFI_Ws?zLwy$@9XnKxFD#lE@dXR~hXOJf&S8=SXp&UNzoTDB@K#q? zROJ(A7g0Afq;N6ykNwRGtIr8sH5B}NY{9WCOEA_(zK5QDV9pn=3gAri+Q7mbtVl#2 z8btw{0w4!hxv%b)YSx_d+gh$=s})v(D(f!QzeW;)Lbg_slAgUec=M0f z2k*&A@wAj0OlH$-s0dI}gGAU{YET)h z!MKezW}n5^c1eLrm_6w0Li}hIpq4m z0HG_OxVpT#bBu#HL-#}sE*^~}V0UsAGb|O(LZT^zsXt8q1&{(iNzWIzxx^}CoHGz$m)1@g${bUI@ zf(2DTc=adR0hUlaZ+VLzH-Nvcos;TZdjK_PdvAg_c$xwKl)?Oj`^`1|ytV~$3qvLw zY7Rm6^nc*6AFxNzp2AMDl6o9>4D_P~g`R`DgA{NU4WjWiDtoZiq4162h*9ZcaE33k z!C`Psq6(}h+?W)-Ova45)KRt428@y zVRn*WEMy*xur5damo-^uhX&{c%ZZXN0A(sD!!q&^4}!_ilvf)S+S~vM`mS}9`6hma z{Mt6(R2a5e&2lq&jj1e8Eun&7pGtV)t0es>88wlpP?aELW8a+4SWZ$qUhWMs5@TFo zG4CRXi0*8zDk7v4gzgRoX8a@fvLK!W1J%7-;Ny%-|js2 zl;+V=fxPK5WYZfYtVM8G6 z(_LRSp&<^-Y-{$_OulbZVf9jfKt!M*0wrGrml2Q(MczT0fmI625=iP4`>}wekezxG ze8>V|BD-5JJvWd)|J86Zalsn?AvA*wK(ms3P$5jBg)6MAAHEW7O(U3%@YLv8t}(IR zIHj=S7`y=4MoIm57z>G1Nm$Id*TGiTKZB*Y2pCx)a0{jS2U z4iFd2cuN3^AEfUchM^WAd0kN)z6Alj0Gt1K0Z~b-Y^>k`nkbLhIEV(BU(3&i!^6!k91jIELqFxF7d#$N^Ia;g#_WODimP)@Or zr+%%`D96^9?XXH3S-V4rHCN8{+Vr^)k+`4*=rT%dy2X}NC5IH!G0;DJj7FzGyGrOm zX0Lwxc>T9d;YdB@{zFS8SI06>R#g|b$vJCCc_=Kf7RAU?vp^`;EqteA)mR?k_d!-s zXq&|(XcarMZz<4|vF(`{`LY&|)J=r4A>kk9Fwxadf!A_oE^Swb?xM1T0|q8}4qz}% zQ^rPIWumd6(F8HYUWIgYob*BI20l#!4Q?G#rZR~rWrOm|qyfOh-6wDogVpft8i#Sp zt)13<{h4t>5N)*R7Y=3$E2FrUG2ai&?#%01bgta z?4_<2`t%s~v*=1yOCxUqbG;a+Kz0uMebh+h(D)7R1eMJdY-x0MD8CfLq>xuk3}XS&WVfd*o0%S()6Mki4psHOo`(0*Ga8e zu2&l@Q#NL5J8yS!1uc~U0lySwgfGuR$_(FMY$4x;@?FoI|Lvsjp*{|JD^ZooP4rdw zl9E#mEoISx?U&{6j|+;4wQk&g6qdOCRjg#rJDmo+U|W+g!QCDgh9kDPz`riN<<7MU&Ys_30exH|6XoewzaxAuG(MO)L?I?ZoT8^q*1!txp_CtW@mMrZ>j2V zTK{!;@J1Y=qJDt}a!7xe^~jpM{?1sWkGx3lwiMB>20*c#Gc+h>*4=|Gu9BnWZ=!mo zsICs?KVMeApXRUqC}zUTzgtv^m51;&G2L9(mci%PhLPRfFrxK*L2VxY|xx zH7nS)odM!jMp$yHR5($pLZXX9^oGu<)Sl{s@!MnrpnC>WOT%s$U4}i%PLIwNm^|bA z+(`;@wh~aMJzy#5?*w^RSrpwRs zOAm2oleQjir?FS`)Z>ybAn`csshV@Ln z_=47h|3xBNiE#Egx`sN2nMFb?&QOu9nKDkyc9qh`)hYN7uYX0ceF%Qz09OKC_p1qW zT9o@wvAF6p12ic zWwaek&vI^|Asc0Y?y=MvGo?r7?tKg8yMVU6ne4@-KF1P3vC=;tKg`_VJRNh5t!9Fg|n+SFtBnQ<}10I9M<$NOYrDm(@D}& zoV5H?!N~#t@ZN?(6nQ7X@Gen1$H85D#~+)QC*F868ibjB4lULc{~-oWjEP#?@yx*U z<03|arOFUu2uK0FI-y>aX}~3gk$6Bp*BB8QIUN#)WE5 zyVS+wnp3>ymY=C7FY}?M(J`GivH{(cXISVw9-$XGdRoZs3h@KC^~K7&?1mG)j{ut4KN#f z6A)nr-m|!uqP=0&U(yk%tSKqF#E?UbgrFy1O&(q#4ddN~8nCyRuAoN$k}QklU!!s` zE}jj7MFS4Kd4TI_*~Yi7=vz3DM)OFRx-yHHl*Lyf=BWBM<&eiIkp*;++=ti~lUVbq zMFpomXPKoGk%$(@y@>cXg;fP1xZ3UOv`AxRjzpGeD^FXzqKrVKJm_6{qKFme6u`#K z9n^{^#QKU! zk{O&Oz){Gq$NCY@j?BDuiMZ*cXo2_hNys*vu z#TBayg0E&q>@7MLbeS4?*_z+d9J;S$K1x6rAXn|yrp!&rlyOEzIu}nkW3r0F2GkS8 z*ZGC!o`x5enb8fL2z(MHxA=ul7u&@ec47C^ww07D z|Alh~J$UGlK^y zUS$zXu+;$X>vg={-6UYTYxv4-U0<=6F0lR)WO$wWEDTXR1Hl^vG!)er z@C1U+RO}Mi0tjc+HDv@1IPi%+@x*7!zQ>ZqJW^2Mn;E6|lwY?!?D4ic;wT3F2(+_$ zHaR0vq{-b##&^Bv5b*qC;ckT4Pzk8Mp)TVU>f>GNu$T8`x+H#8QseH$6 zG7F%E-6T-vca)B6o9_=>$d&$OZXoBUl>=n=$WR+vG z7%lBCPF3y zpNX3ldCQ#oqu|ZS_+2*$mZZ!#QSAC5VZ6y9dnXo-_#gom3q=G8Fx z7#@ZLiswjm`V++n)oV=W42rpgFJ;g`afVX=!vJuaU7}vjVubh1UJEh6EeO~piY^iEXhq9=5V6O zv6y|#?H51?&dc7BeHC0q%~?R9{Sa@%=wEa$>w5=`MYdH^(>av0#an%y^Bgh|GJcMg7`f2=YCk6%VERB+wVxg zR?<0|@OTj+n=$XURRA_nLHf4%ZUWx7P-HP;ed~l6u(sua%;0>)RH$mrAkgoCvA?h; zeTUxq?psx%v}^%Fu6d)t*!Cx7Tiea?2(+}t;%3m`csiIcy4a302o4-+55T-p1q)@I zTDeZwa->yLohZVk*Gvo)S^)PU)r;I~Ri(Ui5lF66=6Acag3}}3v;Ib>1h{jnF6G~& z3k48rrWt9)ch$)v+*~h7s%@7Sc6*3|1&2D}p2@TBiTm9upPwxHqNgYihh8E_ct>l9 z+LA|A#Qkat=Sdl*deux0gb<8k$vf5ZG}dl<$2FIpG1-nGE_}+(F21Uo9Qr21#^2Jn z+DSumkjyfnFj6%>VX4^$7M;)WQcKAtvNJ}|ka9K`gTnPr?gelhm(?Asrcb6u(l4{i zsEGOmfn47(sD1&yJJ`=@=8T)M09Cc7Go%#QHzT9uEn_7A;VX1I-(7?UnDbhA*|f;s%)GQ|4%W>nL zJ*ZxBL}gfQm%dds@^jiQyb+zjnj0lN+Nqa1g;nHPrZ%YoOVt$9Av!b=wJt?16J}(q zu6au;XZ4kOcF+$JF2|hWd5Vpb>zhuQG@n{IRK2jF6J+1)Bl2rIS0J+tFYXtMluYbE zyCQl&DEDKttH4r|?wFVPx>VH{6YN`v*WDOV%qHcs581e0rzLA+7`+LY!R*A<1~mfj2d&Nhkg4N6>SH7u; zLg;S0n(#DgRb1q?OfFGj4fSc=6`iS0yrhrm10cz0} z#XK0ZVUTlTv7-T*XUbu}kB3yIM^+o(doGbACG!#nDZ7@X3v{j``${i-A0#Vo#J5|p zXmAoc6LQ7O5iK&_7$fikYXK%L@D2~(;Xxh8;S9(+lwPCb;YSDjQ6k=T%s;4q0#wym`dn>+|Jkl1Y)TTTA2)~1F_iukfq|{FHQ=DW@h*a*_-&+i@#g6)I{E3c>N^phWy5~HPc!^ zM7(2;sZJ+~Ya(CBoJH7+q&PBDY?eM%odM|nloqI$IR4FmxH}_BEwd{8$oB%Mh}uRWr;5<$1LXR zviKchHOu-5Vi$}8MS3@CrcJO{?x<&4GE*^G{91>-van>Y3J{>wEUnujqus76O6FuZ z_w3W#$*b3OL#e(w%_`TytJo^Wke}rQ*)(-m27N19+!gDh#*w4%CuOii2oP&J#iGcx z6pCMVRbKa9Bt#TY+oGmiX1E4ld)C0O8mkP{~H2Kyf*=TR5Y$=#<3 z&@ODI7#+Tnyht8n6SHfZ#Ha@RE!g*O-NcKcLcWk8F;~i%g;P1SYO^WlLw&lC=Ws`t zm(3)=+I}jfXt2ehlDmMy5sb=YoJY!_9T?{wU3NPUE>pfZ#%rnM-tIKi&eE)n@mb0{ z6M;OWIBMb|=rre$U2v3``55R;ZkE& zas+)0I4D-xuxVZPlF(V*fhSi}9R4(phQb}l;e)xD@FQC7!z9yk92RbhZ$spoaLAn( zKta#?*ibgkt>;pr)Tf=dNbs}iaZz??_|J}WZ&kl9(~y)ownRI@Y#ary$XKM&F~jG*4-oVdsZcmoF%UMZ{USzzo|blL~=N|RqWJ}a|-2o*G}YCe1ERGbI6 z)pLYngE`K9J5eyL_jUpct;pX(a&{9Xmd)D@q^ABXYfK!ZcI>lSd{b1qjAG>M$tA9p zw`lhcN~XD-vhTTDV(LDwOvEJ@V4_(rz#Pvzp`YhZ8ik{05z$=^|G7)LrA`x7YQC2iRaDZ;)+*CtJrb*T_UqiIe?WC`SUgF zJ0D}=Ig`=0?Gq>7giJ@hI)^9Fs)sU0sr!vhc5QW=Fggq=c2H}8at?`vSD~%R_}=>% z_NwtD29yr2o3`$jpxs}RA(p`A6-I&>Y)U~ae)qURACwe;wqL{BSRo@!T-7>zzt?*TLv0A)$cWa{}CU z0p=v8OB^}S=*Ja~P<}m#KuNK!Pog#UcHrVA&^7J~aCJNP8*X~PESfKGa{Id%;pL#75|u)rFUoU8cW zKACBu`-$!VDxhyCDIcfm!w|az*o5kX)rPjo(5`=(d{kB)?jKnu#e(T02>kyuPwq0n z&WQor@#1qZ$W+Q+4V!jtw0Sb_(8Ow8RI(gUwB+UI!T&2v6B=xWNwmp`N@9T33Va2c zBHa>ENk<9#0tKED_`Xjc(CLA#*eRzPj!6Q-HN%FYOf?*!0f}T4-=DJ&5(_J|ZaU(u z74y1;_SBVH)cI~LXnV6OE6cP>c#G8fE+axnEk(-jg=lb|fo5rAmh$`AOKn$)d#c0> zS*L|U%{gVGaF|Nw%umezW3V7hA@VUI`p8hy3I=>}ENd$o^M3GN0O@v7hEpqN>gr(A zp<1Sz*2JHQKzjC)&0lz;wbDiJ84z5^Pl}8VX~?U>5U)syzJQd@9>nO5ld*ljX<|KD zc<2jpASKe3CF?>onL3b(@G276c)(=rTztw*$Hg`p685Kpt&5ft-jbT$H`)cGkiqc> zwnwr=JHqYJ#JP#t%M0;?0g41NR@FJ{wNM_Vr4uAch|Sf;fWz8Kv%0qx8xs!K$&-86CZUtN$X*isjVF1P19kq7Auv#045ncK1mRLOFGDqjrb zX+YbzmR7-|w{`G6Hc$3wVF}?si+jJ2ScEf-m&8>IRHv$|>L#sK$eMWzOXY3Nf~*p# z=3(0@RMx-SxV3_yB9mq8lst7Jo#f$G%(N^QfzZ}GN`{fMAK!5ddCTVPomXm#HHaB) zDt9%aO_R7w4!|4AFW&b1x0iX|U}j-ZQMbLezLrX~@#R#ayX!cJlg@Z*ES%NW=f;n+ zf!`}+lntm{#lrJv*d%hgje*}QpEJl<&}BuBL< z-t?MwXRI9ce&AEIak_SIn@ZZB0}A_YB`0n&Ov?`RP*C${k`D#fK23ZGm~%8+9A8>r zTD<2hJvcIzO!H9iRJ@RfL!iqnH~*8E= zJUmO1|BtlS z=D?_z$W4tSfFK7h4kp?iu){f82%_bLSRW;4;|$Fg9${HPe&n9T0~hN+x7%cQV}I-2 z{+`!og_~~rlxZ$$#3@8?{cW}SZj4$e(PnxQ^Dka(byY7BNi$Q9SgH7@X+F&xDm^!q zU_zTD_}Lvxg1?4to_07O7Nv>e0}BML8}eR}wI|35Puse2;tc zBifd7h`#fDFhb1~1^9;5pW*_rs~d%0IdvVyQ`!lGw`kRjnj`R>?Q&D9RS^W|0F)>Kh07BqUB9vh^7u+jVaVbX zPYL_>P`BE~OVipv{t*Qc64&{w;8|+G&tYtiqc_0n=1Cg`dETmYNFNcjLYCEh;7PD5uw~86t$^N(C1!on(Fhyv zBFS5#=)GT@lDQe(0is0!_;>{0*hvv%L%AZlD|c!HK4aH84bSm0DFX=fW2Q=KhK9hC zUq-^KDT1LTz~#BhCuD4Zz=HRK`Z^Sq?$7T=0D>3EXC^ZKq2s+qeF&l*-sN}Ls=TqW zs?6jjbX2Sms6Rc)DXd;lhjlv_`S?sX=43i%zh64)?tos|p%~zN?XF&>@FyphYo8VZ z(Z56dL^zOec_Z>NknF};a3|k2{WF4pV8m_i3c1+2M_)gtHz*&QktGZ~5cxyp}T3j#hCN#E{4KVtRwFr8G5eO}s7St|^C% zOg&X(L7IsV!}5|18VQvENd$EI?!09;eD>MZ!$*N?05M!< z9Gix*E18I6XXvwsU2(gF3;TJFT8<2DaP=1>Q(e7X#W%c(!+~VFTS!Mh`0{Yru z4pB87MG?^vJ98__=CatvQN(bKyz3*9)0uV|xIi zY{xt(KIE)!lnxM{F3@qjB}(Zt@?1c&to+Dd*-mbvW@eAz3s9ACCmLGYu&U&N&N^c_ z1gIKU4IOgJ6{|PVOq_@;2F0a?TN+rB>dY(wmw1C2Zw@$ovet$CjPq>^`u723br$M;{*Vrl#rwB`<083>!9WS z#^JrsIRq#Z5yb6IO7=oDgqKJI+EvajxvlfbWK^v!Eu8^gnjWKx>C&k%*h^&1wNz9U z41Vd!>XYv}FqQ=|5aSiZT~a`UX1&k?3NC+W(6W*@UX+H3#Bq{+7!84ss?x@+ox2@|h#3r<3)rahFB-JqufetqZ; zQKUy-ns-Kfpd0efz^86nS5YFY14#LA&15@ay7az8KRpg2?!WV5(l?!^^@aKdcomV8 z2>Y5{$x9gYGP1$zWI9EJpK(I7UH&?~7%3!G>MaZWh={P-v%2m!&U45$ zz|zoEgrRbOIMLetdWgfle%2z3fcN*8Pcrm;`HKp3>(be$|CY|qkj^G5p`}E6nibQ~ zV3UlU$_N_7S%*`maWF3{`5C%dH5bSQU~IBWcG z+IYR++xltiEzG31|CimZ#N=sgOijrj4v_k69oAm7TSPUaIZp)0EkIn$pWxl|*paD^ zAk@1(U-{S4MEo1p=V&5i(Ohu;h0|kmJU|rVp=g)Qfib}-hh9$vWHgXH@f;*h(Cpfk zI`xd)0QC4ystPZT{~w|&B^O{>799g(&td$VTfd0xOB^$WmZn>o!)XCCL^qG-N5>O1 z0M2-dc`R9~i2U_*MB2_mD3}FDWAd8CR6u>vMIKdtJP}QWe^>0ohW!Bmt4Uk&)UBl` zqd^t2Y!os$5vqZXX?vKpwxP;*%Xe1dcxkkobVNGo%b7ZvCwEig_~y<)ijIk@rDQ)F z{XRg&^rCHb#I>DDMY`x3Sq|B{vau}sCQ;~ICk1FU^sfNwK3L1`;A`6J31;z%xhrPUe?{x9 zn{tRy#CDZGrTQk7BiUa1pXsB6zy9^FONUFqn6)~#@&I~$$M>A6Zr^#X5xVe}HHO2B z>um-AYrcjroJL7Oz8+nFL2?L?xTtQH(-(PjDK?vji-L80|xzk2rac*OFwKAZ$k*Ld8gleDx4s|BzLG z%&&f~a(j?IUk7JK;M?FLf++;9Hak1)o3yE{i9IdV(6i~Rk%1#;On2CS8|O&&-wMB_ z7s(P%fwNI=?R;5teuSa0oi9V<0!-o|)0>ltm&fm(OAPrrK+|wNp(J4C2#&v{1i^OH z03km#98_$%0aVOQhYkef%8Fhp#Pu-T5D>Y_7rtH?60~wrNk%7vDH88VvTnZB&d}c+ zFS+U*R`3G~>iH%d=VTF&o;Vv6sz|`cgz_P`&jHYJ{VR^@qZcq|cM*)+7Yz;%K6waZ zen^)y-4ns+6M_l4Sf>>KmEv!azOiz02h*L8(qWaOSLY}+FNtIoxi4PrV>4fuF8g{G{p+G0?1B&t0V)Hf;TS|S?=UL!mi$`I| z!jb#rK$e5a@J1qxVkj-`kg*%OK##<$lspAhUc`}k2s0Jz_Y18VlQP!C7!)v5HWs8SGg0c^yj(I*haYPh;?T|GJzAAe}npppnSv2jjEV20M zfTo}v9S)OB6HtS}M3RL74W9QkLM{+D#5AH|3bTzAU5)r-H!%URVP;l7I(8@Vpr-Sv zeU<6gFtvyiS{A!$<3Vb_*t)4DpmgX-=foTW?-pvVqmdD?=5m0*aTJe{@J3rPSrs5E z&dLcJ{gB97L}5zWo0t|P<416PNM<%V;9{6QbWIifJI9D1`SNTMNrt|^6l2MhjnBe< zce<~K%hTd>L{X6mXw6#^-C<5EA?^26@;RzWSVwWu>S%^cmCZWc&uc-pf`(C#rq%g7 z3j8(fXXCyw@HB(AWQKRg>-%HhiOq6xoPp(H773IvJ>@_1Sd zCX0m=%MLCevM?pgx@55zR-r-_P&9#271Tl80^q)ud|NT&C8vz{;uZf~bB~}JC%FiA z_6nDyrUkAM$Ofk>QhVv)Y=70#Y&05NiMgLKH1F6b2>YZxpokZutixFq)j6K03^>n| z53*=eAc!wKJNhYG%t=E#n>%aCCPtC92Bd6Z!7}Is(=>5_yYdpZtTL36pNQELLcH|l zRYoK#-`Cwmfl=&zC`QBvsy;}hqyjs5K``)elvqStSX$^VjvanhoM>|@RF$g)L);A) z8PY8L@C;A`NHO`w6!dm@%2HmwJyPfL;%ka5Zu3tl{^7VS7>rrM6p>-S$@SdNKe7QJ zoEXy%5Y>{_NJGhEw-Ur1t))(ZpC}2DStT%dC;h*xe?BpsrM@=jr6)VJNHM82FdK1*{(}|^>?j8no zj+tbWp=3B1K+rgjR@b{U^C4{A813=bIG$M7`8d;da;Ej9w*a0AWonYypR1jqNuka+ z0Ef0hIen&yoEy)V~6+v=1he3~h?P_N(tyVMJJ!2xQ( ztTC$G>JXX<^I?9u)o_nEtu|gGcRc&^PQD#g>Kvo%hO=)=cRWR{eQyog>sCXtQ~gye z=T`r+Z^^SdtFvY*)Y2D4vVDNamw zB1cRIk0Z;DD>ST_pq~s4*Eo75VH30x^Wr5h zk_Aq=z9)vHXY`{C z`%AegCiiw!G()<-vtn`=cg4HIA1#f>@pL4aGhoMYHJpDc8}Gh|YoQNh@7Xwy?9%2$ zX8@$Rd1In_wIcE%GSx_pB{}zz?mAP>CG?)R)g>a;tDeRHvedd&YE>=^a$uvIs6jCz!u4a#Ha zNxY8mHPYDI`&;if_IKX*_Wttr$DN;U?46XVnFG5JyxI8qzk2nyTEF|9mTRq}!0$&E zK1t(9hop`_3&*se{9kI2Aypm`I2*;>Vo>arnnCe-j z#OIncp&aH6yOoQpZK;okjjKdVQXUzZ*i2KCSZfIer`I3XVPpnHPLwcSD=)YVi6xzV zn~Go_Zhgo0+?}~shIqwrzbRO~Q|KTlaEJ_}Um^xKhsID3}X$aoZ&xfh|imM z%@gkF*N;GX>)?&d#^w(Cqu-Sz<6AU&z;(cqJ%Ldq!2cjWov`sby~13R6dcJMDOAv4 zyoC$QI5`^RPV6Nl3@7&fCq#p}94OS&DLYn7jIzv#K8Wkq4nm6`0O&V{pTj~G4bBc9 zc^RH$>cDc9e74m#oXoMuf)FTY6m>4-L49RRP^e&WfTo9y$&eoFYTxbCZgSR5&M8Cz z%zj9=kVM&(Vo2YX#1Wn3cI#-gG+RuI48Xt2AMl5fAqUIi9XiG~AVyd6}^J zA{OfaxP2hY@a1)W`Yl!GA6Ak~H4pIJq1!UQF~+`lz^G)@&LNDLkD}KgJnAw@-@n;iG;PN4!kB7lNBn8r2x=OskFjNxxL&?7FP&o)CL{&i#2klTuG{9bvCWEi5o#y(cQ zd;SGGxko7SXnX&hxZoS~hSM8rEb@3#C>zd}$vh2aC$qj((`f}I+aoeZ$4y#@rm|n6|?Weu!LS<%t1k=;97TZe#uylV97#F-C>blsk+o$8>K32V2^~$QLKa z&XsuZ9Z4harEV>rn7zfd5$84+Pcq9142|4{h7Wf#nkXyX;e#8^PfQjKz?70|CmaUA z`gL+J;slp@pLpg&5f8X9Y2>ULm=k?YWzh>-Y3$;vKbAOMG8SX)M`w*3HKxM?^HFAG zJW`SS22{mM2{$%li|PDhK~XcY9*4f^qxb_e>QJ{e~p^FbFQbX1hH5k)2Waw%m4iJm~Xfy;sM9Y0mhBo$%tW`5Kw5MhE~B8)j$L z!-d_WT#2;72Xx=;$M3B2)LiNmV$Ep!mfTg*{2L)#<8Ix0ZP*+AenlRkM4f2H+E`3x za_U2DnJM*0re(5OoC8EL5=DRp92_Aq5U-C)lwlTx*u4yq2J>SqCDA<+QDi4~#J8fL z#>i?F!wTKOH1IVlX=8fPI(hS>-x zw+WuhU-?=kQ78L@dc(khiC#c1a*N=BCUEj%i*p$c%_h^v-Z-P7sF?XO=LU`PRU#e$ zqX0DF$wbAa-au4$BWuj`G|&!bW3-Xs2LIq>x@KamHkYn3zZg>D98!kYYfSJ&2vIXM^1UIwIA>w)+FapAgUYVyJXqc8aiz<1hD~Ag z2Z5m4w!u`!6#l&-r1}6^8PS&UVyOQe9_|9yte8|Wy_u!n%zQQ+gAp$WETU(~ zV!Wuhj?T73tu3k=TB>8cNVe_zm2ZZ7`zzm6op;^y-DUGg`6&)(Us>FccLR|FiJL(@ zDtDW@xz;_CPnvn`|tk+@nXhT95S53SwlgS33yKi;MM-b55UD zgf=-j2Z2WSX)@?#mkwrnIJ#Qp4{6j|BMKnvvpH zxrk!Qlc}Awnnw~ed|ISo9wjK311c^}wm#-VyU(@*USKDihgpQ!x``mfF=dJ2+8xo| z38l5+H#N>huZ=DJ@Bj7xTv8?yCZhiL|N4LBEC@lCoRwuCbrhM2U8O@&DFP|&s#45O zQ4|h~$^M;WSVA7QvW6mQUZ zIx^KK(FWi`S<=^S^Ia+4@Lj~iDu*$?V2=1fgVYd+`;=Fyw>{^9^bQI8-WfwEhKL-CY3R$DY%;*Qa~;X z>-1Zf70eo&z@!EYvworvu|*qyOUC;LEJxzgqN+wY^HBykUqy!LvA;7$q;fVhq)<8( zt^o$kFa$!tW7{AdNyzE@f`PXCwJTj|Kgp>?C2H!%SRZ>t(_jYE9a0hz=NXC5Vp@qi z&zR2##bG-tr{THOX$@m(>55YZtbwSIo zilG@i0&bkjllGmp(@WN@7Mbr!goO|;9g~T*qe7+ARfPI?2XZ%=pWDJbKAohudf(h{%OS+EAUPNo#tj=3$Kwox+0>TQ zmPXF&q8Jtz7$4ufwYh?l0i#(wP>r> zH`;zP{EZ5x*DVSur?57Lf5Bj+`t13(VJ(wp#4K%M=-|j&cyb4aT1%qD8dpTNczC6h zf+UF}Gd)5UndD{SqNzUw(}L9Y1EU=wEFDG0VK&zt?={j~uGR*+J#sikZO9DKHmGC8 z)9J{Yf{nIHEM|+?jyo@!DyQ{T2}C$%I`PTu1P)3590a=6aX zH_I7|2^OAwJb^kmjk$L1VHb1vMd1;O0idqYPFPK$cz2AnGjs!sTiZ$z} z@4lY()9pNe?_ey|bM$+S)=STy-8l_-pkJS1Aobnd`dIDt&`^n?@HIzFoz=}9r}CuN z3-seN`gnS`KAzHYp-o=%PTaBSXT9EZQVgoOY1yAYj~Zsd;b+q<2V5BHn@jpTFQse6 zzPOp$twDuslAA2j%s7MHpFer>{9y|=wqjebF2h;U$LvR*0)c&=C5VmrKmq#DZIP5Z z*+7&iS48!l8nvo1RWlV$9WE$g&l=ssyBui^n?RWvwCLDj6xHkTw1WGFQ$yW6Yo23Q zVcJMJ=Aau54oU@|sUh=DXrJ2(d+I4K2*Y%ok_z zS7*Y1ZMlx^>=RG-^ObZlo(_ksf2%Mw66V5#>$e;c?}}lpC=e~Psoat#Q^uQNPy$RX z!iu9wQ9H_^j3;GvzT_6{5VLg*!!D9 z)NSkezn~+8fTnST*o6~89*-ufmDr}jqL+hQf{C-gV`!$fN5|>f1cO4(Oq-E+f$xFH zDcrNJK_aArB+3Ius2ae?7J+OdCTdtN>X6u}-wnjc?*p4A2Ny_*lpwT*|zaAAC)h!&_d(QsbXL&sc~ z`tNED^a3X~c$BHWfddlYGG`Lc0rQ41_ZZ4@+$lHg0Hqh?`Cj_aX#pcG3>}i-jjro&^P90Y9{TTzPKA{G`GKdSliES`>u2~3Cwz=t!k!2 zpMHN=l6rQ-&+ka80}TzRAN@Ofz;5Ej()+cV(G6}W|2e7cN5li}mlWf+EjFelrz$me zaZ89uIli_EZNw2k)G!=V6NQj4iZPZWt0F|Jh%Nau8Lo>&XD)GhV=!uW+MlnTA^VA$ zV1lZB&^aon9GRRdL^-0tDM`nHUh&6lB{Wie?bei(fe0m_>U1>IQaCd+UKVx;!)%~M zPm^4gv#-b74m3C!I$S`_L!?7!i~$UFBWvE7(M1y!$7su%FXoGXX}9-S zz?*h)*SoW!bsH?cdC~4j2i&O7d#u=v+P|wPE#CB~tSD#FYa8~BBQ!Lh-8(Mc9Y%1E zrMyFLcNHYYJ1T}igA|iyApHK0CwG2__gJ?1jo)q1-w7Ggcp~peL7R5(F=x}p-G=ZS zuYpmIjMAFtxAG+#zsDr~hVC|)?|T>7WRj0DwuBIrEKUSY9$scZBzw^?Hw` zxmgE>_0r&|yG--$GRfE!by13F^Vg#ZOhegl6|r={;*+9!$V?->7-ml2?C2iQAalWINpj7jbMudyAvPs zt2GQei2L5^I;WEYyE~S8SfCcXo)e{E{9vv8vS9tOThK8UO@T;GIZayF=T^T3g0g{Q2c7u3yBCysxlU-#wWA3J5FT5 zoLC)8Nz6D^b2l8>&y|D_lx}fD*lV*KHU zHEF9nJw?q*tDCg4%j~L!qTW_Hq<8*WQ7iXYuKKug4x}xyvUO~lcsu!Xe*Av_H928< zBPpsMr`6S+MuGvlYvXw1+7?h0Q;owunJZ zv;kDM9|OL{3rzBHqyIG8?q=hYbBWGY$!!)a<@-PEeYutVsXRO5?4r1lEi$RQ$h{uv z%~t|+RO2E}$&P_SnF7Ut$Tm?F>J7uix_27QaC&hJ=;=120o*=&F#Cx7zvx(q`0+G3 z2GL3ZLB(P->69tQ>ZyzB5)&;*$LwfGZjTQzs0>_?9cRc37>_By{ce&*LnZ3zchc$b zd9(&S@UzWv+Z`CE@;d8n)BvGXPKKF#GFT+(i_v6s#je-ytegq&P^6BOD!PO2=4OoP z!NUt6MX8TBfIRl`+rz_-6ZMXXFh81vrHl;OvR0?he^$3ZY{6K+pyJ0@~@yw@o^w~Z$C*E2aeL{Ap=qJYm7-CTD@7w6gyq3IxKZsWboX6O~{)+X1yBzJBHB~1eoilL#S zm7v_L4!DG=!1i>j4J|)g4hlY*(Xuq#RVxibdWz;CkE=9KPnEJtZ13F5`UJZDWXxFYb06 zX)YbE%zVH@C-=H-*dU$`G)%7n1YzPaIGbtvH5bmJO2!rRW~$xGv7)P;R1%(IiqtdA z65tQ-#r=r&`0!B8jj;R;_dRcHk+}r1K-;_BWRsyvc3qlI-S52m!Tjz=^vCD-{L9TR z$U|F9x~Qw@!u#qZI^mfWqAPGe_9DIl-`^ep&pe!7ALjkIjrcHM+`_daji6t_{Qk$$%{^U+HRRVJe~T;Z^G=v`5Jq% z6_Xn2SxkVc^!!!$a_lz5!9O!_d>+=G^z&!Lz^&*)89p?RamiyqxS#M>i@baOwN z2h+$?=Fi0+IFrY3Bvc-LAs)~Dax$0#P9i)xDYs{0$`^u9C*@C)Xd`Z1v+~3g+z=Vr zwuJDDmtTzmmR+&!z25e_*FXKdxwYrvT3g~9HfF$Z+o-dk-rUe0J4of}?6|ZjAt_jp z&PFHJ-jRSmP9Y6K7|f|{`s*gOIz+awtH+VQ;wYJ{lD+IA{{>6^51=)lqD73~u!!n1^czBoW)a1o8Ak`D^Wdx*QeF7~&qWRtAcuEt%bb7Ud3AhF z1E#riKp!4IK2&AxZAZc5;P#+zdgvGnka1*T2uKqkf66gxXUhS`QVmvZ5sxjiEgZOv z;x?`O(^*es@SWOP0GY@;SqzgMKf0w%`H*NwTq+rBv^qR2Yltc-_aIpF#T8A+Qa|DM zqc&m9$j!~Le<}^f@c7-tEEdO4s8sZi`Q4k&pwdcbJG*;LSbasxjJCI$nu!t|b&M@( zb(m9;k>N*;*Nu7#9y@-AA*H9vpW09E0k3Rn^IaR%FsfUyTo`72dy89>_Z05S{Dc+c zA97Bl;nV_HM?$J$b8JZ^#2vD-T>7AZbJOX_6glcD6kwjn$qWP^W6-g(d_QU*=b73ZJQ%toCBPP*PC3w*W`13GFW zEx0W_u8zOFY2Uj}pa*`39?ZFv-fndh8xYC)=!x!xNsSEmGu2*mwxGSDEwbp$ zU-EkYM09RD1aSp=Hs6(Z6wiD?4u|-5Yk#AOtz3rVc9BoAmTW>%&D;YcF2dL)4L-pZ|7^lZX;P_l z@cyM9`@EcTKchh-*-<0?sfIVsTNjD9J>X_?@>&wZzTevVA4s9Z;?DxN;aVejt+<`F zWdIU-PCme?MiY__>(gbbZ($9iRE{hI(FeE@U3&<{tYj@|?O=qC$B&DC7fE5ExtKAX?K0e5aFJGf&Yg=YB>A0c{Jru=0Wl$i&lcv?oAl=de1QpS+71r#t^-HkIj) znOEKuz4B&LC(oX#qJd{;uP>v`ft8S`tC!{Y1EX5yS;=q33CY^e(af$GVzi4B8^E5d z!; zrOwWaUq1{khUMsQ<7z@!bmL$TZ4{s5^B*Zk$E4kA0bx*%x3ZISXP_UD_W$wV0~Y_V zF4VRvTLhZW?O~&XO+J7&aRFrgk?v}{rGD&m(qGGBh@D~KKjKXex0C5F3ZEphtu2RL z35+tg2$Qa4?)yZ0%GJqDnRUs2iY8wUiOiKbqL8>qLr78TBM|NBJ}E_Pb2KYm>Ih3L zeXM=IGQ{#;2c1h!vWX*#ftRS>w?!ht)qtYrufNWgz8ISN*SgeYPlYZ-T>r`vm;D1t zLA`fiGEXbC?89EeAirr)v92uN&(Mij^xa09moY>(oK0gZCbR{GV9&uwl4(E;XZG(@d8 zh&p*?Bf`lx;>49&^1`RNg`BCmsT8jX0{rulp1S?U2ChS?w@tzEWKmV*%VNRi+jvJ;GsXBj`%4}2p|1#wtY zLI~ZC8`adxeinm9#1$3QT4(@5w@YF8EO~N@w`Cjq71cjp@4$l}K-oik)zeQ!CD61X zW8j&KzNCiRr<__urrVZ((>>ry_4!Tmh-cx`OE8o+j34(3*mgcNv?uYcT)CeRAH$9V zsVGRq+RI@Mtu)zzef;>nFngAyBx6V_X>!~wL}L?j8OdFKQ^C(oFE5Uj>+b7Lmq!)7 zM|??xl!Ft;W3)!1p(dZdKTaO5IZSU>B}SzC;34l!l&6BiYl_AKlVbp?cFU}I3sr@m zui<3JNkGC!j(USI9B)jcrfWS7xm&(X-jh^dUM+8KEV zXVy(t9fwGh6QiPb29ws)mNJwB32ZY*re{};`;6H*G z`^An6VS{?qVITc!c6@jubSeLr27 zPyoY8ewH_BbDrpN(ri!-XqST3IEEd3P5maDc!nVI7DN5+Vvd)M$t*m)zth{>f4}|i z_YL+IoQiBz`Z`!7yQ!PD44KMx9A=(9 zFB2<4H{(S?W6Rx5uA5QYC+FGtH7vjeT)@(?=4rxqKlQ&~rp7ZMJmJ^z=_z;hI9VZ) z{eUpTajh*Z0K5k^al%a;a}%ehrvh}ZyfJcp8V3wElQL^T8K!88E)8K7OSZFQQ3v|l z-vYUS!c-X1qI8Wvmp`p6!(XHA!OF`0^q04S-HQyF*|*u`JcUPjR}9U&VmRAgz%#62 zIh?V>Q7~dQ*OjVK5rmXiH~=mHE5prnlVw~==sIXVzF7COcO<3uO1kna*%#ZQTdvSY2)F&^Nm!Ge^c(MBI z>GP+{FJ7!f7wLYA!iYvZ>-YD|pNG{+Il_y!iJp96G)|Lz)I^pnt2vsgUmFcAtypkA zb4J>6)Qmq#pNg@8xrEbvIKebo?T%9lASoWf+#j*#n>da@jr3Ka1-lMH;< zX;U*@wRY%w(1gulj++l~N`yzl5Fx#Zr&!f;9ReSgb(x})O0WKhx&+MYO$X2vN173P ztJQ$w_}(nRGm zS_TWjLYcN0u#IpKlO(#pg?6*N?zG-LuJ&!xevv+f|9#g@_~ChH!JM{qLt8`fqw^M8 zf$qYi-j+pJk9@JCtbda;7cn+oS-GDgUDX&*=BP0`H)Nz2W-^~HbNN~1(QyaPmF4f) z{G>MD`)P4*HVdoVSxw*(&*YQznJ$pn((EJ$uBh&?Q=hv(U#=IQ?~~<*>E2&(dz)cAG_RZN%9DSeBT^on~7oB#?Z=_X6`62HT47!*EBE?`>ZKKC2gp<)=3gPnJTXLs3 z=0#jAVOiT7LhPKA=C|H}VSvNHVMGCH^(F!?np~~s{kZ1{z4%SmD3wCJCo;!Mv#l_t z^;~$>Mk1<-X5wnFmi!Q*y1}7OFpHf;}-&moBa|LP(bVGYf1;JbVr2X32h4v z!K3zt8d4yU%(5?Wrx21YNu#rW{F2K!B7m@Y`mRm0XrtjYu6|J)U0C+5*KarW$o4b& z&S>td^WuUP9E0*W8#LNl-_&kyb8GMQ`|aKRo%c<~4aU;oM$-Cm&fC#cOf4m5SP8By zKkKA_-1>`jJ6E_*%-DH0Zj@I&(dD?Ek@B=?6o9FH^yP=fkv*|Rwmvo9OfPJy%~|XA zMEOJ@R2wg@m1UhMx@pW%=DyHw)mFW!Jzd_Lis5hW&b4c702?N(0Ls+a4BJj)f<8N{ zhOuc!y;$>(tSswFfAjmD-OZ*mVf=hI=c(Vn`EWDaBJ7H~R0S(3_Mv_KEoxaAzP|m2 z%^~muAq3;MNgw}nZ|9x;gui5|*hmtSzrB=F|M4IEkeW|iboc$v{?7hicG0k@WiGB3 zfBeJt=H?dm0Px#x_0EfaKOd@b@BU72_x<+U?fvavwzP<|@zw@dOiDgqr)qh$P4C#z zh)eOb-sfk)9gfNGg-(21j6oO2@gBkeQ0U+iZ>N9m>W3WKM}}&7agCoMIcJW@*aWg$ZWLEQZOSCJEmK-Do26 zL0OE;lMhR%v|RkPS}LjvxYnhW=T8*zO-SnfkBKi$Q!H!Xof zCqsshr@8Hb4V5;s6jQPT%+(+Vgyj@9CPXkor<+<`vH_itrqZd6mMgW6yLN0HHb?63 zs+q<(8+iiVNp@zZ1m^%g+JkfeUnvEXEV#h811Id3a&^ISH7M>%gRU-E+RbO)pe^U* z*nEJ}bgIO0VD{Z8fsWdV^Q31Gk?=(5qhUUzgn z3Y{(n3Qyj(gEqWRVn_W=&C0C_NQ#^%yBk;~6g58~rQq7Tp6q+KV+wkfY=gM9Ti`Cl z)@>pDSzl7u){U1wZaDspp|rwiEY9RKt~MP2!==IL?U}Nu1gb4w+xd=-*?$rGg=cg?~_9LCb5ttI{{V9onYr;n`rTX3Hq72!adsGB-k0akO~XrBq1Y)O%M)s9kN& zZ22bWr<1sN(!po4d7DjZTQfbJWdexxhf*PGx)->x9~?#zfq&wuLC=xg!Tym&ftIKW zdz0g0;7cHagwVGy$j9Wy-sX|Tv7~py@;EN_W`VZ%dOL^^>+rK4TS6}W$|3aElCQn2 zH(FIQGJ@=oQj{Ybc=J1im_f}^&wiHcJ|z!oagjJsFJf5c!w#iue_#nO9=_!y&4#Fh zg)==ugLQhTZYtN3=1kNZC(57%zTu^vkR)bW^xL6>f>;w+w}ItD&uYrH@eP}{SsKrA zM)pQtC&r*A-vthW;o9p9K9y3#xB61iMHlDN>G*h9h-Qyq@u>}N7s`cH6%Rv66>E|d zut&_?b%ItssG`O{N1`!y*(mWF6}UTE31kk4ArK8jVq|*}%D;;l-|Nz8eb){&9*)|Z zM5&32K2RLdbor1CEy_c%kWa(lr$&2qS7=gipRjOK{S~PnB|VxdJz43*Iuhuj*+zCT zs*PKH(XlHhi|=i0D>g9Lf#`spOPInWvS`w`QYYLNn!F<3j3^!aS`k+s76A zXq#NIZLU0pZd-7~w*}dCi|REwA?=MY?F22T@~2%22;Uv&qd^8GIUz;28s#TI(00k! ztm{xj-HDY#cc<2(ptaCZ$Fwd+qhMDhXEiKh{B^y9J7PbvJCeJIm-%4u$6Gzt#Ru*pENeUZu->uK>2_G|;Dhu!SJ~`tzuXNXsIhyi_Z9l&5j}xh0M9L# zeK+K%fltK4zI>3c-N!GJR!fr!y$VE#bcq@($jCQbF1Y{=Y18$F`%H%m-`~K9tE-C+ z6TojUlCBxDe0B!Tj%7~kZeWI;)7WeTIfvIQ&C?Ao$3hReVQIkAD&M0kA{2%hsh}8B zYvBUZC^Z)5n+zRZZoltV7i<=itvTkIa3sb`LwL`w*TB;o8$~2Fi-zDT@f&{9QhviC%#HTV!Hu!2&x_9a|O3%eu#!XMw2lIDqZRq+35xevpTRU9-uP? zV|%-oZ1vA_q^CaSXzs{|jtMr*Y)8XJ#}LX|h<-Ks@gIxH4Jx4D30L{$dp_(HMiMwK zKjnQBT+Pb9?aCbN9g=%->j0ZLY>`j4{row}0L#HOOJzP^hu?)KLZ@0OfMRbn2Evia zi8aL?8I=_7wsPvtt70Sp|r%zT#PrEEQv4Y-jTb#<_EXvuLAI@=zJsD=2al^ig7s)%mxYTp>XCzl@vZiR-rbh8epc`Xf(KL z)6wiwHT9S5IJ_!aG|Oe`8pk*^(_#C(z`$&E-s8YkG#)m_B3SK2`4+cwH>sCkYiP>d zU=kSKNMEp;SL5bf6My}kFa4rrL&g=b2&wV9s` zG8hadzkqiXP?ie}3P7Ik;WDA0(3tzoz0t2$@)*f`c)4GG$cJ1an`HarY*?M zw>bUbEDikPRe-th3o`cpae8_xP0}9ho##1M-_JiypvK9E*Rl)JrFqY#%IOJ>ujR6t zF3Ttef#~z*LV;?Pk^91gICDKHX?3a21YZuXbOt)BLq zWF_=;;6XW1Ka>z}#DWp;8^=SWd&e9h9!$(V;JS_-zGR3ZXiyT~CBJOEPqyFv=ho}} zZJ_=hE!nnV78vsisza{}2`053T~SI*xHDFsEMjUJgy-Z9T)oF-`JtO^4^L7o2`7Y; zXI3Z`2Ar4o@%;j&YNV{zluQ;aG>~gVhrc1_)|gUOY)oMHOQ8qh3h-U!f6KoF3 zj)12dPITZW*$@-$xZNhZ8~a=D_V>I#D-3gC`jlxdX@>fqiH#IRmaB^JC@%U;yS48W z1NVv{{8MC&QEn-BlK?C3V44p-d5b`yRsbpJnF*%`O`F4il5K| zreEDH;gF)u0p+h}Jr5imjl%&4<%oO1Y)9ylIfl;jqm*h>epEKbM(EG`Zwa1659W45 zgRF{4ZnIuiK+WfXbkEN7@!}x=m=D}Jwd z8-<~Uo;Yni7UJgoP70YKluAfoM%A+9h%?0>$qu+v;-!9jWi}kvxi+BoXDysa(s|2l zs~UyBnzQuVe(~`KIQ)YW<97`Dzg@x?>$c>zK8lJ*ml)9kEsa05YC2*sPP?#tTc4Bz zTo{Ednm^(RXMF&zU*s8~vUZ-HrDi=kX|k8+abVOe;g6CF4E93k3f5?xpJRwaz(d+Q z-XK>3O(Sb=gMp45fTv3eTZ>KZvVi*$4oLPfD+V0MUJ|Dp|5s;;epl!qlgPl`GH{{E zk>YKR6gN0XP8C+h8<9+~VO{C)X%rO%SBa_*xH%U?B3xI7ONF6STG9r8M+fCIHF|Ac zmLtA%$zS8EPaq*de~xn#N5Uk6 zHhW8BZ&j{VnAFO7)=$WS&k3rMv@t0=0HO5KX_zyQa?Yf=srj=eg-4+`CQg@7kmi>! zs<~Tmqv4F?#<=Z(A72fjT$ztkEu^DDtH{RE1Z3 zUz^hQ@FQ@feLi*`z#`TMx(Pb$r^zoYycJUPA{&kHU?_e;qRE2&5ox?}v#TTIW$2s` zP>JG3kQDUVE>fVBrxdLg$l#-5c*H?rYG6;~JkKN{s|+6Yaej(e^yn;~Y;*3sJ%D+@ zvUpGtb@F$hv9aTEKDg2bVPSZn6<2_*Le@pzVIpsQUE4ABnYz)QoneG(oA2D;vEJLQ z_rKrTjDVT$NjW^pb%xDbgEyNix-`3jVKcSKjB<2qenBaS6o#_|;aq9_?yA-=XM1_O ziN^KHE~=fOpE*;%oR;N}+27ZQV1b7>W!dhyC9ds{>-+A2KZBd?z^yxZ?bFXU>f~q4 zP(;UsvMTxKhN9Nuklk+rs&HE}p`o`wQ6zM;Ovi?0X+)3j%H(XCAwQbuOxIpyaPelx z<#fV$fT-0=XlRnN{Yw4hp;Nv#SWGx;EFLjpr7D!~<)^0{AuWWeCQ45?UrpQ8Uy@dY zxU=;L%vpl4n|#JX*AE<;a1IRlJju25ov7o!x6L|k-QAscuea)GcaWdquH6Ia${__J zok`_B0RwLjY&|kOa`t`X2!vH_^)XZ$Q0hQP0$>v1hDlXgqhI`kk`W7qBy?tk_8v1@xdQ@2%S}}Z?p~w!^ zHY`ITve+!!AIeMM<60|iU>(=K$Es7m@J%WUO4O<4iYgJ(;+4u z!=Qm9a!^((9NUdg#%zN-r?zH?{ku$%0TSJznI-~UQH)`uCdEZw+l3KK>mvCKeG12Y zO;Rir{L(;j;p)s<;hh}CBlC82v*_P$L!(#RI6uiTdM4cwi~?@8)?+-{Bo-2a7KO}A z5CL#cQN|!Mv=|ikhKZ4o3`ky2$7388<7-5k80WJ>VdBRk^Kf?^<9WdTo+l<0fkA@k zQ%>(V@r~Ri0c!L{)ef%PLGd961`JO!&S5PvO{VziHSS6BgNswmYwzyu%)p%QcJ{Z{ zkmNAu1u-R%6Sy`fQ#TpceqXhWW)!E>%_9VJk|F25MdMM6m?~30f8))V`XA)ceajP z*N!8`VX)dQq_lxi&Im~|@{DY=idS_+OEjP*Wv7UIWon%+VKS$diEC>->-s_Cbukw@ zZ)@`*BiNjE-Zb@Kj+rCf+V&8ki;8~^ozl{QCEjM1mN7_qS&vz#aXx%Xfmdz`8q~}Z zGLRa%bX=B509+^g73Q+DoR`3lyEX65|1G1!yxGbaDWe~=@_Hh^+{~J zUXR>uAgcSwEHIWgYk6e2EUe`$U=5+nK2|^-pcWL91dT-Btal?6mPwT-C)085E@Zs? z7r=Or9x=1~=uw29ZFi2Cf-$7s?NQ#B0Vyd%1UR5bV08iGks>&wqk7Go#y@U>ZbLx2 zH7(hyA|#_FFa_WKGw8mCuEHI{6k4-)2usY~AuQ3bL;oCt@!s3!o&RH$h+LE(p(Jt7 zBw@{neq+Yqqge|46xr{74*Ya^b=!^Z=ct4{;rrF$xu9uM4L6)ym!3NEmPL3f;OS5n z z*R-u4uTa*GQZ>FQtxBq5O+>2_)`-Q5$S5&_DR^^D`ey^6d*$ey@&OSobwXx6%u!z! z)j1tuU=+v5SQ9>NIFh%-X09%Uw}d-EO^vrJj0wzTiD~VA*?RwedvmMz<lf8%kdb}5L)dx=QJo^zWY*2f>J)%>onK=1%Fd4qZfB)`@O=*;W_vg(4amp(J}BG}`x+kq+MPl~X%e4Jt)M@#TbO0=-$yiU z0Pw}OHuKXtopr_HLf*B^w5}tYSF4S7G!ih?^#55FU~XkwtoBL1bUdIqxyfSwv(_APQlika7WJh1i+#3dui&9X4cMHl36gf=2#o+012{@XKy85VJHLow@1|U=JJ<%BpmXzufwL3V~Lk!j07`2px3d$xsVk^m?0Hzw~;h z(w%@S(IL90F3~7bGUo%GBq!0fu036^QtMlQiEk^mQ#<+=)%>Iw#En@u>OeF+GP~A= zbz-`WNK&@h_S$5sPpt~8H0ZO5e)-2gq$*L0L8WFx#RG+pL%)VDfb+7M$XF2P@)~Hq zB?50pc!qXSZ4A(l`f5|dx4NF^6n_j33|Ti`shyl}P89+p)tAA%id8tk64vJz{p8jS zU1~&C_}Svw7f(D;l(*}U)-4r z8OyDJo!bzf*z~$rs^Ak(X56M6R|*neVqKGJPVms32iS0vxufxM`a`^~{=)hx9{|

_N)iz**{1W1Xsu=Qy~M(t|8iuA)7jPctqbCFiMtF$Dq_@6ar%jeyf@?Zm* znU{5pX6Q4FW~dUztS3AVO_ljh99XLA0Wv!WqmvO?~` zzQuOxKcNDS>=-Dbbbj~Bkx9H+Y=cSHb*Df`&KL-c&DvJH4K2Rzu193o=B;nN3QwcX z#AE$taRsdP9^lB4fj^G*$p>=HErxc#rzKK;Oe>-buBj!GB)p}N4O3AOF<{5&Y3Mbz z0yMAQ9~L2*#@ccQ9vTOchn>`|znUhpzWvPnLXt`JY05m|$zt6*54;+y> z!cTn5J|n0_`ZnY=r4?c!2<@V<$+fJfXqRg^7tAHiz zCWv1MQ{suTn=={H)h%N%P^$qo2cx)DD$+(cgu5PI!~RZ!ebE!*}4Pc=*7{9A|$6wd-4vd&=>qftyz|lNL_g9yt5KBKR z0~972IBMaA#U!)dB)bfq77QOHhUp6rw+%5p6++FCJ!M8{6UvP&GD3k=*LC+C{i;y6`cdLPLow z)ftfFoNRgkcZ%a~&7L7>(lKvnmTq|qzC8qHsF-*w?ts>ur8c$ivesWv&KC+{)zb3@ zaz0N2(ts8tvOv5alF4PMKFey9jv*@HKpX=@t3JavTnEAf)#pY+(><6llkw!X!EY5w zqJ`#kVhjN5m2oUsxk7s*mHSB1z-oQ7)>|3NYiPdnM!n3H#ne6hRvNrNCLL@$42fE z03=I5T+mx1%oU!XT9c0G+@7Iz(nMxsz-uT$5=%QNN=_Oq+JydV4F*n^?GDOT0!=%- zRAP{UmE=1zlUj>3HI&*BWK!}EkI;oT=9fbr*$u#fntVfg!u7v$TA=iL?cBd6x~y_E znIa@6OVo-Mzy_A#@BpweB)l!go?~tmLj_uw)yNj8l=Fm6bjDq;7LN{kcI02|n9 zZ{l+~XMobEkf9|Y^gk{>iXE|!6J`+6Aw~!@#$Gs;+CCwY!Nx'HEA98JhdN6<4) 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

6pb18P{vZ(vfGI?N&JYmGjI??^*MW_B(_Aau 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

Q6>6kbG@K_H#HLeiWd<6U(=5jfFMb-`U(* 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�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 From 74a20cbf7e84983aa01a9dbfa73638538eb977eb Mon Sep 17 00:00:00 2001 From: Harrison Healey Date: Tue, 10 Jan 2023 17:26:08 -0500 Subject: [PATCH 10/41] Add Boards build information to client config (#22046) --- config/client.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/client.go b/config/client.go index 6ce5433dc1..047d9eef1a 100644 --- a/config/client.go +++ b/config/client.go @@ -223,6 +223,8 @@ func GenerateLimitedClientConfig(c *model.Config, telemetryID string, license *m props["BuildHash"] = model.BuildHash props["BuildHashEnterprise"] = model.BuildHashEnterprise props["BuildEnterpriseReady"] = model.BuildEnterpriseReady + props["BuildHashBoards"] = model.BuildHashBoards + props["BuildBoards"] = model.BuildBoards props["EnableBotAccountCreation"] = strconv.FormatBool(*c.ServiceSettings.EnableBotAccountCreation) props["EnableFile"] = strconv.FormatBool(*c.LogSettings.EnableFile) From a9bac806f3f4e0a0b949e1722955008b06cfda00 Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Wed, 11 Jan 2023 08:39:54 +0530 Subject: [PATCH 11/41] MM-39215: Add DBStatsCollector to metrics (#21957) https://mattermost.atlassian.net/browse/MM-39215 ```release-note We now have Grafana metrics for DB connection metrics. They are: max_open_connections open_connections in_use_connections idle_connections wait_count_total wait_duration_seconds_total max_idle_closed_total max_idle_time_closed_total max_lifetime_closed_total ``` --- app/platform/service_test.go | 1 + einterfaces/metrics.go | 3 +++ einterfaces/mocks/MetricsInterface.go | 7 +++++++ store/sqlstore/store.go | 9 +++++++++ store/sqlstore/store_test.go | 2 ++ 5 files changed, 22 insertions(+) diff --git a/app/platform/service_test.go b/app/platform/service_test.go index 8654b18685..3b97b68eed 100644 --- a/app/platform/service_test.go +++ b/app/platform/service_test.go @@ -141,6 +141,7 @@ func TestMetrics(t *testing.T) { mockMetricsImpl := &mocks.MetricsInterface{} mockMetricsImpl.On("Register").Return() mockMetricsImpl.On("ObserveStoreMethodDuration", mock.Anything, mock.Anything, mock.Anything).Return() + mockMetricsImpl.On("RegisterDBCollector", mock.AnythingOfType("*sql.DB"), "master") th := Setup(t, StartMetrics(), func(ps *PlatformService) error { ps.metricsIFace = mockMetricsImpl diff --git a/einterfaces/metrics.go b/einterfaces/metrics.go index 56e6cb5aa0..fa7b5d714a 100644 --- a/einterfaces/metrics.go +++ b/einterfaces/metrics.go @@ -4,12 +4,15 @@ package einterfaces import ( + "database/sql" + "github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/mattermost-server/v6/shared/mlog" ) type MetricsInterface interface { Register() + RegisterDBCollector(db *sql.DB, name string) IncrementPostCreate() IncrementWebhookPost() diff --git a/einterfaces/mocks/MetricsInterface.go b/einterfaces/mocks/MetricsInterface.go index 18ae7ad658..9eb7d06b13 100644 --- a/einterfaces/mocks/MetricsInterface.go +++ b/einterfaces/mocks/MetricsInterface.go @@ -9,6 +9,8 @@ import ( mock "github.com/stretchr/testify/mock" model "github.com/mattermost/mattermost-server/v6/model" + + sql "database/sql" ) // MetricsInterface is an autogenerated mock type for the MetricsInterface type @@ -302,6 +304,11 @@ func (_m *MetricsInterface) Register() { _m.Called() } +// RegisterDBCollector provides a mock function with given fields: db, name +func (_m *MetricsInterface) RegisterDBCollector(db *sql.DB, name string) { + _m.Called(db, name) +} + // SetReplicaLagAbsolute provides a mock function with given fields: node, value func (_m *MetricsInterface) SetReplicaLagAbsolute(node string, value float64) { _m.Called(node, value) diff --git a/store/sqlstore/store.go b/store/sqlstore/store.go index 28a86886cf..4e5641c219 100644 --- a/store/sqlstore/store.go +++ b/store/sqlstore/store.go @@ -301,6 +301,9 @@ func (ss *SqlStore) initConnection() { if ss.DriverName() == model.DatabaseDriverMysql { ss.masterX.MapperFunc(noOpMapper) } + if ss.metrics != nil { + ss.metrics.RegisterDBCollector(ss.masterX.DB.DB, "master") + } if len(ss.settings.DataSourceReplicas) > 0 { ss.ReplicaXs = make([]*sqlxDBWrapper, len(ss.settings.DataSourceReplicas)) @@ -312,6 +315,9 @@ func (ss *SqlStore) initConnection() { if ss.DriverName() == model.DatabaseDriverMysql { ss.ReplicaXs[i].MapperFunc(noOpMapper) } + if ss.metrics != nil { + ss.metrics.RegisterDBCollector(ss.ReplicaXs[i].DB.DB, "replica-"+strconv.Itoa(i)) + } } } @@ -325,6 +331,9 @@ func (ss *SqlStore) initConnection() { if ss.DriverName() == model.DatabaseDriverMysql { ss.searchReplicaXs[i].MapperFunc(noOpMapper) } + if ss.metrics != nil { + ss.metrics.RegisterDBCollector(ss.searchReplicaXs[i].DB.DB, "searchreplica-"+strconv.Itoa(i)) + } } } diff --git a/store/sqlstore/store_test.go b/store/sqlstore/store_test.go index 180780661c..bfd10d14c1 100644 --- a/store/sqlstore/store_test.go +++ b/store/sqlstore/store_test.go @@ -24,6 +24,7 @@ import ( "github.com/mattermost/mattermost-server/v6/db" "github.com/mattermost/mattermost-server/v6/einterfaces/mocks" "github.com/mattermost/mattermost-server/v6/model" + "github.com/mattermost/mattermost-server/v6/plugin/plugintest/mock" "github.com/mattermost/mattermost-server/v6/store" "github.com/mattermost/mattermost-server/v6/store/searchtest" "github.com/mattermost/mattermost-server/v6/store/storetest" @@ -731,6 +732,7 @@ func TestReplicaLagQuery(t *testing.T) { defer mockMetrics.AssertExpectations(t) mockMetrics.On("SetReplicaLagAbsolute", tableName, float64(1)) mockMetrics.On("SetReplicaLagTime", tableName, float64(1)) + mockMetrics.On("RegisterDBCollector", mock.AnythingOfType("*sql.DB"), "master") store := &SqlStore{ rrCounter: 0, From 605e16fd4d181b601f7926b63c287e1e0ce91da3 Mon Sep 17 00:00:00 2001 From: jprusch Date: Tue, 10 Jan 2023 16:23:53 +0100 Subject: [PATCH 12/41] Translated using Weblate (German) Currently translated at 100.0% (2433 of 2433 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/de/ Translated using Weblate (German) Currently translated at 100.0% (2428 of 2428 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/de/ Translated using Weblate (German) Currently translated at 100.0% (2428 of 2428 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/de/ --- i18n/de.json | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/i18n/de.json b/i18n/de.json index 82a8cccb82..3015f856b6 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -648,15 +648,15 @@ }, { "id": "api.command_invite.hint", - "translation": "@[Benutzername] ~[Kanal]" + "translation": "@[username]... ~[channel]..." }, { "id": "api.command_invite.missing_message.app_error", - "translation": "Benutzername und Kanal fehlen." + "translation": "Benutzername und/oder Kanal fehlen." }, { "id": "api.command_invite.missing_user.app_error", - "translation": "Der Benutzer konnte nicht gefunden werden. Er/sie wurde eventuell vom Systemadministrator deaktiviert." + "translation": "Benutzer {{.User}} konnte nicht gefunden werden. Er/sie wurde eventuell vom Systemadministrator deaktiviert." }, { "id": "api.command_invite.name", @@ -668,7 +668,7 @@ }, { "id": "api.command_invite.private_channel.app_error", - "translation": "Konnte den Kanal {{.Channel}} nicht finden. Bitte verwende den Kanal-Handle, um Kanäle zu identifizieren." + "translation": "Konnte den Kanal {{.Channel}} nicht finden. Bitte den [Kanal Handle](https://docs.mattermost.com/messaging/managing-channels.html#naming-a-channel) verwenden, um Kanäle zu identifizieren." }, { "id": "api.command_invite.success", @@ -999,7 +999,7 @@ }, { "id": "api.emoji.create.too_large.app_error", - "translation": "Das Emoji konnte nicht erstellt werden. Das Bild muss kleiner als 1 MB sein." + "translation": "Das Emoji konnte nicht erstellt werden. Das Bild muss kleiner als 512 KiB sein." }, { "id": "api.emoji.disabled.app_error", @@ -7237,7 +7237,7 @@ }, { "id": "api.license.request-trial.can-start-trial.not-allowed", - "translation": "Dieser Test-Lizenzschlüssel für Mattermost Enterprise Edition ist abgelaufen und nicht mehr gültig. Wenn du deine Testphase verlängern willst, kontaktiere bitte [unser Vertriebsteam](https://mattermost.com/contact-us/)." + "translation": "Neue Testlizenz konnte nicht angewendet werden. Du hast bereits eine Testlizenz auf diese Mattermost-Instanz angewendet... Wenn du deine Testphase verlängern willst, kontaktiere bitte [unser Vertriebsteam](https://mattermost.com/contact-us/)." }, { "id": "api.license.request-trial.can-start-trial.error", @@ -9725,5 +9725,25 @@ { "id": "api.server.hosted_signup_unavailable.error", "translation": "Das Portal ist für selbst gehostete Anmeldungen nicht verfügbar." + }, + { + "id": "ent.elasticsearch.create_client.client_key_missing", + "translation": "Die Client-Schlüsseldatei für Elasticsearch konnte nicht geöffnet werden" + }, + { + "id": "ent.elasticsearch.create_client.client_cert_missing", + "translation": "Die Client-Zertifikatsdatei für Elasticsearch konnte nicht geöffnet werden" + }, + { + "id": "ent.elasticsearch.create_client.client_cert_malformed", + "translation": "Dekodierung des Client-Zertifikats für Elasticsearch fehlgeschlagen" + }, + { + "id": "ent.elasticsearch.create_client.ca_cert_missing", + "translation": "Die CA-Datei für Elasticsearch konnte nicht geöffnet werden" + }, + { + "id": "ent.elasticsearch.create_client.ca_cert_malformed", + "translation": "Dekodierung der CA für Elasticsearch fehlgeschlagen" } ] From 19f4b36e0a44fd5dd29aef58309d6298981ef6b0 Mon Sep 17 00:00:00 2001 From: Tom De Moor Date: Tue, 10 Jan 2023 16:23:53 +0100 Subject: [PATCH 13/41] Translated using Weblate (Dutch) Currently translated at 100.0% (2433 of 2433 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/nl/ Translated using Weblate (Dutch) Currently translated at 100.0% (2428 of 2428 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/nl/ --- i18n/nl.json | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/i18n/nl.json b/i18n/nl.json index 45c0f6813e..a10623f90d 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -648,15 +648,15 @@ }, { "id": "api.command_invite.hint", - "translation": "@[gebruikersnaam] ~[kanaal]" + "translation": "@[gebruikersnaam]... ~[kanaal]..." }, { "id": "api.command_invite.missing_message.app_error", - "translation": "Ontbrekende gebruikersnaam en kanaal." + "translation": "Ontbrekende gebruikersnaam en/of kanaal." }, { "id": "api.command_invite.missing_user.app_error", - "translation": "We kunnen de gebruiker niet vinden. Deze kan gedeactiveerd zijn door de systeembeheerder." + "translation": "We kunnen de gebruiker {{.User}} niet vinden. Deze kan gedeactiveerd zijn door de systeembeheerder." }, { "id": "api.command_invite.name", @@ -668,7 +668,7 @@ }, { "id": "api.command_invite.private_channel.app_error", - "translation": "Kan het kanaal{{.Channel}} niet vinden. Gebruik de kanaalaanduiding om kanalen te identificeren." + "translation": "Kan het kanaal{{.Channel}} niet vinden. Gebruik de [kanaalaanduiding](https://docs.mattermost.com/messaging/managing-channels.html#naming-a-channel) om kanalen aan te duiden." }, { "id": "api.command_invite.success", @@ -999,7 +999,7 @@ }, { "id": "api.emoji.create.too_large.app_error", - "translation": "Kon emoji niet aanmaken. Afbeelding moet minstens 1MB groot zijn." + "translation": "Kon emoji niet aanmaken. Afbeelding moet minder dan 512KiB groot zijn." }, { "id": "api.emoji.disabled.app_error", @@ -8772,7 +8772,7 @@ }, { "id": "api.license.request-trial.can-start-trial.not-allowed", - "translation": "Deze proeflicentiesleutel voor Mattermost Enterprise Edition is verlopen en is niet langer geldig. Als je jouw proefperiode wil verlengen, neem dan [contact op met ons verkoopteam](https://mattermost.com/contact-us/)." + "translation": "Fout bij het toevoegen van de nieuwe proeflicentie. Je hebt eerder al een proeflicentie toegepast op deze Mattermost instance.Als je jouw proefperiode wil verlengen, neem dan [contact op met ons verkoopteam](https://mattermost.com/contact-us/)." }, { "id": "api.license.request-trial.can-start-trial.error", @@ -9725,5 +9725,25 @@ { "id": "api.draft.create_draft.can_not_draft_to_deleted.error", "translation": "Kan concept niet bewaren in een verwijderd kanaal" + }, + { + "id": "ent.elasticsearch.create_client.client_key_missing", + "translation": "Kon het client-keybestand voor Elasticsearch niet openen" + }, + { + "id": "ent.elasticsearch.create_client.client_cert_missing", + "translation": "Kon het client-certificaatbestand voor Elasticsearch niet openen" + }, + { + "id": "ent.elasticsearch.create_client.client_cert_malformed", + "translation": "Het decoderen van het client-certificaat voor Elasticsearch is mislukt" + }, + { + "id": "ent.elasticsearch.create_client.ca_cert_missing", + "translation": "Kon het CA-bestand voor Elasticsearch niet openen" + }, + { + "id": "ent.elasticsearch.create_client.ca_cert_malformed", + "translation": "Decodering van de CA voor Elasticsearch is mislukt" } ] From 5ce9563d390d4cddcca5d9b2e2d20aa8171a4a14 Mon Sep 17 00:00:00 2001 From: Kaya Zeren Date: Tue, 10 Jan 2023 16:23:53 +0100 Subject: [PATCH 14/41] Translated using Weblate (Turkish) Currently translated at 100.0% (2428 of 2428 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/tr/ --- i18n/tr.json | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/i18n/tr.json b/i18n/tr.json index 2eadae012a..df4ab52fed 100644 --- a/i18n/tr.json +++ b/i18n/tr.json @@ -648,15 +648,15 @@ }, { "id": "api.command_invite.hint", - "translation": "@[kullanıcıadı] ~[kanal]" + "translation": "@[username]... ~[channel]..." }, { "id": "api.command_invite.missing_message.app_error", - "translation": "Kullanıcı adı ya da kanal eksik." + "translation": "Kullanıcı adı ve/veya kanal eksik." }, { "id": "api.command_invite.missing_user.app_error", - "translation": "Kullanıcı bulunamadı. Sistem yöneticisi tarafından devre dışı bırakılmış olabilir." + "translation": "{{.User}} kullanıcısı bulunamadı. Sistem yöneticisi tarafından devre dışı bırakılmış olabilir." }, { "id": "api.command_invite.name", @@ -668,7 +668,7 @@ }, { "id": "api.command_invite.private_channel.app_error", - "translation": "{{.Channel}} kanalı bulunamadı. Lütfen kanalları belirtmek için kanal kısaltması kullanın." + "translation": "{{.Channel}} kanalı bulunamadı. Lütfen kanalları belirtmek için [kanal kısaltmasını](https://docs.mattermost.com/messaging/managing-channels.html#naming-a-channel) kullanın." }, { "id": "api.command_invite.success", @@ -999,7 +999,7 @@ }, { "id": "api.emoji.create.too_large.app_error", - "translation": "Emoji eklenemedi. Görsel boyutu 1 MB değerinden küçük olmalıdır." + "translation": "Emoji eklenemedi. Görsel 512 KiB boyutundan küçük olmalıdır." }, { "id": "api.emoji.disabled.app_error", @@ -8772,7 +8772,7 @@ }, { "id": "api.license.request-trial.can-start-trial.not-allowed", - "translation": "Mattermost Enterprise sürümünün deneme süresi sona ermiş olduğundan artık kullanılamaz. Deneme sürenizi uzatmak istiyorsanız [satış ekibimizle](https://mattermost.com/contact-us/) görüşebilirsiniz." + "translation": "Yeni deneme lisansı kullanılamadı. Bu Mattermost kopyasında daha önce deneme lisansı kullanmışsınız. Deneme sürenizi uzatmak istiyorsanız [satış ekibimizle](https://mattermost.com/contact-us/) görüşebilirsiniz." }, { "id": "api.license.request-trial.can-start-trial.error", @@ -9721,5 +9721,9 @@ { "id": "api.templates.cloud_upgrade_confirmation_monthly.subtitle", "translation": "{{.WorkspaceName}} çalışma alanınız güncellendi. Faturanız {{.Date}} tarihinden başlayarak hesaplanacak" + }, + { + "id": "api.server.hosted_signup_unavailable.error", + "translation": "Portal kişisel barındırma hesabı açmak için kullanılamaz." } ] From e0bcda5e9757a4aa79ac098e37cc09ed3ab4f8fa Mon Sep 17 00:00:00 2001 From: Matthew Williams Date: Tue, 10 Jan 2023 16:23:54 +0100 Subject: [PATCH 15/41] Translated using Weblate (English (Australia)) Currently translated at 99.6% (2419 of 2428 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/en_AU/ --- i18n/en_AU.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/i18n/en_AU.json b/i18n/en_AU.json index e03b05824f..094e51ed6e 100644 --- a/i18n/en_AU.json +++ b/i18n/en_AU.json @@ -6461,7 +6461,7 @@ }, { "id": "api.emoji.create.too_large.app_error", - "translation": "Unable to create emoji. Image must be less than 1 MB in size." + "translation": "Unable to create emoji. Image must be less than 512 KiB in size." }, { "id": "api.emoji.create.parse.app_error", @@ -7055,7 +7055,7 @@ }, { "id": "api.command_invite.private_channel.app_error", - "translation": "Could not find the channel {{.Channel}}. Please use the channel handle to identify channels." + "translation": "Could not find the channel {{.Channel}}. Please use the [channel handle](https://docs.mattermost.com/messaging/managing-channels.html#naming-a-channel) to identify channels." }, { "id": "api.command_invite.permission.app_error", @@ -7067,15 +7067,15 @@ }, { "id": "api.command_invite.missing_user.app_error", - "translation": "Couldn't find a matching user. They may have been deactivated by the System Administrator." + "translation": "Couldn't find a matching user {{.User}}. They may have been deactivated by the System Administrator." }, { "id": "api.command_invite.missing_message.app_error", - "translation": "Missing Username and Channel." + "translation": "Missing Username and/or Channel." }, { "id": "api.command_invite.hint", - "translation": "@[username] ~[channel]" + "translation": "@[username]... ~[channel]..." }, { "id": "api.command_invite.group_constrained_user_denied", @@ -8772,7 +8772,7 @@ }, { "id": "api.license.request-trial.can-start-trial.not-allowed", - "translation": "This trial licence key for Mattermost Enterprise Edition has expired and is no longer valid. If you would like to extend your trial period please [contact our sales team](https://mattermost.com/contact-us/)." + "translation": "Failed to apply new trial licence. You have previously applied a trial license to this Mattermost instance. If you would like to extend your trial period please [contact the sales team](https://mattermost.com/contact-us/)." }, { "id": "api.license.request-trial.can-start-trial.error", From f2ee2d420ecb838f5c7cd279e29e5f6d60454c8a Mon Sep 17 00:00:00 2001 From: master7 Date: Tue, 10 Jan 2023 16:23:54 +0100 Subject: [PATCH 16/41] Translated using Weblate (Polish) Currently translated at 100.0% (2433 of 2433 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/pl/ Translated using Weblate (Polish) Currently translated at 100.0% (2428 of 2428 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/pl/ --- i18n/pl.json | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/i18n/pl.json b/i18n/pl.json index ae492d4db1..8b6fbce3eb 100644 --- a/i18n/pl.json +++ b/i18n/pl.json @@ -649,15 +649,15 @@ }, { "id": "api.command_invite.hint", - "translation": "@[użytkownik] ~[kanał]" + "translation": "@[nazwa użytkownika]... ~[kanał]..." }, { "id": "api.command_invite.missing_message.app_error", - "translation": "Brak nazwy użytkownika oraz kanału." + "translation": "Brak nazwy użytkownika i/lub kanału." }, { "id": "api.command_invite.missing_user.app_error", - "translation": "Nie możemy odnaleźć użytkownika. Mógł on zostać dezaktywowany przez administratora systemu." + "translation": "Nie mogliśmy znaleźć użytkownika {{.User}}. Być może został on dezaktywowany przez Administratora systemu." }, { "id": "api.command_invite.name", @@ -669,7 +669,7 @@ }, { "id": "api.command_invite.private_channel.app_error", - "translation": "Nie można znaleźć kanału {{.Channel}}. Użyj uchwytu kanału, aby zidentyfikować kanały." + "translation": "Nie można znaleźć kanału {{.Channel}}. Użyj [uchwytu kanału](https://docs.mattermost.com/messaging/managing-channels.html#naming-a-channel), aby zidentyfikować kanały." }, { "id": "api.command_invite.success", @@ -1001,7 +1001,7 @@ }, { "id": "api.emoji.create.too_large.app_error", - "translation": "Nie można utworzyć emoji. Obraz musi być mniejszy niż 1 MB." + "translation": "Nie można utworzyć emoji. Obraz musi być mniejszy niż 512 KiB." }, { "id": "api.emoji.disabled.app_error", @@ -7325,7 +7325,7 @@ }, { "id": "api.license.request-trial.can-start-trial.not-allowed", - "translation": "Ten klucz licencji próbnej dla Mattermost Enterprise Edition wygasł i nie jest już ważny. Jeśli chcesz przedłużyć okres próbny, prosimy o [kontakt z naszym zespołem sprzedaży](https://mattermost.com/contact-us/)." + "translation": "Nie udało się zastosować nowej licencji próbnej. Zastosowano już wcześniej licencję próbną do tej instancji Mattermost... Jeśli chcesz przedłużyć okres próbny, prosimy o [kontakt z naszym zespołem sprzedaży](https://mattermost.com/contact-us/)." }, { "id": "api.license.request-trial.can-start-trial.error", @@ -9726,5 +9726,25 @@ { "id": "api.server.hosted_signup_unavailable.error", "translation": "Portal niedostępny dla samodzielnej rejestracji." + }, + { + "id": "ent.elasticsearch.create_client.client_key_missing", + "translation": "Nie można otworzyć pliku klucza klienta dla Elasticsearch" + }, + { + "id": "ent.elasticsearch.create_client.client_cert_missing", + "translation": "Nie można otworzyć pliku z certyfikatem klienta dla Elasticsearch" + }, + { + "id": "ent.elasticsearch.create_client.client_cert_malformed", + "translation": "Dekodowanie certyfikatu klienta dla Elasticsearch nie powiodło się" + }, + { + "id": "ent.elasticsearch.create_client.ca_cert_missing", + "translation": "Nie można otworzyć pliku CA dla Elasticsearch" + }, + { + "id": "ent.elasticsearch.create_client.ca_cert_malformed", + "translation": "Dekodowanie CA dla Elasticsearch nie powiodło się" } ] From f11e5316317220aaa31a98c261682b7702f629dc Mon Sep 17 00:00:00 2001 From: MArtin Johnson Date: Tue, 10 Jan 2023 16:23:54 +0100 Subject: [PATCH 17/41] Translated using Weblate (Swedish) Currently translated at 100.0% (2428 of 2428 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/sv/ --- i18n/sv.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/i18n/sv.json b/i18n/sv.json index f5b180b542..b9b189c4c7 100644 --- a/i18n/sv.json +++ b/i18n/sv.json @@ -6329,7 +6329,7 @@ }, { "id": "api.emoji.create.too_large.app_error", - "translation": "Det gick inte att skapa emoji. Bildfilen måste vara mindre än 1 MB i storlek." + "translation": "Det gick inte att skapa emoji. Bildfilen måste vara mindre än 512 KiB i storlek." }, { "id": "api.emoji.create.parse.app_error", @@ -6716,7 +6716,7 @@ }, { "id": "api.command_invite.private_channel.app_error", - "translation": "Kunde inte hitta kanalen {{.Channel}}. Använd Channel handle för att identifiera kanaler." + "translation": "Kunde inte hitta kanalen {{.Channel}}. Använd [channel handle](https://docs.mattermost.com/messaging/managing-channels.html#naming-a-channel) för att identifiera kanaler." }, { "id": "api.command_invite.permission.app_error", @@ -6728,15 +6728,15 @@ }, { "id": "api.command_invite.missing_user.app_error", - "translation": "Kunde inte hitta användaren. Kan ha blivit avstängd av Systemadministratören." + "translation": "Kunde inte hitta användaren {{.User}}. Kan ha blivit avstängd av Systemadministratören." }, { "id": "api.command_invite.missing_message.app_error", - "translation": "Saknar Användarnamn och Kanal." + "translation": "Saknar Användarnamn och/eller Kanal." }, { "id": "api.command_invite.hint", - "translation": "@[användarnamn] ~[kanal]" + "translation": "@[username]... ~[channel]..." }, { "id": "api.command_invite.group_constrained_user_denied", @@ -8772,7 +8772,7 @@ }, { "id": "api.license.request-trial.can-start-trial.not-allowed", - "translation": "Licensnyckeln för testperioden av Mattermost Enterprise Edition är inte längre giltig. [Kontakta Sales team] (https://mattermost.com/contact-us/) om du vill utöka testperionden." + "translation": "Misslyckades med att installera ny testlicens. Du har tidigare använt en testlicens på denna Mattermost-instans. [Kontakta försäljningsteamet] (https://mattermost.com/contact-us/) om du vill utöka testperioden." }, { "id": "api.license.request-trial.can-start-trial.error", From 46d85ea91067dd064852840b9aac38cf847211e9 Mon Sep 17 00:00:00 2001 From: Konstantin Date: Tue, 10 Jan 2023 16:23:54 +0100 Subject: [PATCH 18/41] Translated using Weblate (Russian) Currently translated at 100.0% (2433 of 2433 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/ru/ --- i18n/ru.json | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/i18n/ru.json b/i18n/ru.json index 62022682fd..f8e6b9cb60 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -649,15 +649,15 @@ }, { "id": "api.command_invite.hint", - "translation": "@[имя пользователя] ~[канал]" + "translation": "@[имя пользователя]... ~[канал]..." }, { "id": "api.command_invite.missing_message.app_error", - "translation": "Отсутствует имя пользователя и канал." + "translation": "Отсутствует имя пользователя и/или канал." }, { "id": "api.command_invite.missing_user.app_error", - "translation": "Мы не смогли найти пользователя. Вероятно он заблокирован Системным администратором." + "translation": "Мы не смогли найти пользователя {{.User}}. Вероятно он заблокирован Системным администратором." }, { "id": "api.command_invite.name", @@ -669,7 +669,7 @@ }, { "id": "api.command_invite.private_channel.app_error", - "translation": "Невозможно найти канал {{.Channel}}. Пожалуйста, используйте управление каналом для идентификации." + "translation": "Невозможно найти канал {{.Channel}}. Пожалуйста, используйте [управление каналом](https://docs.mattermost.com/messaging/managing-channels.html#naming-a-channel) для идентификации." }, { "id": "api.command_invite.success", @@ -1001,7 +1001,7 @@ }, { "id": "api.emoji.create.too_large.app_error", - "translation": "Невозможно создать смайлик. Изображение должно быть не более 1 MB." + "translation": "Невозможно создать смайлик. Изображение должно быть не более 512 КБ." }, { "id": "api.emoji.disabled.app_error", @@ -8713,7 +8713,7 @@ }, { "id": "api.license.request-trial.can-start-trial.not-allowed", - "translation": "Срок действия этого пробного лицензионного ключа для Mattermost Enterprise Edition истек и больше не действует. Если вы хотите продлить пробный период, пожалуйста, [свяжитесь с нашим отделом продаж] (https://mattermost.com/contact-us/)." + "translation": "Не удалось применить новую пробную лицензию. Вы уже применяли пробную лицензию к этому экземпляру Mattermost. Если вы хотите продлить пробный период, пожалуйста, [свяжитесь с нашим отделом продаж] (https://mattermost.com/contact-us/)." }, { "id": "api.license.request-trial.can-start-trial.error", @@ -9726,5 +9726,25 @@ { "id": "api.server.hosted_signup_unavailable.error", "translation": "Портал недоступен для самостоятельной регистрации." + }, + { + "id": "ent.elasticsearch.create_client.client_key_missing", + "translation": "Не удалось открыть файл клиентского ключа для Elasticsearch" + }, + { + "id": "ent.elasticsearch.create_client.client_cert_missing", + "translation": "Не удалось открыть файл сертификата клиента для Elasticsearch" + }, + { + "id": "ent.elasticsearch.create_client.client_cert_malformed", + "translation": "Не удалось декодировать сертификат клиента для Elasticsearch" + }, + { + "id": "ent.elasticsearch.create_client.ca_cert_missing", + "translation": "Не удалось открыть файл CA для Elasticsearch" + }, + { + "id": "ent.elasticsearch.create_client.ca_cert_malformed", + "translation": "Расшифровка CA для Elasticsearch не удалась" } ] From 51ac81d81618fa8486239482b18ac91265d9c397 Mon Sep 17 00:00:00 2001 From: Tim Scheuermann Date: Wed, 11 Jan 2023 11:23:09 +0100 Subject: [PATCH 19/41] MM-49083 Disable write timeouts for exports (#22035) --- app/file.go | 16 +--------------- shared/filestore/filesstore.go | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/app/file.go b/app/file.go index 7a66d25010..2d3de4d2f3 100644 --- a/app/file.go +++ b/app/file.go @@ -178,22 +178,8 @@ func (s *Server) writeFile(fr io.Reader, path string) (int64, *model.AppError) { } func (s *Server) writeFileContext(ctx context.Context, fr io.Reader, path string) (int64, *model.AppError) { - type ContextWriter interface { - WriteFileContext(context.Context, io.Reader, string) (int64, error) - } - - var ( - fileBackend = s.FileBackend() - written int64 - err error - ) - // Check if we can provide a custom context, otherwise just use the default method. - if cw, ok := fileBackend.(ContextWriter); ok { - written, err = cw.WriteFileContext(ctx, fr, path) - } else { - written, err = fileBackend.WriteFile(fr, path) - } + written, err := filestore.TryWriteFileContext(s.FileBackend(), ctx, fr, path) if err != nil { return written, model.NewAppError("WriteFile", "api.file.write_file.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } diff --git a/shared/filestore/filesstore.go b/shared/filestore/filesstore.go index 59b0d28947..fd1017591c 100644 --- a/shared/filestore/filesstore.go +++ b/shared/filestore/filesstore.go @@ -4,6 +4,7 @@ package filestore import ( + "context" "io" "time" @@ -84,3 +85,18 @@ func NewFileBackend(settings FileBackendSettings) (FileBackend, error) { } return nil, errors.New("no valid filestorage driver found") } + +// TryWriteFileContext checks if the file backend supports context writes and passes the context in that case. +// Should the file backend not support contexts, it just calls WriteFile instead. This can be used to disable +// the timeouts for long writes (like exports). +func TryWriteFileContext(fb FileBackend, ctx context.Context, fr io.Reader, path string) (int64, error) { + type ContextWriter interface { + WriteFileContext(context.Context, io.Reader, string) (int64, error) + } + + if cw, ok := fb.(ContextWriter); ok { + return cw.WriteFileContext(ctx, fr, path) + } + + return fb.WriteFile(fr, path) +} From 3ad240c16766ba68adf2d26c98cb7a09e58ede11 Mon Sep 17 00:00:00 2001 From: Konstantinos Pittas Date: Thu, 12 Jan 2023 13:17:53 +0200 Subject: [PATCH 20/41] [MM-46579] Add a limit for preferences (#21780) * add a limit for preferences * add limits to preferences * add config to telemetry * remove unneeded tags from config --- app/preference.go | 3 ++- model/config.go | 5 +++++ services/telemetry/telemetry.go | 1 + store/opentracinglayer/opentracinglayer.go | 4 ++-- store/retrylayer/retrylayer.go | 4 ++-- store/sqlstore/preference_store.go | 17 +++++++++++------ store/store.go | 2 +- store/storetest/mocks/PreferenceStore.go | 14 +++++++------- store/storetest/preference_store.go | 18 +++++++++--------- store/timerlayer/timerlayer.go | 4 ++-- 10 files changed, 42 insertions(+), 30 deletions(-) diff --git a/app/preference.go b/app/preference.go index f995eb9391..6bf536249f 100644 --- a/app/preference.go +++ b/app/preference.go @@ -33,7 +33,8 @@ func (w *preferencesServiceWrapper) DeletePreferencesForUser(userID string, pref } func (a *App) GetPreferencesForUser(userID string) (model.Preferences, *model.AppError) { - preferences, err := a.Srv().Store().Preference().GetAll(userID) + limit := *a.Config().ServiceSettings.ExperimentalMaxUserPreferences + preferences, err := a.Srv().Store().Preference().GetAll(userID, limit) if err != nil { return nil, model.NewAppError("GetPreferencesForUser", "app.preference.get_all.app_error", nil, "", http.StatusBadRequest).Wrap(err) } diff --git a/model/config.go b/model/config.go index ef948375cf..2a8fb848c9 100644 --- a/model/config.go +++ b/model/config.go @@ -385,6 +385,7 @@ type ServiceSettings struct { EnableCustomGroups *bool `access:"site_users_and_teams"` SelfHostedPurchase *bool `access:"write_restrictable,cloud_restrictable"` AllowSyncedDrafts *bool `access:"site_posts"` + ExperimentalMaxUserPreferences *int } func (s *ServiceSettings) SetDefaults(isUpdate bool) { @@ -857,6 +858,10 @@ func (s *ServiceSettings) SetDefaults(isUpdate bool) { if s.SelfHostedPurchase == nil { s.SelfHostedPurchase = NewBool(true) } + + if s.ExperimentalMaxUserPreferences == nil { + s.ExperimentalMaxUserPreferences = NewInt(1000) + } } type ClusterSettings struct { diff --git a/services/telemetry/telemetry.go b/services/telemetry/telemetry.go index 860960c379..fb30db7979 100644 --- a/services/telemetry/telemetry.go +++ b/services/telemetry/telemetry.go @@ -460,6 +460,7 @@ func (ts *TelemetryService) trackConfig() { "post_priority": *cfg.ServiceSettings.PostPriority, "self_hosted_purchase": *cfg.ServiceSettings.SelfHostedPurchase, "allow_synced_drafts": *cfg.ServiceSettings.AllowSyncedDrafts, + "experimental_max_user_preferences": *cfg.ServiceSettings.ExperimentalMaxUserPreferences, }) ts.SendTelemetry(TrackConfigTeam, map[string]any{ diff --git a/store/opentracinglayer/opentracinglayer.go b/store/opentracinglayer/opentracinglayer.go index 129ef5254b..e7e9aa5264 100644 --- a/store/opentracinglayer/opentracinglayer.go +++ b/store/opentracinglayer/opentracinglayer.go @@ -6919,7 +6919,7 @@ func (s *OpenTracingLayerPreferenceStore) Get(userID string, category string, na return result, err } -func (s *OpenTracingLayerPreferenceStore) GetAll(userID string) (model.Preferences, error) { +func (s *OpenTracingLayerPreferenceStore) GetAll(userID string, limit int) (model.Preferences, error) { origCtx := s.Root.Store.Context() span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "PreferenceStore.GetAll") s.Root.Store.SetContext(newCtx) @@ -6928,7 +6928,7 @@ func (s *OpenTracingLayerPreferenceStore) GetAll(userID string) (model.Preferenc }() defer span.Finish() - result, err := s.PreferenceStore.GetAll(userID) + result, err := s.PreferenceStore.GetAll(userID, limit) if err != nil { span.LogFields(spanlog.Error(err)) ext.Error.Set(span, true) diff --git a/store/retrylayer/retrylayer.go b/store/retrylayer/retrylayer.go index 065a1400a9..cfe39a65d4 100644 --- a/store/retrylayer/retrylayer.go +++ b/store/retrylayer/retrylayer.go @@ -7845,11 +7845,11 @@ func (s *RetryLayerPreferenceStore) Get(userID string, category string, name str } -func (s *RetryLayerPreferenceStore) GetAll(userID string) (model.Preferences, error) { +func (s *RetryLayerPreferenceStore) GetAll(userID string, limit int) (model.Preferences, error) { tries := 0 for { - result, err := s.PreferenceStore.GetAll(userID) + result, err := s.PreferenceStore.GetAll(userID, limit) if err == nil { return result, nil } diff --git a/store/sqlstore/preference_store.go b/store/sqlstore/preference_store.go index 6815e950e8..ed223e7233 100644 --- a/store/sqlstore/preference_store.go +++ b/store/sqlstore/preference_store.go @@ -175,17 +175,22 @@ func (s SqlPreferenceStore) GetCategory(userId string, category string) (model.P } -func (s SqlPreferenceStore) GetAll(userId string) (model.Preferences, error) { - var preferences model.Preferences - query, args, err := s.getQueryBuilder(). +func (s SqlPreferenceStore) GetAll(userId string, limit int) (model.Preferences, error) { + query := s.getQueryBuilder(). Select("*"). From("Preferences"). - Where(sq.Eq{"UserId": userId}). - ToSql() + Where(sq.Eq{"UserId": userId}) + if limit > 0 { + query = query.Limit(uint64(limit)) + } + + queryString, args, err := query.ToSql() if err != nil { return nil, errors.Wrap(err, "could not build sql query to get preference") } - if err = s.GetReplicaX().Select(&preferences, query, args...); err != nil { + + var preferences model.Preferences + if err = s.GetReplicaX().Select(&preferences, queryString, args...); err != nil { return nil, errors.Wrapf(err, "failed to find Preference with userId=%s", userId) } return preferences, nil diff --git a/store/store.go b/store/store.go index 8a1c69d91a..94156513fd 100644 --- a/store/store.go +++ b/store/store.go @@ -641,7 +641,7 @@ type PreferenceStore interface { GetCategory(userID string, category string) (model.Preferences, error) GetCategoryAndName(category string, nane string) (model.Preferences, error) Get(userID string, category string, name string) (*model.Preference, error) - GetAll(userID string) (model.Preferences, error) + GetAll(userID string, limit int) (model.Preferences, error) Delete(userID, category, name string) error DeleteCategory(userID string, category string) error DeleteCategoryAndName(category string, name string) error diff --git a/store/storetest/mocks/PreferenceStore.go b/store/storetest/mocks/PreferenceStore.go index c651e905bc..9c7cbd84c4 100644 --- a/store/storetest/mocks/PreferenceStore.go +++ b/store/storetest/mocks/PreferenceStore.go @@ -121,13 +121,13 @@ func (_m *PreferenceStore) Get(userID string, category string, name string) (*mo return r0, r1 } -// GetAll provides a mock function with given fields: userID -func (_m *PreferenceStore) GetAll(userID string) (model.Preferences, error) { - ret := _m.Called(userID) +// GetAll provides a mock function with given fields: userID, limit +func (_m *PreferenceStore) GetAll(userID string, limit int) (model.Preferences, error) { + ret := _m.Called(userID, limit) var r0 model.Preferences - if rf, ok := ret.Get(0).(func(string) model.Preferences); ok { - r0 = rf(userID) + if rf, ok := ret.Get(0).(func(string, int) model.Preferences); ok { + r0 = rf(userID, limit) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(model.Preferences) @@ -135,8 +135,8 @@ func (_m *PreferenceStore) GetAll(userID string) (model.Preferences, error) { } var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(userID) + if rf, ok := ret.Get(1).(func(string, int) error); ok { + r1 = rf(userID, limit) } else { r1 = ret.Error(1) } diff --git a/store/storetest/preference_store.go b/store/storetest/preference_store.go index 5d645f345a..42a5ae9ed1 100644 --- a/store/storetest/preference_store.go +++ b/store/storetest/preference_store.go @@ -184,7 +184,7 @@ func testPreferenceGetAll(t *testing.T, ss store.Store) { err := ss.Preference().Save(preferences) require.NoError(t, err) - result, err := ss.Preference().GetAll(userId) + result, err := ss.Preference().GetAll(userId, 0) require.NoError(t, err) require.Equal(t, 3, len(result), "got the wrong number of preferences") @@ -243,13 +243,13 @@ func testPreferenceDelete(t *testing.T, ss store.Store) { err := ss.Preference().Save(model.Preferences{preference}) require.NoError(t, err) - preferences, err := ss.Preference().GetAll(preference.UserId) + preferences, err := ss.Preference().GetAll(preference.UserId, 0) require.NoError(t, err) assert.Len(t, preferences, 1, "should've returned 1 preference") err = ss.Preference().Delete(preference.UserId, preference.Category, preference.Name) require.NoError(t, err) - preferences, err = ss.Preference().GetAll(preference.UserId) + preferences, err = ss.Preference().GetAll(preference.UserId, 0) require.NoError(t, err) assert.Empty(t, preferences, "should've returned no preferences") } @@ -275,14 +275,14 @@ func testPreferenceDeleteCategory(t *testing.T, ss store.Store) { err := ss.Preference().Save(model.Preferences{preference1, preference2}) require.NoError(t, err) - preferences, err := ss.Preference().GetAll(userId) + preferences, err := ss.Preference().GetAll(userId, 0) require.NoError(t, err) assert.Len(t, preferences, 2, "should've returned 2 preferences") err = ss.Preference().DeleteCategory(userId, category) require.NoError(t, err) - preferences, err = ss.Preference().GetAll(userId) + preferences, err = ss.Preference().GetAll(userId, 0) require.NoError(t, err) assert.Empty(t, preferences, "should've returned no preferences") } @@ -310,22 +310,22 @@ func testPreferenceDeleteCategoryAndName(t *testing.T, ss store.Store) { err := ss.Preference().Save(model.Preferences{preference1, preference2}) require.NoError(t, err) - preferences, err := ss.Preference().GetAll(userId) + preferences, err := ss.Preference().GetAll(userId, 0) require.NoError(t, err) assert.Len(t, preferences, 1, "should've returned 1 preference") - preferences, err = ss.Preference().GetAll(userId2) + preferences, err = ss.Preference().GetAll(userId2, 0) require.NoError(t, err) assert.Len(t, preferences, 1, "should've returned 1 preference") err = ss.Preference().DeleteCategoryAndName(category, name) require.NoError(t, err) - preferences, err = ss.Preference().GetAll(userId) + preferences, err = ss.Preference().GetAll(userId, 0) require.NoError(t, err) assert.Empty(t, preferences, "should've returned no preference") - preferences, err = ss.Preference().GetAll(userId2) + preferences, err = ss.Preference().GetAll(userId2, 0) require.NoError(t, err) assert.Empty(t, preferences, "should've returned no preference") } diff --git a/store/timerlayer/timerlayer.go b/store/timerlayer/timerlayer.go index 19ccaf656d..2a2ed7eefe 100644 --- a/store/timerlayer/timerlayer.go +++ b/store/timerlayer/timerlayer.go @@ -6256,10 +6256,10 @@ func (s *TimerLayerPreferenceStore) Get(userID string, category string, name str return result, err } -func (s *TimerLayerPreferenceStore) GetAll(userID string) (model.Preferences, error) { +func (s *TimerLayerPreferenceStore) GetAll(userID string, limit int) (model.Preferences, error) { start := time.Now() - result, err := s.PreferenceStore.GetAll(userID) + result, err := s.PreferenceStore.GetAll(userID, limit) elapsed := float64(time.Since(start)) / float64(time.Second) if s.Root.Metrics != nil { From 0cd07df84468e1a173770b55e0b831b3ed8bffda Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Thu, 12 Jan 2023 19:30:04 +0530 Subject: [PATCH 21/41] MM-48504: Bump dependencies (#21994) * MM-48504: Bump dependencies https://mattermost.atlassian.net/browse/MM-48504 ```release-note NONE ``` --- app/server.go | 5 +- go.mod | 90 ++++++++++---------- go.sum | 178 ++++++++++++++++++++++------------------ plugin/hclog_adapter.go | 2 + 4 files changed, 148 insertions(+), 127 deletions(-) diff --git a/app/server.go b/app/server.go index f7a9e9b912..69eb4d057c 100644 --- a/app/server.go +++ b/app/server.go @@ -290,8 +290,9 @@ func NewServer(options ...Option) (*Server, error) { } return event }, - TracesSampler: sentry.TracesSamplerFunc(func(ctx sentry.SamplingContext) sentry.Sampled { - return sentry.SampledFalse + EnableTracing: false, + TracesSampler: sentry.TracesSampler(func(ctx sentry.SamplingContext) float64 { + return 0.0 }), }); err2 != nil { mlog.Warn("Sentry could not be initiated, probably bad DSN?", mlog.Err(err2)) diff --git a/go.mod b/go.mod index 2e04b4e93c..7a5550ac0b 100644 --- a/go.mod +++ b/go.mod @@ -4,20 +4,20 @@ go 1.18 require ( code.sajari.com/docconv v1.3.5 - github.com/Masterminds/semver/v3 v3.1.1 + github.com/Masterminds/semver/v3 v3.2.0 github.com/avct/uasurfer v0.0.0-20191028135549-26b5daa857f1 - github.com/aws/aws-sdk-go v1.44.138 + github.com/aws/aws-sdk-go v1.44.173 github.com/blang/semver v3.5.1+incompatible - github.com/blevesearch/bleve/v2 v2.3.6-0.20221111171245-56dc9b25507e - github.com/cespare/xxhash/v2 v2.1.2 + github.com/blevesearch/bleve/v2 v2.3.6 + github.com/cespare/xxhash/v2 v2.2.0 github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dgryski/dgoogauth v0.0.0-20190221195224-5a805980a5f3 github.com/disintegration/imaging v1.6.2 github.com/dyatlov/go-opengraph/opengraph v0.0.0-20220524092352-606d7b1e5f8a github.com/francoispqt/gojay v1.2.13 github.com/fsnotify/fsnotify v1.6.0 - github.com/getsentry/sentry-go v0.15.0 - github.com/go-sql-driver/mysql v1.6.0 + github.com/getsentry/sentry-go v0.16.0 + github.com/go-sql-driver/mysql v1.7.0 github.com/golang-migrate/migrate/v4 v4.15.2 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 github.com/gorilla/handlers v1.5.1 @@ -25,15 +25,15 @@ require ( github.com/gorilla/schema v1.2.0 github.com/gorilla/websocket v1.5.0 github.com/graph-gophers/dataloader/v6 v6.0.0 - github.com/graph-gophers/graphql-go v1.4.0 + github.com/graph-gophers/graphql-go v1.5.1-0.20230110080634-edea822f558a github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c - github.com/hashicorp/go-hclog v1.3.1 - github.com/hashicorp/go-plugin v1.4.6 + github.com/hashicorp/go-hclog v1.4.0 + github.com/hashicorp/go-plugin v1.4.8 github.com/jaytaylor/html2text v0.0.0-20211105163654-bc68cce691ba github.com/jmoiron/sqlx v1.3.5 github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 github.com/lib/pq v1.10.7 - github.com/mattermost/focalboard/server v0.0.0-20221222174020-fd4cf95f8ac9 + github.com/mattermost/focalboard/server v0.0.0-20230104182634-f909c2552e37 github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404 github.com/mattermost/gziphandler v0.0.1 github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d @@ -43,32 +43,32 @@ require ( github.com/mattermost/squirrel v0.2.0 github.com/mholt/archiver/v3 v3.5.1 github.com/microcosm-cc/bluemonday v1.0.21 - github.com/minio/minio-go/v7 v7.0.43 + github.com/minio/minio-go/v7 v7.0.45 github.com/oov/psd v0.0.0-20220121172623-5db5eafcecbb github.com/opentracing/opentracing-go v1.2.0 github.com/pborman/uuid v1.2.1 github.com/pkg/errors v0.9.1 github.com/reflog/dateconstraints v0.2.1 - github.com/rs/cors v1.8.2 + github.com/rs/cors v1.8.3 github.com/rudderlabs/analytics-go v3.3.3+incompatible github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd github.com/spf13/cobra v1.6.1 github.com/splitio/go-client/v6 v6.2.1 github.com/stretchr/testify v1.8.1 github.com/throttled/throttled v2.2.5+incompatible - github.com/tinylib/msgp v1.1.6 + github.com/tinylib/msgp v1.1.8 github.com/uber/jaeger-client-go v2.30.0+incompatible github.com/uber/jaeger-lib v2.4.1+incompatible github.com/vmihailenco/msgpack/v5 v5.3.5 github.com/wiggin77/merror v1.0.4 github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c github.com/yuin/goldmark v1.5.3 - golang.org/x/crypto v0.2.0 - golang.org/x/image v0.1.0 - golang.org/x/net v0.2.0 + golang.org/x/crypto v0.5.0 + golang.org/x/image v0.3.0 + golang.org/x/net v0.5.0 golang.org/x/sync v0.1.0 - golang.org/x/text v0.4.0 - golang.org/x/tools v0.3.0 + golang.org/x/text v0.6.0 + golang.org/x/tools v0.5.0 gopkg.in/mail.v2 v2.3.1 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 @@ -84,24 +84,24 @@ require ( github.com/andybalholm/cascadia v1.3.1 // indirect github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de // indirect github.com/aymerick/douceur v0.2.0 // indirect - github.com/bits-and-blooms/bitset v1.3.3 // indirect + github.com/bits-and-blooms/bitset v1.4.0 // indirect github.com/bits-and-blooms/bloom/v3 v3.3.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/blevesearch/bleve_index_api v1.0.5 // indirect - github.com/blevesearch/geo v0.1.15 // indirect + github.com/blevesearch/geo v0.1.17 // indirect github.com/blevesearch/go-porterstemmer v1.0.3 // indirect github.com/blevesearch/gtreap v0.1.1 // indirect github.com/blevesearch/mmap-go v1.0.4 // indirect github.com/blevesearch/scorch_segment_api/v2 v2.1.4 // indirect - github.com/blevesearch/segment v0.9.0 // indirect + github.com/blevesearch/segment v0.9.1 // indirect github.com/blevesearch/snowballstem v0.9.0 // indirect - github.com/blevesearch/upsidedown_store_api v1.0.1 // indirect + github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect github.com/blevesearch/vellum v1.0.9 // indirect github.com/blevesearch/zapx/v11 v11.3.7 // indirect github.com/blevesearch/zapx/v12 v12.3.7 // indirect github.com/blevesearch/zapx/v13 v13.3.7 // indirect github.com/blevesearch/zapx/v14 v14.3.7 // indirect - github.com/blevesearch/zapx/v15 v15.3.7 // indirect + github.com/blevesearch/zapx/v15 v15.3.8 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect @@ -122,20 +122,20 @@ require ( github.com/gorilla/css v1.0.0 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/yamux v0.1.1 // indirect - github.com/inconshreveable/mousetrap v1.0.1 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect - github.com/klauspost/compress v1.15.12 // indirect - github.com/klauspost/cpuid/v2 v2.2.1 // indirect + github.com/klauspost/compress v1.15.14 // indirect + github.com/klauspost/cpuid/v2 v2.2.3 // indirect github.com/klauspost/pgzip v1.2.5 // indirect github.com/kr/pretty v0.3.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/levigross/exp-html v0.0.0-20120902181939-8df60c69a8f5 // indirect - github.com/mattermost/mattermost-plugin-api v0.0.29-0.20220801143717-73008cfda2fb // indirect + github.com/mattermost/mattermost-plugin-api v0.1.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/minio/md5-simd v1.1.2 // indirect github.com/minio/sha256-simd v1.0.0 // indirect @@ -148,10 +148,10 @@ require ( github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/otiai10/gosseract/v2 v2.4.0 // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/philhofer/fwd v1.1.1 // indirect + github.com/philhofer/fwd v1.1.2 // indirect github.com/pierrec/lz4/v4 v4.1.17 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa // indirect github.com/richardlehane/mscfb v1.0.4 // indirect github.com/richardlehane/msoleps v1.0.3 // indirect github.com/rivo/uniseg v0.4.3 // indirect @@ -160,37 +160,37 @@ require ( github.com/segmentio/backo-go v1.0.1 // indirect github.com/sirupsen/logrus v1.9.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/splitio/go-split-commons/v4 v4.2.2 // indirect + github.com/splitio/go-split-commons/v4 v4.2.3 // indirect github.com/splitio/go-toolkit/v5 v5.2.2 // indirect github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect github.com/stretchr/objx v0.5.0 // indirect - github.com/tidwall/gjson v1.14.3 // indirect + github.com/tidwall/gjson v1.14.4 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect - github.com/ulikunitz/xz v0.5.10 // indirect + github.com/ulikunitz/xz v0.5.11 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/wiggin77/srslog v1.0.1 // indirect github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect go.etcd.io/bbolt v1.3.6 // indirect go.uber.org/atomic v1.10.0 // indirect golang.org/x/mod v0.7.0 // indirect - golang.org/x/sys v0.2.0 // indirect - google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1 // indirect - google.golang.org/grpc v1.50.1 // indirect + golang.org/x/sys v0.4.0 // indirect + google.golang.org/genproto v0.0.0-20230104163317-caabf589fcbf // indirect + google.golang.org/grpc v1.51.0 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect lukechampine.com/uint128 v1.2.0 // indirect - modernc.org/cc/v3 v3.36.0 // indirect - modernc.org/ccgo/v3 v3.16.6 // indirect - modernc.org/libc v1.16.7 // indirect - modernc.org/mathutil v1.4.1 // indirect - modernc.org/memory v1.1.1 // indirect - modernc.org/opt v0.1.1 // indirect - modernc.org/sqlite v1.18.0 // indirect - modernc.org/strutil v1.1.1 // indirect - modernc.org/token v1.0.0 // indirect + modernc.org/cc/v3 v3.40.0 // indirect + modernc.org/ccgo/v3 v3.16.13 // indirect + modernc.org/libc v1.22.2 // indirect + modernc.org/mathutil v1.5.0 // indirect + modernc.org/memory v1.5.0 // indirect + modernc.org/opt v0.1.3 // indirect + modernc.org/sqlite v1.20.1 // indirect + modernc.org/strutil v1.1.3 // indirect + modernc.org/token v1.1.0 // indirect ) // Hack to prevent the willf/bitset module from being upgraded to 1.2.0. diff --git a/go.sum b/go.sum index 196d356a53..d7365acb4f 100644 --- a/go.sum +++ b/go.sum @@ -92,8 +92,8 @@ github.com/HdrHistogram/hdrhistogram-go v0.9.0/go.mod h1:nxrse8/Tzg2tg3DZcZjm6qE github.com/JalfResi/justext v0.0.0-20170829062021-c0282dea7198/go.mod h1:0SURuH1rsE8aVWvutuMZghRNrNrYEUzibzJfhEYR8L0= github.com/JalfResi/justext v0.0.0-20221106200834-be571e3e3052 h1:8T2zMbhLBbH9514PIQVHdsGhypMrsB4CxwbldKA9sBA= github.com/JalfResi/justext v0.0.0-20221106200834-be571e3e3052/go.mod h1:0SURuH1rsE8aVWvutuMZghRNrNrYEUzibzJfhEYR8L0= -github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= -github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= @@ -167,8 +167,8 @@ github.com/avct/uasurfer v0.0.0-20191028135549-26b5daa857f1 h1:9h8f71kuF1pqovnn9 github.com/avct/uasurfer v0.0.0-20191028135549-26b5daa857f1/go.mod h1:noBAuukeYOXa0aXGqxr24tADqkwDO2KRD15FsuaZ5a8= github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.44.138 h1:9aoHAowstvD0s4cktYwT4Ok3oFLl3Hfbap8iFLamsdc= -github.com/aws/aws-sdk-go v1.44.138/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.173 h1:8kXIxvQnBpGhmR3Eof6SnCKgR0q5/L/3Qbv9vAC5wic= +github.com/aws/aws-sdk-go v1.44.173/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v1.8.0/go.mod h1:xEFuWz+3TYdlPRuo+CqATbeDWIWyaT5uAPwPaWtgse0= github.com/aws/aws-sdk-go-v2 v1.9.2/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= github.com/aws/aws-sdk-go-v2/config v1.6.0/go.mod h1:TNtBVmka80lRPk5+S9ZqVfFszOQAGJJ9KbT3EM3CHNU= @@ -207,8 +207,8 @@ github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCS github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bits-and-blooms/bitset v1.3.1/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/bits-and-blooms/bitset v1.3.3 h1:R1XWiopGiXf66xygsiLpzLo67xEYvMkHw3w+rCOSAwg= -github.com/bits-and-blooms/bitset v1.3.3/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/bits-and-blooms/bitset v1.4.0 h1:+YZ8ePm+He2pU3dZlIZiOeAKfrBkXi1lSrXJ/Xzgbu8= +github.com/bits-and-blooms/bitset v1.4.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bits-and-blooms/bloom/v3 v3.3.1 h1:K2+A19bXT8gJR5mU7y+1yW6hsKfNCjcP2uNfLFKncjQ= github.com/bits-and-blooms/bloom/v3 v3.3.1/go.mod h1:bhUUknWd5khVbTe4UgMCSiOOVJzr3tMoijSK3WwvW90= github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4= @@ -218,13 +218,12 @@ github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdn github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/blevesearch/bleve/v2 v2.3.6-0.20221111171245-56dc9b25507e h1:r/cWPLUPgAM3SWWniQ6j0Hzb++h+uEycDD9UOUuC1Vk= -github.com/blevesearch/bleve/v2 v2.3.6-0.20221111171245-56dc9b25507e/go.mod h1:mfCWvuwg/XnPVZHEejATm5TyFqyeLmm8p9Y3xDvwz4k= -github.com/blevesearch/bleve_index_api v1.0.3/go.mod h1:fiwKS0xLEm+gBRgv5mumf0dhgFr2mDgZah1pqv1c1M4= +github.com/blevesearch/bleve/v2 v2.3.6 h1:NlntUHcV5CSWIhpugx4d/BRMGCiaoI8ZZXrXlahzNq4= +github.com/blevesearch/bleve/v2 v2.3.6/go.mod h1:JM2legf1cKVkdV8Ehu7msKIOKC0McSw0Q16Fmv9vsW4= github.com/blevesearch/bleve_index_api v1.0.5 h1:Lc986kpC4Z0/n1g3gg8ul7H+lxgOQPcXb9SxvQGu+tw= github.com/blevesearch/bleve_index_api v1.0.5/go.mod h1:YXMDwaXFFXwncRS8UobWs7nvo0DmusriM1nztTlj1ms= -github.com/blevesearch/geo v0.1.15 h1:0NybEduqE5fduFRYiUKF0uqybAIFKXYjkBdXKYn7oA4= -github.com/blevesearch/geo v0.1.15/go.mod h1:cRIvqCdk3cgMhGeHNNe6yPzb+w56otxbfo1FBJfR2Pc= +github.com/blevesearch/geo v0.1.17 h1:AguzI6/5mHXapzB0gE9IKWo+wWPHZmXZoscHcjFgAFA= +github.com/blevesearch/geo v0.1.17/go.mod h1:uRMGWG0HJYfWfFJpK3zTdnnr1K+ksZTuWKhXeSokfnM= github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo= github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M= github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y= @@ -233,12 +232,12 @@ github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCD github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs= github.com/blevesearch/scorch_segment_api/v2 v2.1.4 h1:LmGmo5twU3gV+natJbKmOktS9eMhokPGKWuR+jX84vk= github.com/blevesearch/scorch_segment_api/v2 v2.1.4/go.mod h1:PgVnbbg/t1UkgezPDu8EHLi1BHQ17xUwsFdU6NnOYS0= -github.com/blevesearch/segment v0.9.0 h1:5lG7yBCx98or7gK2cHMKPukPZ/31Kag7nONpoBt22Ac= -github.com/blevesearch/segment v0.9.0/go.mod h1:9PfHYUdQCgHktBgvtUOF4x+pc4/l8rdH0u5spnW85UQ= +github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU= +github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw= github.com/blevesearch/snowballstem v0.9.0 h1:lMQ189YspGP6sXvZQ4WZ+MLawfV8wOmPoD/iWeNXm8s= github.com/blevesearch/snowballstem v0.9.0/go.mod h1:PivSj3JMc8WuaFkTSRDW2SlrulNWPl4ABg1tC/hlgLs= -github.com/blevesearch/upsidedown_store_api v1.0.1 h1:1SYRwyoFLwG3sj0ed89RLtM15amfX2pXlYbFOnF8zNU= -github.com/blevesearch/upsidedown_store_api v1.0.1/go.mod h1:MQDVGpHZrpe3Uy26zJBf/a8h0FZY6xJbthIMm8myH2Q= +github.com/blevesearch/upsidedown_store_api v1.0.2 h1:U53Q6YoWEARVLd1OYNc9kvhBMGZzVrdmaozG2MfoB+A= +github.com/blevesearch/upsidedown_store_api v1.0.2/go.mod h1:M01mh3Gpfy56Ps/UXHjEO/knbqyQ1Oamg8If49gRwrQ= github.com/blevesearch/vellum v1.0.9 h1:PL+NWVk3dDGPCV0hoDu9XLLJgqU4E5s/dOeEJByQ2uQ= github.com/blevesearch/vellum v1.0.9/go.mod h1:ul1oT0FhSMDIExNjIxHqJoGpVrBpKCdgDQNxfqgJt7k= github.com/blevesearch/zapx/v11 v11.3.7 h1:Y6yIAF/DVPiqZUA/jNgSLXmqewfzwHzuwfKyfdG+Xaw= @@ -249,8 +248,8 @@ github.com/blevesearch/zapx/v13 v13.3.7 h1:igIQg5eKmjw168I7av0Vtwedf7kHnQro/M+ub github.com/blevesearch/zapx/v13 v13.3.7/go.mod h1:yyrB4kJ0OT75UPZwT/zS+Ru0/jYKorCOOSY5dBzAy+s= github.com/blevesearch/zapx/v14 v14.3.7 h1:gfe+fbWslDWP/evHLtp/GOvmNM3sw1BbqD7LhycBX20= github.com/blevesearch/zapx/v14 v14.3.7/go.mod h1:9J/RbOkqZ1KSjmkOes03AkETX7hrXT0sFMpWH4ewC4w= -github.com/blevesearch/zapx/v15 v15.3.7 h1:r8ZcNrlcMj2TmLlbNH16wZiL9reU0s7C2rAQKjFDtuE= -github.com/blevesearch/zapx/v15 v15.3.7/go.mod h1:m7Y6m8soYUvS7MjN9eKlz1xrLCcmqfFadmu7GhWIrLY= +github.com/blevesearch/zapx/v15 v15.3.8 h1:q4uMngBHzL1IIhRc8AJUEkj6dGOE3u1l3phLu7hq8uk= +github.com/blevesearch/zapx/v15 v15.3.8/go.mod h1:m7Y6m8soYUvS7MjN9eKlz1xrLCcmqfFadmu7GhWIrLY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= @@ -270,8 +269,9 @@ github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6 github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= @@ -518,8 +518,8 @@ github.com/gabriel-vasile/mimetype v1.3.1/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmx github.com/gabriel-vasile/mimetype v1.4.0/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= -github.com/getsentry/sentry-go v0.15.0 h1:CP9bmA7pralrVUedYZsmIHWpq/pBtXTSew7xvVpfLaA= -github.com/getsentry/sentry-go v0.15.0/go.mod h1:RZPJKSw+adu8PBNygiri/A98FqVr2HtRckJk9XVxJ9I= +github.com/getsentry/sentry-go v0.16.0 h1:owk+S+5XcgJLlGR/3+3s6N4d+uKwqYvh/eS0AIMjPWo= +github.com/getsentry/sentry-go v0.16.0/go.mod h1:ZXCloQLj0pG7mja5NK6NPf2V4A88YJ4pNlc2mOHwh6Y= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gigawattio/window v0.0.0-20180317192513-0f5467e35573 h1:u8AQ9bPa9oC+8/A/jlWouakhIvkFfuxgIIRjiy8av7I= @@ -576,8 +576,9 @@ github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPr github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= @@ -720,6 +721,7 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -759,8 +761,8 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/graph-gophers/dataloader/v6 v6.0.0 h1:qBpmq3B8PIQesoh0EJXKGfw+ulMUb+KFl4IZOe9ScWg= github.com/graph-gophers/dataloader/v6 v6.0.0/go.mod h1:J15OZSnOoZgMkijpbZcwCmglIDYqlUiTEE1xLPbyqZM= -github.com/graph-gophers/graphql-go v1.4.0 h1:JE9wveRTSXwJyjdRd6bOQ7Ob5bewTUQ58Jv4OiVdpdE= -github.com/graph-gophers/graphql-go v1.4.0/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= +github.com/graph-gophers/graphql-go v1.5.1-0.20230110080634-edea822f558a h1:i0+Se9S+2zL5CBxJouqn2Ej6UQMwH1c57ZB6DVnqck4= +github.com/graph-gophers/graphql-go v1.5.1-0.20230110080634-edea822f558a/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -780,16 +782,16 @@ github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-hclog v1.3.1 h1:vDwF1DFNZhntP4DAjuTpOw3uEgMUpXh1pB5fW9DqHpo= -github.com/hashicorp/go-hclog v1.3.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.4.0 h1:ctuWFGrhFha8BnnzxqeRGidlEcQkDyL5u8J8t5eA11I= +github.com/hashicorp/go-hclog v1.4.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-plugin v1.4.6 h1:MDV3UrKQBM3du3G7MApDGvOsMYy3JQJ4exhSoKBAeVA= -github.com/hashicorp/go-plugin v1.4.6/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= +github.com/hashicorp/go-plugin v1.4.8 h1:CHGwpxYDOttQOY7HOWgETU9dyVjOXzniXDqJcYJE1zM= +github.com/hashicorp/go-plugin v1.4.8/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= @@ -817,8 +819,9 @@ github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/intel/goresctrl v0.2.0/go.mod h1:+CZdzouYFn5EsxgqAQTEzMfwKwuc0fVdMrT9FCCAVRQ= github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbBFOsPw= @@ -890,7 +893,6 @@ github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22 github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v0.0.0-20171115153421-f7279a603ede/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -923,13 +925,13 @@ github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdY github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM= -github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.15.14 h1:i7WCKDToww0wA+9qrUZ1xOjp218vfFo3nTU6UHp+gOc= +github.com/klauspost/compress v1.15.14/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.1 h1:U33DW0aiEj633gHYw3LoDNfkDiYnE5Q8M/TKJn2f2jI= -github.com/klauspost/cpuid/v2 v2.2.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= +github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -981,8 +983,8 @@ github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsI github.com/markbates/pkger v0.15.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= -github.com/mattermost/focalboard/server v0.0.0-20221222174020-fd4cf95f8ac9 h1:UE3KuILWJwTnaXAy2YHqkCu1f7i+VdX2VNukBGYbPuI= -github.com/mattermost/focalboard/server v0.0.0-20221222174020-fd4cf95f8ac9/go.mod h1:h1HQ8UVoNMyDHzjPD7UtYbTPMWjP6d1qJZuLdT6ElNg= +github.com/mattermost/focalboard/server v0.0.0-20230104182634-f909c2552e37 h1:yK5Pb2R0PwS/RU4b4RbJjTj9xclZHJ064JFkZdAoHLY= +github.com/mattermost/focalboard/server v0.0.0-20230104182634-f909c2552e37/go.mod h1:h1HQ8UVoNMyDHzjPD7UtYbTPMWjP6d1qJZuLdT6ElNg= github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404 h1:Khvh6waxG1cHc4Cz5ef9n3XVCxRWpAKUtqg9PJl5+y8= github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404/go.mod h1:RyS7FDNQlzF1PsjbJWHRI35exqaKGSO9qD4iv8QjE34= github.com/mattermost/gziphandler v0.0.1 h1:uXHcXF5agnQ6bXabvpiwwwZOlCYoa7mKHH0lxns/o8w= @@ -991,8 +993,8 @@ github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d h1:/RJ/UV7M5c7L2TQ github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d/go.mod h1:HLbgMEI5K131jpxGazJ97AxfPDt31osq36YS1oxFQPQ= github.com/mattermost/logr/v2 v2.0.15 h1:+WNbGcsc3dBao65eXlceB6dTILNJRIrvubnsTl3zBew= github.com/mattermost/logr/v2 v2.0.15/go.mod h1:mpPp935r5dIkFDo2y9Q87cQWhFR/4xXpNh0k/y8Hmwg= -github.com/mattermost/mattermost-plugin-api v0.0.29-0.20220801143717-73008cfda2fb h1:q1qXKVv59rA2gcQ7lVLc5OlWBmfsR3i8mdGD5EZesyk= -github.com/mattermost/mattermost-plugin-api v0.0.29-0.20220801143717-73008cfda2fb/go.mod h1:PIeo40t9VTA4Wu1FwjzH7QmcgC3SRyk/ohCwJw4/oSo= +github.com/mattermost/mattermost-plugin-api v0.1.1 h1:bNnPbWCLWZpT/k2kjUxNnzCfUggU8WKs2ddz7hNjg1U= +github.com/mattermost/mattermost-plugin-api v0.1.1/go.mod h1:9yZhtg0bBj3kqSTjXnjYBMZoTsWbe3ajdFMdl9/Jz34= github.com/mattermost/morph v1.0.5-0.20221115094356-4c18a75b1f5e h1:VfNz+fvJ3DxOlALM22Eea8ONp5jHrybKBCcCtDPVlss= github.com/mattermost/morph v1.0.5-0.20221115094356-4c18a75b1f5e/go.mod h1:xo0ljDknTpPxEdhhrUdwhLCexIsYyDKS6b41HqG8wGU= github.com/mattermost/rsc v0.0.0-20160330161541-bbaefb05eaa0 h1:G9tL6JXRBMzjuD1kkBtcnd42kUiT6QDwxfFYu7adM6o= @@ -1017,8 +1019,9 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= @@ -1046,8 +1049,8 @@ github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3N github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= -github.com/minio/minio-go/v7 v7.0.43 h1:14Q4lwblqTdlAmba05oq5xL0VBLHi06zS4yLnIkz6hI= -github.com/minio/minio-go/v7 v7.0.43/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw= +github.com/minio/minio-go/v7 v7.0.45 h1:g4IeM9M9pW/Lo8AGGNOjBZYlvmtlE1N5TQEYWXRWzIs= +github.com/minio/minio-go/v7 v7.0.45/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw= github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= @@ -1191,8 +1194,8 @@ github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= -github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= +github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= +github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= @@ -1253,8 +1256,9 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T github.com/reflog/dateconstraints v0.2.1 h1:Hz1n2Q1vEm0Rj5gciDQcCN1iPBwfFjxUJy32NknGP/s= github.com/reflog/dateconstraints v0.2.1/go.mod h1:Ax8AxTBcJc3E/oVS2hd2j7RDM/5MDtuPwuR7lIHtPLo= github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa h1:tEkEyxYeZ43TR55QU/hsIt9aRGBxbgGuz9CGykjvogY= +github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/richardlehane/mscfb v1.0.3/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk= github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM= github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk= @@ -1273,8 +1277,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= -github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo= +github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY= github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= @@ -1371,8 +1375,8 @@ github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5q github.com/splitio/go-client/v6 v6.2.1 h1:EH3xYH7fr2c0I0ZtYvsyn7DjC9ZmoNAFLoKoT3BmQFU= github.com/splitio/go-client/v6 v6.2.1/go.mod h1:+HnGMevmSUk56va2egs9W2s9mJ7LW9IXiDPB1ExOi+k= github.com/splitio/go-split-commons/v4 v4.2.0/go.mod h1:mzanM00PV8t1FL6IHc2UXepIH2z79d49ArZ2LoJHGrY= -github.com/splitio/go-split-commons/v4 v4.2.2 h1:p4Gq4+Wxto+f+7g4AoxmMON1jkOU8abqAIV1pb8ke9M= -github.com/splitio/go-split-commons/v4 v4.2.2/go.mod h1:mzanM00PV8t1FL6IHc2UXepIH2z79d49ArZ2LoJHGrY= +github.com/splitio/go-split-commons/v4 v4.2.3 h1:/bQg8Z0eCkF9RHl7Dh1SJ8j7Ci024bgtkZEWwEKXywc= +github.com/splitio/go-split-commons/v4 v4.2.3/go.mod h1:mzanM00PV8t1FL6IHc2UXepIH2z79d49ArZ2LoJHGrY= github.com/splitio/go-toolkit/v5 v5.2.2 h1:VHSJoIH9tsRt2cCzGKN4WG3BoGCr0tCPZIl8APtJ4bw= github.com/splitio/go-toolkit/v5 v5.2.2/go.mod h1:SYi/svhhtEgdMSb5tNcDcMjOSUH/7XVkvjp5dPL+nBE= github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cmavspvIl9nulOYwdy6IFRRo= @@ -1406,16 +1410,16 @@ github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cb github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= github.com/throttled/throttled v2.2.5+incompatible h1:65UB52X0qNTYiT0Sohp8qLYVFwZQPDw85uSa65OljjQ= github.com/throttled/throttled v2.2.5+incompatible/go.mod h1:0BjlrEGQmvxps+HuXLsyRdqpSRvJpq0PNIsOtqP9Nos= -github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw= -github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= +github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/tinylib/msgp v1.1.6 h1:i+SbKraHhnrf9M5MYmvQhFnbLhAXSDWF8WWsuyRdocw= -github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw= +github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0= +github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -1429,8 +1433,8 @@ github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6 github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= -github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= +github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= @@ -1572,8 +1576,8 @@ golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.2.0 h1:BRXPfhNivWL5Yq0BGQ39a2sW6t44aODpfxkWjYdzewE= -golang.org/x/crypto v0.2.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= +golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1598,8 +1602,8 @@ golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+o golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.1.0 h1:r8Oj8ZA2Xy12/b5KZYj3tuv7NG/fBz3TwQVvpJ9l8Rk= -golang.org/x/image v0.1.0/go.mod h1:iyPr49SD/G/TBxYVB/9RRtGUT5eNbo2u4NamWeQcD5c= +golang.org/x/image v0.3.0 h1:HTDXbdK9bjfSWkPzDJIw89W8CAtfFGduujWs33NLLsg= +golang.org/x/image v0.3.0/go.mod h1:fXd9211C/0VTlYuAcOhW8dY/RtEJqODXOWBDpmYBf+A= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -1702,8 +1706,9 @@ golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1874,14 +1879,16 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1891,8 +1898,10 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1969,7 +1978,6 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -1984,8 +1992,9 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= +golang.org/x/tools v0.5.0 h1:+bSpV5HIeWkuvgaMfI3UmKRThoTA5ODJTUd8T17NO+4= +golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2123,8 +2132,8 @@ google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1 h1:jCw9YRd2s40X9Vxi4zKsPRvSPlHWNqadVkpbMsCPzPQ= -google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20230104163317-caabf589fcbf h1:/JqRexUvugu6JURQ0O7RfV1EnvgrOxUV4tSjuAv0Sr0= +google.golang.org/genproto v0.0.0-20230104163317-caabf589fcbf/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= @@ -2162,8 +2171,8 @@ google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ5 google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= -google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= +google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -2292,14 +2301,16 @@ lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= modernc.org/b v1.0.0/go.mod h1:uZWcZfRj1BpYzfN9JTerzlNUnnPsV9O2ZA8JsRcubNg= modernc.org/cc/v3 v3.32.4/go.mod h1:0R6jl1aZlIl2avnYfbfHBS1QB6/f+16mihBObaBC878= -modernc.org/cc/v3 v3.36.0 h1:0kmRkTmqNidmu3c7BNDSdVHCxXCkWLmWmCIVX4LUboo= modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw= +modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= modernc.org/ccgo/v3 v3.9.2/go.mod h1:gnJpy6NIVqkETT+L5zPsQFj7L2kkhfPMzOghRNv/CFo= modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.6 h1:3l18poV+iUemQ98O3X5OMr97LOqlzis+ytivU4NqGhA= modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw= +modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= modernc.org/db v1.0.0/go.mod h1:kYD/cO29L/29RM0hXYl4i3+Q5VojL31kTUVpVJDw0s8= @@ -2314,36 +2325,43 @@ modernc.org/libc v1.7.13-0.20210308123627-12f642a52bb8/go.mod h1:U1eq8YWr/Kc1RWC modernc.org/libc v1.9.5/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= -modernc.org/libc v1.16.7 h1:qzQtHhsZNpVPpeCu+aMIQldXeV1P0vRhSqCL0nOIJOA= modernc.org/libc v1.16.7/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= +modernc.org/libc v1.22.2 h1:4U7v51GyhlWqQmwCHj28Rdq2Yzwk55ovjFrdPjs8Hb0= +modernc.org/libc v1.22.2/go.mod h1:uvQavJ1pZ0hIoC/jfqNoMLURIMhKzINIWypNM17puug= modernc.org/lldb v1.0.0/go.mod h1:jcRvJGWfCGodDZz8BPwiKMJxGJngQ/5DrRapkQnLob8= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8= modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc= -modernc.org/memory v1.1.1 h1:bDOL0DIDLQv7bWhP3gMvIrnoFw+Eo6F7a2QK9HPDiFU= modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A= +modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds= +modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/ql v1.0.0/go.mod h1:xGVyrLIatPcO2C1JvI/Co8c0sr6y91HKFNy4pt9JXEY= modernc.org/sortutil v1.1.0/go.mod h1:ZyL98OQHJgH9IEfN71VsamvJgrtRX9Dj2gX+vH86L1k= modernc.org/sqlite v1.10.6/go.mod h1:Z9FEjUtZP4qFEg6/SiADg9XCER7aYy9a/j7Pg9P7CPs= -modernc.org/sqlite v1.18.0 h1:ef66qJSgKeyLyrF4kQ2RHw/Ue3V89fyFNbGL073aDjI= modernc.org/sqlite v1.18.0/go.mod h1:B9fRWZacNxJBHoCJZQr1R54zhVn3fjfl0aszflrTSxY= +modernc.org/sqlite v1.20.1 h1:z6qRLw72B0VfRrJjs3l6hWkzYDx1bo0WGVrBGP4ohhM= +modernc.org/sqlite v1.20.1/go.mod h1:fODt+bFmc/j8LcoCbMSkAuKuGmhxjG45KGc25N2705M= modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= -modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs= modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= +modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY= +modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= modernc.org/tcl v1.5.2/go.mod h1:pmJYOLgpiys3oI4AeAafkcUfE+TKKilminxNyU/+Zlo= -modernc.org/tcl v1.13.1 h1:npxzTwFTZYM8ghWicVIX1cRWzj7Nd8i6AqqX2p+IYao= modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= -modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk= +modernc.org/tcl v1.15.0 h1:oY+JeD11qVVSgVvodMJsu7Edf8tr5E/7tuhF5cNYz34= modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA= modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA= -modernc.org/z v1.5.1 h1:RTNHdsrOpeoSeOF4FbzTo8gBYByaJ5xT7NgZ9ZqRiJM= modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= +modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE= modernc.org/zappy v1.0.0/go.mod h1:hHe+oGahLVII/aTTyWK/b53VDHMAGCBYYeZ9sn83HC4= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/plugin/hclog_adapter.go b/plugin/hclog_adapter.go index a12e8f692c..beac14dfd1 100644 --- a/plugin/hclog_adapter.go +++ b/plugin/hclog_adapter.go @@ -124,6 +124,8 @@ func (h *hclogAdapter) StandardWriter(opts *hclog.StandardLoggerOptions) io.Writ func (h *hclogAdapter) SetLevel(hclog.Level) {} +func (h *hclogAdapter) GetLevel() hclog.Level { return hclog.NoLevel } + func (h *hclogAdapter) ImpliedArgs() []any { return []any{} } From 360d590728c77cc4a1245e1f8cb2ccf82334bd70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Garc=C3=ADa=20Montoro?= Date: Thu, 12 Jan 2023 16:13:32 +0100 Subject: [PATCH 22/41] Skip TestReplicaLagQuery until MM-49604 is fixed (#22048) --- store/sqlstore/store_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/store/sqlstore/store_test.go b/store/sqlstore/store_test.go index bfd10d14c1..d9836c8c41 100644 --- a/store/sqlstore/store_test.go +++ b/store/sqlstore/store_test.go @@ -703,6 +703,7 @@ func TestVersionString(t *testing.T) { } func TestReplicaLagQuery(t *testing.T) { + t.Skip("MM-49604") testDrivers := []string{ model.DatabaseDriverPostgres, model.DatabaseDriverMysql, From e7deb3904635cc2ac15590dd622fa59e9891dc9e Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Thu, 12 Jan 2023 23:14:29 +0530 Subject: [PATCH 23/41] MM-49154: Do not translate server side logs (#22058) https://mattermost.atlassian.net/browse/MM-49154 ```release-note NONE ``` --- web/handlers.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web/handlers.go b/web/handlers.go index 333e3906e5..9cc655eb40 100644 --- a/web/handlers.go +++ b/web/handlers.go @@ -360,9 +360,11 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Handle errors that have occurred if c.Err != nil { - c.Err.Translate(c.AppContext.T) c.Err.RequestId = c.AppContext.RequestId() c.LogErrorByCode(c.Err) + // The locale translation needs to happen after we have logged it. + // We don't want the server logs to be translated as per user locale. + c.Err.Translate(c.AppContext.T) c.Err.Where = r.URL.Path From daa83d4a78d8e68797b38004e37350465414cabe Mon Sep 17 00:00:00 2001 From: Mylon Suren <23694620+mylonsuren@users.noreply.github.com> Date: Thu, 12 Jan 2023 12:58:45 -0500 Subject: [PATCH 24/41] [MM-47896] Channel names can collide with GM names (#21639) * Block channel creation if name matches GM naming pattern * Fix regex and error text * Add test for DM names * Update error string * Trigger build Co-authored-by: Mattermod Co-authored-by: Mattermost Build --- i18n/en.json | 2 +- model/channel.go | 11 ++++++++--- model/channel_test.go | 6 ++++++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/i18n/en.json b/i18n/en.json index 6bf836abe8..f6f7237066 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -8121,7 +8121,7 @@ }, { "id": "model.channel.is_valid.name.app_error", - "translation": "Invalid channel name. User ids are not permitted in channel name for non-direct message channels." + "translation": "Channel names can't be in a hexadecimal format. Please enter a different channel name." }, { "id": "model.channel.is_valid.purpose.app_error", diff --git a/model/channel.go b/model/channel.go index e900011cc9..29f2b9ab8c 100644 --- a/model/channel.go +++ b/model/channel.go @@ -10,6 +10,7 @@ import ( "errors" "io" "net/http" + "regexp" "sort" "strings" "unicode/utf8" @@ -185,6 +186,8 @@ type ChannelMemberCountByGroup struct { type ChannelOption func(channel *Channel) +var gmNameRegex = regexp.MustCompile("^[a-f0-9]{40}$") + func WithID(ID string) ChannelOption { return func(channel *Channel) { channel.Id = ID @@ -281,9 +284,11 @@ func (o *Channel) IsValid() *AppError { return NewAppError("Channel.IsValid", "model.channel.is_valid.creator_id.app_error", nil, "", http.StatusBadRequest) } - userIds := strings.Split(o.Name, "__") - if o.Type != ChannelTypeDirect && len(userIds) == 2 && IsValidId(userIds[0]) && IsValidId(userIds[1]) { - return NewAppError("Channel.IsValid", "model.channel.is_valid.name.app_error", nil, "", http.StatusBadRequest) + if o.Type != ChannelTypeDirect && o.Type != ChannelTypeGroup { + userIds := strings.Split(o.Name, "__") + if ok := gmNameRegex.MatchString(o.Name); ok || (o.Type != ChannelTypeDirect && len(userIds) == 2 && IsValidId(userIds[0]) && IsValidId(userIds[1])) { + return NewAppError("Channel.IsValid", "model.channel.is_valid.name.app_error", nil, "", http.StatusBadRequest) + } } return nil diff --git a/model/channel_test.go b/model/channel_test.go index 6cee525f37..038720a6d2 100644 --- a/model/channel_test.go +++ b/model/channel_test.go @@ -79,6 +79,12 @@ func TestChannelIsValid(t *testing.T) { o.Purpose = strings.Repeat("0123456789", 25) require.Nil(t, o.IsValid()) + + o.Name = "beu8cc6b3jnxfe9r4na9baooma__36atajbs87dqmpym6o8eiy9saa" + require.NotNil(t, o.IsValid()) + + o.Name = "71b03afcbb2d503d49f87f057549c43db4e19f92" + require.NotNil(t, o.IsValid()) } func TestChannelPreSave(t *testing.T) { From c31494131735db064f31134c3938e6923bb20cf8 Mon Sep 17 00:00:00 2001 From: Martin Kraft Date: Thu, 12 Jan 2023 13:47:35 -0500 Subject: [PATCH 25/41] Adds description of some channel searching options. (#22009) Co-authored-by: Mattermost Build --- model/channel.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/model/channel.go b/model/channel.go index 29f2b9ab8c..0ca11c75e6 100644 --- a/model/channel.go +++ b/model/channel.go @@ -160,7 +160,7 @@ type ChannelModeratedRolesPatch struct { type ChannelSearchOpts struct { NotAssociatedToGroup string ExcludeDefaultChannels bool - IncludeDeleted bool + IncludeDeleted bool // If true, deleted channels will be included in the results. Deleted bool ExcludeChannelNames []string TeamIds []string @@ -174,7 +174,7 @@ type ChannelSearchOpts struct { Private bool Page *int PerPage *int - LastDeleteAt int + LastDeleteAt int // When combined with IncludeDeleted, only channels deleted after this time will be returned. LastUpdateAt int } From 309df7917f56da44b76812aa426a93659e6af822 Mon Sep 17 00:00:00 2001 From: Nick Misasi Date: Thu, 12 Jan 2023 15:04:22 -0500 Subject: [PATCH 26/41] [MM-48973] Enable test that was fixed separately (#22043) * Enable test that was fixed separately * Add cloud check to be safe * Feedback Co-authored-by: Mattermost Build --- app/team_test.go | 1 - app/user.go | 14 ++++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/app/team_test.go b/app/team_test.go index e281a1feaa..23fd15117b 100644 --- a/app/team_test.go +++ b/app/team_test.go @@ -102,7 +102,6 @@ func TestAddUserToTeam(t *testing.T) { }) t.Run("block user by domain but allow bot", func(t *testing.T) { - t.Skip("MM-48973") th.BasicTeam.AllowedDomains = "example.com" _, err := th.App.UpdateTeam(th.BasicTeam) require.Nil(t, err, "Should update the team") diff --git a/app/user.go b/app/user.go index 991457f7ba..b59774fd13 100644 --- a/app/user.go +++ b/app/user.go @@ -321,12 +321,14 @@ func (a *App) createUserOrGuest(c request.CTX, user *model.User, guest bool) (*m // table in CWS. This is then used to calculate how much the customers have to pay in addition for the extra users. If the // workspace is currently on a monthly plan, then this function will not do anything. - go func() { - _, err := a.SendSubscriptionHistoryEvent(ruser.Id) - if err != nil { - c.Logger().Error("Failed to create/update the SubscriptionHistoryEvent", mlog.Err(err)) - } - }() + if a.Channels().License().IsCloud() { + go func(userId string) { + _, err := a.SendSubscriptionHistoryEvent(userId) + if err != nil { + c.Logger().Error("Failed to create/update the SubscriptionHistoryEvent", mlog.Err(err)) + } + }(ruser.Id) + } return ruser, nil } From b13a866a1c1f543fad6e9a358ccf28e4220eb210 Mon Sep 17 00:00:00 2001 From: Michael Kochell <6913320+mickmister@users.noreply.github.com> Date: Thu, 12 Jan 2023 15:41:37 -0500 Subject: [PATCH 27/41] bump gitlab plugin version to 1.6.0 (#22057) Co-authored-by: Mattermost Build --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 63bb84e727..ff9d00800f 100644 --- a/Makefile +++ b/Makefile @@ -154,7 +154,7 @@ PLUGIN_PACKAGES += mattermost-plugin-channel-export-v1.0.0 PLUGIN_PACKAGES += mattermost-plugin-confluence-v1.3.0 PLUGIN_PACKAGES += mattermost-plugin-custom-attributes-v1.3.1 PLUGIN_PACKAGES += mattermost-plugin-github-v2.1.4 -PLUGIN_PACKAGES += mattermost-plugin-gitlab-v1.5.2 +PLUGIN_PACKAGES += mattermost-plugin-gitlab-v1.6.0 PLUGIN_PACKAGES += mattermost-plugin-playbooks-v1.35.0 PLUGIN_PACKAGES += mattermost-plugin-jenkins-v1.1.0 PLUGIN_PACKAGES += mattermost-plugin-jira-v3.2.2 From b79cb7e7d72a3ee74f9c21f1308abcf694048c10 Mon Sep 17 00:00:00 2001 From: Christopher Poile Date: Thu, 12 Jan 2023 17:37:41 -0500 Subject: [PATCH 28/41] MM-49638 - Prepackage Calls 0.12.1 (#22067) Co-authored-by: Mattermost Build --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ff9d00800f..3f3477094e 100644 --- a/Makefile +++ b/Makefile @@ -149,7 +149,7 @@ TEMPLATES_DIR=templates PLUGIN_PACKAGES ?= mattermost-plugin-antivirus-v0.1.2 PLUGIN_PACKAGES += mattermost-plugin-autolink-v1.2.2 PLUGIN_PACKAGES += mattermost-plugin-aws-SNS-v1.2.0 -PLUGIN_PACKAGES += mattermost-plugin-calls-v0.12.0 +PLUGIN_PACKAGES += mattermost-plugin-calls-v0.12.1 PLUGIN_PACKAGES += mattermost-plugin-channel-export-v1.0.0 PLUGIN_PACKAGES += mattermost-plugin-confluence-v1.3.0 PLUGIN_PACKAGES += mattermost-plugin-custom-attributes-v1.3.1 From 0e6dc9389de6729776bbd8e07ad5c7535fd15cae Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Fri, 13 Jan 2023 18:03:49 +0530 Subject: [PATCH 29/41] MM-49658: Correctly disable plugin in product mode (#22071) Automatic Merge --- app/plugin.go | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/app/plugin.go b/app/plugin.go index 679576e723..0f40611e97 100644 --- a/app/plugin.go +++ b/app/plugin.go @@ -130,23 +130,6 @@ func (ch *Channels) syncPluginsActiveState() { } if pluginEnabled { - // Disable focalboard in product mode. - if pluginID == model.PluginIdFocalboard && ch.cfgSvc.Config().FeatureFlags.BoardsProduct { - msg := "Plugin cannot run in product mode. Disabling." - mlog.Warn(msg, mlog.String("plugin_id", model.PluginIdFocalboard)) - - // This is a mini-version of ch.disablePlugin. - // We don't call that directly, because that will recursively call - // this method. - ch.cfgSvc.UpdateConfig(func(cfg *model.Config) { - cfg.PluginSettings.PluginStates[pluginID] = &model.PluginState{Enable: false} - }) - pluginsEnvironment.SetPluginError(pluginID, msg) - ch.unregisterPluginCommands(pluginID) - disabledPlugins = append(disabledPlugins, plugin) - continue - } - enabledPlugins = append(enabledPlugins, plugin) } else { disabledPlugins = append(disabledPlugins, plugin) @@ -322,6 +305,16 @@ func (ch *Channels) syncPlugins() *model.AppError { var wg sync.WaitGroup for _, plugin := range availablePlugins { + // Disable focalboard in product mode. + if plugin.Manifest.Id == model.PluginIdFocalboard && ch.cfgSvc.Config().FeatureFlags.BoardsProduct { + mlog.Info("Plugin cannot run in product mode, disabling.", mlog.String("plugin_id", model.PluginIdFocalboard)) + appErr := ch.disablePlugin(model.PluginIdFocalboard) + if appErr != nil { + mlog.Error("Error disabling plugin", mlog.Err(err)) + } + continue + } + wg.Add(1) go func(pluginID string) { defer wg.Done() From 5ae6d6e1082f535d819b7ed584260830ea990497 Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Fri, 13 Jan 2023 21:44:58 +0530 Subject: [PATCH 30/41] Revert "MM-49485: Set BoardsProduct FF to on by default (#22006)" (#22075) This reverts commit d27d7bc8f75326b690e63530ab783fea78224ee5. --- config/diff_test.go | 6 +++--- model/config.go | 4 ++-- model/config_test.go | 4 ++-- model/feature_flags.go | 2 +- scripts/test.sh | 1 - 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/config/diff_test.go b/config/diff_test.go index 427045dae7..15ec6f41f7 100644 --- a/config/diff_test.go +++ b/config/diff_test.go @@ -808,7 +808,7 @@ func TestDiff(t *testing.T) { Enable: !defaultConfigGen().PluginSettings.PluginStates["com.mattermost.nps"].Enable, }, "focalboard": { - Enable: false, + Enable: true, }, "playbooks": { Enable: true, @@ -846,7 +846,7 @@ func TestDiff(t *testing.T) { Enable: true, }, "focalboard": { - Enable: false, + Enable: true, }, "playbooks": { Enable: true, @@ -876,7 +876,7 @@ func TestDiff(t *testing.T) { BaseVal: defaultConfigGen().PluginSettings.PluginStates, ActualVal: map[string]*model.PluginState{ "focalboard": { - Enable: false, + Enable: true, }, "playbooks": { Enable: true, diff --git a/model/config.go b/model/config.go index 2a8fb848c9..ff083bf629 100644 --- a/model/config.go +++ b/model/config.go @@ -2872,8 +2872,8 @@ func (s *PluginSettings) SetDefaults(ls LogSettings) { } if s.PluginStates[PluginIdFocalboard] == nil { - // Disable the focalboard plugin by default - s.PluginStates[PluginIdFocalboard] = &PluginState{Enable: false} + // Enable the focalboard plugin by default + s.PluginStates[PluginIdFocalboard] = &PluginState{Enable: true} } if s.PluginStates[PluginIdApps] == nil { diff --git a/model/config_test.go b/model/config_test.go index 752ace1547..cedffbcb08 100644 --- a/model/config_test.go +++ b/model/config_test.go @@ -387,11 +387,11 @@ func TestConfigDefaultChannelExportPluginState(t *testing.T) { } func TestConfigDefaultFocalboardPluginState(t *testing.T) { - t.Run("should not enable Focalboard plugin by default", func(t *testing.T) { + t.Run("should enable Focalboard plugin by default", func(t *testing.T) { c1 := Config{} c1.SetDefaults() - assert.False(t, c1.PluginSettings.PluginStates["focalboard"].Enable) + assert.True(t, c1.PluginSettings.PluginStates["focalboard"].Enable) }) t.Run("should not re-enable focalboard plugin after it has been disabled", func(t *testing.T) { diff --git a/model/feature_flags.go b/model/feature_flags.go index 449a04b5bc..4864a660c1 100644 --- a/model/feature_flags.go +++ b/model/feature_flags.go @@ -95,7 +95,7 @@ func (f *FeatureFlags) SetDefaults() { f.InsightsEnabled = true f.CommandPalette = false f.CallsEnabled = true - f.BoardsProduct = true + f.BoardsProduct = false f.SendWelcomePost = true f.PostPriority = true f.PeopleProduct = false diff --git a/scripts/test.sh b/scripts/test.sh index f13d9244c5..63f89fc785 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -14,7 +14,6 @@ COVERMODE=$8 PACKAGES_COMMA=$(echo $PACKAGES | tr ' ' ',') export MM_SERVER_PATH=$PWD -export MM_FEATUREFLAGS_BoardsProduct=false echo "Packages to test: $PACKAGES" echo "GOFLAGS: $GOFLAGS" From 6b6150d37453403eaf834904bc4139aa2d8d1bed Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Mon, 16 Jan 2023 12:40:15 +0530 Subject: [PATCH 31/41] Revert "Revert "MM-49485: Set BoardsProduct FF to on by default (#22006)" (#22075)" (#22083) This reverts commit 5ae6d6e1082f535d819b7ed584260830ea990497. ```release-note NONE ``` --- config/diff_test.go | 6 +++--- model/config.go | 4 ++-- model/config_test.go | 4 ++-- model/feature_flags.go | 2 +- scripts/test.sh | 1 + 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/config/diff_test.go b/config/diff_test.go index 15ec6f41f7..427045dae7 100644 --- a/config/diff_test.go +++ b/config/diff_test.go @@ -808,7 +808,7 @@ func TestDiff(t *testing.T) { Enable: !defaultConfigGen().PluginSettings.PluginStates["com.mattermost.nps"].Enable, }, "focalboard": { - Enable: true, + Enable: false, }, "playbooks": { Enable: true, @@ -846,7 +846,7 @@ func TestDiff(t *testing.T) { Enable: true, }, "focalboard": { - Enable: true, + Enable: false, }, "playbooks": { Enable: true, @@ -876,7 +876,7 @@ func TestDiff(t *testing.T) { BaseVal: defaultConfigGen().PluginSettings.PluginStates, ActualVal: map[string]*model.PluginState{ "focalboard": { - Enable: true, + Enable: false, }, "playbooks": { Enable: true, diff --git a/model/config.go b/model/config.go index ff083bf629..2a8fb848c9 100644 --- a/model/config.go +++ b/model/config.go @@ -2872,8 +2872,8 @@ func (s *PluginSettings) SetDefaults(ls LogSettings) { } if s.PluginStates[PluginIdFocalboard] == nil { - // Enable the focalboard plugin by default - s.PluginStates[PluginIdFocalboard] = &PluginState{Enable: true} + // Disable the focalboard plugin by default + s.PluginStates[PluginIdFocalboard] = &PluginState{Enable: false} } if s.PluginStates[PluginIdApps] == nil { diff --git a/model/config_test.go b/model/config_test.go index cedffbcb08..752ace1547 100644 --- a/model/config_test.go +++ b/model/config_test.go @@ -387,11 +387,11 @@ func TestConfigDefaultChannelExportPluginState(t *testing.T) { } func TestConfigDefaultFocalboardPluginState(t *testing.T) { - t.Run("should enable Focalboard plugin by default", func(t *testing.T) { + t.Run("should not enable Focalboard plugin by default", func(t *testing.T) { c1 := Config{} c1.SetDefaults() - assert.True(t, c1.PluginSettings.PluginStates["focalboard"].Enable) + assert.False(t, c1.PluginSettings.PluginStates["focalboard"].Enable) }) t.Run("should not re-enable focalboard plugin after it has been disabled", func(t *testing.T) { diff --git a/model/feature_flags.go b/model/feature_flags.go index 4864a660c1..449a04b5bc 100644 --- a/model/feature_flags.go +++ b/model/feature_flags.go @@ -95,7 +95,7 @@ func (f *FeatureFlags) SetDefaults() { f.InsightsEnabled = true f.CommandPalette = false f.CallsEnabled = true - f.BoardsProduct = false + f.BoardsProduct = true f.SendWelcomePost = true f.PostPriority = true f.PeopleProduct = false diff --git a/scripts/test.sh b/scripts/test.sh index 63f89fc785..f13d9244c5 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -14,6 +14,7 @@ COVERMODE=$8 PACKAGES_COMMA=$(echo $PACKAGES | tr ' ' ',') export MM_SERVER_PATH=$PWD +export MM_FEATUREFLAGS_BoardsProduct=false echo "Packages to test: $PACKAGES" echo "GOFLAGS: $GOFLAGS" From 1fdedf30f10628fa20f5d9d7b72993c3d187bfaf Mon Sep 17 00:00:00 2001 From: Konstantinos Pittas Date: Mon, 16 Jan 2023 15:30:14 +0200 Subject: [PATCH 32/41] Revert "[MM-46579] Add a limit for preferences" (#22086) --- app/preference.go | 3 +-- model/config.go | 5 ----- services/telemetry/telemetry.go | 1 - store/opentracinglayer/opentracinglayer.go | 4 ++-- store/retrylayer/retrylayer.go | 4 ++-- store/sqlstore/preference_store.go | 17 ++++++----------- store/store.go | 2 +- store/storetest/mocks/PreferenceStore.go | 14 +++++++------- store/storetest/preference_store.go | 18 +++++++++--------- store/timerlayer/timerlayer.go | 4 ++-- 10 files changed, 30 insertions(+), 42 deletions(-) diff --git a/app/preference.go b/app/preference.go index 6bf536249f..f995eb9391 100644 --- a/app/preference.go +++ b/app/preference.go @@ -33,8 +33,7 @@ func (w *preferencesServiceWrapper) DeletePreferencesForUser(userID string, pref } func (a *App) GetPreferencesForUser(userID string) (model.Preferences, *model.AppError) { - limit := *a.Config().ServiceSettings.ExperimentalMaxUserPreferences - preferences, err := a.Srv().Store().Preference().GetAll(userID, limit) + preferences, err := a.Srv().Store().Preference().GetAll(userID) if err != nil { return nil, model.NewAppError("GetPreferencesForUser", "app.preference.get_all.app_error", nil, "", http.StatusBadRequest).Wrap(err) } diff --git a/model/config.go b/model/config.go index 2a8fb848c9..ef948375cf 100644 --- a/model/config.go +++ b/model/config.go @@ -385,7 +385,6 @@ type ServiceSettings struct { EnableCustomGroups *bool `access:"site_users_and_teams"` SelfHostedPurchase *bool `access:"write_restrictable,cloud_restrictable"` AllowSyncedDrafts *bool `access:"site_posts"` - ExperimentalMaxUserPreferences *int } func (s *ServiceSettings) SetDefaults(isUpdate bool) { @@ -858,10 +857,6 @@ func (s *ServiceSettings) SetDefaults(isUpdate bool) { if s.SelfHostedPurchase == nil { s.SelfHostedPurchase = NewBool(true) } - - if s.ExperimentalMaxUserPreferences == nil { - s.ExperimentalMaxUserPreferences = NewInt(1000) - } } type ClusterSettings struct { diff --git a/services/telemetry/telemetry.go b/services/telemetry/telemetry.go index fb30db7979..860960c379 100644 --- a/services/telemetry/telemetry.go +++ b/services/telemetry/telemetry.go @@ -460,7 +460,6 @@ func (ts *TelemetryService) trackConfig() { "post_priority": *cfg.ServiceSettings.PostPriority, "self_hosted_purchase": *cfg.ServiceSettings.SelfHostedPurchase, "allow_synced_drafts": *cfg.ServiceSettings.AllowSyncedDrafts, - "experimental_max_user_preferences": *cfg.ServiceSettings.ExperimentalMaxUserPreferences, }) ts.SendTelemetry(TrackConfigTeam, map[string]any{ diff --git a/store/opentracinglayer/opentracinglayer.go b/store/opentracinglayer/opentracinglayer.go index e7e9aa5264..129ef5254b 100644 --- a/store/opentracinglayer/opentracinglayer.go +++ b/store/opentracinglayer/opentracinglayer.go @@ -6919,7 +6919,7 @@ func (s *OpenTracingLayerPreferenceStore) Get(userID string, category string, na return result, err } -func (s *OpenTracingLayerPreferenceStore) GetAll(userID string, limit int) (model.Preferences, error) { +func (s *OpenTracingLayerPreferenceStore) GetAll(userID string) (model.Preferences, error) { origCtx := s.Root.Store.Context() span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "PreferenceStore.GetAll") s.Root.Store.SetContext(newCtx) @@ -6928,7 +6928,7 @@ func (s *OpenTracingLayerPreferenceStore) GetAll(userID string, limit int) (mode }() defer span.Finish() - result, err := s.PreferenceStore.GetAll(userID, limit) + result, err := s.PreferenceStore.GetAll(userID) if err != nil { span.LogFields(spanlog.Error(err)) ext.Error.Set(span, true) diff --git a/store/retrylayer/retrylayer.go b/store/retrylayer/retrylayer.go index cfe39a65d4..065a1400a9 100644 --- a/store/retrylayer/retrylayer.go +++ b/store/retrylayer/retrylayer.go @@ -7845,11 +7845,11 @@ func (s *RetryLayerPreferenceStore) Get(userID string, category string, name str } -func (s *RetryLayerPreferenceStore) GetAll(userID string, limit int) (model.Preferences, error) { +func (s *RetryLayerPreferenceStore) GetAll(userID string) (model.Preferences, error) { tries := 0 for { - result, err := s.PreferenceStore.GetAll(userID, limit) + result, err := s.PreferenceStore.GetAll(userID) if err == nil { return result, nil } diff --git a/store/sqlstore/preference_store.go b/store/sqlstore/preference_store.go index ed223e7233..6815e950e8 100644 --- a/store/sqlstore/preference_store.go +++ b/store/sqlstore/preference_store.go @@ -175,22 +175,17 @@ func (s SqlPreferenceStore) GetCategory(userId string, category string) (model.P } -func (s SqlPreferenceStore) GetAll(userId string, limit int) (model.Preferences, error) { - query := s.getQueryBuilder(). +func (s SqlPreferenceStore) GetAll(userId string) (model.Preferences, error) { + var preferences model.Preferences + query, args, err := s.getQueryBuilder(). Select("*"). From("Preferences"). - Where(sq.Eq{"UserId": userId}) - if limit > 0 { - query = query.Limit(uint64(limit)) - } - - queryString, args, err := query.ToSql() + Where(sq.Eq{"UserId": userId}). + ToSql() if err != nil { return nil, errors.Wrap(err, "could not build sql query to get preference") } - - var preferences model.Preferences - if err = s.GetReplicaX().Select(&preferences, queryString, args...); err != nil { + if err = s.GetReplicaX().Select(&preferences, query, args...); err != nil { return nil, errors.Wrapf(err, "failed to find Preference with userId=%s", userId) } return preferences, nil diff --git a/store/store.go b/store/store.go index 94156513fd..8a1c69d91a 100644 --- a/store/store.go +++ b/store/store.go @@ -641,7 +641,7 @@ type PreferenceStore interface { GetCategory(userID string, category string) (model.Preferences, error) GetCategoryAndName(category string, nane string) (model.Preferences, error) Get(userID string, category string, name string) (*model.Preference, error) - GetAll(userID string, limit int) (model.Preferences, error) + GetAll(userID string) (model.Preferences, error) Delete(userID, category, name string) error DeleteCategory(userID string, category string) error DeleteCategoryAndName(category string, name string) error diff --git a/store/storetest/mocks/PreferenceStore.go b/store/storetest/mocks/PreferenceStore.go index 9c7cbd84c4..c651e905bc 100644 --- a/store/storetest/mocks/PreferenceStore.go +++ b/store/storetest/mocks/PreferenceStore.go @@ -121,13 +121,13 @@ func (_m *PreferenceStore) Get(userID string, category string, name string) (*mo return r0, r1 } -// GetAll provides a mock function with given fields: userID, limit -func (_m *PreferenceStore) GetAll(userID string, limit int) (model.Preferences, error) { - ret := _m.Called(userID, limit) +// GetAll provides a mock function with given fields: userID +func (_m *PreferenceStore) GetAll(userID string) (model.Preferences, error) { + ret := _m.Called(userID) var r0 model.Preferences - if rf, ok := ret.Get(0).(func(string, int) model.Preferences); ok { - r0 = rf(userID, limit) + if rf, ok := ret.Get(0).(func(string) model.Preferences); ok { + r0 = rf(userID) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(model.Preferences) @@ -135,8 +135,8 @@ func (_m *PreferenceStore) GetAll(userID string, limit int) (model.Preferences, } var r1 error - if rf, ok := ret.Get(1).(func(string, int) error); ok { - r1 = rf(userID, limit) + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(userID) } else { r1 = ret.Error(1) } diff --git a/store/storetest/preference_store.go b/store/storetest/preference_store.go index 42a5ae9ed1..5d645f345a 100644 --- a/store/storetest/preference_store.go +++ b/store/storetest/preference_store.go @@ -184,7 +184,7 @@ func testPreferenceGetAll(t *testing.T, ss store.Store) { err := ss.Preference().Save(preferences) require.NoError(t, err) - result, err := ss.Preference().GetAll(userId, 0) + result, err := ss.Preference().GetAll(userId) require.NoError(t, err) require.Equal(t, 3, len(result), "got the wrong number of preferences") @@ -243,13 +243,13 @@ func testPreferenceDelete(t *testing.T, ss store.Store) { err := ss.Preference().Save(model.Preferences{preference}) require.NoError(t, err) - preferences, err := ss.Preference().GetAll(preference.UserId, 0) + preferences, err := ss.Preference().GetAll(preference.UserId) require.NoError(t, err) assert.Len(t, preferences, 1, "should've returned 1 preference") err = ss.Preference().Delete(preference.UserId, preference.Category, preference.Name) require.NoError(t, err) - preferences, err = ss.Preference().GetAll(preference.UserId, 0) + preferences, err = ss.Preference().GetAll(preference.UserId) require.NoError(t, err) assert.Empty(t, preferences, "should've returned no preferences") } @@ -275,14 +275,14 @@ func testPreferenceDeleteCategory(t *testing.T, ss store.Store) { err := ss.Preference().Save(model.Preferences{preference1, preference2}) require.NoError(t, err) - preferences, err := ss.Preference().GetAll(userId, 0) + preferences, err := ss.Preference().GetAll(userId) require.NoError(t, err) assert.Len(t, preferences, 2, "should've returned 2 preferences") err = ss.Preference().DeleteCategory(userId, category) require.NoError(t, err) - preferences, err = ss.Preference().GetAll(userId, 0) + preferences, err = ss.Preference().GetAll(userId) require.NoError(t, err) assert.Empty(t, preferences, "should've returned no preferences") } @@ -310,22 +310,22 @@ func testPreferenceDeleteCategoryAndName(t *testing.T, ss store.Store) { err := ss.Preference().Save(model.Preferences{preference1, preference2}) require.NoError(t, err) - preferences, err := ss.Preference().GetAll(userId, 0) + preferences, err := ss.Preference().GetAll(userId) require.NoError(t, err) assert.Len(t, preferences, 1, "should've returned 1 preference") - preferences, err = ss.Preference().GetAll(userId2, 0) + preferences, err = ss.Preference().GetAll(userId2) require.NoError(t, err) assert.Len(t, preferences, 1, "should've returned 1 preference") err = ss.Preference().DeleteCategoryAndName(category, name) require.NoError(t, err) - preferences, err = ss.Preference().GetAll(userId, 0) + preferences, err = ss.Preference().GetAll(userId) require.NoError(t, err) assert.Empty(t, preferences, "should've returned no preference") - preferences, err = ss.Preference().GetAll(userId2, 0) + preferences, err = ss.Preference().GetAll(userId2) require.NoError(t, err) assert.Empty(t, preferences, "should've returned no preference") } diff --git a/store/timerlayer/timerlayer.go b/store/timerlayer/timerlayer.go index 2a2ed7eefe..19ccaf656d 100644 --- a/store/timerlayer/timerlayer.go +++ b/store/timerlayer/timerlayer.go @@ -6256,10 +6256,10 @@ func (s *TimerLayerPreferenceStore) Get(userID string, category string, name str return result, err } -func (s *TimerLayerPreferenceStore) GetAll(userID string, limit int) (model.Preferences, error) { +func (s *TimerLayerPreferenceStore) GetAll(userID string) (model.Preferences, error) { start := time.Now() - result, err := s.PreferenceStore.GetAll(userID, limit) + result, err := s.PreferenceStore.GetAll(userID) elapsed := float64(time.Since(start)) / float64(time.Second) if s.Root.Metrics != nil { From 861ad713d5f6ad4a310c885708f43c8845311d75 Mon Sep 17 00:00:00 2001 From: mattermod Date: Mon, 16 Jan 2023 13:43:17 +0000 Subject: [PATCH 33/41] Update latest version to 7.7.0 --- build/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Dockerfile b/build/Dockerfile index aaa82b99ca..de0d18800b 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -8,7 +8,7 @@ SHELL ["/bin/bash", "-o", "pipefail", "-c"] ENV PATH="/mattermost/bin:${PATH}" ARG PUID=2000 ARG PGID=2000 -ARG MM_PACKAGE="https://releases.mattermost.com/7.5.2/mattermost-7.5.2-linux-amd64.tar.gz?src=docker" +ARG MM_PACKAGE="https://releases.mattermost.com/7.7.0/mattermost-7.7.0-linux-amd64.tar.gz?src=docker" # # Install needed packages and indirect dependencies RUN apt-get update \ From ad93c10bb31817a3e55ea8c3c69d3ea358e6274f Mon Sep 17 00:00:00 2001 From: Mattermod Date: Mon, 16 Jan 2023 16:15:07 +0200 Subject: [PATCH 34/41] Update minor version to 7.8.0 (#22082) Automatic Merge --- model/version.go | 1 + 1 file changed, 1 insertion(+) diff --git a/model/version.go b/model/version.go index 6090666ca3..7cf3f2c531 100644 --- a/model/version.go +++ b/model/version.go @@ -13,6 +13,7 @@ import ( // It should be maintained in chronological order with most current // release at the front of the list. var versions = []string{ + "7.8.0", "7.7.0", "7.6.0", "7.5.0", From ebd58bc8c7cf7205628708b39c586e7460aa2f15 Mon Sep 17 00:00:00 2001 From: jprusch Date: Mon, 16 Jan 2023 16:23:35 +0100 Subject: [PATCH 35/41] Translated using Weblate (German) Currently translated at 100.0% (2433 of 2433 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/de/ --- i18n/de.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/de.json b/i18n/de.json index 3015f856b6..a5b898781f 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -4989,7 +4989,7 @@ }, { "id": "model.channel.is_valid.name.app_error", - "translation": "Ungültiger Kanalname. Benutzerkennungen sind in Kanalnamen für Kanäle, die keine Direktnachrichtenkanäle sind, nicht erlaubt." + "translation": "Kanalnamen können nicht im hexadezimalen Format angegeben werden. Bitte gib einen anderen Kanalnamen ein." }, { "id": "interactive_message.decode_trigger_id.base64_decode_failed_signature", From 3c63787376bbbc3df912e853fd522aab07f7f3e0 Mon Sep 17 00:00:00 2001 From: Tom De Moor Date: Mon, 16 Jan 2023 16:23:35 +0100 Subject: [PATCH 36/41] Translated using Weblate (Dutch) Currently translated at 100.0% (2433 of 2433 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/nl/ --- i18n/nl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/nl.json b/i18n/nl.json index a10623f90d..56b3c7366b 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -4969,7 +4969,7 @@ }, { "id": "model.channel.is_valid.name.app_error", - "translation": "Ongeldige kanaalnaam. Gebruikersindentifiers zijn niet toegestaan in een kanaalnaam voor niet directe -berichtenkanalen." + "translation": "Kanaalnamen kunnen niet hexadecimaal zijn. Voer een andere kanaalnaam in." }, { "id": "interactive_message.decode_trigger_id.base64_decode_failed_signature", From e835568a30184fb480e17f902ad9133a440aa436 Mon Sep 17 00:00:00 2001 From: master7 Date: Mon, 16 Jan 2023 16:23:35 +0100 Subject: [PATCH 37/41] Translated using Weblate (Polish) Currently translated at 100.0% (2433 of 2433 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/pl/ --- i18n/pl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/pl.json b/i18n/pl.json index 8b6fbce3eb..5239a71389 100644 --- a/i18n/pl.json +++ b/i18n/pl.json @@ -4949,7 +4949,7 @@ }, { "id": "model.channel.is_valid.name.app_error", - "translation": "Invalid channel name. User ids are not permitted in channel name for non-direct message channels." + "translation": "Nazwy kanałów nie mogą być w formacie szesnastkowym. Proszę wprowadzić inną nazwę kanału." }, { "id": "interactive_message.decode_trigger_id.base64_decode_failed_signature", From d3d9702823d703a6ee41adb9546761fbb3878b7c Mon Sep 17 00:00:00 2001 From: Matthew Williams Date: Mon, 16 Jan 2023 16:23:36 +0100 Subject: [PATCH 38/41] Translated using Weblate (English (Australia)) Currently translated at 99.6% (2424 of 2433 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/en_AU/ --- i18n/en_AU.json | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/i18n/en_AU.json b/i18n/en_AU.json index 094e51ed6e..461533cfdf 100644 --- a/i18n/en_AU.json +++ b/i18n/en_AU.json @@ -2737,7 +2737,7 @@ }, { "id": "model.channel.is_valid.name.app_error", - "translation": "Invalid channel name. User IDs are not permitted in channel name for non-direct message channels." + "translation": "Channel names can't be in a hexadecimal format. Please enter a different channel name." }, { "id": "model.channel.is_valid.id.app_error", @@ -9689,5 +9689,25 @@ { "id": "api.server.hosted_signup_unavailable.error", "translation": "Portal unavailable for self-hosted signup." + }, + { + "id": "ent.elasticsearch.create_client.client_key_missing", + "translation": "Could not open the client key file for Elasticsearch" + }, + { + "id": "ent.elasticsearch.create_client.client_cert_missing", + "translation": "Could not open the client certificate file for Elasticsearch" + }, + { + "id": "ent.elasticsearch.create_client.client_cert_malformed", + "translation": "Decoding of the client certificate for Elasticsearch failed" + }, + { + "id": "ent.elasticsearch.create_client.ca_cert_missing", + "translation": "Could not open the CA file for Elasticsearch" + }, + { + "id": "ent.elasticsearch.create_client.ca_cert_malformed", + "translation": "Decoding of the CA for Elasticsearch failed" } ] From 56c2c3ae4db678fe4bf2d0b3c891d7fef467fa1c Mon Sep 17 00:00:00 2001 From: kaakaa Date: Mon, 16 Jan 2023 16:23:36 +0100 Subject: [PATCH 39/41] Translated using Weblate (Japanese) Currently translated at 100.0% (2433 of 2433 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/ja/ --- i18n/ja.json | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/i18n/ja.json b/i18n/ja.json index 7625ed5305..7e01e8c320 100644 --- a/i18n/ja.json +++ b/i18n/ja.json @@ -647,15 +647,15 @@ }, { "id": "api.command_invite.hint", - "translation": "@[ユーザー名] ~[チャンネル]" + "translation": "@[ユーザー名]... ~[チャンネル]..." }, { "id": "api.command_invite.missing_message.app_error", - "translation": "ユーザー名とチャンネルが存在しません。" + "translation": "ユーザー名もしくはチャンネルが存在しません。" }, { "id": "api.command_invite.missing_user.app_error", - "translation": "ユーザーが見付かりませんでした。システム管理者によって無効化されている可能性があります。" + "translation": "ユーザー {{.User}} が見付かりませんでした。システム管理者によって無効化されている可能性があります。" }, { "id": "api.command_invite.name", @@ -667,7 +667,7 @@ }, { "id": "api.command_invite.private_channel.app_error", - "translation": "チャンネル {{.Channel}} が見つかりませんでした。チャンネルの指定にはチャンネルのハンドル名を使用してください。" + "translation": "チャンネル {{.Channel}} が見つかりませんでした。チャンネルの指定には[チャンネルのハンドル名](https://docs.mattermost.com/messaging/managing-channels.html#naming-a-channel)を使用してください。" }, { "id": "api.command_invite.success", @@ -997,7 +997,7 @@ }, { "id": "api.emoji.create.too_large.app_error", - "translation": "絵文字を作成できません。画像サイズは1MB未満でなければなりません。" + "translation": "絵文字を作成できません。画像サイズは 512 KiB 未満でなければなりません。" }, { "id": "api.emoji.disabled.app_error", @@ -4941,7 +4941,7 @@ }, { "id": "model.channel.is_valid.name.app_error", - "translation": "不正なチャンネル名です。ユーザーIDはダイレクトメッセージチャンネル以外でチャンネル名に使用することはできません。" + "translation": "チャンネル名を16進数にすることはできません。別のチャンネル名を入力してください。" }, { "id": "interactive_message.decode_trigger_id.base64_decode_failed_signature", @@ -8769,7 +8769,7 @@ }, { "id": "api.license.request-trial.can-start-trial.not-allowed", - "translation": "このMattermost Enterprise Editionのトライアルライセンスキーは期限が切れており、有効ではありません。トライアル期間の延長をご希望の場合は[営業までご連絡ください](https://mattermost.com/contact-us/)。" + "translation": "新しいトライアルライセンスを適用できませんでした。あなたは、以前このMattermostインスタンスにトライアルライセンスを適用したことがあります。トライアル期間の延長をご希望の場合は[営業までご連絡ください](https://mattermost.com/contact-us/)。" }, { "id": "api.license.request-trial.can-start-trial.error", @@ -9718,5 +9718,25 @@ { "id": "api.server.hosted_signup_unavailable.error", "translation": "セルフホスティングの利用登録では、ポータルは利用できません。" + }, + { + "id": "ent.elasticsearch.create_client.client_key_missing", + "translation": "Elasticsearch用のクライアントキーファイルを開くことができませんでした" + }, + { + "id": "ent.elasticsearch.create_client.client_cert_missing", + "translation": "Elasticsearchのクライアント証明書ファイルを開くことができませんでした" + }, + { + "id": "ent.elasticsearch.create_client.client_cert_malformed", + "translation": "Elasticsearchのクライアント証明書のデコードに失敗しました" + }, + { + "id": "ent.elasticsearch.create_client.ca_cert_missing", + "translation": "ElasticsearchのCAファイルを開くことができませんでした" + }, + { + "id": "ent.elasticsearch.create_client.ca_cert_malformed", + "translation": "Elasticsearch用CAのデコードに失敗しました" } ] From 1c996631a6d780e23ee4471aba779cfafd07c0bf Mon Sep 17 00:00:00 2001 From: Roman Ilnytskyi Date: Mon, 16 Jan 2023 16:23:36 +0100 Subject: [PATCH 40/41] Translated using Weblate (Ukrainian) Currently translated at 69.1% (1683 of 2433 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/uk/ --- i18n/uk.json | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/i18n/uk.json b/i18n/uk.json index 7ffd8d2e6d..1be08e8b4f 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -6850,5 +6850,41 @@ { "id": "Channels", "translation": "Канали" + }, + { + "id": "api.cloud.cws_webhook_event_missing_error", + "translation": "Подія Webhook не оброблена. Або вона відсутня, або недійсна." + }, + { + "id": "api.channel.create_channel.direct_channel.team_restricted_error", + "translation": "Неможливо створити прямий канал між цими користувачами, оскільки вони не мають спільної команди." + }, + { + "id": "api.admin.syncables_error", + "translation": "не вдалося додати користувача до group-teams та group-channels" + }, + { + "id": "api.admin.saml.failure_reset_authdata_to_email.app_error", + "translation": "Не вдалося скинути поле AuthData в Email." + }, + { + "id": "api.acknowledgement.save.archived_channel.app_error", + "translation": "Підтвердження в архівному каналі неможливо." + }, + { + "id": "api.acknowledgement.delete.deadline.app_error", + "translation": "Ви не можете видалити підтвердження після закінчення 5 хвилин." + }, + { + "id": "api.acknowledgement.delete.archived_channel.app_error", + "translation": "Ви не можете видалити підтвердження в заархівованому каналі." + }, + { + "id": "Playbooks", + "translation": "Сценарії" + }, + { + "id": "Boards", + "translation": "Дошки" } ] From 240304ad0728b8b619f2f0a12a7d935cf0e9e479 Mon Sep 17 00:00:00 2001 From: Konstantin Date: Mon, 16 Jan 2023 16:23:36 +0100 Subject: [PATCH 41/41] Translated using Weblate (Russian) Currently translated at 100.0% (2433 of 2433 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/ru/ --- i18n/ru.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/ru.json b/i18n/ru.json index f8e6b9cb60..0d1447466b 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -5493,7 +5493,7 @@ }, { "id": "model.channel.is_valid.name.app_error", - "translation": "Некорректное имя канала. Запрещено использовать идентификаторы пользователей в качестве имени канала (кроме каналов личных сообщений)." + "translation": "Имена каналов не могут быть в шестнадцатеричном формате. Пожалуйста, введите другое имя канала." }, { "id": "model.config.is_valid.bleve_search.enable_autocomplete.app_error",