diff --git a/Makefile b/Makefile index 8166fa88b6..c0f5a19bd8 100644 --- a/Makefile +++ b/Makefile @@ -149,12 +149,12 @@ 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.7.0 +PLUGIN_PACKAGES += mattermost-plugin-calls-v0.7.1 PLUGIN_PACKAGES += mattermost-plugin-channel-export-v1.0.0 PLUGIN_PACKAGES += mattermost-plugin-custom-attributes-v1.3.0 PLUGIN_PACKAGES += mattermost-plugin-github-v2.0.1 PLUGIN_PACKAGES += mattermost-plugin-gitlab-v1.3.0 -PLUGIN_PACKAGES += mattermost-plugin-playbooks-v1.29.1 +PLUGIN_PACKAGES += mattermost-plugin-playbooks-v1.31.0 PLUGIN_PACKAGES += mattermost-plugin-jenkins-v1.1.0 PLUGIN_PACKAGES += mattermost-plugin-jira-v2.4.0 PLUGIN_PACKAGES += mattermost-plugin-nps-v1.2.0 @@ -184,7 +184,10 @@ endif # Prepare optional Boards build. BOARDS_PACKAGES=$(shell $(GO) list $(BUILD_BOARDS_DIR)/server/...) ifeq ($(BUILD_BOARDS),true) - ALL_PACKAGES += $(BOARDS_PACKAGES) +# We removed `ALL_PACKAGES += $(BOARDS_PACKAGES)` since board tests needs `-tag 'json1'` in the tests. +# Adding that flag to server breaks the build with unsupported flag error. +# PR: https://github.com/mattermost/mattermost-server/pull/20772 +# Ticket: https://mattermost.atlassian.net/browse/CLD-3800 IGNORE:=$(shell echo Boards build selected, preparing) IGNORE:=$(shell rm -f imports/boards_imports.go) IGNORE:=$(shell cp $(BUILD_BOARDS_DIR)/mattermost-plugin/product/imports/boards_imports.go imports/) @@ -317,7 +320,7 @@ ifeq ($(BUILD_ENTERPRISE_READY),true) endif ifeq ($(BUILD_BOARDS),true) ifneq ($(MM_NO_BOARDS_LINT),true) - $(GOBIN)/golangci-lint run $(BUILD_BOARDS_DIR)/server/... + cd $(BUILD_BOARDS_DIR); make server-lint endif endif diff --git a/api4/apitestlib.go b/api4/apitestlib.go index f2577e6ab9..b835853170 100644 --- a/api4/apitestlib.go +++ b/api4/apitestlib.go @@ -10,7 +10,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "math/rand" "net" "net/http" @@ -84,7 +83,7 @@ func SetMainHelper(mh *testlib.MainHelper) { func setupTestHelper(dbStore store.Store, searchEngine *searchengine.Broker, enterprise bool, includeCache bool, updateConfig func(*model.Config), options []app.Option) *TestHelper { - tempWorkspace, err := ioutil.TempDir("", "apptest") + tempWorkspace, err := os.MkdirTemp("", "apptest") if err != nil { panic(err) } diff --git a/api4/bot_test.go b/api4/bot_test.go index c5b7bc1413..5a76d23f45 100644 --- a/api4/bot_test.go +++ b/api4/bot_test.go @@ -5,7 +5,7 @@ package api4 import ( "encoding/json" - "io/ioutil" + "io" "strings" "testing" @@ -461,7 +461,7 @@ func TestPatchBot(t *testing.T) { r, err := th.Client.DoAPIPut("/bots/"+createdBot.UserId, `{"creator_id":"`+th.BasicUser2.Id+`"}`) require.NoError(t, err) defer func() { - _, _ = ioutil.ReadAll(r.Body) + _, _ = io.ReadAll(r.Body) _ = r.Body.Close() }() var patchedBot *model.Bot diff --git a/api4/channel.go b/api4/channel.go index 954ec5632e..1bc8c1db06 100644 --- a/api4/channel.go +++ b/api4/channel.go @@ -1820,7 +1820,7 @@ func updateChannelScheme(c *Context, w http.ResponseWriter, r *http.Request) { auditRec.AddEventParameter("scheme_id", *schemeID) if c.App.Channels().License() == nil { - c.Err = model.NewAppError("Api4.UpdateChannelScheme", "api.channel.update_channel_scheme.license.error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.UpdateChannelScheme", "api.channel.update_channel_scheme.license.error", nil, "", http.StatusForbidden) return } @@ -1891,23 +1891,23 @@ func channelMembersMinusGroupMembers(c *Context, w http.ResponseWriter, r *http. return } - users, totalCount, err := c.App.ChannelMembersMinusGroupMembers( + users, totalCount, appErr := c.App.ChannelMembersMinusGroupMembers( c.Params.ChannelId, groupIDs, c.Params.Page, c.Params.PerPage, ) - if err != nil { - c.Err = err + if appErr != nil { + c.Err = appErr return } - b, marshalErr := json.Marshal(&model.UsersWithGroupsAndCount{ + b, err := json.Marshal(&model.UsersWithGroupsAndCount{ Users: users, Count: totalCount, }) - if marshalErr != nil { - c.Err = model.NewAppError("Api4.channelMembersMinusGroupMembers", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + if err != nil { + c.Err = model.NewAppError("Api4.channelMembersMinusGroupMembers", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -1916,7 +1916,7 @@ func channelMembersMinusGroupMembers(c *Context, w http.ResponseWriter, r *http. func channelMemberCountsByGroup(c *Context, w http.ResponseWriter, r *http.Request) { if c.App.Channels().License() == nil { - c.Err = model.NewAppError("Api4.channelMemberCountsByGroup", "api.channel.channel_member_counts_by_group.license.error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.channelMemberCountsByGroup", "api.channel.channel_member_counts_by_group.license.error", nil, "", http.StatusForbidden) return } @@ -1932,15 +1932,15 @@ func channelMemberCountsByGroup(c *Context, w http.ResponseWriter, r *http.Reque includeTimezones := r.URL.Query().Get("include_timezones") == "true" - channelMemberCounts, err := c.App.GetMemberCountsByGroup(app.WithMaster(context.Background()), c.Params.ChannelId, includeTimezones) - if err != nil { - c.Err = err + channelMemberCounts, appErr := c.App.GetMemberCountsByGroup(app.WithMaster(context.Background()), c.Params.ChannelId, includeTimezones) + if appErr != nil { + c.Err = appErr return } - b, marshalErr := json.Marshal(channelMemberCounts) - if marshalErr != nil { - c.Err = model.NewAppError("Api4.channelMemberCountsByGroup", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + b, err := json.Marshal(channelMemberCounts) + if err != nil { + c.Err = model.NewAppError("Api4.channelMemberCountsByGroup", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -1949,7 +1949,7 @@ func channelMemberCountsByGroup(c *Context, w http.ResponseWriter, r *http.Reque func getChannelModerations(c *Context, w http.ResponseWriter, r *http.Request) { if c.App.Channels().License() == nil { - c.Err = model.NewAppError("Api4.GetChannelModerations", "api.channel.get_channel_moderations.license.error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.GetChannelModerations", "api.channel.get_channel_moderations.license.error", nil, "", http.StatusForbidden) return } @@ -1963,21 +1963,21 @@ func getChannelModerations(c *Context, w http.ResponseWriter, r *http.Request) { return } - channel, err := c.App.GetChannel(c.AppContext, c.Params.ChannelId) - if err != nil { - c.Err = err + channel, appErr := c.App.GetChannel(c.AppContext, c.Params.ChannelId) + if appErr != nil { + c.Err = appErr return } - channelModerations, err := c.App.GetChannelModerationsForChannel(c.AppContext, channel) - if err != nil { - c.Err = err + channelModerations, appErr := c.App.GetChannelModerationsForChannel(c.AppContext, channel) + if appErr != nil { + c.Err = appErr return } - b, marshalErr := json.Marshal(channelModerations) - if marshalErr != nil { - c.Err = model.NewAppError("Api4.getChannelModerations", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + b, err := json.Marshal(channelModerations) + if err != nil { + c.Err = model.NewAppError("Api4.getChannelModerations", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -1986,7 +1986,7 @@ func getChannelModerations(c *Context, w http.ResponseWriter, r *http.Request) { func patchChannelModerations(c *Context, w http.ResponseWriter, r *http.Request) { if c.App.Channels().License() == nil { - c.Err = model.NewAppError("Api4.patchChannelModerations", "api.channel.patch_channel_moderations.license.error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.patchChannelModerations", "api.channel.patch_channel_moderations.license.error", nil, "", http.StatusForbidden) return } @@ -2024,9 +2024,9 @@ func patchChannelModerations(c *Context, w http.ResponseWriter, r *http.Request) } auditRec.AddEventParameter("patch", channelModerationsPatch) - b, marshalErr := json.Marshal(channelModerations) - if marshalErr != nil { - c.Err = model.NewAppError("Api4.patchChannelModerations", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + b, err := json.Marshal(channelModerations) + if err != nil { + c.Err = model.NewAppError("Api4.patchChannelModerations", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } diff --git a/api4/channel_category.go b/api4/channel_category.go index c92b3ff27b..ce40ef3560 100644 --- a/api4/channel_category.go +++ b/api4/channel_category.go @@ -23,15 +23,15 @@ func getCategoriesForTeamForUser(c *Context, w http.ResponseWriter, r *http.Requ return } - categories, err := c.App.GetSidebarCategoriesForTeamForUser(c.AppContext, c.Params.UserId, c.Params.TeamId) - if err != nil { - c.Err = err + categories, appErr := c.App.GetSidebarCategoriesForTeamForUser(c.AppContext, c.Params.UserId, c.Params.TeamId) + if appErr != nil { + c.Err = appErr return } - categoriesJSON, jsonErr := json.Marshal(categories) - if jsonErr != nil { - c.Err = model.NewAppError("getCategoriesForTeamForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + categoriesJSON, err := json.Marshal(categories) + if err != nil { + c.Err = model.NewAppError("getCategoriesForTeamForUser", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -70,9 +70,9 @@ func createCategoryForTeamForUser(c *Context, w http.ResponseWriter, r *http.Req return } - categoryJSON, jsonErr := json.Marshal(category) - if jsonErr != nil { - c.Err = model.NewAppError("createCategoryForTeamForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + categoryJSON, err := json.Marshal(category) + if err != nil { + c.Err = model.NewAppError("createCategoryForTeamForUser", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -92,13 +92,16 @@ func getCategoryOrderForTeamForUser(c *Context, w http.ResponseWriter, r *http.R return } - order, err := c.App.GetSidebarCategoryOrder(c.AppContext, c.Params.UserId, c.Params.TeamId) - if err != nil { - c.Err = err + order, appErr := c.App.GetSidebarCategoryOrder(c.AppContext, c.Params.UserId, c.Params.TeamId) + if appErr != nil { + c.Err = appErr return } - w.Write([]byte(model.ArrayToJSON(order))) + err := json.NewEncoder(w).Encode(order) + if err != nil { + c.Logger.Warn("Error writing response", mlog.Err(err)) + } } func updateCategoryOrderForTeamForUser(c *Context, w http.ResponseWriter, r *http.Request) { @@ -145,15 +148,15 @@ func getCategoryForTeamForUser(c *Context, w http.ResponseWriter, r *http.Reques return } - categories, err := c.App.GetSidebarCategory(c.AppContext, c.Params.CategoryId) - if err != nil { - c.Err = err + categories, appErr := c.App.GetSidebarCategory(c.AppContext, c.Params.CategoryId) + if appErr != nil { + c.Err = appErr return } - categoriesJSON, jsonErr := json.Marshal(categories) - if jsonErr != nil { - c.Err = model.NewAppError("getCategoryForTeamForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + categoriesJSON, err := json.Marshal(categories) + if err != nil { + c.Err = model.NewAppError("getCategoryForTeamForUser", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -199,9 +202,9 @@ func updateCategoriesForTeamForUser(c *Context, w http.ResponseWriter, r *http.R return } - categoriesJSON, jsonErr := json.Marshal(categories) - if jsonErr != nil { - c.Err = model.NewAppError("updateCategoriesForTeamForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + categoriesJSON, err := json.Marshal(categories) + if err != nil { + c.Err = model.NewAppError("updateCategoriesForTeamForUser", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -210,12 +213,12 @@ func updateCategoriesForTeamForUser(c *Context, w http.ResponseWriter, r *http.R } func validateSidebarCategory(c *Context, teamId, userId string, category *model.SidebarCategoryWithChannels) *model.AppError { - channels, err := c.App.GetChannelsForTeamForUser(c.AppContext, teamId, userId, &model.ChannelSearchOpts{ + channels, appErr := c.App.GetChannelsForTeamForUser(c.AppContext, teamId, userId, &model.ChannelSearchOpts{ IncludeDeleted: true, LastDeleteAt: 0, }) - if err != nil { - return model.NewAppError("validateSidebarCategory", "api.invalid_channel", nil, err.Error(), http.StatusBadRequest) + if appErr != nil { + return model.NewAppError("validateSidebarCategory", "api.invalid_channel", nil, "", http.StatusBadRequest).Wrap(appErr) } category.Channels = validateSidebarCategoryChannels(c, userId, category.Channels, channels) @@ -295,9 +298,9 @@ func updateCategoryForTeamForUser(c *Context, w http.ResponseWriter, r *http.Req return } - categoryJSON, jsonErr := json.Marshal(categories[0]) - if jsonErr != nil { - c.Err = model.NewAppError("updateCategoryForTeamForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + categoryJSON, err := json.Marshal(categories[0]) + if err != nil { + c.Err = model.NewAppError("updateCategoryForTeamForUser", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } diff --git a/api4/channel_test.go b/api4/channel_test.go index a47a92b12b..e45312b71a 100644 --- a/api4/channel_test.go +++ b/api4/channel_test.go @@ -569,7 +569,7 @@ func TestCreateGroupChannel(t *testing.T) { require.Equal(t, rgc.Id, rgc2.Id, "should have returned existing channel") m2, _ := th.App.GetChannelMembersPage(th.Context, rgc2.Id, 0, 10) - require.Equal(t, m, m2) + require.ElementsMatch(t, m, m2) _, resp, err = client.CreateGroupChannel([]string{user2.Id}) require.Error(t, err) @@ -3840,7 +3840,7 @@ func TestUpdateChannelScheme(t *testing.T) { th.App.Srv().SetLicense(nil) resp, err = th.SystemAdminClient.UpdateChannelScheme(channel.Id, channelScheme.Id) require.Error(t, err) - CheckNotImplementedStatus(t, resp) + CheckForbiddenStatus(t, resp) th.App.Srv().SetLicense(model.NewTestLicense("")) // Test an invalid scheme scope. diff --git a/api4/cloud.go b/api4/cloud.go index 825db6d5bb..655eddd4ad 100644 --- a/api4/cloud.go +++ b/api4/cloud.go @@ -7,7 +7,7 @@ import ( "bytes" "encoding/binary" "encoding/json" - "io/ioutil" + "io" "net/http" "time" @@ -73,7 +73,7 @@ func handleNotifyAdminToUpgrade(c *Context, w http.ResponseWriter, r *http.Reque func getSubscription(c *Context, w http.ResponseWriter, r *http.Request) { if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.Cloud { - c.Err = model.NewAppError("Api4.getSubscription", "api.cloud.license_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.getSubscription", "api.cloud.license_error", nil, "", http.StatusForbidden) return } @@ -105,7 +105,7 @@ func getSubscription(c *Context, w http.ResponseWriter, r *http.Request) { json, err := json.Marshal(subscription) if err != nil { - c.Err = model.NewAppError("Api4.getSubscription", "api.cloud.request_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.getSubscription", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -123,40 +123,40 @@ func changeSubscription(c *Context, w http.ResponseWriter, r *http.Request) { return } - bodyBytes, err := ioutil.ReadAll(r.Body) + bodyBytes, err := io.ReadAll(r.Body) if err != nil { - c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.app_error", nil, err.Error(), http.StatusBadRequest) + c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.app_error", nil, "", http.StatusBadRequest).Wrap(err) return } var subscriptionChange *model.SubscriptionChange if err = json.Unmarshal(bodyBytes, &subscriptionChange); err != nil { - c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.app_error", nil, err.Error(), http.StatusBadRequest) + c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.app_error", nil, "", http.StatusBadRequest).Wrap(err) return } currentSubscription, appErr := c.App.Cloud().GetSubscription(c.AppContext.Session().UserId) if appErr != nil { - c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.app_error", nil, appErr.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(appErr) return } changedSub, err := c.App.Cloud().ChangeSubscription(c.AppContext.Session().UserId, currentSubscription.ID, subscriptionChange) if err != nil { - c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } json, err := json.Marshal(changedSub) if err != nil { - c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } // Log failures for purchase confirmation email, but don't show an error to the user so as not to confuse them // At this point, the upgrade is complete. - if nErr := c.App.SendUpgradeConfirmationEmail(); nErr != nil { - c.Logger.Error("Error sending purchase confirmation email") + if appErr := c.App.SendUpgradeConfirmationEmail(); appErr != nil { + c.Logger.Error("Error sending purchase confirmation email", mlog.Err(appErr)) } w.Write(json) @@ -174,28 +174,28 @@ func requestCloudTrial(c *Context, w http.ResponseWriter, r *http.Request) { } // check if the email needs to be set - bodyBytes, err := ioutil.ReadAll(r.Body) + bodyBytes, err := io.ReadAll(r.Body) if err != nil { - c.Err = model.NewAppError("Api4.requestCloudTrial", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.requestCloudTrial", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } // this value will not be empty when both emails (user admin and CWS customer) are not business email and // we need to request a new email from the user via the request business email modal var startTrialRequest *model.StartCloudTrialRequest if err = json.Unmarshal(bodyBytes, &startTrialRequest); err != nil { - c.Err = model.NewAppError("Api4.requestCloudTrial", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.requestCloudTrial", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } changedSub, err := c.App.Cloud().RequestCloudTrial(c.AppContext.Session().UserId, startTrialRequest.SubscriptionID, startTrialRequest.Email) if err != nil { - c.Err = model.NewAppError("Api4.requestCloudTrial", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.requestCloudTrial", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } json, err := json.Marshal(changedSub) if err != nil { - c.Err = model.NewAppError("Api4.requestCloudTrial", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.requestCloudTrial", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -215,36 +215,37 @@ func validateBusinessEmail(c *Context, w http.ResponseWriter, r *http.Request) { return } - user, userErr := c.App.GetUser(c.AppContext.Session().UserId) - if userErr != nil { - c.Err = model.NewAppError("Api4.validateBusinessEmail", "api.cloud.request_error", nil, "", http.StatusInternalServerError) + user, appErr := c.App.GetUser(c.AppContext.Session().UserId) + if appErr != nil { + c.Err = model.NewAppError("Api4.validateBusinessEmail", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(appErr) return } - bodyBytes, err := ioutil.ReadAll(r.Body) + bodyBytes, err := io.ReadAll(r.Body) if err != nil { - c.Err = model.NewAppError("Api4.requestCloudTrial", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.requestCloudTrial", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } var emailToValidate *model.ValidateBusinessEmailRequest - if err := json.Unmarshal(bodyBytes, &emailToValidate); err != nil { - c.Err = model.NewAppError("Api4.requestCloudTrial", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + err = json.Unmarshal(bodyBytes, &emailToValidate) + if err != nil { + c.Err = model.NewAppError("Api4.requestCloudTrial", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } - emailErr := c.App.Cloud().ValidateBusinessEmail(user.Id, emailToValidate.Email) - if emailErr != nil { - c.Err = model.NewAppError("Api4.validateBusinessEmail", "api.cloud.request_error", nil, emailErr.Error(), http.StatusForbidden) + err = c.App.Cloud().ValidateBusinessEmail(user.Id, emailToValidate.Email) + if err != nil { + c.Err = model.NewAppError("Api4.validateBusinessEmail", "api.cloud.request_error", nil, "", http.StatusForbidden).Wrap(err) emailResp := model.ValidateBusinessEmailResponse{IsValid: false} if err := json.NewEncoder(w).Encode(emailResp); err != nil { - mlog.Warn("Error while writing response", mlog.Err(err)) + c.Logger.Warn("Error while writing response", mlog.Err(err)) } return } emailResp := model.ValidateBusinessEmailResponse{IsValid: true} if err := json.NewEncoder(w).Encode(emailResp); err != nil { - mlog.Warn("Error while writing response", mlog.Err(err)) + c.Logger.Warn("Error while writing response", mlog.Err(err)) } } @@ -296,7 +297,7 @@ func validateWorkspaceBusinessEmail(c *Context, w http.ResponseWriter, r *http.R func getCloudProducts(c *Context, w http.ResponseWriter, r *http.Request) { if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.Cloud { - c.Err = model.NewAppError("Api4.getCloudProducts", "api.cloud.license_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.getCloudProducts", "api.cloud.license_error", nil, "", http.StatusForbidden) return } @@ -304,28 +305,27 @@ func getCloudProducts(c *Context, w http.ResponseWriter, r *http.Request) { products, err := c.App.Cloud().GetCloudProducts(c.AppContext.Session().UserId, includeLegacyProducts) if err != nil { - c.Err = model.NewAppError("Api4.getCloudProducts", "api.cloud.request_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.getCloudProducts", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(err) return } byteProductsData, err := json.Marshal(products) if err != nil { - c.Err = model.NewAppError("Api4.getCloudProducts", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.getCloudProducts", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleReadBilling) { - sanitizedProducts := []model.UserFacingProduct{} err = json.Unmarshal(byteProductsData, &sanitizedProducts) if err != nil { - c.Err = model.NewAppError("Api4.getCloudProducts", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.getCloudProducts", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } byteSanitizedProductsData, err := json.Marshal(sanitizedProducts) if err != nil { - c.Err = model.NewAppError("Api4.getCloudProducts", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.getCloudProducts", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -338,19 +338,19 @@ func getCloudProducts(c *Context, w http.ResponseWriter, r *http.Request) { func getCloudLimits(c *Context, w http.ResponseWriter, r *http.Request) { if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.Cloud { - c.Err = model.NewAppError("Api4.getCloudLimits", "api.cloud.license_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.getCloudLimits", "api.cloud.license_error", nil, "", http.StatusForbidden) return } limits, err := c.App.Cloud().GetCloudLimits(c.AppContext.Session().UserId) if err != nil { - c.Err = model.NewAppError("Api4.getCloudLimits", "api.cloud.request_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.getCloudLimits", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(err) return } json, err := json.Marshal(limits) if err != nil { - c.Err = model.NewAppError("Api4.getCloudLimits", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.getCloudLimits", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -359,7 +359,7 @@ func getCloudLimits(c *Context, w http.ResponseWriter, r *http.Request) { func getCloudCustomer(c *Context, w http.ResponseWriter, r *http.Request) { if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.Cloud { - c.Err = model.NewAppError("Api4.getCloudCustomer", "api.cloud.license_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.getCloudCustomer", "api.cloud.license_error", nil, "", http.StatusForbidden) return } @@ -370,13 +370,13 @@ func getCloudCustomer(c *Context, w http.ResponseWriter, r *http.Request) { customer, err := c.App.Cloud().GetCloudCustomer(c.AppContext.Session().UserId) if err != nil { - c.Err = model.NewAppError("Api4.getCloudCustomer", "api.cloud.request_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.getCloudCustomer", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(err) return } json, err := json.Marshal(customer) if err != nil { - c.Err = model.NewAppError("Api4.getCloudCustomer", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.getCloudCustomer", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -385,7 +385,7 @@ func getCloudCustomer(c *Context, w http.ResponseWriter, r *http.Request) { func updateCloudCustomer(c *Context, w http.ResponseWriter, r *http.Request) { if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.Cloud { - c.Err = model.NewAppError("Api4.updateCloudCustomer", "api.cloud.license_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.updateCloudCustomer", "api.cloud.license_error", nil, "", http.StatusForbidden) return } @@ -394,27 +394,27 @@ func updateCloudCustomer(c *Context, w http.ResponseWriter, r *http.Request) { return } - bodyBytes, err := ioutil.ReadAll(r.Body) + bodyBytes, err := io.ReadAll(r.Body) if err != nil { - c.Err = model.NewAppError("Api4.updateCloudCustomer", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.updateCloudCustomer", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } var customerInfo *model.CloudCustomerInfo if err = json.Unmarshal(bodyBytes, &customerInfo); err != nil { - c.Err = model.NewAppError("Api4.updateCloudCustomer", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.updateCloudCustomer", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } customer, appErr := c.App.Cloud().UpdateCloudCustomer(c.AppContext.Session().UserId, customerInfo) if appErr != nil { - c.Err = model.NewAppError("Api4.updateCloudCustomer", "api.cloud.request_error", nil, appErr.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.updateCloudCustomer", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(appErr) return } json, err := json.Marshal(customer) if err != nil { - c.Err = model.NewAppError("Api4.updateCloudCustomer", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.updateCloudCustomer", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -423,7 +423,7 @@ func updateCloudCustomer(c *Context, w http.ResponseWriter, r *http.Request) { func updateCloudCustomerAddress(c *Context, w http.ResponseWriter, r *http.Request) { if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.Cloud { - c.Err = model.NewAppError("Api4.updateCloudCustomerAddress", "api.cloud.license_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.updateCloudCustomerAddress", "api.cloud.license_error", nil, "", http.StatusForbidden) return } @@ -432,27 +432,27 @@ func updateCloudCustomerAddress(c *Context, w http.ResponseWriter, r *http.Reque return } - bodyBytes, err := ioutil.ReadAll(r.Body) + bodyBytes, err := io.ReadAll(r.Body) if err != nil { - c.Err = model.NewAppError("Api4.updateCloudCustomerAddress", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.updateCloudCustomerAddress", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } var address *model.Address if err = json.Unmarshal(bodyBytes, &address); err != nil { - c.Err = model.NewAppError("Api4.updateCloudCustomerAddress", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.updateCloudCustomerAddress", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } customer, appErr := c.App.Cloud().UpdateCloudCustomerAddress(c.AppContext.Session().UserId, address) if appErr != nil { - c.Err = model.NewAppError("Api4.updateCloudCustomerAddress", "api.cloud.request_error", nil, appErr.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.updateCloudCustomerAddress", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(appErr) return } json, err := json.Marshal(customer) if err != nil { - c.Err = model.NewAppError("Api4.updateCloudCustomerAddress", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.updateCloudCustomerAddress", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -461,7 +461,7 @@ func updateCloudCustomerAddress(c *Context, w http.ResponseWriter, r *http.Reque func createCustomerPayment(c *Context, w http.ResponseWriter, r *http.Request) { if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.Cloud { - c.Err = model.NewAppError("Api4.createCustomerPayment", "api.cloud.license_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.createCustomerPayment", "api.cloud.license_error", nil, "", http.StatusForbidden) return } @@ -475,13 +475,13 @@ func createCustomerPayment(c *Context, w http.ResponseWriter, r *http.Request) { intent, err := c.App.Cloud().CreateCustomerPayment(c.AppContext.Session().UserId) if err != nil { - c.Err = model.NewAppError("Api4.createCustomerPayment", "api.cloud.request_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.createCustomerPayment", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(err) return } json, err := json.Marshal(intent) if err != nil { - c.Err = model.NewAppError("Api4.createCustomerPayment", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.createCustomerPayment", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -492,7 +492,7 @@ func createCustomerPayment(c *Context, w http.ResponseWriter, r *http.Request) { func confirmCustomerPayment(c *Context, w http.ResponseWriter, r *http.Request) { if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.Cloud { - c.Err = model.NewAppError("Api4.confirmCustomerPayment", "api.cloud.license_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.confirmCustomerPayment", "api.cloud.license_error", nil, "", http.StatusForbidden) return } @@ -504,21 +504,21 @@ func confirmCustomerPayment(c *Context, w http.ResponseWriter, r *http.Request) auditRec := c.MakeAuditRecord("confirmCustomerPayment", audit.Fail) defer c.LogAuditRec(auditRec) - bodyBytes, err := ioutil.ReadAll(r.Body) + bodyBytes, err := io.ReadAll(r.Body) if err != nil { - c.Err = model.NewAppError("Api4.confirmCustomerPayment", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.confirmCustomerPayment", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } var confirmRequest *model.ConfirmPaymentMethodRequest if err = json.Unmarshal(bodyBytes, &confirmRequest); err != nil { - c.Err = model.NewAppError("Api4.confirmCustomerPayment", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.confirmCustomerPayment", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } err = c.App.Cloud().ConfirmCustomerPayment(c.AppContext.Session().UserId, confirmRequest) if err != nil { - c.Err = model.NewAppError("Api4.createCustomerPayment", "api.cloud.request_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.createCustomerPayment", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -529,7 +529,7 @@ func confirmCustomerPayment(c *Context, w http.ResponseWriter, r *http.Request) func getInvoicesForSubscription(c *Context, w http.ResponseWriter, r *http.Request) { if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.Cloud { - c.Err = model.NewAppError("Api4.getInvoicesForSubscription", "api.cloud.license_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.getInvoicesForSubscription", "api.cloud.license_error", nil, "", http.StatusForbidden) return } @@ -540,13 +540,13 @@ func getInvoicesForSubscription(c *Context, w http.ResponseWriter, r *http.Reque invoices, appErr := c.App.Cloud().GetInvoicesForSubscription(c.AppContext.Session().UserId) if appErr != nil { - c.Err = model.NewAppError("Api4.getInvoicesForSubscription", "api.cloud.request_error", nil, appErr.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.getInvoicesForSubscription", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(appErr) return } json, err := json.Marshal(invoices) if err != nil { - c.Err = model.NewAppError("Api4.getInvoicesForSubscription", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.getInvoicesForSubscription", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -555,7 +555,7 @@ func getInvoicesForSubscription(c *Context, w http.ResponseWriter, r *http.Reque func getSubscriptionInvoicePDF(c *Context, w http.ResponseWriter, r *http.Request) { if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.Cloud { - c.Err = model.NewAppError("Api4.getSubscriptionInvoicePDF", "api.cloud.license_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.getSubscriptionInvoicePDF", "api.cloud.license_error", nil, "", http.StatusForbidden) return } @@ -590,11 +590,11 @@ func getSubscriptionInvoicePDF(c *Context, w http.ResponseWriter, r *http.Reques func handleCWSWebhook(c *Context, w http.ResponseWriter, r *http.Request) { if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.Cloud { - c.Err = model.NewAppError("Api4.handleCWSWebhook", "api.cloud.license_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.handleCWSWebhook", "api.cloud.license_error", nil, "", http.StatusForbidden) return } - bodyBytes, err := ioutil.ReadAll(r.Body) + bodyBytes, err := io.ReadAll(r.Body) if err != nil { c.Err = model.NewAppError("Api4.handleCWSWebhook", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) return diff --git a/api4/cloud_test.go b/api4/cloud_test.go index a689c68a8e..1964c6981d 100644 --- a/api4/cloud_test.go +++ b/api4/cloud_test.go @@ -30,7 +30,7 @@ func Test_getCloudLimits(t *testing.T) { limits, r, err := th.Client.GetProductLimits() require.Error(t, err) require.Nil(t, limits) - require.Equal(t, http.StatusNotImplemented, r.StatusCode, "Expected 501 Not Implemented") + require.Equal(t, http.StatusForbidden, r.StatusCode, "Expected 403 forbidden") }) t.Run("non cloud license returns not implemented", func(t *testing.T) { @@ -44,7 +44,7 @@ func Test_getCloudLimits(t *testing.T) { limits, r, err := th.Client.GetProductLimits() require.Error(t, err) require.Nil(t, limits) - require.Equal(t, http.StatusNotImplemented, r.StatusCode, "Expected 501 Not Implemented") + require.Equal(t, http.StatusForbidden, r.StatusCode, "Expected 403 forbidden") }) t.Run("error fetching limits returns internal server error", func(t *testing.T) { diff --git a/api4/cluster.go b/api4/cluster.go index a51c7fbb06..74e6e2b26d 100644 --- a/api4/cluster.go +++ b/api4/cluster.go @@ -26,9 +26,9 @@ func getClusterStatus(c *Context, w http.ResponseWriter, r *http.Request) { } infos := c.App.GetClusterStatus() - js, jsonErr := json.Marshal(infos) - if jsonErr != nil { - c.Err = model.NewAppError("getClusterStatus", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(infos) + if err != nil { + c.Err = model.NewAppError("getClusterStatus", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } w.Write(js) diff --git a/api4/command.go b/api4/command.go index c267c869fc..1025424c83 100644 --- a/api4/command.go +++ b/api4/command.go @@ -417,9 +417,9 @@ func listCommandAutocompleteSuggestions(c *Context, w http.ResponseWriter, r *ht } userInput = strings.TrimPrefix(userInput, "/") - commands, err := c.App.ListAutocompleteCommands(c.Params.TeamId, c.AppContext.T) - if err != nil { - c.Err = err + commands, appErr := c.App.ListAutocompleteCommands(c.Params.TeamId, c.AppContext.T) + if appErr != nil { + c.Err = appErr return } @@ -436,9 +436,9 @@ func listCommandAutocompleteSuggestions(c *Context, w http.ResponseWriter, r *ht suggestions := c.App.GetSuggestions(c.AppContext, commandArgs, commands, roleId) - js, jsonErr := json.Marshal(suggestions) - if jsonErr != nil { - c.Err = model.NewAppError("listCommandAutocompleteSuggestions", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(suggestions) + if err != nil { + c.Err = model.NewAppError("listCommandAutocompleteSuggestions", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } w.Write(js) diff --git a/api4/config.go b/api4/config.go index c20e3e2912..2b6779c31f 100644 --- a/api4/config.go +++ b/api4/config.go @@ -108,9 +108,10 @@ func configReload(c *Context, w http.ResponseWriter, r *http.Request) { } func updateConfig(c *Context, w http.ResponseWriter, r *http.Request) { - cfg := model.ConfigFromJSON(r.Body) - if cfg == nil { - c.SetInvalidParam("config") + var cfg *model.Config + err := json.NewDecoder(r.Body).Decode(&cfg) + if err != nil || cfg == nil { + c.SetInvalidParamWithErr("config", err) return } @@ -132,14 +133,13 @@ func updateConfig(c *Context, w http.ResponseWriter, r *http.Request) { return } - var err1 error - cfg, err1 = config.Merge(appCfg, cfg, &utils.MergeConfig{ + cfg, err = config.Merge(appCfg, cfg, &utils.MergeConfig{ StructFieldFilter: func(structField reflect.StructField, base, patch reflect.Value) bool { return writeFilter(c, structField) }, }) - if err1 != nil { - c.Err = model.NewAppError("updateConfig", "api.config.update_config.restricted_merge.app_error", nil, err1.Error(), http.StatusInternalServerError) + if err != nil { + c.Err = model.NewAppError("updateConfig", "api.config.update_config.restricted_merge.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -156,8 +156,8 @@ func updateConfig(c *Context, w http.ResponseWriter, r *http.Request) { *cfg.PluginSettings.MarketplaceURL = *appCfg.PluginSettings.MarketplaceURL } - if err := c.App.CheckFreemiumLimitsForConfigSave(appCfg, cfg); err != nil { - c.Err = err + if appErr := c.App.CheckFreemiumLimitsForConfigSave(appCfg, cfg); appErr != nil { + c.Err = appErr return } @@ -173,33 +173,33 @@ func updateConfig(c *Context, w http.ResponseWriter, r *http.Request) { c.App.HandleMessageExportConfig(cfg, appCfg) - if err := cfg.IsValid(); err != nil { - c.Err = err + if appErr := cfg.IsValid(); appErr != nil { + c.Err = appErr return } - oldCfg, newCfg, err := c.App.SaveConfig(cfg, true) + oldCfg, newCfg, appErr := c.App.SaveConfig(cfg, true) + if appErr != nil { + c.Err = appErr + return + } + + diffs, err := config.Diff(oldCfg, newCfg) if err != nil { - c.Err = err - return - } - - diffs, diffErr := config.Diff(oldCfg, newCfg) - if diffErr != nil { - c.Err = model.NewAppError("updateConfig", "api.config.update_config.diff.app_error", nil, diffErr.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("updateConfig", "api.config.update_config.diff.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } auditRec.AddEventPriorState(&diffs) newCfg.Sanitize() - cfg, mergeErr := config.Merge(&model.Config{}, newCfg, &utils.MergeConfig{ + cfg, err = config.Merge(&model.Config{}, newCfg, &utils.MergeConfig{ StructFieldFilter: func(structField reflect.StructField, base, patch reflect.Value) bool { return readFilter(c, structField) }, }) - if mergeErr != nil { - c.Err = model.NewAppError("updateConfig", "api.config.update_config.restricted_merge.app_error", nil, mergeErr.Error(), http.StatusInternalServerError) + if err != nil { + c.Err = model.NewAppError("updateConfig", "api.config.update_config.restricted_merge.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -210,9 +210,9 @@ func updateConfig(c *Context, w http.ResponseWriter, r *http.Request) { w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") if c.App.Channels().License() != nil && *c.App.Channels().License().Features.Cloud { - js, jsonErr := cfg.ToJSONFiltered(model.ConfigAccessTagType, model.ConfigAccessTagCloudRestrictable) - if jsonErr != nil { - c.Err = model.NewAppError("updateConfig", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := cfg.ToJSONFiltered(model.ConfigAccessTagType, model.ConfigAccessTagCloudRestrictable) + if err != nil { + c.Err = model.NewAppError("updateConfig", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } w.Write(js) @@ -259,9 +259,10 @@ func getEnvironmentConfig(c *Context, w http.ResponseWriter, r *http.Request) { } func patchConfig(c *Context, w http.ResponseWriter, r *http.Request) { - cfg := model.ConfigFromJSON(r.Body) - if cfg == nil { - c.SetInvalidParam("config") + var cfg *model.Config + err := json.NewDecoder(r.Body).Decode(&cfg) + if err != nil || cfg == nil { + c.SetInvalidParamWithErr("config", err) return } @@ -298,8 +299,8 @@ func patchConfig(c *Context, w http.ResponseWriter, r *http.Request) { } } - if err := c.App.CheckFreemiumLimitsForConfigSave(appCfg, cfg); err != nil { - c.Err = err + if appErr := c.App.CheckFreemiumLimitsForConfigSave(appCfg, cfg); appErr != nil { + c.Err = appErr return } @@ -315,30 +316,29 @@ func patchConfig(c *Context, w http.ResponseWriter, r *http.Request) { c.App.HandleMessageExportConfig(cfg, appCfg) } - updatedCfg, mergeErr := config.Merge(appCfg, cfg, &utils.MergeConfig{ + updatedCfg, err := config.Merge(appCfg, cfg, &utils.MergeConfig{ StructFieldFilter: filterFn, }) - - if mergeErr != nil { - c.Err = model.NewAppError("patchConfig", "api.config.update_config.restricted_merge.app_error", nil, mergeErr.Error(), http.StatusInternalServerError) - return - } - - err := updatedCfg.IsValid() if err != nil { - c.Err = err + c.Err = model.NewAppError("patchConfig", "api.config.update_config.restricted_merge.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } - oldCfg, newCfg, err := c.App.SaveConfig(updatedCfg, true) + appErr := updatedCfg.IsValid() + if appErr != nil { + c.Err = appErr + return + } + + oldCfg, newCfg, appErr := c.App.SaveConfig(updatedCfg, true) + if appErr != nil { + c.Err = appErr + return + } + + diffs, err := config.Diff(oldCfg, newCfg) if err != nil { - c.Err = err - return - } - - diffs, diffErr := config.Diff(oldCfg, newCfg) - if diffErr != nil { - c.Err = model.NewAppError("patchConfig", "api.config.patch_config.diff.app_error", nil, diffErr.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("patchConfig", "api.config.patch_config.diff.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -348,21 +348,21 @@ func patchConfig(c *Context, w http.ResponseWriter, r *http.Request) { auditRec.Success() - cfg, mergeErr = config.Merge(&model.Config{}, newCfg, &utils.MergeConfig{ + cfg, err = config.Merge(&model.Config{}, newCfg, &utils.MergeConfig{ StructFieldFilter: func(structField reflect.StructField, base, patch reflect.Value) bool { return readFilter(c, structField) }, }) - if mergeErr != nil { - c.Err = model.NewAppError("patchConfig", "api.config.patch_config.restricted_merge.app_error", nil, mergeErr.Error(), http.StatusInternalServerError) + if err != nil { + c.Err = model.NewAppError("patchConfig", "api.config.patch_config.restricted_merge.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") if c.App.Channels().License() != nil && *c.App.Channels().License().Features.Cloud { - js, jsonErr := cfg.ToJSONFiltered(model.ConfigAccessTagType, model.ConfigAccessTagCloudRestrictable) - if jsonErr != nil { - c.Err = model.NewAppError("patchConfig", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := cfg.ToJSONFiltered(model.ConfigAccessTagType, model.ConfigAccessTagCloudRestrictable) + if err != nil { + c.Err = model.NewAppError("patchConfig", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } w.Write(js) diff --git a/api4/config_local.go b/api4/config_local.go index baf019ecc9..910c938e3e 100644 --- a/api4/config_local.go +++ b/api4/config_local.go @@ -35,9 +35,10 @@ func localGetConfig(c *Context, w http.ResponseWriter, r *http.Request) { } func localUpdateConfig(c *Context, w http.ResponseWriter, r *http.Request) { - cfg := model.ConfigFromJSON(r.Body) - if cfg == nil { - c.SetInvalidParam("config") + var cfg *model.Config + err := json.NewDecoder(r.Body).Decode(&cfg) + if err != nil || cfg == nil { + c.SetInvalidParamWithErr("config", err) return } @@ -56,15 +57,15 @@ func localUpdateConfig(c *Context, w http.ResponseWriter, r *http.Request) { c.App.HandleMessageExportConfig(cfg, appCfg) - err := cfg.IsValid() - if err != nil { - c.Err = err + appErr := cfg.IsValid() + if appErr != nil { + c.Err = appErr return } - oldCfg, newCfg, err := c.App.SaveConfig(cfg, true) - if err != nil { - c.Err = err + oldCfg, newCfg, appErr := c.App.SaveConfig(cfg, true) + if appErr != nil { + c.Err = appErr return } @@ -87,9 +88,10 @@ func localUpdateConfig(c *Context, w http.ResponseWriter, r *http.Request) { } func localPatchConfig(c *Context, w http.ResponseWriter, r *http.Request) { - cfg := model.ConfigFromJSON(r.Body) - if cfg == nil { - c.SetInvalidParam("config") + var cfg *model.Config + err := json.NewDecoder(r.Body).Decode(&cfg) + if err != nil || cfg == nil { + c.SetInvalidParamWithErr("config", err) return } @@ -114,21 +116,21 @@ func localPatchConfig(c *Context, w http.ResponseWriter, r *http.Request) { return } - err := updatedCfg.IsValid() - if err != nil { - c.Err = err + appErr := updatedCfg.IsValid() + if appErr != nil { + c.Err = appErr return } - oldCfg, newCfg, err := c.App.SaveConfig(updatedCfg, true) - if err != nil { - c.Err = err + oldCfg, newCfg, appErr := c.App.SaveConfig(updatedCfg, true) + if appErr != nil { + c.Err = appErr return } - diffs, diffErr := config.Diff(oldCfg, newCfg) - if diffErr != nil { - c.Err = model.NewAppError("patchConfig", "api.config.patch_config.diff.app_error", nil, diffErr.Error(), http.StatusInternalServerError) + diffs, err := config.Diff(oldCfg, newCfg) + if err != nil { + c.Err = model.NewAppError("patchConfig", "api.config.patch_config.diff.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } auditRec.AddEventPriorState(&diffs) diff --git a/api4/config_test.go b/api4/config_test.go index c200e306fc..52de0491c8 100644 --- a/api4/config_test.go +++ b/api4/config_test.go @@ -6,7 +6,7 @@ package api4 import ( "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "os" "strings" @@ -533,7 +533,7 @@ func TestUpdateConfigRestrictSystemAdmin(t *testing.T) { } func TestUpdateConfigDiffInAuditRecord(t *testing.T) { - logFile, err := ioutil.TempFile("", "adv.log") + logFile, err := os.CreateTemp("", "adv.log") require.NoError(t, err) defer os.Remove(logFile.Name()) @@ -569,7 +569,7 @@ func TestUpdateConfigDiffInAuditRecord(t *testing.T) { require.NoError(t, logFile.Sync()) - data, err := ioutil.ReadAll(logFile) + data, err := io.ReadAll(logFile) require.NoError(t, err) require.NotEmpty(t, data) @@ -955,7 +955,7 @@ func TestMigrateConfig(t *testing.T) { file, err := json.MarshalIndent(cfg, "", " ") require.NoError(t, err) - err = ioutil.WriteFile("from.json", file, 0644) + err = os.WriteFile("from.json", file, 0644) require.NoError(t, err) defer os.Remove("from.json") diff --git a/api4/data_retention.go b/api4/data_retention.go index 0059e8ea89..8fdabc9f7c 100644 --- a/api4/data_retention.go +++ b/api4/data_retention.go @@ -9,6 +9,7 @@ import ( "github.com/mattermost/mattermost-server/v6/audit" "github.com/mattermost/mattermost-server/v6/model" + "github.com/mattermost/mattermost-server/v6/shared/mlog" ) func (api *API) InitDataRetention() { @@ -34,15 +35,15 @@ func (api *API) InitDataRetention() { func getGlobalPolicy(c *Context, w http.ResponseWriter, r *http.Request) { // No permission check required. - policy, err := c.App.GetGlobalRetentionPolicy() - if err != nil { - c.Err = err + policy, appErr := c.App.GetGlobalRetentionPolicy() + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(policy) - if jsonErr != nil { - c.Err = model.NewAppError("getGlobalPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(policy) + if err != nil { + c.Err = model.NewAppError("getGlobalPolicy", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } w.Write(js) @@ -57,15 +58,15 @@ func getPolicies(c *Context, w http.ResponseWriter, r *http.Request) { limit := c.Params.PerPage offset := c.Params.Page * limit - policies, err := c.App.GetRetentionPolicies(offset, limit) - if err != nil { - c.Err = err + policies, appErr := c.App.GetRetentionPolicies(offset, limit) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(policies) - if jsonErr != nil { - c.Err = model.NewAppError("getPolicies", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(policies) + if err != nil { + c.Err = model.NewAppError("getPolicies", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } w.Write(js) @@ -77,14 +78,19 @@ func getPoliciesCount(c *Context, w http.ResponseWriter, r *http.Request) { return } - count, err := c.App.GetRetentionPoliciesCount() - if err != nil { - c.Err = err + count, appErr := c.App.GetRetentionPoliciesCount() + if appErr != nil { + c.Err = appErr return } - body := map[string]int64{"total_count": count} - b, _ := json.Marshal(body) - w.Write(b) + + body := struct { + TotalCount int64 `json:"total_count"` + }{count} + err := json.NewEncoder(w).Encode(body) + if err != nil { + c.Logger.Warn("Error writing response", mlog.Err(err)) + } } func getPolicy(c *Context, w http.ResponseWriter, r *http.Request) { @@ -94,15 +100,15 @@ func getPolicy(c *Context, w http.ResponseWriter, r *http.Request) { } c.RequirePolicyId() - policy, err := c.App.GetRetentionPolicy(c.Params.PolicyId) - if err != nil { - c.Err = err + policy, appErr := c.App.GetRetentionPolicy(c.Params.PolicyId) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(policy) - if jsonErr != nil { - c.Err = model.NewAppError("getPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(policy) + if err != nil { + c.Err = model.NewAppError("getPolicy", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } w.Write(js) @@ -123,17 +129,17 @@ func createPolicy(c *Context, w http.ResponseWriter, r *http.Request) { return } - newPolicy, err := c.App.CreateRetentionPolicy(&policy) - if err != nil { - c.Err = err + newPolicy, appErr := c.App.CreateRetentionPolicy(&policy) + if appErr != nil { + c.Err = appErr return } auditRec.AddEventResultState(newPolicy) auditRec.AddEventObjectType("policy") - js, jsonErr := json.Marshal(newPolicy) - if jsonErr != nil { - c.Err = model.NewAppError("createPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(newPolicy) + if err != nil { + c.Err = model.NewAppError("createPolicy", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } auditRec.Success() @@ -159,18 +165,18 @@ func patchPolicy(c *Context, w http.ResponseWriter, r *http.Request) { return } - policy, err := c.App.PatchRetentionPolicy(&patch) - if err != nil { - c.Err = err + policy, appErr := c.App.PatchRetentionPolicy(&patch) + if appErr != nil { + c.Err = appErr return } auditRec.AddEventResultState(policy) auditRec.AddEventObjectType("retention_policy") - js, jsonErr := json.Marshal(policy) - if jsonErr != nil { - c.Err = model.NewAppError("patchPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(policy) + if err != nil { + c.Err = model.NewAppError("patchPolicy", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } auditRec.Success() @@ -209,15 +215,15 @@ func getTeamsForPolicy(c *Context, w http.ResponseWriter, r *http.Request) { limit := c.Params.PerPage offset := c.Params.Page * limit - teams, err := c.App.GetTeamsForRetentionPolicy(policyId, offset, limit) - if err != nil { - c.Err = err + teams, appErr := c.App.GetTeamsForRetentionPolicy(policyId, offset, limit) + if appErr != nil { + c.Err = appErr return } - b, jsonErr := json.Marshal(teams) - if jsonErr != nil { - c.Err = model.NewAppError("Api4.getTeamsForPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + b, err := json.Marshal(teams) + if err != nil { + c.Err = model.NewAppError("Api4.getTeamsForPolicy", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } w.Write(b) @@ -232,24 +238,24 @@ func searchTeamsInPolicy(c *Context, w http.ResponseWriter, r *http.Request) { } var props model.TeamSearch - if jsonErr := json.NewDecoder(r.Body).Decode(&props); jsonErr != nil { - c.SetInvalidParamWithErr("team_search", jsonErr) + if err := json.NewDecoder(r.Body).Decode(&props); err != nil { + c.SetInvalidParamWithErr("team_search", err) return } props.PolicyID = model.NewString(c.Params.PolicyId) props.IncludePolicyID = model.NewBool(true) - teams, _, err := c.App.SearchAllTeams(&props) - if err != nil { - c.Err = err + teams, _, appErr := c.App.SearchAllTeams(&props) + if appErr != nil { + c.Err = appErr return } c.App.SanitizeTeams(*c.AppContext.Session(), teams) - js, jsonErr := json.Marshal(teams) - if jsonErr != nil { - c.Err = model.NewAppError("searchTeamsInPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(teams) + if err != nil { + c.Err = model.NewAppError("searchTeamsInPolicy", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } w.Write(js) @@ -323,15 +329,15 @@ func getChannelsForPolicy(c *Context, w http.ResponseWriter, r *http.Request) { limit := c.Params.PerPage offset := c.Params.Page * limit - channels, err := c.App.GetChannelsForRetentionPolicy(policyId, offset, limit) - if err != nil { - c.Err = err + channels, appErr := c.App.GetChannelsForRetentionPolicy(policyId, offset, limit) + if appErr != nil { + c.Err = appErr return } - b, jsonErr := json.Marshal(channels) - if jsonErr != nil { - c.Err = model.NewAppError("Api4.getChannelsForPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + b, err := json.Marshal(channels) + if err != nil { + c.Err = model.NewAppError("Api4.getChannelsForPolicy", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } w.Write(b) diff --git a/api4/elasticsearch.go b/api4/elasticsearch.go index 6bda0aa75a..9ae796157c 100644 --- a/api4/elasticsearch.go +++ b/api4/elasticsearch.go @@ -4,10 +4,12 @@ package api4 import ( + "encoding/json" "net/http" "github.com/mattermost/mattermost-server/v6/audit" "github.com/mattermost/mattermost-server/v6/model" + "github.com/mattermost/mattermost-server/v6/shared/mlog" ) func (api *API) InitElasticsearch() { @@ -16,7 +18,11 @@ func (api *API) InitElasticsearch() { } func testElasticsearch(c *Context, w http.ResponseWriter, r *http.Request) { - cfg := model.ConfigFromJSON(r.Body) + var cfg *model.Config + err := json.NewDecoder(r.Body).Decode(&cfg) + if err != nil { + c.Logger.Warn("Error decoding config.", mlog.Err(err)) + } if cfg == nil { cfg = c.App.Config() } diff --git a/api4/emoji_test.go b/api4/emoji_test.go index ac8395c26e..93b915fc8f 100644 --- a/api4/emoji_test.go +++ b/api4/emoji_test.go @@ -7,7 +7,6 @@ import ( "bytes" "image" _ "image/gif" - "io/ioutil" "os" "path/filepath" "testing" @@ -100,7 +99,7 @@ func TestCreateEmoji(t *testing.T) { } path, _ := fileutils.FindDir("tests") - bytes, err := ioutil.ReadFile(filepath.Join(path, "testwebp.webp")) + bytes, err := os.ReadFile(filepath.Join(path, "testwebp.webp")) require.NoError(t, err) newEmoji, _, err = client.CreateEmoji(emoji, bytes, "image.webp") require.NoError(t, err) diff --git a/api4/export.go b/api4/export.go index 36248746fe..4abec62fde 100644 --- a/api4/export.go +++ b/api4/export.go @@ -33,7 +33,7 @@ func listExports(c *Context, w http.ResponseWriter, r *http.Request) { data, err := json.Marshal(exports) if err != nil { - c.Err = model.NewAppError("listImports", "app.export.marshal.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("listImports", "app.export.marshal.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } diff --git a/api4/export_test.go b/api4/export_test.go index db3a961807..5a591598d4 100644 --- a/api4/export_test.go +++ b/api4/export_test.go @@ -6,7 +6,6 @@ package api4 import ( "bytes" "fmt" - "io/ioutil" "os" "path/filepath" "testing" @@ -151,7 +150,7 @@ func TestDownloadExport(t *testing.T) { data := randomBytes(t, 1024*1024) var buf bytes.Buffer exportName := "export.zip" - err = ioutil.WriteFile(filepath.Join(exportDir, exportName), data, 0600) + err = os.WriteFile(filepath.Join(exportDir, exportName), data, 0600) require.NoError(t, err) n, _, err := c.DownloadExport(exportName, &buf, 0) @@ -168,7 +167,7 @@ func TestDownloadExport(t *testing.T) { data := randomBytes(t, 1024*1024) var buf bytes.Buffer exportName := "export.zip" - err = ioutil.WriteFile(filepath.Join(exportDir, exportName), data, 0600) + err = os.WriteFile(filepath.Join(exportDir, exportName), data, 0600) require.NoError(t, err) offset := 1024 * 512 diff --git a/api4/file.go b/api4/file.go index 1eadda69b8..c1cf36d4a5 100644 --- a/api4/file.go +++ b/api4/file.go @@ -103,7 +103,7 @@ func uploadFileStream(c *Context, w http.ResponseWriter, r *http.Request) { if !*c.App.Config().FileSettings.EnableFileAttachments { c.Err = model.NewAppError("uploadFileStream", "api.file.attachments.disabled.app_error", - nil, "", http.StatusNotImplemented) + nil, "", http.StatusForbidden) return } @@ -545,7 +545,7 @@ func getFileLink(c *Context, w http.ResponseWriter, r *http.Request) { } if !*c.App.Config().FileSettings.EnablePublicLink { - c.Err = model.NewAppError("getPublicLink", "api.file.get_public_link.disabled.app_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("getPublicLink", "api.file.get_public_link.disabled.app_error", nil, "", http.StatusForbidden) return } @@ -643,7 +643,7 @@ func getPublicFile(c *Context, w http.ResponseWriter, r *http.Request) { } if !*c.App.Config().FileSettings.EnablePublicLink { - c.Err = model.NewAppError("getPublicFile", "api.file.get_public_link.disabled.app_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("getPublicFile", "api.file.get_public_link.disabled.app_error", nil, "", http.StatusForbidden) return } diff --git a/api4/file_test.go b/api4/file_test.go index dafb76110e..49fcfd9b79 100644 --- a/api4/file_test.go +++ b/api4/file_test.go @@ -9,7 +9,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "mime/multipart" "net/http" "net/textproto" @@ -55,7 +54,7 @@ func fileBytes(t *testing.T, path string) []byte { f, err := os.Open(path) require.NoError(t, err) defer f.Close() - bb, err := ioutil.ReadAll(f) + bb, err := io.ReadAll(f) require.NoError(t, err) return bb } @@ -512,7 +511,7 @@ func TestUploadFiles(t *testing.T) { client: th.SystemAdminClient, names: []string{"test.png"}, skipSuccessValidation: true, - checkResponse: CheckNotImplementedStatus, + checkResponse: CheckForbiddenStatus, setupConfig: func(a *app.App) func(a *app.App) { enableFileAttachments := *a.Config().FileSettings.EnableFileAttachments a.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.EnableFileAttachments = false }) @@ -701,10 +700,10 @@ func TestUploadFiles(t *testing.T) { data, _, err := get(ri.Id) require.NoError(t, err) - expected, err := ioutil.ReadFile(filepath.Join(testDir, name)) + expected, err := os.ReadFile(filepath.Join(testDir, name)) require.NoError(t, err) if !bytes.Equal(data, expected) { - tf, err := ioutil.TempFile("", fmt.Sprintf("test_%v_*_%s", i, name)) + tf, err := os.CreateTemp("", fmt.Sprintf("test_%v_*_%s", i, name)) require.NoError(t, err) defer tf.Close() _, err = io.Copy(tf, bytes.NewReader(data)) @@ -919,7 +918,7 @@ func TestGetFileLink(t *testing.T) { th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.EnablePublicLink = false }) _, resp, err = client.GetFileLink(fileId) require.Error(t, err) - CheckNotImplementedStatus(t, resp) + CheckForbiddenStatus(t, resp) th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.EnablePublicLink = true }) link, _, err := client.GetFileLink(fileId) @@ -1090,7 +1089,7 @@ func TestGetPublicFile(t *testing.T) { resp, err = http.Get(link) require.NoError(t, err) - require.Equal(t, http.StatusNotImplemented, resp.StatusCode, "should've failed to get image with disabled public link") + require.Equal(t, http.StatusForbidden, resp.StatusCode, "should've failed to get image with disabled public link") // test after the salt has changed th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.EnablePublicLink = true }) diff --git a/api4/group.go b/api4/group.go index 9d13c18325..4be5bc4201 100644 --- a/api4/group.go +++ b/api4/group.go @@ -6,7 +6,7 @@ package api4 import ( "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "strconv" "strings" @@ -99,11 +99,11 @@ func getGroup(c *Context, w http.ResponseWriter, r *http.Request) { return } - group, err := c.App.GetGroup(c.Params.GroupId, &model.GetGroupOpts{ + group, appErr := c.App.GetGroup(c.Params.GroupId, &model.GetGroupOpts{ IncludeMemberCount: c.Params.IncludeMemberCount, }) - if err != nil { - c.Err = err + if appErr != nil { + c.Err = appErr return } @@ -114,15 +114,15 @@ func getGroup(c *Context, w http.ResponseWriter, r *http.Request) { } } - if lcErr := licensedAndConfiguredForGroupBySource(c.App, group.Source); lcErr != nil { - lcErr.Where = "Api4.getGroup" - c.Err = lcErr + if appErr := licensedAndConfiguredForGroupBySource(c.App, group.Source); appErr != nil { + appErr.Where = "Api4.getGroup" + c.Err = appErr return } - b, marshalErr := json.Marshal(group) - if marshalErr != nil { - c.Err = model.NewAppError("Api4.getGroup", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + b, err := json.Marshal(group) + if err != nil { + c.Err = model.NewAppError("Api4.getGroup", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -131,19 +131,19 @@ func getGroup(c *Context, w http.ResponseWriter, r *http.Request) { func createGroup(c *Context, w http.ResponseWriter, r *http.Request) { var group *model.GroupWithUserIds - if jsonErr := json.NewDecoder(r.Body).Decode(&group); jsonErr != nil { - c.SetInvalidParamWithErr("group", jsonErr) + if err := json.NewDecoder(r.Body).Decode(&group); err != nil { + c.SetInvalidParamWithErr("group", err) return } if group.Source != model.GroupSourceCustom { - c.Err = model.NewAppError("createGroup", "app.group.crud_permission", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("createGroup", "app.group.crud_permission", nil, "", http.StatusBadRequest) return } - if lcErr := licensedAndConfiguredForGroupBySource(c.App, group.Source); lcErr != nil { - lcErr.Where = "Api4.createGroup" - c.Err = lcErr + if appErr := licensedAndConfiguredForGroupBySource(c.App, group.Source); appErr != nil { + appErr.Where = "Api4.createGroup" + c.Err = appErr return } @@ -153,12 +153,12 @@ func createGroup(c *Context, w http.ResponseWriter, r *http.Request) { } if !group.AllowReference { - c.Err = model.NewAppError("createGroup", "api.custom_groups.must_be_referenceable", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("createGroup", "api.custom_groups.must_be_referenceable", nil, "", http.StatusBadRequest) return } if group.GetRemoteId() != "" { - c.Err = model.NewAppError("createGroup", "api.custom_groups.no_remote_id", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("createGroup", "api.custom_groups.no_remote_id", nil, "", http.StatusBadRequest) return } @@ -166,17 +166,17 @@ func createGroup(c *Context, w http.ResponseWriter, r *http.Request) { defer c.LogAuditRec(auditRec) auditRec.AddEventParameter("group", group) - newGroup, err := c.App.CreateGroupWithUserIds(group) - if err != nil { - c.Err = err + newGroup, appErr := c.App.CreateGroupWithUserIds(group) + if appErr != nil { + c.Err = appErr return } auditRec.AddEventResultState(newGroup) auditRec.AddEventObjectType("group") - js, jsonErr := json.Marshal(newGroup) - if jsonErr != nil { - c.Err = model.NewAppError("createGroup", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(newGroup) + if err != nil { + c.Err = model.NewAppError("createGroup", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } auditRec.Success() @@ -190,15 +190,16 @@ func patchGroup(c *Context, w http.ResponseWriter, r *http.Request) { return } - group, err := c.App.GetGroup(c.Params.GroupId, nil) - if err != nil { - c.Err = err + group, appErr := c.App.GetGroup(c.Params.GroupId, nil) + if appErr != nil { + c.Err = appErr return } - if lcErr := licensedAndConfiguredForGroupBySource(c.App, group.Source); lcErr != nil { - lcErr.Where = "Api4.patchGroup" - c.Err = lcErr + appErr = licensedAndConfiguredForGroupBySource(c.App, group.Source) + if appErr != nil { + appErr.Where = "Api4.patchGroup" + c.Err = appErr return } @@ -214,8 +215,8 @@ func patchGroup(c *Context, w http.ResponseWriter, r *http.Request) { } var groupPatch model.GroupPatch - if jsonErr := json.NewDecoder(r.Body).Decode(&groupPatch); jsonErr != nil { - c.SetInvalidParamWithErr("group", jsonErr) + if err := json.NewDecoder(r.Body).Decode(&groupPatch); err != nil { + c.SetInvalidParamWithErr("group", err) return } @@ -234,13 +235,13 @@ func patchGroup(c *Context, w http.ResponseWriter, r *http.Request) { groupPatch.Name = &tmp } else { if *groupPatch.Name == model.UserNotifyAll || *groupPatch.Name == model.ChannelMentionsNotifyProp || *groupPatch.Name == model.UserNotifyHere { - c.Err = model.NewAppError("Api4.patchGroup", "api.ldap_groups.existing_reserved_name_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.patchGroup", "api.ldap_groups.existing_reserved_name_error", nil, "", http.StatusBadRequest) return } //check if a user already has this group name user, _ := c.App.GetUserByUsername(*groupPatch.Name) if user != nil { - c.Err = model.NewAppError("Api4.patchGroup", "api.ldap_groups.existing_user_name_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.patchGroup", "api.ldap_groups.existing_user_name_error", nil, "", http.StatusBadRequest) return } //check if a mentionable group already has this name @@ -249,7 +250,7 @@ func patchGroup(c *Context, w http.ResponseWriter, r *http.Request) { } existingGroup, _ := c.App.GetGroupByName(*groupPatch.Name, searchOpts) if existingGroup != nil { - c.Err = model.NewAppError("Api4.patchGroup", "api.ldap_groups.existing_group_name_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.patchGroup", "api.ldap_groups.existing_group_name_error", nil, "", http.StatusBadRequest) return } } @@ -257,17 +258,17 @@ func patchGroup(c *Context, w http.ResponseWriter, r *http.Request) { group.Patch(&groupPatch) - group, err = c.App.UpdateGroup(group) - if err != nil { - c.Err = err + group, appErr = c.App.UpdateGroup(group) + if appErr != nil { + c.Err = appErr return } auditRec.AddEventResultState(group) auditRec.AddEventObjectType("group") - b, marshalErr := json.Marshal(group) - if marshalErr != nil { - c.Err = model.NewAppError("Api4.patchGroup", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + b, err := json.Marshal(group) + if err != nil { + c.Err = model.NewAppError("Api4.patchGroup", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -293,15 +294,15 @@ func linkGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) { } syncableType := c.Params.SyncableType - body, err := ioutil.ReadAll(r.Body) + body, err := io.ReadAll(r.Body) if err != nil { - c.Err = model.NewAppError("Api4.createGroupSyncable", "api.io_error", nil, err.Error(), http.StatusBadRequest) + c.Err = model.NewAppError("Api4.createGroupSyncable", "api.io_error", nil, "", http.StatusBadRequest).Wrap(err) return } - group, groupErr := c.App.GetGroup(c.Params.GroupId, nil) - if groupErr != nil { - c.Err = groupErr + group, appErr := c.App.GetGroup(c.Params.GroupId, nil) + if appErr != nil { + c.Err = appErr return } @@ -319,18 +320,18 @@ func linkGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) { var patch *model.GroupSyncablePatch err = json.Unmarshal(body, &patch) if err != nil || patch == nil { - c.SetInvalidParam(fmt.Sprintf("Group%s", syncableType.String())) + c.SetInvalidParamWithErr(fmt.Sprintf("Group%s", syncableType), err) return } auditRec.AddEventParameter("patch", patch) if !*c.App.Channels().License().Features.LDAPGroups { - c.Err = model.NewAppError("Api4.createGroupSyncable", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.createGroupSyncable", "api.ldap_groups.license_error", nil, "", http.StatusForbidden) return } - appErr := verifyLinkUnlinkPermission(c, syncableType, syncableID) + appErr = verifyLinkUnlinkPermission(c, syncableType, syncableID) if appErr != nil { c.Err = appErr return @@ -357,9 +358,9 @@ func linkGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusCreated) - b, marshalErr := json.Marshal(groupSyncable) - if marshalErr != nil { - c.Err = model.NewAppError("Api4.createGroupSyncable", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + b, err := json.Marshal(groupSyncable) + if err != nil { + c.Err = model.NewAppError("Api4.createGroupSyncable", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } auditRec.Success() @@ -385,7 +386,7 @@ func getGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) { syncableType := c.Params.SyncableType if !*c.App.Channels().License().Features.LDAPGroups { - c.Err = model.NewAppError("Api4.getGroupSyncable", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.getGroupSyncable", "api.ldap_groups.license_error", nil, "", http.StatusForbidden) return } @@ -394,15 +395,15 @@ func getGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) { return } - groupSyncable, err := c.App.GetGroupSyncable(c.Params.GroupId, syncableID, syncableType) - if err != nil { - c.Err = err + groupSyncable, appErr := c.App.GetGroupSyncable(c.Params.GroupId, syncableID, syncableType) + if appErr != nil { + c.Err = appErr return } - b, marshalErr := json.Marshal(groupSyncable) - if marshalErr != nil { - c.Err = model.NewAppError("Api4.getGroupSyncable", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + b, err := json.Marshal(groupSyncable) + if err != nil { + c.Err = model.NewAppError("Api4.getGroupSyncable", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -422,7 +423,7 @@ func getGroupSyncables(c *Context, w http.ResponseWriter, r *http.Request) { syncableType := c.Params.SyncableType if !*c.App.Channels().License().Features.LDAPGroups { - c.Err = model.NewAppError("Api4.getGroupSyncables", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.getGroupSyncables", "api.ldap_groups.license_error", nil, "", http.StatusForbidden) return } @@ -431,15 +432,15 @@ func getGroupSyncables(c *Context, w http.ResponseWriter, r *http.Request) { return } - groupSyncables, err := c.App.GetGroupSyncables(c.Params.GroupId, syncableType) - if err != nil { - c.Err = err + groupSyncables, appErr := c.App.GetGroupSyncables(c.Params.GroupId, syncableType) + if appErr != nil { + c.Err = appErr return } - b, marshalErr := json.Marshal(groupSyncables) - if marshalErr != nil { - c.Err = model.NewAppError("Api4.getGroupSyncables", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + b, err := json.Marshal(groupSyncables) + if err != nil { + c.Err = model.NewAppError("Api4.getGroupSyncables", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -464,9 +465,9 @@ func patchGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) { } syncableType := c.Params.SyncableType - body, err := ioutil.ReadAll(r.Body) + body, err := io.ReadAll(r.Body) if err != nil { - c.Err = model.NewAppError("Api4.patchGroupSyncable", "api.io_error", nil, err.Error(), http.StatusBadRequest) + c.Err = model.NewAppError("Api4.patchGroupSyncable", "api.io_error", nil, "", http.StatusBadRequest).Wrap(err) return } @@ -479,7 +480,7 @@ func patchGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) { var patch *model.GroupSyncablePatch err = json.Unmarshal(body, &patch) if err != nil || patch == nil { - c.SetInvalidParam(fmt.Sprintf("Group[%s]Patch", syncableType.String())) + c.SetInvalidParamWithErr(fmt.Sprintf("Group[%s]Patch", syncableType), err) return } @@ -487,7 +488,7 @@ func patchGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) { if !*c.App.Channels().License().Features.LDAPGroups { c.Err = model.NewAppError("Api4.patchGroupSyncable", "api.ldap_groups.license_error", nil, "", - http.StatusNotImplemented) + http.StatusForbidden) return } @@ -518,9 +519,9 @@ func patchGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) { c.App.SyncRolesAndMembership(c.AppContext, syncableID, syncableType, false) }) - b, marshalErr := json.Marshal(groupSyncable) - if marshalErr != nil { - c.Err = model.NewAppError("Api4.patchGroupSyncable", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + b, err := json.Marshal(groupSyncable) + if err != nil { + c.Err = model.NewAppError("Api4.patchGroupSyncable", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } auditRec.Success() @@ -552,19 +553,19 @@ func unlinkGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) { auditRec.AddEventParameter("syncable_type", syncableType) if !*c.App.Channels().License().Features.LDAPGroups { - c.Err = model.NewAppError("Api4.unlinkGroupSyncable", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.unlinkGroupSyncable", "api.ldap_groups.license_error", nil, "", http.StatusForbidden) return } - err := verifyLinkUnlinkPermission(c, syncableType, syncableID) - if err != nil { - c.Err = err + appErr := verifyLinkUnlinkPermission(c, syncableType, syncableID) + if appErr != nil { + c.Err = appErr return } - _, err = c.App.DeleteGroupSyncable(c.Params.GroupId, syncableID, syncableType) - if err != nil { - c.Err = err + _, appErr = c.App.DeleteGroupSyncable(c.Params.GroupId, syncableID, syncableType) + if appErr != nil { + c.Err = appErr return } @@ -610,15 +611,16 @@ func getGroupMembers(c *Context, w http.ResponseWriter, r *http.Request) { return } - group, err := c.App.GetGroup(c.Params.GroupId, nil) - if err != nil { - c.Err = err + group, appErr := c.App.GetGroup(c.Params.GroupId, nil) + if appErr != nil { + c.Err = appErr return } - if lcErr := licensedAndConfiguredForGroupBySource(c.App, group.Source); lcErr != nil { - lcErr.Where = "Api4.getGroupMembers" - c.Err = lcErr + appErr = licensedAndConfiguredForGroupBySource(c.App, group.Source) + if appErr != nil { + appErr.Where = "Api4.getGroupMembers" + c.Err = appErr return } @@ -627,21 +629,21 @@ func getGroupMembers(c *Context, w http.ResponseWriter, r *http.Request) { return } - members, count, err := c.App.GetGroupMemberUsersPage(c.Params.GroupId, c.Params.Page, c.Params.PerPage) - if err != nil { - c.Err = err + members, count, appErr := c.App.GetGroupMemberUsersPage(c.Params.GroupId, c.Params.Page, c.Params.PerPage) + if appErr != nil { + c.Err = appErr return } - b, marshalErr := json.Marshal(struct { + b, err := json.Marshal(struct { Members []*model.User `json:"members"` Count int `json:"total_member_count"` }{ Members: members, Count: count, }) - if marshalErr != nil { - c.Err = model.NewAppError("Api4.getGroupMembers", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + if err != nil { + c.Err = model.NewAppError("Api4.getGroupMembers", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -655,7 +657,7 @@ func getGroupStats(c *Context, w http.ResponseWriter, r *http.Request) { } if !*c.App.Channels().License().Features.LDAPGroups { - c.Err = model.NewAppError("Api4.getGroupStats", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.getGroupStats", "api.ldap_groups.license_error", nil, "", http.StatusForbidden) return } @@ -665,18 +667,18 @@ func getGroupStats(c *Context, w http.ResponseWriter, r *http.Request) { } groupID := c.Params.GroupId - count, err := c.App.GetGroupMemberCount(groupID) - if err != nil { - c.Err = err + count, appErr := c.App.GetGroupMemberCount(groupID) + if appErr != nil { + c.Err = appErr return } - b, marshalErr := json.Marshal(model.GroupStats{ + b, err := json.Marshal(model.GroupStats{ GroupID: groupID, TotalMemberCount: count, }) - if marshalErr != nil { - c.Err = model.NewAppError("Api4.getGroupStats", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + if err != nil { + c.Err = model.NewAppError("Api4.getGroupStats", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -695,19 +697,19 @@ func getGroupsByUserId(c *Context, w http.ResponseWriter, r *http.Request) { } if !*c.App.Channels().License().Features.LDAPGroups { - c.Err = model.NewAppError("Api4.getGroupsByUserId", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.getGroupsByUserId", "api.ldap_groups.license_error", nil, "", http.StatusForbidden) return } - groups, err := c.App.GetGroupsByUserId(c.Params.UserId) + groups, appErr := c.App.GetGroupsByUserId(c.Params.UserId) + if appErr != nil { + c.Err = appErr + return + } + + b, err := json.Marshal(groups) if err != nil { - c.Err = err - return - } - - b, marshalErr := json.Marshal(groups) - if marshalErr != nil { - c.Err = model.NewAppError("Api4.getGroupsByUserId", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.getGroupsByUserId", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -721,15 +723,16 @@ func getGroupsByChannel(c *Context, w http.ResponseWriter, r *http.Request) { } if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.LDAPGroups { - c.Err = model.NewAppError("Api4.getGroupsByChannel", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.getGroupsByChannel", "api.ldap_groups.license_error", nil, "", http.StatusForbidden) return } - channel, err := c.App.GetChannel(c.AppContext, c.Params.ChannelId) - if err != nil { - c.Err = err + channel, appErr := c.App.GetChannel(c.AppContext, c.Params.ChannelId) + if appErr != nil { + c.Err = appErr return } + var permission *model.Permission if channel.Type == model.ChannelTypePrivate { permission = model.PermissionReadPrivateChannelGroups @@ -750,22 +753,21 @@ func getGroupsByChannel(c *Context, w http.ResponseWriter, r *http.Request) { opts.PageOpts = &model.PageOpts{Page: c.Params.Page, PerPage: c.Params.PerPage} } - groups, totalCount, err := c.App.GetGroupsByChannel(c.Params.ChannelId, opts) - if err != nil { - c.Err = err + groups, totalCount, appErr := c.App.GetGroupsByChannel(c.Params.ChannelId, opts) + if appErr != nil { + c.Err = appErr return } - b, marshalErr := json.Marshal(struct { + b, err := json.Marshal(struct { Groups []*model.GroupWithSchemeAdmin `json:"groups"` Count int `json:"total_group_count"` }{ Groups: groups, Count: totalCount, }) - - if marshalErr != nil { - c.Err = model.NewAppError("Api4.getGroupsByChannel", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + if err != nil { + c.Err = model.NewAppError("Api4.getGroupsByChannel", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -778,7 +780,7 @@ func getGroupsByTeam(c *Context, w http.ResponseWriter, r *http.Request) { return } if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.LDAPGroups { - c.Err = model.NewAppError("Api4.getGroupsByTeam", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.getGroupsByTeam", "api.ldap_groups.license_error", nil, "", http.StatusForbidden) return } @@ -791,13 +793,13 @@ func getGroupsByTeam(c *Context, w http.ResponseWriter, r *http.Request) { opts.PageOpts = &model.PageOpts{Page: c.Params.Page, PerPage: c.Params.PerPage} } - groups, totalCount, err := c.App.GetGroupsByTeam(c.Params.TeamId, opts) - if err != nil { - c.Err = err + groups, totalCount, appErr := c.App.GetGroupsByTeam(c.Params.TeamId, opts) + if appErr != nil { + c.Err = appErr return } - b, marshalErr := json.Marshal(struct { + b, err := json.Marshal(struct { Groups []*model.GroupWithSchemeAdmin `json:"groups"` Count int `json:"total_group_count"` }{ @@ -805,8 +807,8 @@ func getGroupsByTeam(c *Context, w http.ResponseWriter, r *http.Request) { Count: totalCount, }) - if marshalErr != nil { - c.Err = model.NewAppError("Api4.getGroupsByTeam", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + if err != nil { + c.Err = model.NewAppError("Api4.getGroupsByTeam", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -820,7 +822,7 @@ func getGroupsAssociatedToChannelsByTeam(c *Context, w http.ResponseWriter, r *h } if !*c.App.Channels().License().Features.LDAPGroups { - c.Err = model.NewAppError("Api4.getGroupsAssociatedToChannelsByTeam", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.getGroupsAssociatedToChannelsByTeam", "api.ldap_groups.license_error", nil, "", http.StatusForbidden) return } @@ -833,20 +835,19 @@ func getGroupsAssociatedToChannelsByTeam(c *Context, w http.ResponseWriter, r *h opts.PageOpts = &model.PageOpts{Page: c.Params.Page, PerPage: c.Params.PerPage} } - groupsAssociatedByChannelID, err := c.App.GetGroupsAssociatedToChannelsByTeam(c.Params.TeamId, opts) - if err != nil { - c.Err = err + groupsAssociatedByChannelID, appErr := c.App.GetGroupsAssociatedToChannelsByTeam(c.Params.TeamId, opts) + if appErr != nil { + c.Err = appErr return } - b, marshalErr := json.Marshal(struct { + b, err := json.Marshal(struct { GroupsAssociatedToChannels map[string][]*model.GroupWithSchemeAdmin `json:"groups"` }{ GroupsAssociatedToChannels: groupsAssociatedByChannelID, }) - - if marshalErr != nil { - c.Err = model.NewAppError("Api4.getGroupsAssociatedToChannelsByTeam", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + if err != nil { + c.Err = model.NewAppError("Api4.getGroupsAssociatedToChannelsByTeam", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -867,9 +868,9 @@ func getGroups(c *Context, w http.ResponseWriter, r *http.Request) { } // If they specify the group_source as custom when the feature is disabled, throw an error - if lcErr := licensedAndConfiguredForGroupBySource(c.App, source); lcErr != nil { - lcErr.Where = "Api4.getGroups" - c.Err = lcErr + if appErr := licensedAndConfiguredForGroupBySource(c.App, source); appErr != nil { + appErr.Where = "Api4.getGroups" + c.Err = appErr return } @@ -888,9 +889,9 @@ func getGroups(c *Context, w http.ResponseWriter, r *http.Request) { } if teamID != "" { - _, err := c.App.GetTeam(teamID) - if err != nil { - c.Err = err + _, appErr := c.App.GetTeam(teamID) + if appErr != nil { + c.Err = appErr return } @@ -898,9 +899,9 @@ func getGroups(c *Context, w http.ResponseWriter, r *http.Request) { } if channelID != "" { - channel, err := c.App.GetChannel(c.AppContext, channelID) - if err != nil { - c.Err = err + channel, appErr := c.App.GetChannel(c.AppContext, channelID) + if appErr != nil { + c.Err = appErr return } var permission *model.Permission @@ -918,39 +919,41 @@ func getGroups(c *Context, w http.ResponseWriter, r *http.Request) { sinceString := r.URL.Query().Get("since") if sinceString != "" { - since, parseError := strconv.ParseInt(sinceString, 10, 64) - if parseError != nil { - c.SetInvalidParam("since") + since, err := strconv.ParseInt(sinceString, 10, 64) + if err != nil { + c.SetInvalidParamWithErr("since", err) return } opts.Since = since } - groups, err := c.App.GetGroups(c.Params.Page, c.Params.PerPage, opts) - if err != nil { - c.Err = err + groups, appErr := c.App.GetGroups(c.Params.Page, c.Params.PerPage, opts) + if appErr != nil { + c.Err = appErr return } - var b []byte - var marshalErr error + var ( + b []byte + err error + ) if c.Params.IncludeTotalCount { - totalCount, countErr := c.App.Srv().Store.Group().GroupCount() - if countErr != nil { - c.Err = model.NewAppError("Api4.getGroups", "api.custom_groups.count_err", nil, countErr.Error(), http.StatusInternalServerError) + totalCount, cerr := c.App.Srv().Store.Group().GroupCount() + if cerr != nil { + c.Err = model.NewAppError("Api4.getGroups", "api.custom_groups.count_err", nil, "", http.StatusInternalServerError).Wrap(cerr) return } gwc := &model.GroupsWithCount{ Groups: groups, TotalCount: totalCount, } - b, marshalErr = json.Marshal(gwc) + b, err = json.Marshal(gwc) } else { - b, marshalErr = json.Marshal(groups) + b, err = json.Marshal(groups) } - if marshalErr != nil { - c.Err = model.NewAppError("Api4.getGroups", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + if err != nil { + c.Err = model.NewAppError("Api4.getGroups", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -970,7 +973,7 @@ func deleteGroup(c *Context, w http.ResponseWriter, r *http.Request) { } if group.Source != model.GroupSourceCustom { - c.Err = model.NewAppError("Api4.deleteGroup", "app.group.crud_permission", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.deleteGroup", "app.group.crud_permission", nil, "", http.StatusBadRequest) return } @@ -1006,20 +1009,21 @@ func addGroupMembers(c *Context, w http.ResponseWriter, r *http.Request) { return } - group, err := c.App.GetGroup(c.Params.GroupId, nil) - if err != nil { - c.Err = err + group, appErr := c.App.GetGroup(c.Params.GroupId, nil) + if appErr != nil { + c.Err = appErr return } if group.Source != model.GroupSourceCustom { - c.Err = model.NewAppError("Api4.deleteGroup", "app.group.crud_permission", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.deleteGroup", "app.group.crud_permission", nil, "", http.StatusBadRequest) return } - if lcErr := licensedAndConfiguredForGroupBySource(c.App, model.GroupSourceCustom); lcErr != nil { - lcErr.Where = "Api4.deleteGroup" - c.Err = lcErr + appErr = licensedAndConfiguredForGroupBySource(c.App, model.GroupSourceCustom) + if appErr != nil { + appErr.Where = "Api4.deleteGroup" + c.Err = appErr return } @@ -1029,8 +1033,8 @@ func addGroupMembers(c *Context, w http.ResponseWriter, r *http.Request) { } var newMembers *model.GroupModifyMembers - if jsonErr := json.NewDecoder(r.Body).Decode(&newMembers); jsonErr != nil { - c.SetInvalidParamWithErr("addGroupMembers", jsonErr) + if err := json.NewDecoder(r.Body).Decode(&newMembers); err != nil { + c.SetInvalidParamWithErr("addGroupMembers", err) return } @@ -1038,15 +1042,15 @@ func addGroupMembers(c *Context, w http.ResponseWriter, r *http.Request) { defer c.LogAuditRec(auditRec) auditRec.AddEventParameter("addGroupMembers", newMembers) - members, err := c.App.UpsertGroupMembers(c.Params.GroupId, newMembers.UserIds) - if err != nil { - c.Err = err + members, appErr := c.App.UpsertGroupMembers(c.Params.GroupId, newMembers.UserIds) + if appErr != nil { + c.Err = appErr return } - b, marshalErr := json.Marshal(members) - if marshalErr != nil { - c.Err = model.NewAppError("Api4.addGroupMembers", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + b, err := json.Marshal(members) + if err != nil { + c.Err = model.NewAppError("Api4.addGroupMembers", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } auditRec.Success() @@ -1059,20 +1063,21 @@ func deleteGroupMembers(c *Context, w http.ResponseWriter, r *http.Request) { return } - group, err := c.App.GetGroup(c.Params.GroupId, nil) - if err != nil { - c.Err = err + group, appErr := c.App.GetGroup(c.Params.GroupId, nil) + if appErr != nil { + c.Err = appErr return } if group.Source != model.GroupSourceCustom { - c.Err = model.NewAppError("Api4.deleteGroup", "app.group.crud_permission", nil, "", http.StatusNotImplemented) + c.Err = model.NewAppError("Api4.deleteGroup", "app.group.crud_permission", nil, "", http.StatusBadRequest) return } - if lcErr := licensedAndConfiguredForGroupBySource(c.App, model.GroupSourceCustom); lcErr != nil { - lcErr.Where = "Api4.deleteGroup" - c.Err = lcErr + appErr = licensedAndConfiguredForGroupBySource(c.App, model.GroupSourceCustom) + if appErr != nil { + appErr.Where = "Api4.deleteGroup" + c.Err = appErr return } @@ -1082,8 +1087,8 @@ func deleteGroupMembers(c *Context, w http.ResponseWriter, r *http.Request) { } var deleteBody *model.GroupModifyMembers - if jsonErr := json.NewDecoder(r.Body).Decode(&deleteBody); jsonErr != nil { - c.SetInvalidParamWithErr("deleteGroupMembers", jsonErr) + if err := json.NewDecoder(r.Body).Decode(&deleteBody); err != nil { + c.SetInvalidParamWithErr("deleteGroupMembers", err) return } @@ -1091,15 +1096,15 @@ func deleteGroupMembers(c *Context, w http.ResponseWriter, r *http.Request) { defer c.LogAuditRec(auditRec) auditRec.AddEventParameter("deleteGroupMembers", deleteBody) - members, err := c.App.DeleteGroupMembers(c.Params.GroupId, deleteBody.UserIds) - if err != nil { - c.Err = err + members, appErr := c.App.DeleteGroupMembers(c.Params.GroupId, deleteBody.UserIds) + if appErr != nil { + c.Err = appErr return } - b, marshalErr := json.Marshal(members) - if marshalErr != nil { - c.Err = model.NewAppError("Api4.addGroupMembers", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + b, err := json.Marshal(members) + if err != nil { + c.Err = model.NewAppError("Api4.addGroupMembers", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } auditRec.Success() @@ -1109,27 +1114,27 @@ func deleteGroupMembers(c *Context, w http.ResponseWriter, r *http.Request) { // licensedAndConfiguredForGroupBySource returns an app error if not properly license or configured for the given group type. The returned app error // will have a blank 'Where' field, which should be subsequently set by the caller, for example: // -// err := licensedAndConfiguredForGroupBySource(c.App, group.Source) -// err.Where = "Api4.getGroup" +// err := licensedAndConfiguredForGroupBySource(c.App, group.Source) +// err.Where = "Api4.getGroup" // // Temporarily, this function also checks for the CustomGroups feature flag. func licensedAndConfiguredForGroupBySource(app app.AppIface, source model.GroupSource) *model.AppError { lic := app.Srv().License() if lic == nil { - return model.NewAppError("", "api.license_error", nil, "", http.StatusNotImplemented) + return model.NewAppError("", "api.license_error", nil, "", http.StatusForbidden) } if source == model.GroupSourceLdap && !*lic.Features.LDAPGroups { - return model.NewAppError("", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented) + return model.NewAppError("", "api.ldap_groups.license_error", nil, "", http.StatusForbidden) } if source == model.GroupSourceCustom && lic.SkuShortName != model.LicenseShortSkuProfessional && lic.SkuShortName != model.LicenseShortSkuEnterprise { - return model.NewAppError("", "api.custom_groups.license_error", nil, "", http.StatusNotImplemented) + return model.NewAppError("", "api.custom_groups.license_error", nil, "", http.StatusBadRequest) } if source == model.GroupSourceCustom && (!app.Config().FeatureFlags.CustomGroups || !*app.Config().ServiceSettings.EnableCustomGroups) { - return model.NewAppError("", "api.custom_groups.feature_disabled", nil, "", http.StatusNotImplemented) + return model.NewAppError("", "api.custom_groups.feature_disabled", nil, "", http.StatusBadRequest) } return nil diff --git a/api4/group_test.go b/api4/group_test.go index 14688fc474..2c0f359caa 100644 --- a/api4/group_test.go +++ b/api4/group_test.go @@ -98,7 +98,7 @@ func TestCreateGroup(t *testing.T) { _, response, err := th.SystemAdminClient.CreateGroup(gbroken) require.Error(t, err) - CheckNotImplementedStatus(t, response) + CheckBadRequestStatus(t, response) validGroup := &model.Group{ DisplayName: "dn_" + model.NewId(), @@ -137,7 +137,7 @@ func TestCreateGroup(t *testing.T) { } _, response, err = th.SystemAdminClient.CreateGroup(unReferenceableCustomGroup) require.Error(t, err) - CheckNotImplementedStatus(t, response) + CheckBadRequestStatus(t, response) unReferenceableCustomGroup.AllowReference = true _, response, err = th.SystemAdminClient.CreateGroup(unReferenceableCustomGroup) require.NoError(t, err) @@ -152,7 +152,7 @@ func TestCreateGroup(t *testing.T) { } _, response, err = th.SystemAdminClient.CreateGroup(customGroupWithRemoteID) require.Error(t, err) - CheckNotImplementedStatus(t, response) + CheckBadRequestStatus(t, response) th.SystemAdminClient.Logout() _, response, err = th.SystemAdminClient.CreateGroup(g) @@ -178,16 +178,16 @@ func TestDeleteGroup(t *testing.T) { _, response, err := th.Client.DeleteGroup(g.Id) require.Error(t, err) - CheckNotImplementedStatus(t, response) + CheckBadRequestStatus(t, response) th.AddPermissionToRole(model.PermissionDeleteCustomGroup.Id, model.SystemUserRoleId) _, response, err = th.Client.DeleteGroup(g.Id) require.Error(t, err) - CheckNotImplementedStatus(t, response) + CheckBadRequestStatus(t, response) _, response, err = th.Client.DeleteGroup(g.Id) require.Error(t, err) - CheckNotImplementedStatus(t, response) + CheckBadRequestStatus(t, response) _, response, err = th.Client.DeleteGroup("wertyuijhbgvfcde") require.Error(t, err) @@ -939,7 +939,11 @@ func TestGetGroupsByChannel(t *testing.T) { th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { _, _, response, err := client.GetGroupsByChannel(th.BasicChannel.Id, opts) require.Error(t, err) - CheckNotImplementedStatus(t, response) + if client == th.SystemAdminClient { + CheckNotImplementedStatus(t, response) + } else { + CheckForbiddenStatus(t, response) + } }) th.App.Srv().SetLicense(model.NewTestLicense("ldap")) @@ -1098,7 +1102,11 @@ func TestGetGroupsByTeam(t *testing.T) { th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { _, _, response, err := client.GetGroupsByTeam(th.BasicTeam.Id, opts) require.Error(t, err) - CheckNotImplementedStatus(t, response) + if client == th.SystemAdminClient { + CheckNotImplementedStatus(t, response) + } else { + CheckForbiddenStatus(t, response) + } }) th.App.Srv().SetLicense(model.NewTestLicense("ldap")) @@ -1248,7 +1256,7 @@ func TestGetGroups(t *testing.T) { opts.Source = model.GroupSourceCustom _, response, err := th.Client.GetGroups(opts) require.Error(t, err) - CheckNotImplementedStatus(t, response) + CheckBadRequestStatus(t, response) // Specify ldap groups source when custom groups feature is disabled opts.Source = model.GroupSourceLdap @@ -1527,7 +1535,7 @@ func TestAddMembersToGroup(t *testing.T) { _, response, upsertErr = th.SystemAdminClient.UpsertGroupMembers(ldapGroup.Id, members) require.Error(t, upsertErr) - CheckNotImplementedStatus(t, response) + CheckBadRequestStatus(t, response) } func TestDeleteMembersFromGroup(t *testing.T) { @@ -1605,5 +1613,5 @@ func TestDeleteMembersFromGroup(t *testing.T) { _, response, deleteErr = th.SystemAdminClient.DeleteGroupMembers(ldapGroup.Id, members) require.Error(t, deleteErr) - CheckNotImplementedStatus(t, response) + CheckBadRequestStatus(t, response) } diff --git a/api4/image_test.go b/api4/image_test.go index aead2b5bf0..4c552e7d86 100644 --- a/api4/image_test.go +++ b/api4/image_test.go @@ -4,7 +4,7 @@ package api4 import ( - "io/ioutil" + "io" "net/http" "net/http/httptest" "net/url" @@ -89,7 +89,7 @@ func TestGetImage(t *testing.T) { require.NoError(t, err) assert.Equal(t, http.StatusOK, resp.StatusCode) - respBody, err := ioutil.ReadAll(resp.Body) + respBody, err := io.ReadAll(resp.Body) require.NoError(t, err) assert.Equal(t, "success", string(respBody)) diff --git a/api4/import.go b/api4/import.go index bbb7784f5e..e86cf98bd0 100644 --- a/api4/import.go +++ b/api4/import.go @@ -28,7 +28,7 @@ func listImports(c *Context, w http.ResponseWriter, r *http.Request) { data, err := json.Marshal(imports) if err != nil { - c.Err = model.NewAppError("listImports", "app.import.marshal.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("listImports", "app.import.marshal.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } diff --git a/api4/insights.go b/api4/insights.go index e8302040d3..71a368e96a 100644 --- a/api4/insights.go +++ b/api4/insights.go @@ -36,9 +36,9 @@ func getTopReactionsForTeamSince(c *Context, w http.ResponseWriter, r *http.Requ return } - team, err := c.App.GetTeam(c.Params.TeamId) - if err != nil { - c.Err = err + team, appErr := c.App.GetTeam(c.Params.TeamId) + if appErr != nil { + c.Err = appErr return } @@ -47,27 +47,27 @@ func getTopReactionsForTeamSince(c *Context, w http.ResponseWriter, r *http.Requ return } - user, err := c.App.GetUser(c.AppContext.Session().UserId) - if err != nil { - c.Err = err + user, appErr := c.App.GetUser(c.AppContext.Session().UserId) + if appErr != nil { + c.Err = appErr return } startTime := model.StartOfDayForTimeRange(c.Params.TimeRange, user.GetTimezoneLocation()) - topReactionList, err := c.App.GetTopReactionsForTeamSince(c.Params.TeamId, c.AppContext.Session().UserId, &model.InsightsOpts{ + topReactionList, appErr := c.App.GetTopReactionsForTeamSince(c.Params.TeamId, c.AppContext.Session().UserId, &model.InsightsOpts{ StartUnixMilli: startTime.UnixMilli(), Page: c.Params.Page, PerPage: c.Params.PerPage, }) - if err != nil { - c.Err = err + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(topReactionList) - if jsonErr != nil { - c.Err = model.NewAppError("getTopReactionsForTeamSince", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(topReactionList) + if err != nil { + c.Err = model.NewAppError("getTopReactionsForTeamSince", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -84,9 +84,9 @@ func getTopReactionsForUserSince(c *Context, w http.ResponseWriter, r *http.Requ return } - team, teamErr := c.App.GetTeam(c.Params.TeamId) - if teamErr != nil { - c.Err = teamErr + team, appErr := c.App.GetTeam(c.Params.TeamId) + if appErr != nil { + c.Err = appErr return } @@ -96,27 +96,27 @@ func getTopReactionsForUserSince(c *Context, w http.ResponseWriter, r *http.Requ } } - user, err := c.App.GetUser(c.AppContext.Session().UserId) - if err != nil { - c.Err = err + user, appErr := c.App.GetUser(c.AppContext.Session().UserId) + if appErr != nil { + c.Err = appErr return } startTime := model.StartOfDayForTimeRange(c.Params.TimeRange, user.GetTimezoneLocation()) - topReactionList, err := c.App.GetTopReactionsForUserSince(c.AppContext.Session().UserId, c.Params.TeamId, &model.InsightsOpts{ + topReactionList, appErr := c.App.GetTopReactionsForUserSince(c.AppContext.Session().UserId, c.Params.TeamId, &model.InsightsOpts{ StartUnixMilli: startTime.UnixMilli(), Page: c.Params.Page, PerPage: c.Params.PerPage, }) - if err != nil { - c.Err = err + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(topReactionList) - if jsonErr != nil { - c.Err = model.NewAppError("getTopReactionsForUserSince", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(topReactionList) + if err != nil { + c.Err = model.NewAppError("getTopReactionsForUserSince", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -131,9 +131,9 @@ func getTopChannelsForTeamSince(c *Context, w http.ResponseWriter, r *http.Reque return } - team, err := c.App.GetTeam(c.Params.TeamId) - if err != nil { - c.Err = err + team, appErr := c.App.GetTeam(c.Params.TeamId) + if appErr != nil { + c.Err = appErr return } @@ -142,34 +142,34 @@ func getTopChannelsForTeamSince(c *Context, w http.ResponseWriter, r *http.Reque return } - user, err := c.App.GetUser(c.AppContext.Session().UserId) - if err != nil { - c.Err = err + user, appErr := c.App.GetUser(c.AppContext.Session().UserId) + if appErr != nil { + c.Err = appErr return } loc := user.GetTimezoneLocation() startTime := model.StartOfDayForTimeRange(c.Params.TimeRange, loc) - topChannels, err := c.App.GetTopChannelsForTeamSince(c.AppContext, c.Params.TeamId, c.AppContext.Session().UserId, &model.InsightsOpts{ + topChannels, appErr := c.App.GetTopChannelsForTeamSince(c.AppContext, c.Params.TeamId, c.AppContext.Session().UserId, &model.InsightsOpts{ StartUnixMilli: startTime.UnixMilli(), Page: c.Params.Page, PerPage: c.Params.PerPage, }) - if err != nil { - c.Err = err + if appErr != nil { + c.Err = appErr return } - topChannels.PostCountByDuration, err = postCountByDurationViewModel(c, topChannels, startTime, c.Params.TimeRange, nil, loc) - if err != nil { - c.Err = err + topChannels.PostCountByDuration, appErr = postCountByDurationViewModel(c, topChannels, startTime, c.Params.TimeRange, nil, loc) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(topChannels) - if jsonErr != nil { - c.Err = model.NewAppError("getTopChannelsForTeamSince", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(topChannels) + if err != nil { + c.Err = model.NewAppError("getTopChannelsForTeamSince", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -186,9 +186,9 @@ func getTopChannelsForUserSince(c *Context, w http.ResponseWriter, r *http.Reque return } - team, teamErr := c.App.GetTeam(c.Params.TeamId) - if teamErr != nil { - c.Err = teamErr + team, appErr := c.App.GetTeam(c.Params.TeamId) + if appErr != nil { + c.Err = appErr return } @@ -198,35 +198,34 @@ func getTopChannelsForUserSince(c *Context, w http.ResponseWriter, r *http.Reque } } - user, err := c.App.GetUser(c.AppContext.Session().UserId) - if err != nil { - c.Err = err + user, appErr := c.App.GetUser(c.AppContext.Session().UserId) + if appErr != nil { + c.Err = appErr return } loc := user.GetTimezoneLocation() startTime := model.StartOfDayForTimeRange(c.Params.TimeRange, loc) - topChannels, err := c.App.GetTopChannelsForUserSince(c.AppContext, c.AppContext.Session().UserId, c.Params.TeamId, &model.InsightsOpts{ + topChannels, appErr := c.App.GetTopChannelsForUserSince(c.AppContext, c.AppContext.Session().UserId, c.Params.TeamId, &model.InsightsOpts{ StartUnixMilli: startTime.UnixMilli(), Page: c.Params.Page, PerPage: c.Params.PerPage, }) - - if err != nil { - c.Err = err + if appErr != nil { + c.Err = appErr return } - topChannels.PostCountByDuration, err = postCountByDurationViewModel(c, topChannels, startTime, c.Params.TimeRange, &c.AppContext.Session().UserId, loc) - if err != nil { - c.Err = err + topChannels.PostCountByDuration, appErr = postCountByDurationViewModel(c, topChannels, startTime, c.Params.TimeRange, &c.AppContext.Session().UserId, loc) + if appErr != nil { + c.Err = appErr return } js, jsonErr := json.Marshal(topChannels) if jsonErr != nil { - c.Err = model.NewAppError("getTopChannelsForUserSince", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("getTopChannelsForUserSince", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -240,9 +239,9 @@ func getTopThreadsForTeamSince(c *Context, w http.ResponseWriter, r *http.Reques return } - team, err := c.App.GetTeam(c.Params.TeamId) - if err != nil { - c.Err = err + team, appErr := c.App.GetTeam(c.Params.TeamId) + if appErr != nil { + c.Err = appErr return } @@ -260,19 +259,19 @@ func getTopThreadsForTeamSince(c *Context, w http.ResponseWriter, r *http.Reques startTime := model.StartOfDayForTimeRange(c.Params.TimeRange, user.GetTimezoneLocation()) - topThreads, err := c.App.GetTopThreadsForTeamSince(c.AppContext, c.Params.TeamId, c.AppContext.Session().UserId, &model.InsightsOpts{ + topThreads, appErr := c.App.GetTopThreadsForTeamSince(c.AppContext, c.Params.TeamId, c.AppContext.Session().UserId, &model.InsightsOpts{ StartUnixMilli: startTime.UnixMilli(), Page: c.Params.Page, PerPage: c.Params.PerPage, }) - if err != nil { - c.Err = err + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(topThreads) - if jsonErr != nil { - c.Err = model.NewAppError("getTopThreadsForTeamSince", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, jsonError := json.Marshal(topThreads) + if jsonError != nil { + c.Err = model.NewAppError("getTopThreadsForTeamSince", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -309,20 +308,19 @@ func getTopThreadsForUserSince(c *Context, w http.ResponseWriter, r *http.Reques startTime := model.StartOfDayForTimeRange(c.Params.TimeRange, user.GetTimezoneLocation()) - topThreads, err := c.App.GetTopThreadsForUserSince(c.AppContext, c.Params.TeamId, c.AppContext.Session().UserId, &model.InsightsOpts{ + topThreads, appErr := c.App.GetTopThreadsForUserSince(c.AppContext, c.Params.TeamId, c.AppContext.Session().UserId, &model.InsightsOpts{ StartUnixMilli: startTime.UnixMilli(), Page: c.Params.Page, PerPage: c.Params.PerPage, }) - - if err != nil { - c.Err = err + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(topThreads) - if jsonErr != nil { - c.Err = model.NewAppError("getTopThreadsForUserSince", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(topThreads) + if err != nil { + c.Err = model.NewAppError("getTopThreadsForUserSince", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } diff --git a/api4/integration_action.go b/api4/integration_action.go index aa7e5d7319..41b1e3703c 100644 --- a/api4/integration_action.go +++ b/api4/integration_action.go @@ -33,14 +33,15 @@ func doPostAction(c *Context, w http.ResponseWriter, r *http.Request) { var cookie *model.PostActionCookie if actionRequest.Cookie != "" { cookie = &model.PostActionCookie{} - cookieStr, err := model.DecryptPostActionCookie(actionRequest.Cookie, c.App.PostActionCookieSecret()) + cookieStr := "" + cookieStr, err = model.DecryptPostActionCookie(actionRequest.Cookie, c.App.PostActionCookieSecret()) if err != nil { - c.Err = model.NewAppError("DoPostAction", "api.post.do_action.action_integration.app_error", nil, "err="+err.Error(), http.StatusBadRequest) + c.Err = model.NewAppError("DoPostAction", "api.post.do_action.action_integration.app_error", nil, "", http.StatusBadRequest).Wrap(err) return } err = json.Unmarshal([]byte(cookieStr), &cookie) if err != nil { - c.Err = model.NewAppError("DoPostAction", "api.post.do_action.action_integration.app_error", nil, "err="+err.Error(), http.StatusBadRequest) + c.Err = model.NewAppError("DoPostAction", "api.post.do_action.action_integration.app_error", nil, "", http.StatusBadRequest).Wrap(err) return } if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), cookie.ChannelId, model.PermissionReadChannel) { @@ -64,8 +65,10 @@ func doPostAction(c *Context, w http.ResponseWriter, r *http.Request) { return } - b, _ := json.Marshal(resp) - w.Write(b) + err = json.NewEncoder(w).Encode(resp) + if err != nil { + c.Logger.Warn("Error writing response", mlog.Err(err)) + } } func openDialog(c *Context, w http.ResponseWriter, r *http.Request) { @@ -81,8 +84,8 @@ func openDialog(c *Context, w http.ResponseWriter, r *http.Request) { return } - if err := c.App.OpenInteractiveDialog(dialog); err != nil { - c.Err = err + if appErr := c.App.OpenInteractiveDialog(dialog); appErr != nil { + c.Err = appErr return } diff --git a/api4/integration_action_test.go b/api4/integration_action_test.go index 975e90ee90..92b4f2ccbe 100644 --- a/api4/integration_action_test.go +++ b/api4/integration_action_test.go @@ -5,7 +5,7 @@ package api4 import ( "encoding/json" - "io/ioutil" + "io" "net/http" "net/http/httptest" "testing" @@ -21,7 +21,7 @@ type testHandler struct { } func (th *testHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - bb, err := ioutil.ReadAll(r.Body) + bb, err := io.ReadAll(r.Body) assert.NoError(th.t, err) assert.NotEmpty(th.t, string(bb)) var poir model.PostActionIntegrationRequest diff --git a/api4/job.go b/api4/job.go index b0622ae8e3..58ee1350e2 100644 --- a/api4/job.go +++ b/api4/job.go @@ -162,15 +162,15 @@ func getJobs(c *Context, w http.ResponseWriter, r *http.Request) { return } - jobs, err := c.App.GetJobsByTypesPage(validJobTypes, c.Params.Page, c.Params.PerPage) - if err != nil { - c.Err = err + jobs, appErr := c.App.GetJobsByTypesPage(validJobTypes, c.Params.Page, c.Params.PerPage) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(jobs) - if jsonErr != nil { - c.Err = model.NewAppError("getJobs", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(jobs) + if err != nil { + c.Err = model.NewAppError("getJobs", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } w.Write(js) @@ -192,17 +192,18 @@ func getJobsByType(c *Context, w http.ResponseWriter, r *http.Request) { return } - jobs, err := c.App.GetJobsByTypePage(c.Params.JobType, c.Params.Page, c.Params.PerPage) - if err != nil { - c.Err = err + jobs, appErr := c.App.GetJobsByTypePage(c.Params.JobType, c.Params.Page, c.Params.PerPage) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(jobs) - if jsonErr != nil { - c.Err = model.NewAppError("getJobsByType", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(jobs) + if err != nil { + c.Err = model.NewAppError("getJobsByType", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } + w.Write(js) } diff --git a/api4/ldap.go b/api4/ldap.go index 60cd176c65..b71415c940 100644 --- a/api4/ldap.go +++ b/api4/ldap.go @@ -111,9 +111,9 @@ func getLdapGroups(c *Context, w http.ResponseWriter, r *http.Request) { opts.IsConfigured = c.Params.IsConfigured } - groups, total, err := c.App.GetAllLdapGroupsPage(c.Params.Page, c.Params.PerPage, opts) - if err != nil { - c.Err = err + groups, total, appErr := c.App.GetAllLdapGroupsPage(c.Params.Page, c.Params.PerPage, opts) + if appErr != nil { + c.Err = appErr return } @@ -130,12 +130,12 @@ func getLdapGroups(c *Context, w http.ResponseWriter, r *http.Request) { mugs = append(mugs, mug) } - b, marshalErr := json.Marshal(struct { + b, err := json.Marshal(struct { Count int `json:"count"` Groups []*mixedUnlinkedGroup `json:"groups"` }{Count: total, Groups: mugs}) - if marshalErr != nil { - c.Err = model.NewAppError("Api4.getLdapGroups", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + if err != nil { + c.Err = model.NewAppError("Api4.getLdapGroups", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -162,9 +162,9 @@ func linkLdapGroup(c *Context, w http.ResponseWriter, r *http.Request) { return } - ldapGroup, err := c.App.GetLdapGroup(c.Params.RemoteId) - if err != nil { - c.Err = err + ldapGroup, appErr := c.App.GetLdapGroup(c.Params.RemoteId) + if appErr != nil { + c.Err = appErr return } @@ -175,9 +175,9 @@ func linkLdapGroup(c *Context, w http.ResponseWriter, r *http.Request) { return } - group, err := c.App.GetGroupByRemoteID(ldapGroup.GetRemoteId(), model.GroupSourceLdap) - if err != nil && err.Id != "app.group.no_rows" { - c.Err = err + group, appErr := c.App.GetGroupByRemoteID(ldapGroup.GetRemoteId(), model.GroupSourceLdap) + if appErr != nil && appErr.Id != "app.group.no_rows" { + c.Err = appErr return } if group != nil { @@ -203,9 +203,9 @@ func linkLdapGroup(c *Context, w http.ResponseWriter, r *http.Request) { group.DeleteAt = 0 group.DisplayName = displayName group.RemoteId = ldapGroup.RemoteId - newOrUpdatedGroup, err = c.App.UpdateGroup(group) - if err != nil { - c.Err = err + newOrUpdatedGroup, appErr = c.App.UpdateGroup(group) + if appErr != nil { + c.Err = appErr return } auditRec.AddEventResultState(newOrUpdatedGroup) @@ -222,9 +222,9 @@ func linkLdapGroup(c *Context, w http.ResponseWriter, r *http.Request) { RemoteId: ldapGroup.RemoteId, Source: model.GroupSourceLdap, } - newOrUpdatedGroup, err = c.App.CreateGroup(newGroup) - if err != nil { - c.Err = err + newOrUpdatedGroup, appErr = c.App.CreateGroup(newGroup) + if appErr != nil { + c.Err = appErr return } auditRec.AddEventResultState(newOrUpdatedGroup) @@ -232,9 +232,9 @@ func linkLdapGroup(c *Context, w http.ResponseWriter, r *http.Request) { status = http.StatusCreated } - b, marshalErr := json.Marshal(newOrUpdatedGroup) - if marshalErr != nil { - c.Err = model.NewAppError("Api4.linkLdapGroup", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + b, err := json.Marshal(newOrUpdatedGroup) + if err != nil { + c.Err = model.NewAppError("Api4.linkLdapGroup", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } diff --git a/api4/license.go b/api4/license.go index 4e308a1a45..ee7a79fa54 100644 --- a/api4/license.go +++ b/api4/license.go @@ -8,7 +8,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "net/http" "github.com/mattermost/mattermost-server/v6/shared/mlog" @@ -203,7 +202,7 @@ func requestTrialLicense(c *Context, w http.ResponseWriter, r *http.Request) { ReceiveEmailsAccepted bool `json:"receive_emails_accepted"` } - b, readErr := ioutil.ReadAll(r.Body) + b, readErr := io.ReadAll(r.Body) if readErr != nil { c.Err = model.NewAppError("requestTrialLicense", "api.license.request-trial.bad-request", nil, "", http.StatusBadRequest) return diff --git a/api4/oauth.go b/api4/oauth.go index 96a7ae4586..aa0e72bbfb 100644 --- a/api4/oauth.go +++ b/api4/oauth.go @@ -132,26 +132,27 @@ func getOAuthApps(c *Context, w http.ResponseWriter, r *http.Request) { } var apps []*model.OAuthApp - var err *model.AppError + var appErr *model.AppError if c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageSystemWideOAuth) { - apps, err = c.App.GetOAuthApps(c.Params.Page, c.Params.PerPage) + apps, appErr = c.App.GetOAuthApps(c.Params.Page, c.Params.PerPage) } else if c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageOAuth) { - apps, err = c.App.GetOAuthAppsByCreator(c.AppContext.Session().UserId, c.Params.Page, c.Params.PerPage) + apps, appErr = c.App.GetOAuthAppsByCreator(c.AppContext.Session().UserId, c.Params.Page, c.Params.PerPage) } else { c.SetPermissionError(model.PermissionManageOAuth) return } - if err != nil { - c.Err = err + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(apps) - if jsonErr != nil { - c.Err = model.NewAppError("getOAuthApps", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(apps) + if err != nil { + c.Err = model.NewAppError("getOAuthApps", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } + w.Write(js) } @@ -295,16 +296,17 @@ func getAuthorizedOAuthApps(c *Context, w http.ResponseWriter, r *http.Request) return } - apps, err := c.App.GetAuthorizedAppsForUser(c.Params.UserId, c.Params.Page, c.Params.PerPage) - if err != nil { - c.Err = err + apps, appErr := c.App.GetAuthorizedAppsForUser(c.Params.UserId, c.Params.Page, c.Params.PerPage) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(apps) - if jsonErr != nil { - c.Err = model.NewAppError("getAuthorizedOAuthApps", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(apps) + if err != nil { + c.Err = model.NewAppError("getAuthorizedOAuthApps", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } + w.Write(js) } diff --git a/api4/permission.go b/api4/permission.go index 0ed4351071..a0aac0a6eb 100644 --- a/api4/permission.go +++ b/api4/permission.go @@ -26,8 +26,9 @@ func appendAncillaryPermissions(c *Context, w http.ResponseWriter, r *http.Reque permissions := strings.Split(keys[0], ",") b, err := json.Marshal(model.AddAncillaryPermissions(permissions)) if err != nil { - c.SetJSONEncodingError() + c.SetJSONEncodingError(err) return } + w.Write(b) } diff --git a/api4/plugin.go b/api4/plugin.go index 1ab0aae92c..775b515a57 100644 --- a/api4/plugin.go +++ b/api4/plugin.go @@ -251,9 +251,9 @@ func getWebappPlugins(c *Context, w http.ResponseWriter, r *http.Request) { return } - manifests, err := c.App.GetActivePluginManifests() - if err != nil { - c.Err = err + manifests, appErr := c.App.GetActivePluginManifests() + if appErr != nil { + c.Err = appErr return } @@ -268,11 +268,12 @@ func getWebappPlugins(c *Context, w http.ResponseWriter, r *http.Request) { } } - js, jsonErr := json.Marshal(clientManifests) - if jsonErr != nil { - c.Err = model.NewAppError("getWebappPlugins", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(clientManifests) + if err != nil { + c.Err = model.NewAppError("getWebappPlugins", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } + w.Write(js) } @@ -294,7 +295,7 @@ func getMarketplacePlugins(c *Context, w http.ResponseWriter, r *http.Request) { filter, err := parseMarketplacePluginFilter(r.URL) if err != nil { - c.Err = model.NewAppError("getMarketplacePlugins", "app.plugin.marshal.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("getMarketplacePlugins", "app.plugin.marshal.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -306,7 +307,7 @@ func getMarketplacePlugins(c *Context, w http.ResponseWriter, r *http.Request) { json, err := json.Marshal(plugins) if err != nil { - c.Err = model.NewAppError("getMarketplacePlugins", "app.plugin.marshal.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("getMarketplacePlugins", "app.plugin.marshal.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } diff --git a/api4/plugin_test.go b/api4/plugin_test.go index a6382ce32a..da5f145412 100644 --- a/api4/plugin_test.go +++ b/api4/plugin_test.go @@ -8,7 +8,7 @@ import ( "encoding/base64" "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "net/http/httptest" "os" @@ -44,7 +44,7 @@ func TestPlugin(t *testing.T) { }) path, _ := fileutils.FindDir("tests") - tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin.tar.gz")) + tarData, err := os.ReadFile(filepath.Join(path, "testplugin.tar.gz")) require.NoError(t, err) // Install from URL @@ -295,7 +295,7 @@ func TestNotifyClusterPluginEvent(t *testing.T) { }) path, _ := fileutils.FindDir("tests") - tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin.tar.gz")) + tarData, err := os.ReadFile(filepath.Join(path, "testplugin.tar.gz")) require.NoError(t, err) testCluster.ClearMessages() @@ -378,7 +378,7 @@ func TestNotifyClusterPluginEvent(t *testing.T) { func TestDisableOnRemove(t *testing.T) { path, _ := fileutils.FindDir("tests") - tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin.tar.gz")) + tarData, err := os.ReadFile(filepath.Join(path, "testplugin.tar.gz")) require.NoError(t, err) testCases := []struct { @@ -723,7 +723,7 @@ func TestGetInstalledMarketplacePlugins(t *testing.T) { } path, _ := fileutils.FindDir("tests") - tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin.tar.gz")) + tarData, err := os.ReadFile(filepath.Join(path, "testplugin.tar.gz")) require.NoError(t, err) t.Run("marketplace client returns not-installed plugin", func(t *testing.T) { @@ -752,7 +752,7 @@ func TestGetInstalledMarketplacePlugins(t *testing.T) { manifest, _, err := th.SystemAdminClient.UploadPlugin(bytes.NewReader(tarData)) require.NoError(t, err) - testIcon, err := ioutil.ReadFile(filepath.Join(path, "test.svg")) + testIcon, err := os.ReadFile(filepath.Join(path, "test.svg")) require.NoError(t, err) require.True(t, svg.Is(testIcon)) testIconData := fmt.Sprintf("data:image/svg+xml;base64,%s", base64.StdEncoding.EncodeToString(testIcon)) @@ -860,13 +860,13 @@ func TestSearchGetMarketplacePlugins(t *testing.T) { } path, _ := fileutils.FindDir("tests") - tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin.tar.gz")) + tarData, err := os.ReadFile(filepath.Join(path, "testplugin.tar.gz")) require.NoError(t, err) - tarDataV2, err := ioutil.ReadFile(filepath.Join(path, "testplugin2.tar.gz")) + tarDataV2, err := os.ReadFile(filepath.Join(path, "testplugin2.tar.gz")) require.NoError(t, err) - testIcon, err := ioutil.ReadFile(filepath.Join(path, "test.svg")) + testIcon, err := os.ReadFile(filepath.Join(path, "test.svg")) require.NoError(t, err) require.True(t, svg.Is(testIcon)) testIconData := fmt.Sprintf("data:image/svg+xml;base64,%s", base64.StdEncoding.EncodeToString(testIcon)) @@ -1021,7 +1021,7 @@ func TestGetLocalPluginInMarketplace(t *testing.T) { // Upload one local plugin path, _ := fileutils.FindDir("tests") - tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin.tar.gz")) + tarData, err := os.ReadFile(filepath.Join(path, "testplugin.tar.gz")) require.NoError(t, err) manifest, _, err := th.SystemAdminClient.UploadPlugin(bytes.NewReader(tarData)) @@ -1050,13 +1050,13 @@ func TestGetLocalPluginInMarketplace(t *testing.T) { // Upload one local plugin path, _ := fileutils.FindDir("tests") - tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin.tar.gz")) + tarData, err := os.ReadFile(filepath.Join(path, "testplugin.tar.gz")) require.NoError(t, err) manifest, _, err := th.SystemAdminClient.UploadPlugin(bytes.NewReader(tarData)) require.NoError(t, err) - testIcon, err := ioutil.ReadFile(filepath.Join(path, "test.svg")) + testIcon, err := os.ReadFile(filepath.Join(path, "test.svg")) require.NoError(t, err) require.True(t, svg.Is(testIcon)) testIconData := fmt.Sprintf("data:image/svg+xml;base64,%s", base64.StdEncoding.EncodeToString(testIcon)) @@ -1090,13 +1090,13 @@ func TestGetLocalPluginInMarketplace(t *testing.T) { // Upload one local plugin path, _ := fileutils.FindDir("tests") - tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin.tar.gz")) + tarData, err := os.ReadFile(filepath.Join(path, "testplugin.tar.gz")) require.NoError(t, err) manifest, _, err := th.SystemAdminClient.UploadPlugin(bytes.NewReader(tarData)) require.NoError(t, err) - testIcon, err := ioutil.ReadFile(filepath.Join(path, "test.svg")) + testIcon, err := os.ReadFile(filepath.Join(path, "test.svg")) require.NoError(t, err) require.True(t, svg.Is(testIcon)) testIconData := fmt.Sprintf("data:image/svg+xml;base64,%s", base64.StdEncoding.EncodeToString(testIcon)) @@ -1262,11 +1262,11 @@ func TestInstallMarketplacePlugin(t *testing.T) { signatureFilename := "testplugin2.tar.gz.sig" signatureFileReader, err := os.Open(filepath.Join(path, signatureFilename)) require.NoError(t, err) - sigFile, err := ioutil.ReadAll(signatureFileReader) + sigFile, err := io.ReadAll(signatureFileReader) require.NoError(t, err) pluginSignature := base64.StdEncoding.EncodeToString(sigFile) - tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin2.tar.gz")) + tarData, err := os.ReadFile(filepath.Join(path, "testplugin2.tar.gz")) require.NoError(t, err) pluginServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { res.WriteHeader(http.StatusOK) @@ -1622,7 +1622,7 @@ func TestInstallMarketplacePlugin(t *testing.T) { th2.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { pluginSignatureFile, err := os.Open(filepath.Join(path, "testplugin.tar.gz.asc")) require.NoError(t, err) - pluginSignatureData, err := ioutil.ReadAll(pluginSignatureFile) + pluginSignatureData, err := io.ReadAll(pluginSignatureFile) require.NoError(t, err) key, err := os.Open(filepath.Join(path, "development-private-key.asc")) diff --git a/api4/post.go b/api4/post.go index 7ae86bbc28..5f9cf2e7b1 100644 --- a/api4/post.go +++ b/api4/post.go @@ -970,9 +970,9 @@ func getFileInfosForPost(c *Context, w http.ResponseWriter, r *http.Request) { return } - infos, err := c.App.GetFileInfosForPostWithMigration(c.Params.PostId, includeDeleted) - if err != nil { - c.Err = err + infos, appErr := c.App.GetFileInfosForPostWithMigration(c.Params.PostId, includeDeleted) + if appErr != nil { + c.Err = appErr return } @@ -980,11 +980,12 @@ func getFileInfosForPost(c *Context, w http.ResponseWriter, r *http.Request) { return } - js, jsonErr := json.Marshal(infos) - if jsonErr != nil { - c.Err = model.NewAppError("getFileInfosForPost", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(infos) + if err != nil { + c.Err = model.NewAppError("getFileInfosForPost", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } + w.Header().Set("Cache-Control", "max-age=2592000, private") w.Header().Set(model.HeaderEtagServer, model.GetEtagForFileInfos(infos)) w.Write(js) diff --git a/api4/reaction.go b/api4/reaction.go index da95d63f5b..df097619cf 100644 --- a/api4/reaction.go +++ b/api4/reaction.go @@ -62,17 +62,18 @@ func getReactions(c *Context, w http.ResponseWriter, r *http.Request) { return } - reactions, err := c.App.GetReactionsForPost(c.Params.PostId) - if err != nil { - c.Err = err + reactions, appErr := c.App.GetReactionsForPost(c.Params.PostId) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(reactions) - if jsonErr != nil { - c.Err = model.NewAppError("getReactions", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(reactions) + if err != nil { + c.Err = model.NewAppError("getReactions", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } + w.Write(js) } @@ -125,15 +126,15 @@ func getBulkReactions(c *Context, w http.ResponseWriter, r *http.Request) { return } } - reactions, err := c.App.GetBulkReactionsForPosts(postIds) - if err != nil { - c.Err = err + reactions, appErr := c.App.GetBulkReactionsForPosts(postIds) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(reactions) - if jsonErr != nil { - c.Err = model.NewAppError("getBulkReactions", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(reactions) + if err != nil { + c.Err = model.NewAppError("getBulkReactions", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } w.Write(js) diff --git a/api4/remote_cluster.go b/api4/remote_cluster.go index d0956a38a9..0fe0be57be 100644 --- a/api4/remote_cluster.go +++ b/api4/remote_cluster.go @@ -31,8 +31,8 @@ func remoteClusterPing(c *Context, w http.ResponseWriter, r *http.Request) { } var frame model.RemoteClusterFrame - if jsonErr := json.NewDecoder(r.Body).Decode(&frame); jsonErr != nil { - c.Err = model.NewAppError("remoteClusterPing", "api.unmarshal_error", nil, "", http.StatusBadRequest).Wrap(jsonErr) + if err := json.NewDecoder(r.Body).Decode(&frame); err != nil { + c.Err = model.NewAppError("remoteClusterPing", "api.unmarshal_error", nil, "", http.StatusBadRequest).Wrap(err) return } @@ -47,15 +47,15 @@ func remoteClusterPing(c *Context, w http.ResponseWriter, r *http.Request) { return } - rc, err := c.App.GetRemoteCluster(frame.RemoteId) - if err != nil { + rc, appErr := c.App.GetRemoteCluster(frame.RemoteId) + if appErr != nil { c.SetInvalidRemoteIdError(frame.RemoteId) return } var ping model.RemoteClusterPing - if jsonErr := json.Unmarshal(frame.Msg.Payload, &ping); jsonErr != nil { - c.SetInvalidParam("msg.payload") + if err := json.Unmarshal(frame.Msg.Payload, &ping); err != nil { + c.SetInvalidParamWithErr("msg.payload", err) return } ping.RecvAt = model.GetMillis() @@ -64,8 +64,10 @@ func remoteClusterPing(c *Context, w http.ResponseWriter, r *http.Request) { metrics.IncrementRemoteClusterMsgReceivedCounter(rc.RemoteId) } - resp, _ := json.Marshal(&ping) - w.Write(resp) + err := json.NewEncoder(w).Encode(ping) + if err != nil { + c.Logger.Warn("Error writing response", mlog.Err(err)) + } } func remoteClusterAcceptMessage(c *Context, w http.ResponseWriter, r *http.Request) { @@ -77,12 +79,13 @@ func remoteClusterAcceptMessage(c *Context, w http.ResponseWriter, r *http.Reque } var frame model.RemoteClusterFrame - if jsonErr := json.NewDecoder(r.Body).Decode(&frame); jsonErr != nil { - c.Err = model.NewAppError("remoteClusterAcceptMessage", "api.unmarshal_error", nil, "", http.StatusBadRequest).Wrap(jsonErr) + if err := json.NewDecoder(r.Body).Decode(&frame); err != nil { + c.Err = model.NewAppError("remoteClusterAcceptMessage", "api.unmarshal_error", nil, "", http.StatusBadRequest).Wrap(err) return } - if appErr := frame.IsValid(); appErr != nil { + appErr = frame.IsValid() + if appErr != nil { c.Err = appErr return } @@ -97,8 +100,8 @@ func remoteClusterAcceptMessage(c *Context, w http.ResponseWriter, r *http.Reque return } - rc, err := c.App.GetRemoteCluster(frame.RemoteId) - if err != nil { + rc, appErr := c.App.GetRemoteCluster(frame.RemoteId) + if appErr != nil { c.SetInvalidRemoteIdError(frame.RemoteId) return } @@ -107,11 +110,12 @@ func remoteClusterAcceptMessage(c *Context, w http.ResponseWriter, r *http.Reque // pass message to Remote Cluster Service and write response resp := service.ReceiveIncomingMsg(rc, frame.Msg) - b, errMarshall := json.Marshal(resp) - if errMarshall != nil { - c.Err = model.NewAppError("remoteClusterAcceptMessage", "api.marshal_error", nil, errMarshall.Error(), http.StatusInternalServerError) + b, err := json.Marshal(resp) + if err != nil { + c.Err = model.NewAppError("remoteClusterAcceptMessage", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } + w.Write(b) } diff --git a/api4/role.go b/api4/role.go index f9ea2dda90..e404235ba1 100644 --- a/api4/role.go +++ b/api4/role.go @@ -32,15 +32,15 @@ func getAllRoles(c *Context, w http.ResponseWriter, r *http.Request) { return } - roles, err := c.App.GetAllRoles() - if err != nil { - c.Err = err + roles, appErr := c.App.GetAllRoles() + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(roles) - if jsonErr != nil { - c.Err = model.NewAppError("getAllRoles", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(roles) + if err != nil { + c.Err = model.NewAppError("getAllRoles", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -95,17 +95,18 @@ func getRolesByNames(c *Context, w http.ResponseWriter, r *http.Request) { return } - roles, err := c.App.GetRolesByNames(cleanedRoleNames) - if err != nil { - c.Err = err + roles, appErr := c.App.GetRolesByNames(cleanedRoleNames) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(roles) - if jsonErr != nil { - c.Err = model.NewAppError("getRolesByNames", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(roles) + if err != nil { + c.Err = model.NewAppError("getRolesByNames", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } + w.Write(js) } @@ -116,8 +117,8 @@ func patchRole(c *Context, w http.ResponseWriter, r *http.Request) { } var patch model.RolePatch - if jsonErr := json.NewDecoder(r.Body).Decode(&patch); jsonErr != nil { - c.SetInvalidParamWithErr("role", jsonErr) + if err := json.NewDecoder(r.Body).Decode(&patch); err != nil { + c.SetInvalidParamWithErr("role", err) return } @@ -125,9 +126,9 @@ func patchRole(c *Context, w http.ResponseWriter, r *http.Request) { auditRec.AddEventParameter("role_patch", patch) defer c.LogAuditRec(auditRec) - oldRole, err := c.App.GetRole(c.Params.RoleId) - if err != nil { - c.Err = err + oldRole, appErr := c.App.GetRole(c.Params.RoleId) + if appErr != nil { + c.Err = appErr return } auditRec.AddEventPriorState(oldRole) @@ -203,9 +204,9 @@ func patchRole(c *Context, w http.ResponseWriter, r *http.Request) { } } - role, err := c.App.PatchRole(oldRole, &patch) - if err != nil { - c.Err = err + role, appErr := c.App.PatchRole(oldRole, &patch) + if appErr != nil { + c.Err = appErr return } diff --git a/api4/saml.go b/api4/saml.go index f102870be6..893e34f797 100644 --- a/api4/saml.go +++ b/api4/saml.go @@ -5,7 +5,7 @@ package api4 import ( "encoding/json" - "io/ioutil" + "io" "mime" "mime/multipart" "net/http" @@ -139,7 +139,7 @@ func addSamlIdpCertificate(c *Context, w http.ResponseWriter, r *http.Request) { auditRec.AddMeta("type", d) if d == "application/x-pem-file" { - body, err := ioutil.ReadAll(r.Body) + body, err := io.ReadAll(r.Body) if err != nil { c.Err = model.NewAppError("addSamlIdpCertificate", "api.admin.saml.set_certificate_from_metadata.invalid_body.app_error", nil, err.Error(), http.StatusBadRequest) return diff --git a/api4/scheme.go b/api4/scheme.go index 200d8f554d..efb5f781b0 100644 --- a/api4/scheme.go +++ b/api4/scheme.go @@ -93,17 +93,18 @@ func getSchemes(c *Context, w http.ResponseWriter, r *http.Request) { return } - schemes, err := c.App.GetSchemesPage(c.Params.Scope, c.Params.Page, c.Params.PerPage) - if err != nil { - c.Err = err + schemes, appErr := c.App.GetSchemesPage(c.Params.Scope, c.Params.Page, c.Params.PerPage) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(schemes) - if jsonErr != nil { - c.Err = model.NewAppError("getSchemes", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(schemes) + if err != nil { + c.Err = model.NewAppError("getSchemes", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } + w.Write(js) } @@ -118,9 +119,9 @@ func getTeamsForScheme(c *Context, w http.ResponseWriter, r *http.Request) { return } - scheme, err := c.App.GetScheme(c.Params.SchemeId) - if err != nil { - c.Err = err + scheme, appErr := c.App.GetScheme(c.Params.SchemeId) + if appErr != nil { + c.Err = appErr return } @@ -129,17 +130,18 @@ func getTeamsForScheme(c *Context, w http.ResponseWriter, r *http.Request) { return } - teams, err := c.App.GetTeamsForSchemePage(scheme, c.Params.Page, c.Params.PerPage) - if err != nil { - c.Err = err + teams, appErr := c.App.GetTeamsForSchemePage(scheme, c.Params.Page, c.Params.PerPage) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(teams) - if jsonErr != nil { - c.Err = model.NewAppError("getTeamsForScheme", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(teams) + if err != nil { + c.Err = model.NewAppError("getTeamsForScheme", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } + w.Write(js) } diff --git a/api4/shared_channel.go b/api4/shared_channel.go index b2fc386bce..5e53ee5f33 100644 --- a/api4/shared_channel.go +++ b/api4/shared_channel.go @@ -50,9 +50,10 @@ func getSharedChannels(c *Context, w http.ResponseWriter, r *http.Request) { b, err := json.Marshal(channels) if err != nil { - c.SetJSONEncodingError() + c.SetJSONEncodingError(err) return } + w.Write(b) } @@ -80,7 +81,7 @@ func getRemoteClusterInfo(c *Context, w http.ResponseWriter, r *http.Request) { b, err := json.Marshal(remoteInfo) if err != nil { - c.SetJSONEncodingError() + c.SetJSONEncodingError(err) return } w.Write(b) diff --git a/api4/status.go b/api4/status.go index 5ecc754b9d..06311ee15b 100644 --- a/api4/status.go +++ b/api4/status.go @@ -64,17 +64,18 @@ func getUserStatusesByIds(c *Context, w http.ResponseWriter, r *http.Request) { } // No permission check required - statuses, err := c.App.GetUserStatusesByIds(userIds) - if err != nil { - c.Err = err + statuses, appErr := c.App.GetUserStatusesByIds(userIds) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(statuses) - if jsonErr != nil { - c.Err = model.NewAppError("getUserStatusesByIds", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(statuses) + if err != nil { + c.Err = model.NewAppError("getUserStatusesByIds", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } + w.Write(js) } diff --git a/api4/system.go b/api4/system.go index d35a2068c8..3d60335d63 100644 --- a/api4/system.go +++ b/api4/system.go @@ -195,7 +195,11 @@ func getSystemPing(c *Context, w http.ResponseWriter, r *http.Request) { } func testEmail(c *Context, w http.ResponseWriter, r *http.Request) { - cfg := model.ConfigFromJSON(r.Body) + var cfg *model.Config + err := json.NewDecoder(r.Body).Decode(&cfg) + if err != nil { + c.Logger.Warn("Error decoding the config", mlog.Err(err)) + } if cfg == nil { cfg = c.App.Config() } @@ -215,9 +219,9 @@ func testEmail(c *Context, w http.ResponseWriter, r *http.Request) { return } - err := c.App.TestEmail(c.AppContext.Session().UserId, cfg) - if err != nil { - c.Err = err + appErr := c.App.TestEmail(c.AppContext.Session().UserId, cfg) + if appErr != nil { + c.Err = appErr return } @@ -242,9 +246,9 @@ func testSiteURL(c *Context, w http.ResponseWriter, r *http.Request) { return } - err := c.App.TestSiteURL(siteURL) - if err != nil { - c.Err = err + appErr := c.App.TestSiteURL(siteURL) + if appErr != nil { + c.Err = appErr return } @@ -260,9 +264,9 @@ func getAudits(c *Context, w http.ResponseWriter, r *http.Request) { return } - audits, err := c.App.GetAuditsPage("", c.Params.Page, c.Params.PerPage) - if err != nil { - c.Err = err + audits, appErr := c.App.GetAuditsPage("", c.Params.Page, c.Params.PerPage) + if appErr != nil { + c.Err = appErr return } @@ -309,9 +313,9 @@ func invalidateCaches(c *Context, w http.ResponseWriter, r *http.Request) { return } - err := c.App.Srv().InvalidateAllCaches() - if err != nil { - c.Err = err + appErr := c.App.Srv().InvalidateAllCaches() + if appErr != nil { + c.Err = appErr return } @@ -335,9 +339,9 @@ func getLogs(c *Context, w http.ResponseWriter, r *http.Request) { return } - lines, err := c.App.GetLogs(c.Params.Page, c.Params.LogsPerPage) - if err != nil { - c.Err = err + lines, appErr := c.App.GetLogs(c.Params.Page, c.Params.LogsPerPage) + if appErr != nil { + c.Err = appErr return } @@ -361,7 +365,15 @@ func postLog(c *Context, w http.ResponseWriter, r *http.Request) { } } - m := model.MapFromJSON(r.Body) + var m map[string]string + err := json.NewDecoder(r.Body).Decode(&m) + if err != nil { + c.Logger.Warn("Error decoding request.", mlog.Err(err)) + } + if m == nil { + m = map[string]string{} + } + lvl := m["level"] msg := m["message"] @@ -382,7 +394,10 @@ func postLog(c *Context, w http.ResponseWriter, r *http.Request) { } m["message"] = msg - w.Write([]byte(model.MapToJSON(m))) + err = json.NewEncoder(w).Encode(m) + if err != nil { + c.Logger.Warn("Error while writing response.", mlog.Err(err)) + } } func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) { @@ -398,9 +413,9 @@ func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) { return } - rows, err := c.App.GetAnalytics(name, teamId) - if err != nil { - c.Err = err + rows, appErr := c.App.GetAnalytics(name, teamId) + if appErr != nil { + c.Err = appErr return } @@ -420,15 +435,15 @@ func getLatestVersion(c *Context, w http.ResponseWriter, r *http.Request) { return } - resp, err := c.App.GetLatestVersion("https://api.github.com/repos/mattermost/mattermost-server/releases/latest") - if err != nil { - c.Err = err + resp, appErr := c.App.GetLatestVersion("https://api.github.com/repos/mattermost/mattermost-server/releases/latest") + if appErr != nil { + c.Err = appErr return } - b, jsonErr := json.Marshal(resp) - if jsonErr != nil { - c.Logger.Warn("Unable to marshal JSON for latest version.", mlog.Err(jsonErr)) + b, err := json.Marshal(resp) + if err != nil { + c.Logger.Warn("Unable to marshal JSON for latest version.", mlog.Err(err)) w.WriteHeader(http.StatusInternalServerError) } @@ -451,7 +466,11 @@ func getSupportedTimezones(c *Context, w http.ResponseWriter, r *http.Request) { } func testS3(c *Context, w http.ResponseWriter, r *http.Request) { - cfg := model.ConfigFromJSON(r.Body) + var cfg *model.Config + err := json.NewDecoder(r.Body).Decode(&cfg) + if err != nil { + c.Logger.Warn("Error decoding the config", mlog.Err(err)) + } if cfg == nil { cfg = c.App.Config() } @@ -471,9 +490,9 @@ func testS3(c *Context, w http.ResponseWriter, r *http.Request) { return } - err := c.App.CheckMandatoryS3Fields(&cfg.FileSettings) - if err != nil { - c.Err = err + appErr := c.App.CheckMandatoryS3Fields(&cfg.FileSettings) + if appErr != nil { + c.Err = appErr return } @@ -481,7 +500,7 @@ func testS3(c *Context, w http.ResponseWriter, r *http.Request) { cfg.FileSettings.AmazonS3SecretAccessKey = c.App.Config().FileSettings.AmazonS3SecretAccessKey } - appErr := c.App.TestFileStoreConnectionWithConfig(&cfg.FileSettings) + appErr = c.App.TestFileStoreConnectionWithConfig(&cfg.FileSettings) if appErr != nil { c.Err = appErr return @@ -776,17 +795,18 @@ func getWarnMetricsStatus(c *Context, w http.ResponseWriter, r *http.Request) { return } - status, err := c.App.GetWarnMetricsStatus() - if err != nil { - c.Err = err + status, appErr := c.App.GetWarnMetricsStatus() + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(status) - if jsonErr != nil { - c.Err = model.NewAppError("getWarnMetricsStatus", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(status) + if err != nil { + c.Err = model.NewAppError("getWarnMetricsStatus", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } + w.Write(js) } @@ -871,10 +891,9 @@ func getProductNotices(c *Context, w http.ResponseWriter, r *http.Request) { clientVersion := r.URL.Query().Get("clientVersion") locale := r.URL.Query().Get("locale") - notices, err := c.App.GetProductNotices(c.AppContext, c.AppContext.Session().UserId, c.Params.TeamId, client, clientVersion, locale) - - if err != nil { - c.Err = err + notices, appErr := c.App.GetProductNotices(c.AppContext, c.AppContext.Session().UserId, c.Params.TeamId, client, clientVersion, locale) + if appErr != nil { + c.Err = appErr return } result, _ := notices.Marshal() @@ -887,9 +906,9 @@ func updateViewedProductNotices(c *Context, w http.ResponseWriter, r *http.Reque c.LogAudit("attempt") ids := model.ArrayFromJSON(r.Body) - err := c.App.UpdateViewedProductNotices(c.AppContext.Session().UserId, ids) - if err != nil { - c.Err = err + appErr := c.App.UpdateViewedProductNotices(c.AppContext.Session().UserId, ids) + if appErr != nil { + c.Err = appErr return } @@ -910,7 +929,7 @@ func getOnboarding(c *Context, w http.ResponseWriter, r *http.Request) { firstAdminCompleteSetupObj, err := c.App.GetOnboarding() if err != nil { - c.Err = model.NewAppError("getOnboarding", "app.system.get_onboarding_request.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("getOnboarding", "app.system.get_onboarding_request.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -931,7 +950,7 @@ func completeOnboarding(c *Context, w http.ResponseWriter, r *http.Request) { onboardingRequest, err := model.CompleteOnboardingRequestFromReader(r.Body) if err != nil { - c.Err = model.NewAppError("completeOnboarding", "app.system.complete_onboarding_request.app_error", nil, err.Error(), http.StatusBadRequest) + c.Err = model.NewAppError("completeOnboarding", "app.system.complete_onboarding_request.app_error", nil, "", http.StatusBadRequest).Wrap(err) return } auditRec.AddEventParameter("install_plugin", onboardingRequest.InstallPlugins) @@ -962,9 +981,9 @@ func getAppliedSchemaMigrations(c *Context, w http.ResponseWriter, r *http.Reque return } - js, jsonErr := json.Marshal(migrations) - if jsonErr != nil { - c.Err = model.NewAppError("getAppliedMigrations", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(migrations) + if err != nil { + c.Err = model.NewAppError("getAppliedMigrations", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } diff --git a/api4/system_local.go b/api4/system_local.go index 3b316f0f53..4559ab8d8c 100644 --- a/api4/system_local.go +++ b/api4/system_local.go @@ -33,7 +33,7 @@ func localCheckIntegrity(c *Context, w http.ResponseWriter, r *http.Request) { data, err := json.Marshal(results) if err != nil { - c.Err = model.NewAppError("Api4.localCheckIntegrity", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.localCheckIntegrity", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } diff --git a/api4/system_test.go b/api4/system_test.go index 13eced3f1f..56373ce581 100644 --- a/api4/system_test.go +++ b/api4/system_test.go @@ -8,7 +8,7 @@ import ( "encoding/base64" "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "net/http/httptest" "os" @@ -64,7 +64,7 @@ func TestGetPing(t *testing.T) { resp, err := client.DoAPIGet("/system/ping", "") require.NoError(t, err) require.Equal(t, http.StatusOK, resp.StatusCode) - respBytes, err := ioutil.ReadAll(resp.Body) + respBytes, err := io.ReadAll(resp.Body) require.NoError(t, err) respString := string(respBytes) require.NotContains(t, respString, "TestFeatureFlag") @@ -77,7 +77,7 @@ func TestGetPing(t *testing.T) { resp, err = client.DoAPIGet("/system/ping", "") require.NoError(t, err) require.Equal(t, http.StatusOK, resp.StatusCode) - respBytes, err = ioutil.ReadAll(resp.Body) + respBytes, err = io.ReadAll(resp.Body) require.NoError(t, err) respString = string(respBytes) require.Contains(t, respString, "testvalue") @@ -130,7 +130,7 @@ func TestEmailTest(t *testing.T) { defer th.TearDown() client := th.Client - dir, err := ioutil.TempDir("", "") + dir, err := os.MkdirTemp("", "") require.NoError(t, err) defer os.RemoveAll(dir) @@ -817,7 +817,7 @@ func TestPushNotificationAck(t *testing.T) { resp := httptest.NewRecorder() req := httptest.NewRequest("POST", "/api/v4/notifications/ack", nil) req.Header.Set(model.HeaderAuth, "Bearer "+session.Token) - req.Body = ioutil.NopCloser(bytes.NewBufferString(fmt.Sprintf(`{"id":"123", "is_id_loaded":true, "post_id":"%s", "type": "%s"}`, privatePost.Id, model.PushTypeMessage))) + req.Body = io.NopCloser(bytes.NewBufferString(fmt.Sprintf(`{"id":"123", "is_id_loaded":true, "post_id":"%s", "type": "%s"}`, privatePost.Id, model.PushTypeMessage))) handler.ServeHTTP(resp, req) assert.Equal(t, http.StatusForbidden, resp.Code) @@ -833,11 +833,11 @@ func TestCompleteOnboarding(t *testing.T) { signatureFilename := "testplugin2.tar.gz.sig" signatureFileReader, err := os.Open(filepath.Join(path, signatureFilename)) require.NoError(t, err) - sigFile, err := ioutil.ReadAll(signatureFileReader) + sigFile, err := io.ReadAll(signatureFileReader) require.NoError(t, err) pluginSignature := base64.StdEncoding.EncodeToString(sigFile) - tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin2.tar.gz")) + tarData, err := os.ReadFile(filepath.Join(path, "testplugin2.tar.gz")) require.NoError(t, err) pluginServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { res.WriteHeader(http.StatusOK) diff --git a/api4/team.go b/api4/team.go index fac2d489c3..5ee8a0d3da 100644 --- a/api4/team.go +++ b/api4/team.go @@ -485,19 +485,20 @@ func getTeamsForUser(c *Context, w http.ResponseWriter, r *http.Request) { return } - teams, err := c.App.GetTeamsForUser(c.Params.UserId) - if err != nil { - c.Err = err + teams, appErr := c.App.GetTeamsForUser(c.Params.UserId) + if appErr != nil { + c.Err = appErr return } c.App.SanitizeTeams(*c.AppContext.Session(), teams) - js, jsonErr := json.Marshal(teams) - if jsonErr != nil { - c.Err = model.NewAppError("getTeamsForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(teams) + if err != nil { + c.Err = model.NewAppError("getTeamsForUser", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } + w.Write(js) } @@ -516,15 +517,15 @@ func getTeamsUnreadForUser(c *Context, w http.ResponseWriter, r *http.Request) { teamId := r.URL.Query().Get("exclude_team") includeCollapsedThreads := r.URL.Query().Get("include_collapsed_threads") == "true" - unreadTeamsList, err := c.App.GetTeamsUnreadForUser(teamId, c.Params.UserId, includeCollapsedThreads) - if err != nil { - c.Err = err + unreadTeamsList, appErr := c.App.GetTeamsUnreadForUser(teamId, c.Params.UserId, includeCollapsedThreads) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(unreadTeamsList) - if jsonErr != nil { - c.Err = model.NewAppError("getTeamsUnreadForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(unreadTeamsList) + if err != nil { + c.Err = model.NewAppError("getTeamsUnreadForUser", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } w.Write(js) @@ -541,9 +542,9 @@ func getTeamMember(c *Context, w http.ResponseWriter, r *http.Request) { return } - canSee, err := c.App.UserCanSeeOtherUser(c.AppContext.Session().UserId, c.Params.UserId) - if err != nil { - c.Err = err + canSee, appErr := c.App.UserCanSeeOtherUser(c.AppContext.Session().UserId, c.Params.UserId) + if appErr != nil { + c.Err = appErr return } @@ -552,9 +553,9 @@ func getTeamMember(c *Context, w http.ResponseWriter, r *http.Request) { return } - team, err := c.App.GetTeamMember(c.Params.TeamId, c.Params.UserId) - if err != nil { - c.Err = err + team, appErr := c.App.GetTeamMember(c.Params.TeamId, c.Params.UserId) + if appErr != nil { + c.Err = appErr return } @@ -578,9 +579,9 @@ func getTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) { return } - restrictions, err := c.App.GetViewUsersRestrictions(c.AppContext.Session().UserId) - if err != nil { - c.Err = err + restrictions, appErr := c.App.GetViewUsersRestrictions(c.AppContext.Session().UserId) + if appErr != nil { + c.Err = appErr return } @@ -590,17 +591,18 @@ func getTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) { ViewRestrictions: restrictions, } - members, err := c.App.GetTeamMembers(c.Params.TeamId, c.Params.Page*c.Params.PerPage, c.Params.PerPage, teamMembersGetOptions) - if err != nil { - c.Err = err + members, appErr := c.App.GetTeamMembers(c.Params.TeamId, c.Params.Page*c.Params.PerPage, c.Params.PerPage, teamMembersGetOptions) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(members) - if jsonErr != nil { - c.Err = model.NewAppError("getTeamMembers", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(members) + if err != nil { + c.Err = model.NewAppError("getTeamMembers", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } + w.Write(js) } @@ -615,9 +617,9 @@ func getTeamMembersForUser(c *Context, w http.ResponseWriter, r *http.Request) { return } - canSee, err := c.App.UserCanSeeOtherUser(c.AppContext.Session().UserId, c.Params.UserId) - if err != nil { - c.Err = err + canSee, appErr := c.App.UserCanSeeOtherUser(c.AppContext.Session().UserId, c.Params.UserId) + if appErr != nil { + c.Err = appErr return } @@ -626,17 +628,18 @@ func getTeamMembersForUser(c *Context, w http.ResponseWriter, r *http.Request) { return } - members, err := c.App.GetTeamMembersForUser(c.Params.UserId, "", true) - if err != nil { - c.Err = err + members, appErr := c.App.GetTeamMembersForUser(c.Params.UserId, "", true) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(members) - if jsonErr != nil { - c.Err = model.NewAppError("getTeamMembersForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(members) + if err != nil { + c.Err = model.NewAppError("getTeamMembersForUser", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } + w.Write(js) } @@ -646,10 +649,10 @@ func getTeamMembersByIds(c *Context, w http.ResponseWriter, r *http.Request) { return } - userIds := model.ArrayFromJSON(r.Body) - - if len(userIds) == 0 { - c.SetInvalidParam("user_ids") + var userIDs []string + err := json.NewDecoder(r.Body).Decode(&userIDs) + if err != nil || len(userIDs) == 0 { + c.SetInvalidParamWithErr("user_ids", err) return } @@ -658,23 +661,24 @@ func getTeamMembersByIds(c *Context, w http.ResponseWriter, r *http.Request) { return } - restrictions, err := c.App.GetViewUsersRestrictions(c.AppContext.Session().UserId) - if err != nil { - c.Err = err + restrictions, appErr := c.App.GetViewUsersRestrictions(c.AppContext.Session().UserId) + if appErr != nil { + c.Err = appErr return } - members, err := c.App.GetTeamMembersByIds(c.Params.TeamId, userIds, restrictions) - if err != nil { - c.Err = err + members, appErr := c.App.GetTeamMembersByIds(c.Params.TeamId, userIDs, restrictions) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(members) - if jsonErr != nil { - c.Err = model.NewAppError("getTeamMembersByIds", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(members) + if err != nil { + c.Err = model.NewAppError("getTeamMembersByIds", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } + w.Write(js) } @@ -815,7 +819,7 @@ func addTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) { return } - var err *model.AppError + var appErr *model.AppError var members []*model.TeamMember if jsonErr := json.NewDecoder(r.Body).Decode(&members); jsonErr != nil { c.SetInvalidParamWithErr("members", jsonErr) @@ -843,9 +847,9 @@ func addTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec.AddMeta("user_ids", memberIDs) - team, err := c.App.GetTeam(c.Params.TeamId) - if err != nil { - c.Err = err + team, appErr := c.App.GetTeam(c.Params.TeamId) + if appErr != nil { + c.Err = appErr return } auditRec.AddMeta("team", team) @@ -856,7 +860,7 @@ func addTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) { if v, ok := err.(*model.AppError); ok { c.Err = v } else { - c.Err = model.NewAppError("addTeamMembers", "api.team.add_members.error", nil, err.Error(), http.StatusBadRequest) + c.Err = model.NewAppError("addTeamMembers", "api.team.add_members.error", nil, "", http.StatusBadRequest).Wrap(err) } return } @@ -866,7 +870,7 @@ func addTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) { } } - var userIds []string + var userIDs []string for _, member := range members { if member.TeamId != c.Params.TeamId { c.SetInvalidParam("team_id for member with user_id=" + member.UserId) @@ -878,7 +882,7 @@ func addTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) { return } - userIds = append(userIds, member.UserId) + userIDs = append(userIDs, member.UserId) } if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PermissionAddUserToTeam) { @@ -886,9 +890,9 @@ func addTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) { return } - membersWithErrors, err := c.App.AddTeamMembers(c.AppContext, c.Params.TeamId, userIds, c.AppContext.Session().UserId, graceful) + membersWithErrors, appErr := c.App.AddTeamMembers(c.AppContext, c.Params.TeamId, userIDs, c.AppContext.Session().UserId, graceful) - if membersWithErrors != nil { + if len(membersWithErrors) != 0 { errList := make([]string, 0, len(membersWithErrors)) for _, m := range membersWithErrors { if m.Error != nil { @@ -897,21 +901,23 @@ func addTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec.AddMeta("errors", errList) } - if err != nil { - c.Err = err + if appErr != nil { + c.Err = appErr return } - var js []byte - var jsonErr error + var ( + js []byte + err error + ) if graceful { // in 'graceful' mode we allow a different return value, notifying the client which users were not added - js, jsonErr = json.Marshal(membersWithErrors) + js, err = json.Marshal(membersWithErrors) } else { - js, jsonErr = json.Marshal(model.TeamMembersWithErrorToTeamMembers(membersWithErrors)) + js, err = json.Marshal(model.TeamMembersWithErrorToTeamMembers(membersWithErrors)) } - if jsonErr != nil { - c.Err = model.NewAppError("addTeamMembers", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err != nil { + c.Err = model.NewAppError("addTeamMembers", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -1095,7 +1101,7 @@ func updateTeamMemberSchemeRoles(c *Context, w http.ResponseWriter, r *http.Requ func getAllTeams(c *Context, w http.ResponseWriter, r *http.Request) { teams := []*model.Team{} - var err *model.AppError + var appErr *model.AppError var teamsWithCount *model.TeamsWithCount opts := &model.TeamSearch{} @@ -1126,26 +1132,28 @@ func getAllTeams(c *Context, w http.ResponseWriter, r *http.Request) { } if c.Params.IncludeTotalCount { - teamsWithCount, err = c.App.GetAllTeamsPageWithCount(offset, limit, opts) + teamsWithCount, appErr = c.App.GetAllTeamsPageWithCount(offset, limit, opts) } else { - teams, err = c.App.GetAllTeamsPage(offset, limit, opts) + teams, appErr = c.App.GetAllTeamsPage(offset, limit, opts) } - if err != nil { - c.Err = err + if appErr != nil { + c.Err = appErr return } - var js []byte - var jsonErr error + var ( + js []byte + err error + ) if c.Params.IncludeTotalCount { c.App.SanitizeTeams(*c.AppContext.Session(), teamsWithCount.Teams) - js, jsonErr = json.Marshal(teamsWithCount) + js, err = json.Marshal(teamsWithCount) } else { c.App.SanitizeTeams(*c.AppContext.Session(), teams) - js, jsonErr = json.Marshal(teams) + js, err = json.Marshal(teams) } - if jsonErr != nil { - c.Err = model.NewAppError("getAllTeams", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err != nil { + c.Err = model.NewAppError("getAllTeams", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -1154,8 +1162,8 @@ func getAllTeams(c *Context, w http.ResponseWriter, r *http.Request) { func searchTeams(c *Context, w http.ResponseWriter, r *http.Request) { var props model.TeamSearch - if jsonErr := json.NewDecoder(r.Body).Decode(&props); jsonErr != nil { - c.SetInvalidParamWithErr("team_search", jsonErr) + if err := json.NewDecoder(r.Body).Decode(&props); err != nil { + c.SetInvalidParamWithErr("team_search", err) return } // Only system managers may use the ExcludePolicyConstrained field @@ -1169,30 +1177,32 @@ func searchTeams(c *Context, w http.ResponseWriter, r *http.Request) { props.IncludePolicyID = model.NewBool(true) } - var teams []*model.Team - var totalCount int64 - var err *model.AppError + var ( + teams []*model.Team + totalCount int64 + appErr *model.AppError + ) if c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionListPrivateTeams) && c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionListPublicTeams) { - teams, totalCount, err = c.App.SearchAllTeams(&props) + teams, totalCount, appErr = c.App.SearchAllTeams(&props) } else if c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionListPrivateTeams) { if props.Page != nil || props.PerPage != nil { c.Err = model.NewAppError("searchTeams", "api.team.search_teams.pagination_not_implemented.private_team_search", nil, "", http.StatusNotImplemented) return } - teams, err = c.App.SearchPrivateTeams(&props) + teams, appErr = c.App.SearchPrivateTeams(&props) } else if c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionListPublicTeams) { if props.Page != nil || props.PerPage != nil { c.Err = model.NewAppError("searchTeams", "api.team.search_teams.pagination_not_implemented.public_team_search", nil, "", http.StatusNotImplemented) return } - teams, err = c.App.SearchPublicTeams(&props) + teams, appErr = c.App.SearchPublicTeams(&props) } else { teams = []*model.Team{} } - if err != nil { - c.Err = err + if appErr != nil { + c.Err = appErr return } @@ -1203,9 +1213,9 @@ func searchTeams(c *Context, w http.ResponseWriter, r *http.Request) { twc := map[string]any{"teams": teams, "total_count": totalCount} payload = model.ToJSON(twc) } else { - js, jsonErr := json.Marshal(teams) - if jsonErr != nil { - c.Err = model.NewAppError("searchTeams", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(teams) + if err != nil { + c.Err = model.NewAppError("searchTeams", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } payload = js @@ -1357,26 +1367,26 @@ func inviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) { bf, err := io.ReadAll(r.Body) if err != nil { - c.Err = model.NewAppError("Api4.inviteUsersToTeams", "api.team.invite_members_to_team_and_channels.invalid_body.app_error", nil, err.Error(), http.StatusBadRequest) + c.Err = model.NewAppError("Api4.inviteUsersToTeams", "api.team.invite_members_to_team_and_channels.invalid_body.app_error", nil, "", http.StatusBadRequest).Wrap(err) return } memberInvite := &model.MemberInvite{} - if jsonErr := json.Unmarshal(bf, memberInvite); jsonErr != nil { - c.Err = model.NewAppError("Api4.inviteUsersToTeams", "api.team.invite_members_to_team_and_channels.invalid_body_parsing.app_error", nil, jsonErr.Error(), http.StatusBadRequest) + if err := json.Unmarshal(bf, memberInvite); err != nil { + c.Err = model.NewAppError("Api4.inviteUsersToTeams", "api.team.invite_members_to_team_and_channels.invalid_body_parsing.app_error", nil, "", http.StatusBadRequest).Wrap(err) return } emailList := memberInvite.Emails - for i := range emailList { - emailList[i] = strings.ToLower(emailList[i]) - } - if len(emailList) == 0 { c.SetInvalidParam("user_email") return } + for i := range emailList { + emailList[i] = strings.ToLower(emailList[i]) + } + auditRec := c.MakeAuditRecord("inviteUsersToTeam", audit.Fail) defer c.LogAuditRec(auditRec) auditRec.AddEventParameter("member_invite", memberInvite) @@ -1391,9 +1401,9 @@ func inviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) { if graceful { var invitesWithError []*model.EmailInviteWithError - var err *model.AppError + var appErr *model.AppError if emailList != nil { - invitesWithError, err = c.App.InviteNewUsersToTeamGracefully(memberInvite, c.Params.TeamId, c.AppContext.Session().UserId, "") + invitesWithError, appErr = c.App.InviteNewUsersToTeamGracefully(memberInvite, c.Params.TeamId, c.AppContext.Session().UserId, "") } if invitesWithError != nil { @@ -1405,8 +1415,8 @@ func inviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec.AddMeta("errors", errList) } - if err != nil { - c.Err = err + if appErr != nil { + c.Err = appErr return } @@ -1424,23 +1434,24 @@ func inviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) { } // we then manually schedule the job to send another invite after 48 hours - _, e := c.App.Srv().Jobs.CreateJob(model.JobTypeResendInvitationEmail, jobData) - if e != nil { - c.Err = model.NewAppError("Api4.inviteUsersToTeam", e.Id, nil, e.Error(), e.StatusCode) + _, appErr = c.App.Srv().Jobs.CreateJob(model.JobTypeResendInvitationEmail, jobData) + if appErr != nil { + c.Err = model.NewAppError("Api4.inviteUsersToTeam", appErr.Id, nil, appErr.Error(), appErr.StatusCode) return } // in graceful mode we return both the successful ones and the failed ones - js, jsonErr := json.Marshal(invitesWithError) - if jsonErr != nil { - c.Err = model.NewAppError("inviteUsersToTeam", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(invitesWithError) + if err != nil { + c.Err = model.NewAppError("inviteUsersToTeam", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } + w.Write(js) } else { - err := c.App.InviteNewUsersToTeam(emailList, c.Params.TeamId, c.AppContext.Session().UserId) - if err != nil { - c.Err = err + appErr := c.App.InviteNewUsersToTeam(emailList, c.Params.TeamId, c.AppContext.Session().UserId) + if appErr != nil { + c.Err = appErr return } ReturnStatusOK(w) @@ -1475,8 +1486,8 @@ func inviteGuestsToChannels(c *Context, w http.ResponseWriter, r *http.Request) } var guestsInvite model.GuestsInvite - if jsonErr := json.NewDecoder(r.Body).Decode(&guestsInvite); jsonErr != nil { - c.Err = model.NewAppError("Api4.inviteGuestsToChannels", "api.team.invite_guests_to_channels.invalid_body.app_error", nil, "", http.StatusBadRequest).Wrap(jsonErr) + if err := json.NewDecoder(r.Body).Decode(&guestsInvite); err != nil { + c.Err = model.NewAppError("Api4.inviteGuestsToChannels", "api.team.invite_guests_to_channels.invalid_body.app_error", nil, "", http.StatusBadRequest).Wrap(err) return } auditRec.AddEventParameter("guests_invite", guestsInvite) @@ -1484,8 +1495,8 @@ func inviteGuestsToChannels(c *Context, w http.ResponseWriter, r *http.Request) for i, email := range guestsInvite.Emails { guestsInvite.Emails[i] = strings.ToLower(email) } - if err := guestsInvite.IsValid(); err != nil { - c.Err = err + if appErr := guestsInvite.IsValid(); appErr != nil { + c.Err = appErr return } auditRec.AddMeta("email_count", len(guestsInvite.Emails)) @@ -1495,32 +1506,33 @@ func inviteGuestsToChannels(c *Context, w http.ResponseWriter, r *http.Request) if graceful { var invitesWithError []*model.EmailInviteWithError - var err *model.AppError + var appErr *model.AppError if guestsInvite.Emails != nil { - invitesWithError, err = c.App.InviteGuestsToChannelsGracefully(c.Params.TeamId, &guestsInvite, c.AppContext.Session().UserId) + invitesWithError, appErr = c.App.InviteGuestsToChannelsGracefully(c.Params.TeamId, &guestsInvite, c.AppContext.Session().UserId) } - if err != nil { + if appErr != nil { errList := make([]string, 0, len(invitesWithError)) for _, inv := range invitesWithError { errList = append(errList, model.EmailInviteWithErrorToString(inv)) } auditRec.AddMeta("errors", errList) - c.Err = err + c.Err = appErr return } // in graceful mode we return both the successful ones and the failed ones - js, jsonErr := json.Marshal(invitesWithError) - if jsonErr != nil { - c.Err = model.NewAppError("inviteGuestsToChannel", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(invitesWithError) + if err != nil { + c.Err = model.NewAppError("inviteGuestsToChannel", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } + w.Write(js) } else { - err := c.App.InviteGuestsToChannels(c.Params.TeamId, &guestsInvite, c.AppContext.Session().UserId) - if err != nil { - c.Err = err + appErr := c.App.InviteGuestsToChannels(c.Params.TeamId, &guestsInvite, c.AppContext.Session().UserId) + if appErr != nil { + c.Err = appErr return } ReturnStatusOK(w) @@ -1534,9 +1546,9 @@ func getInviteInfo(c *Context, w http.ResponseWriter, r *http.Request) { return } - team, err := c.App.GetTeamByInviteId(c.Params.InviteId) - if err != nil { - c.Err = err + team, appErr := c.App.GetTeamByInviteId(c.Params.InviteId) + if appErr != nil { + c.Err = appErr return } @@ -1545,12 +1557,22 @@ func getInviteInfo(c *Context, w http.ResponseWriter, r *http.Request) { return } - result := map[string]string{} - result["display_name"] = team.DisplayName - result["description"] = team.Description - result["name"] = team.Name - result["id"] = team.Id - w.Write([]byte(model.MapToJSON(result))) + result := struct { + DisplayName string `json:"display_name"` + Description string `json:"description"` + Name string `json:"name"` + ID string `json:"id"` + }{ + DisplayName: team.DisplayName, + Description: team.Description, + Name: team.Name, + ID: team.Id, + } + + err := json.NewEncoder(w).Encode(result) + if err != nil { + c.Logger.Warn("Error writing response", mlog.Err(err)) + } } func invalidateAllEmailInvites(c *Context, w http.ResponseWriter, r *http.Request) { @@ -1781,23 +1803,23 @@ func teamMembersMinusGroupMembers(c *Context, w http.ResponseWriter, r *http.Req return } - users, totalCount, err := c.App.TeamMembersMinusGroupMembers( + users, totalCount, appErr := c.App.TeamMembersMinusGroupMembers( c.Params.TeamId, groupIDs, c.Params.Page, c.Params.PerPage, ) - if err != nil { - c.Err = err + if appErr != nil { + c.Err = appErr return } - b, marshalErr := json.Marshal(&model.UsersWithGroupsAndCount{ + b, err := json.Marshal(&model.UsersWithGroupsAndCount{ Users: users, Count: totalCount, }) - if marshalErr != nil { - c.Err = model.NewAppError("Api4.teamMembersMinusGroupMembers", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + if err != nil { + c.Err = model.NewAppError("Api4.teamMembersMinusGroupMembers", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } diff --git a/api4/team_local.go b/api4/team_local.go index 29a93c6c0e..66b5bc96b9 100644 --- a/api4/team_local.go +++ b/api4/team_local.go @@ -81,12 +81,13 @@ func localInviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) bf, err := io.ReadAll(r.Body) if err != nil { - c.Err = model.NewAppError("Api4.inviteUsersToTeams", "api.team.invite_members_to_team_and_channels.invalid_body.app_error", nil, err.Error(), http.StatusBadRequest) + c.Err = model.NewAppError("Api4.inviteUsersToTeams", "api.team.invite_members_to_team_and_channels.invalid_body.app_error", nil, "", http.StatusBadRequest).Wrap(err) return } memberInvite := &model.MemberInvite{} - if jsonErr := json.Unmarshal(bf, memberInvite); jsonErr != nil { - c.Err = model.NewAppError("Api4.inviteUsersToTeams", "api.team.invite_members_to_team_and_channels.invalid_body_parsing.app_error", nil, jsonErr.Error(), http.StatusBadRequest) + err = json.Unmarshal(bf, memberInvite) + if err != nil { + c.Err = model.NewAppError("Api4.inviteUsersToTeams", "api.team.invite_members_to_team_and_channels.invalid_body_parsing.app_error", nil, "", http.StatusBadRequest).Wrap(err) return } @@ -117,14 +118,14 @@ func localInviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) auditRec.AddMeta("channels", memberInvite.ChannelIds) } - team, nErr := c.App.Srv().Store.Team().Get(c.Params.TeamId) - if nErr != nil { + team, err := c.App.Srv().Store.Team().Get(c.Params.TeamId) + if err != nil { var nfErr *store.ErrNotFound switch { - case errors.As(nErr, &nfErr): - c.Err = model.NewAppError("localInviteUsersToTeam", "app.team.get.find.app_error", nil, nfErr.Error(), http.StatusNotFound) + case errors.As(err, &nfErr): + c.Err = model.NewAppError("localInviteUsersToTeam", "app.team.get.find.app_error", nil, "", http.StatusNotFound).Wrap(err) default: - c.Err = model.NewAppError("localInviteUsersToTeam", "app.team.get.finding.app_error", nil, nErr.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("localInviteUsersToTeam", "app.team.get.finding.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } return } @@ -135,7 +136,7 @@ func localInviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) if len(memberInvite.ChannelIds) > 0 { channels, err = c.App.Srv().Store.Channel().GetChannelsByIds(memberInvite.ChannelIds, false) if err != nil { - c.Err = model.NewAppError("prepareLocalInviteNewUsersToTeam", "app.channel.get_channels_by_ids.app_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("prepareLocalInviteNewUsersToTeam", "app.channel.get_channels_by_ids.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } } @@ -157,33 +158,34 @@ func localInviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) } auditRec.AddMeta("errors", errList) if len(goodEmails) > 0 { - var eErr error var invitesWithErrors2 []*model.EmailInviteWithError if len(channels) > 0 { - invitesWithErrors2, eErr = c.App.Srv().EmailService.SendInviteEmailsToTeamAndChannels(team, channels, "Administrator", "mmctl "+model.NewId(), nil, goodEmails, *c.App.Config().ServiceSettings.SiteURL, nil, memberInvite.Message, true) + invitesWithErrors2, err = c.App.Srv().EmailService.SendInviteEmailsToTeamAndChannels(team, channels, "Administrator", "mmctl "+model.NewId(), nil, goodEmails, *c.App.Config().ServiceSettings.SiteURL, nil, memberInvite.Message, true) invitesWithErrors = append(invitesWithErrors, invitesWithErrors2...) } else { - eErr = c.App.Srv().EmailService.SendInviteEmails(team, "Administrator", "mmctl "+model.NewId(), goodEmails, *c.App.Config().ServiceSettings.SiteURL, nil, false) + err = c.App.Srv().EmailService.SendInviteEmails(team, "Administrator", "mmctl "+model.NewId(), goodEmails, *c.App.Config().ServiceSettings.SiteURL, nil, false) } - if eErr != nil { + if err != nil { switch { case errors.Is(err, email.NoRateLimiterError): - c.Err = model.NewAppError("SendInviteEmails", "app.email.no_rate_limiter.app_error", nil, fmt.Sprintf("team_id=%s", team.Id), http.StatusInternalServerError) + c.Err = model.NewAppError("SendInviteEmails", "app.email.no_rate_limiter.app_error", nil, fmt.Sprintf("team_id=%s", team.Id), http.StatusInternalServerError).Wrap(err) case errors.Is(err, email.SetupRateLimiterError): - c.Err = model.NewAppError("SendInviteEmails", "app.email.setup_rate_limiter.app_error", nil, fmt.Sprintf("team_id=%s, error=%v", team.Id, err), http.StatusInternalServerError) + c.Err = model.NewAppError("SendInviteEmails", "app.email.setup_rate_limiter.app_error", nil, fmt.Sprintf("team_id=%s, error=%v", team.Id, err), http.StatusInternalServerError).Wrap(err) default: - c.Err = model.NewAppError("SendInviteEmails", "app.email.rate_limit_exceeded.app_error", nil, fmt.Sprintf("team_id=%s, error=%v", team.Id, err), http.StatusRequestEntityTooLarge) + c.Err = model.NewAppError("SendInviteEmails", "app.email.rate_limit_exceeded.app_error", nil, fmt.Sprintf("team_id=%s, error=%v", team.Id, err), http.StatusRequestEntityTooLarge).Wrap(err) } return } } + // in graceful mode we return both the successful ones and the failed ones - js, jsonErr := json.Marshal(invitesWithErrors) - if jsonErr != nil { - c.Err = model.NewAppError("localInviteUsersToTeam", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(invitesWithErrors) + if err != nil { + c.Err = model.NewAppError("localInviteUsersToTeam", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } + w.Write(js) } else { var invalidEmailList []string @@ -202,11 +204,11 @@ func localInviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) if err != nil { switch { case errors.Is(err, email.NoRateLimiterError): - c.Err = model.NewAppError("SendInviteEmails", "app.email.no_rate_limiter.app_error", nil, fmt.Sprintf("team_id=%s", team.Id), http.StatusInternalServerError) + c.Err = model.NewAppError("SendInviteEmails", "app.email.no_rate_limiter.app_error", nil, fmt.Sprintf("team_id=%s", team.Id), http.StatusInternalServerError).Wrap(err) case errors.Is(err, email.SetupRateLimiterError): - c.Err = model.NewAppError("SendInviteEmails", "app.email.setup_rate_limiter.app_error", nil, fmt.Sprintf("team_id=%s, error=%v", team.Id, err), http.StatusInternalServerError) + c.Err = model.NewAppError("SendInviteEmails", "app.email.setup_rate_limiter.app_error", nil, fmt.Sprintf("team_id=%s, error=%v", team.Id, err), http.StatusInternalServerError).Wrap(err) default: - c.Err = model.NewAppError("SendInviteEmails", "app.email.rate_limit_exceeded.app_error", nil, fmt.Sprintf("team_id=%s, error=%v", team.Id, err), http.StatusRequestEntityTooLarge) + c.Err = model.NewAppError("SendInviteEmails", "app.email.rate_limit_exceeded.app_error", nil, fmt.Sprintf("team_id=%s, error=%v", team.Id, err), http.StatusRequestEntityTooLarge).Wrap(err) } return } diff --git a/api4/usage.go b/api4/usage.go index 10581291c0..3822972ba4 100644 --- a/api4/usage.go +++ b/api4/usage.go @@ -25,13 +25,13 @@ func (api *API) InitUsage() { func getPostsUsage(c *Context, w http.ResponseWriter, r *http.Request) { count, appErr := c.App.GetPostsUsage() if appErr != nil { - c.Err = model.NewAppError("Api4.getPostsUsage", "app.post.analytics_posts_count.app_error", nil, appErr.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.getPostsUsage", "app.post.analytics_posts_count.app_error", nil, "", http.StatusInternalServerError).Wrap(appErr) return } json, err := json.Marshal(&model.PostsUsage{Count: count}) if err != nil { - c.Err = model.NewAppError("Api4.getPostsUsage", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.getPostsUsage", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -41,14 +41,14 @@ func getPostsUsage(c *Context, w http.ResponseWriter, r *http.Request) { func getStorageUsage(c *Context, w http.ResponseWriter, r *http.Request) { usage, appErr := c.App.GetStorageUsage() if appErr != nil { - c.Err = model.NewAppError("Api4.getStorageUsage", "app.usage.get_storage_usage.app_error", nil, appErr.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.getStorageUsage", "app.usage.get_storage_usage.app_error", nil, "", http.StatusInternalServerError).Wrap(appErr) return } usage = utils.RoundOffToZeroesResolution(float64(usage), 8) json, err := json.Marshal(&model.StorageUsage{Bytes: usage}) if err != nil { - c.Err = model.NewAppError("Api4.getStorageUsage", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.getStorageUsage", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -58,17 +58,17 @@ func getStorageUsage(c *Context, w http.ResponseWriter, r *http.Request) { func getTeamsUsage(c *Context, w http.ResponseWriter, r *http.Request) { teamsUsage, appErr := c.App.GetTeamsUsage() if appErr != nil { - c.Err = model.NewAppError("Api4.getTeamsUsage", "app.teams.analytics_teams_count.app_error", nil, appErr.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.getTeamsUsage", "app.teams.analytics_teams_count.app_error", nil, "", http.StatusInternalServerError).Wrap(appErr) return } if teamsUsage == nil { - c.Err = model.NewAppError("Api4.getTeamsUsage", "app.teams.analytics_teams_count.app_error", nil, appErr.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.getTeamsUsage", "app.teams.analytics_teams_count.app_error", nil, "", http.StatusInternalServerError).Wrap(appErr) } json, err := json.Marshal(teamsUsage) if err != nil { - c.Err = model.NewAppError("Api4.getTeamsUsage", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.getTeamsUsage", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -79,7 +79,7 @@ func getIntegrationsUsage(c *Context, w http.ResponseWriter, r *http.Request) { if !*c.App.Config().PluginSettings.Enable { json, err := json.Marshal(&model.IntegrationsUsage{}) if err != nil { - c.Err = model.NewAppError("Api4.getIntegrationsUsage", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.getIntegrationsUsage", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -95,7 +95,7 @@ func getIntegrationsUsage(c *Context, w http.ResponseWriter, r *http.Request) { json, err := json.Marshal(usage) if err != nil { - c.Err = model.NewAppError("Api4.getIntegrationsUsage", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("Api4.getIntegrationsUsage", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } diff --git a/api4/user.go b/api4/user.go index c1d682e560..8dd75f03ee 100644 --- a/api4/user.go +++ b/api4/user.go @@ -622,32 +622,37 @@ func getUsersByGroupChannelIds(c *Context, w http.ResponseWriter, r *http.Reques return } - usersByChannelId, err := c.App.GetUsersByGroupChannelIds(c.AppContext, channelIds, c.IsSystemAdmin()) - if err != nil { - c.Err = err + usersByChannelId, appErr := c.App.GetUsersByGroupChannelIds(c.AppContext, channelIds, c.IsSystemAdmin()) + if appErr != nil { + c.Err = appErr return } - b, _ := json.Marshal(usersByChannelId) - w.Write(b) + err := json.NewEncoder(w).Encode(usersByChannelId) + if err != nil { + c.Logger.Warn("Error writing response", mlog.Err(err)) + } } func getUsers(c *Context, w http.ResponseWriter, r *http.Request) { - inTeamId := r.URL.Query().Get("in_team") - notInTeamId := r.URL.Query().Get("not_in_team") - inChannelId := r.URL.Query().Get("in_channel") - inGroupId := r.URL.Query().Get("in_group") - notInGroupId := r.URL.Query().Get("not_in_group") - notInChannelId := r.URL.Query().Get("not_in_channel") - groupConstrained := r.URL.Query().Get("group_constrained") - withoutTeam := r.URL.Query().Get("without_team") - inactive := r.URL.Query().Get("inactive") - active := r.URL.Query().Get("active") - role := r.URL.Query().Get("role") - sort := r.URL.Query().Get("sort") - rolesString := r.URL.Query().Get("roles") - channelRolesString := r.URL.Query().Get("channel_roles") - teamRolesString := r.URL.Query().Get("team_roles") + var ( + query = r.URL.Query() + inTeamId = query.Get("in_team") + notInTeamId = query.Get("not_in_team") + inChannelId = query.Get("in_channel") + inGroupId = query.Get("in_group") + notInGroupId = query.Get("not_in_group") + notInChannelId = query.Get("not_in_channel") + groupConstrained = query.Get("group_constrained") + withoutTeam = query.Get("without_team") + inactive = query.Get("inactive") + active = query.Get("active") + role = query.Get("role") + sort = query.Get("sort") + rolesString = query.Get("roles") + channelRolesString = query.Get("channel_roles") + teamRolesString = query.Get("team_roles") + ) if notInChannelId != "" && inTeamId == "" { c.SetInvalidURLParam("team_id") @@ -674,10 +679,12 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) { return } - withoutTeamBool, _ := strconv.ParseBool(withoutTeam) - groupConstrainedBool, _ := strconv.ParseBool(groupConstrained) - inactiveBool, _ := strconv.ParseBool(inactive) - activeBool, _ := strconv.ParseBool(active) + var ( + withoutTeamBool, _ = strconv.ParseBool(withoutTeam) + groupConstrainedBool, _ = strconv.ParseBool(groupConstrained) + inactiveBool, _ = strconv.ParseBool(inactive) + activeBool, _ = strconv.ParseBool(active) + ) if inactiveBool && activeBool { c.SetInvalidURLParam("inactive") @@ -709,9 +716,9 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) { } } - restrictions, err := c.App.GetViewUsersRestrictions(c.AppContext.Session().UserId) - if err != nil { - c.Err = err + restrictions, appErr := c.App.GetViewUsersRestrictions(c.AppContext.Session().UserId) + if appErr != nil { + c.Err = appErr return } @@ -736,14 +743,16 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) { ViewRestrictions: restrictions, } - var profiles []*model.User - etag := "" + var ( + profiles []*model.User + etag string + ) if inChannelId != "" { if !*c.App.Config().TeamSettings.ExperimentalViewArchivedChannels { - channel, appErr := c.App.GetChannel(c.AppContext, inChannelId) - if appErr != nil { - c.Err = appErr + channel, cErr := c.App.GetChannel(c.AppContext, inChannelId) + if cErr != nil { + c.Err = cErr return } if channel.DeleteAt != 0 { @@ -760,14 +769,14 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) { return } - profiles, err = c.App.GetUsersWithoutTeamPage(userGetOptions, c.IsSystemAdmin()) + profiles, appErr = c.App.GetUsersWithoutTeamPage(userGetOptions, c.IsSystemAdmin()) } else if notInChannelId != "" { if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), notInChannelId, model.PermissionReadChannel) { c.SetPermissionError(model.PermissionReadChannel) return } - profiles, err = c.App.GetUsersNotInChannelPage(inTeamId, notInChannelId, groupConstrainedBool, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), restrictions) + profiles, appErr = c.App.GetUsersNotInChannelPage(inTeamId, notInChannelId, groupConstrainedBool, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), restrictions) } else if notInTeamId != "" { if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), notInTeamId, model.PermissionViewTeam) { c.SetPermissionError(model.PermissionViewTeam) @@ -779,7 +788,7 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) { return } - profiles, err = c.App.GetUsersNotInTeamPage(notInTeamId, groupConstrainedBool, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), restrictions) + profiles, appErr = c.App.GetUsersNotInTeamPage(notInTeamId, groupConstrainedBool, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), restrictions) } else if inTeamId != "" { if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), inTeamId, model.PermissionViewTeam) { c.SetPermissionError(model.PermissionViewTeam) @@ -787,15 +796,15 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) { } if sort == "last_activity_at" { - profiles, err = c.App.GetRecentlyActiveUsersForTeamPage(inTeamId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), restrictions) + profiles, appErr = c.App.GetRecentlyActiveUsersForTeamPage(inTeamId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), restrictions) } else if sort == "create_at" { - profiles, err = c.App.GetNewUsersForTeamPage(inTeamId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), restrictions) + profiles, appErr = c.App.GetNewUsersForTeamPage(inTeamId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), restrictions) } else { etag = c.App.GetUsersInTeamEtag(inTeamId, restrictions.Hash()) if c.HandleEtag(etag, "Get Users in Team", w, r) { return } - profiles, err = c.App.GetUsersInTeamPage(userGetOptions, c.IsSystemAdmin()) + profiles, appErr = c.App.GetUsersInTeamPage(userGetOptions, c.IsSystemAdmin()) } } else if inChannelId != "" { if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), inChannelId, model.PermissionReadChannel) { @@ -804,11 +813,11 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) { } if sort == "status" { - profiles, err = c.App.GetUsersInChannelPageByStatus(userGetOptions, c.IsSystemAdmin()) + profiles, appErr = c.App.GetUsersInChannelPageByStatus(userGetOptions, c.IsSystemAdmin()) } else if sort == "admin" { - profiles, err = c.App.GetUsersInChannelPageByAdmin(userGetOptions, c.IsSystemAdmin()) + profiles, appErr = c.App.GetUsersInChannelPageByAdmin(userGetOptions, c.IsSystemAdmin()) } else { - profiles, err = c.App.GetUsersInChannelPage(userGetOptions, c.IsSystemAdmin()) + profiles, appErr = c.App.GetUsersInChannelPage(userGetOptions, c.IsSystemAdmin()) } } else if inGroupId != "" { if gErr := requireGroupAccess(c, inGroupId); gErr != nil { @@ -817,34 +826,35 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) { return } - profiles, _, err = c.App.GetGroupMemberUsersPage(inGroupId, c.Params.Page, c.Params.PerPage) - if err != nil { - c.Err = err + profiles, _, appErr = c.App.GetGroupMemberUsersPage(inGroupId, c.Params.Page, c.Params.PerPage) + if appErr != nil { + c.Err = appErr return } } else if notInGroupId != "" { - if gErr := requireGroupAccess(c, notInGroupId); gErr != nil { - gErr.Where = "Api.getUsers" - c.Err = gErr + appErr = requireGroupAccess(c, notInGroupId) + if appErr != nil { + appErr.Where = "Api.getUsers" + c.Err = appErr return } - profiles, err = c.App.GetUsersNotInGroupPage(notInGroupId, c.Params.Page, c.Params.PerPage) - if err != nil { - c.Err = err + profiles, appErr = c.App.GetUsersNotInGroupPage(notInGroupId, c.Params.Page, c.Params.PerPage) + if appErr != nil { + c.Err = appErr return } } else { - userGetOptions, err = c.App.RestrictUsersGetByPermissions(c.AppContext.Session().UserId, userGetOptions) - if err != nil { - c.Err = err + userGetOptions, appErr = c.App.RestrictUsersGetByPermissions(c.AppContext.Session().UserId, userGetOptions) + if appErr != nil { + c.Err = appErr return } - profiles, err = c.App.GetUsersPage(userGetOptions, c.IsSystemAdmin()) + profiles, appErr = c.App.GetUsersPage(userGetOptions, c.IsSystemAdmin()) } - if err != nil { - c.Err = err + if appErr != nil { + c.Err = appErr return } @@ -853,9 +863,9 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) { } c.App.UpdateLastActivityAtIfNeeded(*c.AppContext.Session()) - js, jsonErr := json.Marshal(profiles) - if jsonErr != nil { - c.Err = model.NewAppError("getUsers", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(profiles) + if err != nil { + c.Err = model.NewAppError("getUsers", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -882,10 +892,10 @@ func requireGroupAccess(c *web.Context, groupID string) *model.AppError { } func getUsersByIds(c *Context, w http.ResponseWriter, r *http.Request) { - userIds := model.ArrayFromJSON(r.Body) - - if len(userIds) == 0 { - c.SetInvalidParam("user_ids") + var userIDs []string + err := json.NewDecoder(r.Body).Decode(&userIDs) + if err != nil || len(userIDs) == 0 { + c.SetInvalidParamWithErr("user_ids", err) return } @@ -896,30 +906,30 @@ func getUsersByIds(c *Context, w http.ResponseWriter, r *http.Request) { } if sinceString != "" { - since, parseError := strconv.ParseInt(sinceString, 10, 64) - if parseError != nil { - c.SetInvalidParam("since") + since, sErr := strconv.ParseInt(sinceString, 10, 64) + if sErr != nil { + c.SetInvalidParamWithErr("since", sErr) return } options.Since = since } - restrictions, err := c.App.GetViewUsersRestrictions(c.AppContext.Session().UserId) - if err != nil { - c.Err = err + restrictions, appErr := c.App.GetViewUsersRestrictions(c.AppContext.Session().UserId) + if appErr != nil { + c.Err = appErr return } options.ViewRestrictions = restrictions - users, err := c.App.GetUsersByIds(userIds, options) - if err != nil { - c.Err = err + users, appErr := c.App.GetUsersByIds(userIDs, options) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(users) - if jsonErr != nil { - c.Err = model.NewAppError("getUsersByIds", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(users) + if err != nil { + c.Err = model.NewAppError("getUsersByIds", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -927,28 +937,28 @@ func getUsersByIds(c *Context, w http.ResponseWriter, r *http.Request) { } func getUsersByNames(c *Context, w http.ResponseWriter, r *http.Request) { - usernames := model.ArrayFromJSON(r.Body) - - if len(usernames) == 0 { - c.SetInvalidParam("usernames") + var usernames []string + err := json.NewDecoder(r.Body).Decode(&usernames) + if err != nil || len(usernames) == 0 { + c.SetInvalidParamWithErr("usernames", err) return } - restrictions, err := c.App.GetViewUsersRestrictions(c.AppContext.Session().UserId) + restrictions, appErr := c.App.GetViewUsersRestrictions(c.AppContext.Session().UserId) + if appErr != nil { + c.Err = appErr + return + } + + users, appErr := c.App.GetUsersByUsernames(usernames, c.IsSystemAdmin(), restrictions) + if appErr != nil { + c.Err = appErr + return + } + + js, err := json.Marshal(users) if err != nil { - c.Err = err - return - } - - users, err := c.App.GetUsersByUsernames(usernames, c.IsSystemAdmin(), restrictions) - if err != nil { - c.Err = err - return - } - - js, jsonErr := json.Marshal(users) - if jsonErr != nil { - c.Err = model.NewAppError("getUsersByNames", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + c.Err = model.NewAppError("getUsersByNames", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -956,21 +966,22 @@ func getUsersByNames(c *Context, w http.ResponseWriter, r *http.Request) { } func getKnownUsers(c *Context, w http.ResponseWriter, r *http.Request) { - userIds, err := c.App.GetKnownUsers(c.AppContext.Session().UserId) - if err != nil { - c.Err = err + userIDs, appErr := c.App.GetKnownUsers(c.AppContext.Session().UserId) + if appErr != nil { + c.Err = appErr return } - data, _ := json.Marshal(userIds) - - w.Write(data) + err := json.NewEncoder(w).Encode(userIDs) + if err != nil { + c.Logger.Warn("Error writing response", mlog.Err(err)) + } } func searchUsers(c *Context, w http.ResponseWriter, r *http.Request) { var props model.UserSearch - if jsonErr := json.NewDecoder(r.Body).Decode(&props); jsonErr != nil { - c.SetInvalidParamWithErr("props", jsonErr) + if err := json.NewDecoder(r.Body).Decode(&props); err != nil { + c.SetInvalidParamWithErr("props", err) return } @@ -989,17 +1000,17 @@ func searchUsers(c *Context, w http.ResponseWriter, r *http.Request) { } if props.InGroupId != "" { - if gErr := requireGroupAccess(c, props.InGroupId); gErr != nil { - gErr.Where = "Api.searchUsers" - c.Err = gErr + if appErr := requireGroupAccess(c, props.InGroupId); appErr != nil { + appErr.Where = "Api.searchUsers" + c.Err = appErr return } } if props.NotInGroupId != "" { - if gErr := requireGroupAccess(c, props.NotInGroupId); gErr != nil { - gErr.Where = "Api.searchUsers" - c.Err = gErr + if appErr := requireGroupAccess(c, props.NotInGroupId); appErr != nil { + appErr.Where = "Api.searchUsers" + c.Err = appErr return } } @@ -1048,21 +1059,21 @@ func searchUsers(c *Context, w http.ResponseWriter, r *http.Request) { options.AllowFullNames = *c.App.Config().PrivacySettings.ShowFullName } - options, err := c.App.RestrictUsersSearchByPermissions(c.AppContext.Session().UserId, options) - if err != nil { - c.Err = err + options, appErr := c.App.RestrictUsersSearchByPermissions(c.AppContext.Session().UserId, options) + if appErr != nil { + c.Err = appErr return } - profiles, err := c.App.SearchUsers(&props, options) - if err != nil { - c.Err = err + profiles, appErr := c.App.SearchUsers(&props, options) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(profiles) - if jsonErr != nil { - c.Err = model.NewAppError("searchUsers", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(profiles) + if err != nil { + c.Err = model.NewAppError("searchUsers", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -1973,9 +1984,9 @@ func getSessions(c *Context, w http.ResponseWriter, r *http.Request) { return } - sessions, err := c.App.GetSessions(c.Params.UserId) - if err != nil { - c.Err = err + sessions, appErr := c.App.GetSessions(c.Params.UserId) + if appErr != nil { + c.Err = appErr return } @@ -1983,11 +1994,12 @@ func getSessions(c *Context, w http.ResponseWriter, r *http.Request) { session.Sanitize() } - js, jsonErr := json.Marshal(sessions) - if jsonErr != nil { - c.Err = model.NewAppError("getSessions", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(sessions) + if err != nil { + c.Err = model.NewAppError("getSessions", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } + w.Write(js) } @@ -2343,8 +2355,8 @@ func searchUserAccessTokens(c *Context, w http.ResponseWriter, r *http.Request) } var props model.UserAccessTokenSearch - if jsonErr := json.NewDecoder(r.Body).Decode(&props); jsonErr != nil { - c.SetInvalidParamWithErr("user_access_token_search", jsonErr) + if err := json.NewDecoder(r.Body).Decode(&props); err != nil { + c.SetInvalidParamWithErr("user_access_token_search", err) return } @@ -2353,15 +2365,15 @@ func searchUserAccessTokens(c *Context, w http.ResponseWriter, r *http.Request) return } - accessTokens, err := c.App.SearchUserAccessTokens(props.Term) - if err != nil { - c.Err = err + accessTokens, appErr := c.App.SearchUserAccessTokens(props.Term) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(accessTokens) - if jsonErr != nil { - c.Err = model.NewAppError("searchUserAccessTokens", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(accessTokens) + if err != nil { + c.Err = model.NewAppError("searchUserAccessTokens", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -2374,15 +2386,15 @@ func getUserAccessTokens(c *Context, w http.ResponseWriter, r *http.Request) { return } - accessTokens, err := c.App.GetUserAccessTokens(c.Params.Page, c.Params.PerPage) - if err != nil { - c.Err = err + accessTokens, appErr := c.App.GetUserAccessTokens(c.Params.Page, c.Params.PerPage) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(accessTokens) - if jsonErr != nil { - c.Err = model.NewAppError("searchUserAccessTokens", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(accessTokens) + if err != nil { + c.Err = model.NewAppError("searchUserAccessTokens", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -2405,15 +2417,15 @@ func getUserAccessTokensForUser(c *Context, w http.ResponseWriter, r *http.Reque return } - accessTokens, err := c.App.GetUserAccessTokensForUser(c.Params.UserId, c.Params.Page, c.Params.PerPage) - if err != nil { - c.Err = err + accessTokens, appErr := c.App.GetUserAccessTokensForUser(c.Params.UserId, c.Params.Page, c.Params.PerPage) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(accessTokens) - if jsonErr != nil { - c.Err = model.NewAppError("searchUserAccessTokens", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(accessTokens) + if err != nil { + c.Err = model.NewAppError("searchUserAccessTokens", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -2431,9 +2443,9 @@ func getUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { return } - accessToken, err := c.App.GetUserAccessToken(c.Params.TokenId, true) - if err != nil { - c.Err = err + accessToken, appErr := c.App.GetUserAccessToken(c.Params.TokenId, true) + if appErr != nil { + c.Err = appErr return } @@ -2791,9 +2803,9 @@ func convertUserToBot(c *Context, w http.ResponseWriter, r *http.Request) { return } - user, err := c.App.GetUser(c.Params.UserId) - if err != nil { - c.Err = err + user, appErr := c.App.GetUser(c.Params.UserId) + if appErr != nil { + c.Err = appErr return } @@ -2807,9 +2819,9 @@ func convertUserToBot(c *Context, w http.ResponseWriter, r *http.Request) { return } - bot, err := c.App.ConvertUserToBot(user) - if err != nil { - c.Err = err + bot, appErr := c.App.ConvertUserToBot(user) + if appErr != nil { + c.Err = appErr return } @@ -2817,9 +2829,9 @@ func convertUserToBot(c *Context, w http.ResponseWriter, r *http.Request) { auditRec.AddEventResultState(bot) auditRec.AddEventObjectType("bot") - js, jsonErr := json.Marshal(bot) - if jsonErr != nil { - c.Err = model.NewAppError("convertUserToBot", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(bot) + if err != nil { + c.Err = model.NewAppError("convertUserToBot", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -2839,15 +2851,15 @@ func getUploadsForUser(c *Context, w http.ResponseWriter, r *http.Request) { return } - uss, err := c.App.GetUploadSessionsForUser(c.Params.UserId) - if err != nil { - c.Err = err + uss, appErr := c.App.GetUploadSessionsForUser(c.Params.UserId) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(uss) - if jsonErr != nil { - c.Err = model.NewAppError("getUploadsForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(uss) + if err != nil { + c.Err = model.NewAppError("getUploadsForUser", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } w.Write(js) @@ -3252,14 +3264,16 @@ func getUsersWithInvalidEmails(c *Context, w http.ResponseWriter, r *http.Reques return } - users, err := c.App.GetUsersWithInvalidEmails(c.Params.Page, c.Params.PerPage) - if err != nil { - c.Err = err + users, appErr := c.App.GetUsersWithInvalidEmails(c.Params.Page, c.Params.PerPage) + if appErr != nil { + c.Err = appErr return } - b, _ := json.Marshal(users) - w.Write(b) + err := json.NewEncoder(w).Encode(users) + if err != nil { + c.Logger.Warn("Error writing response", mlog.Err(err)) + } } func getRecentSearches(c *Context, w http.ResponseWriter, r *http.Request) { diff --git a/api4/user_local.go b/api4/user_local.go index 1b9c4fdf33..50a451ea96 100644 --- a/api4/user_local.go +++ b/api4/user_local.go @@ -100,45 +100,47 @@ func localGetUsers(c *Context, w http.ResponseWriter, r *http.Request) { ViewRestrictions: nil, } - var err *model.AppError - var profiles []*model.User - etag := "" + var ( + appErr *model.AppError + profiles []*model.User + etag string + ) if withoutTeamBool, _ := strconv.ParseBool(withoutTeam); withoutTeamBool { - profiles, err = c.App.GetUsersWithoutTeamPage(userGetOptions, c.IsSystemAdmin()) + profiles, appErr = c.App.GetUsersWithoutTeamPage(userGetOptions, c.IsSystemAdmin()) } else if notInChannelId != "" { - profiles, err = c.App.GetUsersNotInChannelPage(inTeamId, notInChannelId, groupConstrainedBool, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), nil) + profiles, appErr = c.App.GetUsersNotInChannelPage(inTeamId, notInChannelId, groupConstrainedBool, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), nil) } else if notInTeamId != "" { etag = c.App.GetUsersNotInTeamEtag(inTeamId, "") if c.HandleEtag(etag, "Get Users Not in Team", w, r) { return } - profiles, err = c.App.GetUsersNotInTeamPage(notInTeamId, groupConstrainedBool, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), nil) + profiles, appErr = c.App.GetUsersNotInTeamPage(notInTeamId, groupConstrainedBool, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), nil) } else if inTeamId != "" { if sort == "last_activity_at" { - profiles, err = c.App.GetRecentlyActiveUsersForTeamPage(inTeamId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), nil) + profiles, appErr = c.App.GetRecentlyActiveUsersForTeamPage(inTeamId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), nil) } else if sort == "create_at" { - profiles, err = c.App.GetNewUsersForTeamPage(inTeamId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), nil) + profiles, appErr = c.App.GetNewUsersForTeamPage(inTeamId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin(), nil) } else { etag = c.App.GetUsersInTeamEtag(inTeamId, "") if c.HandleEtag(etag, "Get Users in Team", w, r) { return } - profiles, err = c.App.GetUsersInTeamPage(userGetOptions, c.IsSystemAdmin()) + profiles, appErr = c.App.GetUsersInTeamPage(userGetOptions, c.IsSystemAdmin()) } } else if inChannelId != "" { if sort == "status" { - profiles, err = c.App.GetUsersInChannelPageByStatus(userGetOptions, c.IsSystemAdmin()) + profiles, appErr = c.App.GetUsersInChannelPageByStatus(userGetOptions, c.IsSystemAdmin()) } else { - profiles, err = c.App.GetUsersInChannelPage(userGetOptions, c.IsSystemAdmin()) + profiles, appErr = c.App.GetUsersInChannelPage(userGetOptions, c.IsSystemAdmin()) } } else { - profiles, err = c.App.GetUsersPage(userGetOptions, c.IsSystemAdmin()) + profiles, appErr = c.App.GetUsersPage(userGetOptions, c.IsSystemAdmin()) } - if err != nil { - c.Err = err + if appErr != nil { + c.Err = appErr return } @@ -146,9 +148,9 @@ func localGetUsers(c *Context, w http.ResponseWriter, r *http.Request) { w.Header().Set(model.HeaderEtagServer, etag) } - js, jsonErr := json.Marshal(profiles) - if jsonErr != nil { - c.Err = model.NewAppError("localGetUsers", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(profiles) + if err != nil { + c.Err = model.NewAppError("localGetUsers", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -170,23 +172,23 @@ func localGetUsersByIds(c *Context, w http.ResponseWriter, r *http.Request) { } if sinceString != "" { - since, parseError := strconv.ParseInt(sinceString, 10, 64) - if parseError != nil { - c.SetInvalidParam("since") + since, err := strconv.ParseInt(sinceString, 10, 64) + if err != nil { + c.SetInvalidParamWithErr("since", err) return } options.Since = since } - users, err := c.App.GetUsersByIds(userIds, options) - if err != nil { - c.Err = err + users, appErr := c.App.GetUsersByIds(userIds, options) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(users) - if jsonErr != nil { - c.Err = model.NewAppError("localGetUsersByIds", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(users) + if err != nil { + c.Err = model.NewAppError("localGetUsersByIds", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } @@ -344,16 +346,17 @@ func localGetUserByEmail(c *Context, w http.ResponseWriter, r *http.Request) { } func localGetUploadsForUser(c *Context, w http.ResponseWriter, r *http.Request) { - uss, err := c.App.GetUploadSessionsForUser(c.Params.UserId) - if err != nil { - c.Err = err + uss, appErr := c.App.GetUploadSessionsForUser(c.Params.UserId) + if appErr != nil { + c.Err = appErr return } - js, jsonErr := json.Marshal(uss) - if jsonErr != nil { - c.Err = model.NewAppError("localGetUploadsForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(uss) + if err != nil { + c.Err = model.NewAppError("localGetUploadsForUser", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } + w.Write(js) } diff --git a/api4/user_test.go b/api4/user_test.go index 733f6e0e27..91b2df4703 100644 --- a/api4/user_test.go +++ b/api4/user_test.go @@ -1188,7 +1188,7 @@ func TestSearchUsers(t *testing.T) { t.Run("Requires ldap license when searching in group", func(t *testing.T) { _, resp, err = th.SystemAdminClient.SearchUsers(search) require.Error(t, err) - CheckNotImplementedStatus(t, resp) + CheckForbiddenStatus(t, resp) }) th.App.Srv().SetLicense(model.NewTestLicense("ldap")) @@ -2719,7 +2719,7 @@ func TestGetUsersInGroup(t *testing.T) { t.Run("Requires ldap license", func(t *testing.T) { _, response, err := th.SystemAdminClient.GetUsersInGroup(group.Id, 0, 60, "") require.Error(t, err) - CheckNotImplementedStatus(t, response) + CheckForbiddenStatus(t, response) }) th.App.Srv().SetLicense(model.NewTestLicense("ldap")) diff --git a/api4/webhook.go b/api4/webhook.go index 744fc38263..3f871d9952 100644 --- a/api4/webhook.go +++ b/api4/webhook.go @@ -178,24 +178,26 @@ func updateIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) { } func getIncomingHooks(c *Context, w http.ResponseWriter, r *http.Request) { - teamId := r.URL.Query().Get("team_id") - userId := c.AppContext.Session().UserId + var ( + teamID = r.URL.Query().Get("team_id") + userID = c.AppContext.Session().UserId - var hooks []*model.IncomingWebhook - var err *model.AppError + hooks []*model.IncomingWebhook + appErr *model.AppError + ) - if teamId != "" { - if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), teamId, model.PermissionManageIncomingWebhooks) { + if teamID != "" { + if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), teamID, model.PermissionManageIncomingWebhooks) { c.SetPermissionError(model.PermissionManageIncomingWebhooks) return } // Remove userId as a filter if they have permission to manage others. - if c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), teamId, model.PermissionManageOthersIncomingWebhooks) { - userId = "" + if c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), teamID, model.PermissionManageOthersIncomingWebhooks) { + userID = "" } - hooks, err = c.App.GetIncomingWebhooksForTeamPageByUser(teamId, userId, c.Params.Page, c.Params.PerPage) + hooks, appErr = c.App.GetIncomingWebhooksForTeamPageByUser(teamID, userID, c.Params.Page, c.Params.PerPage) } else { if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageIncomingWebhooks) { c.SetPermissionError(model.PermissionManageIncomingWebhooks) @@ -204,22 +206,23 @@ func getIncomingHooks(c *Context, w http.ResponseWriter, r *http.Request) { // Remove userId as a filter if they have permission to manage others. if c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageOthersIncomingWebhooks) { - userId = "" + userID = "" } - hooks, err = c.App.GetIncomingWebhooksPageByUser(userId, c.Params.Page, c.Params.PerPage) + hooks, appErr = c.App.GetIncomingWebhooksPageByUser(userID, c.Params.Page, c.Params.PerPage) } + if appErr != nil { + c.Err = appErr + return + } + + js, err := json.Marshal(hooks) if err != nil { - c.Err = err + c.Err = model.NewAppError("getIncomingHooks", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } - js, jsonErr := json.Marshal(hooks) - if jsonErr != nil { - c.Err = model.NewAppError("getIncomingHooks", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) - return - } w.Write(js) } @@ -451,37 +454,40 @@ func createOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) { } func getOutgoingHooks(c *Context, w http.ResponseWriter, r *http.Request) { - channelId := r.URL.Query().Get("channel_id") - teamId := r.URL.Query().Get("team_id") - userId := c.AppContext.Session().UserId + var ( + query = r.URL.Query() + channelID = query.Get("channel_id") + teamID = query.Get("team_id") + userID = c.AppContext.Session().UserId - var hooks []*model.OutgoingWebhook - var err *model.AppError + hooks []*model.OutgoingWebhook + appErr *model.AppError + ) - if channelId != "" { - if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channelId, model.PermissionManageOutgoingWebhooks) { + if channelID != "" { + if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channelID, model.PermissionManageOutgoingWebhooks) { c.SetPermissionError(model.PermissionManageOutgoingWebhooks) return } // Remove userId as a filter if they have permission to manage others. - if c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channelId, model.PermissionManageOthersOutgoingWebhooks) { - userId = "" + if c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channelID, model.PermissionManageOthersOutgoingWebhooks) { + userID = "" } - hooks, err = c.App.GetOutgoingWebhooksForChannelPageByUser(channelId, userId, c.Params.Page, c.Params.PerPage) - } else if teamId != "" { - if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), teamId, model.PermissionManageOutgoingWebhooks) { + hooks, appErr = c.App.GetOutgoingWebhooksForChannelPageByUser(channelID, userID, c.Params.Page, c.Params.PerPage) + } else if teamID != "" { + if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), teamID, model.PermissionManageOutgoingWebhooks) { c.SetPermissionError(model.PermissionManageOutgoingWebhooks) return } // Remove userId as a filter if they have permission to manage others. - if c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), teamId, model.PermissionManageOthersOutgoingWebhooks) { - userId = "" + if c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), teamID, model.PermissionManageOthersOutgoingWebhooks) { + userID = "" } - hooks, err = c.App.GetOutgoingWebhooksForTeamPageByUser(teamId, userId, c.Params.Page, c.Params.PerPage) + hooks, appErr = c.App.GetOutgoingWebhooksForTeamPageByUser(teamID, userID, c.Params.Page, c.Params.PerPage) } else { if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageOutgoingWebhooks) { c.SetPermissionError(model.PermissionManageOutgoingWebhooks) @@ -490,22 +496,23 @@ func getOutgoingHooks(c *Context, w http.ResponseWriter, r *http.Request) { // Remove userId as a filter if they have permission to manage others. if c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageOthersOutgoingWebhooks) { - userId = "" + userID = "" } - hooks, err = c.App.GetOutgoingWebhooksPageByUser(userId, c.Params.Page, c.Params.PerPage) + hooks, appErr = c.App.GetOutgoingWebhooksPageByUser(userID, c.Params.Page, c.Params.PerPage) } + if appErr != nil { + c.Err = appErr + return + } + + js, err := json.Marshal(hooks) if err != nil { - c.Err = err + c.Err = model.NewAppError("getOutgoingHooks", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) return } - js, jsonErr := json.Marshal(hooks) - if jsonErr != nil { - c.Err = model.NewAppError("getOutgoingHooks", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) - return - } w.Write(js) } diff --git a/app/admin.go b/app/admin.go index 890a0d7d89..7abca6951c 100644 --- a/app/admin.go +++ b/app/admin.go @@ -7,7 +7,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "net/http" "os" "runtime/debug" @@ -29,7 +28,7 @@ func (s *Server) GetLogs(page, perPage int) ([]string, *model.AppError) { var lines []string license := s.License() - if license != nil && *license.Features.Cluster && s.Cluster != nil && *s.Config().ClusterSettings.Enable { + if license != nil && *license.Features.Cluster && s.Cluster != nil && *s.platform.Config().ClusterSettings.Enable { if info := s.Cluster.GetMyClusterInfo(); info != nil { lines = append(lines, "-----------------------------------------------------------------------------------------------------------") lines = append(lines, "-----------------------------------------------------------------------------------------------------------") @@ -48,7 +47,7 @@ func (s *Server) GetLogs(page, perPage int) ([]string, *model.AppError) { lines = append(lines, melines...) - if s.Cluster != nil && *s.Config().ClusterSettings.Enable { + if s.Cluster != nil && *s.platform.Config().ClusterSettings.Enable { clines, err := s.Cluster.GetLogs(page, perPage) if err != nil { return nil, err @@ -67,9 +66,9 @@ func (a *App) GetLogs(page, perPage int) ([]string, *model.AppError) { func (s *Server) GetLogsSkipSend(page, perPage int) ([]string, *model.AppError) { var lines []string - if *s.Config().LogSettings.EnableFile { + if *s.platform.Config().LogSettings.EnableFile { s.Log.Flush() - logFile := config.GetLogFileLocation(*s.Config().LogSettings.FileLocation) + logFile := config.GetLogFileLocation(*s.platform.Config().LogSettings.FileLocation) file, err := os.Open(logFile) if err != nil { return nil, model.NewAppError("getLogs", "api.admin.file_read_error", nil, err.Error(), http.StatusInternalServerError) @@ -261,7 +260,7 @@ func (a *App) GetLatestVersion(latestVersionUrl string) (*model.GithubReleaseInf defer res.Body.Close() - responseData, err := ioutil.ReadAll(res.Body) + responseData, err := io.ReadAll(res.Body) if err != nil { return nil, model.NewAppError("GetLatestVersion", "app.admin.latest_version_read_all.failure", nil, "", http.StatusInternalServerError) } diff --git a/app/app_iface.go b/app/app_iface.go index 3d34c490b8..cbcaecb372 100644 --- a/app/app_iface.go +++ b/app/app_iface.go @@ -283,6 +283,8 @@ type AppIface interface { // PromoteGuestToUser Convert user's roles and all his membership's roles from // guest roles to regular user roles. PromoteGuestToUser(c *request.Context, user *model.User, requestorId string) *model.AppError + // Removes a listener function by the unique ID returned when AddConfigListener was called + RemoveConfigListener(id string) // RenameChannel is used to rename the channel Name and the DisplayName fields RenameChannel(c request.CTX, channel *model.Channel, newChannelName string, newDisplayName string) (*model.Channel, *model.AppError) // RenameTeam is used to rename the team Name and the DisplayName fields @@ -942,7 +944,6 @@ type AppIface interface { ReloadConfig() error RemoveAllDeactivatedMembersFromChannel(c request.CTX, channel *model.Channel) *model.AppError RemoveChannelsFromRetentionPolicy(policyID string, channelIDs []string) *model.AppError - RemoveConfigListener(id string) RemoveCustomStatus(c request.CTX, userID string) *model.AppError RemoveDirectory(path string) *model.AppError RemoveFile(path string) *model.AppError diff --git a/app/audit.go b/app/audit.go index 9f6e727235..7b250c769e 100644 --- a/app/audit.go +++ b/app/audit.go @@ -109,10 +109,10 @@ func (s *Server) configureAudit(adt *audit.Audit, bAllowAdvancedLogging bool) er adt.OnError = s.onAuditError var logConfigSrc config.LogConfigSrc - dsn := *s.Config().ExperimentalAuditSettings.AdvancedLoggingConfig + dsn := *s.platform.Config().ExperimentalAuditSettings.AdvancedLoggingConfig if bAllowAdvancedLogging && dsn != "" { var err error - logConfigSrc, err = config.NewLogConfigSrc(dsn, s.configStore.Store) + logConfigSrc, err = config.NewLogConfigSrc(dsn, s.platform.GetConfigStore()) if err != nil { return fmt.Errorf("invalid config source for audit, %w", err) } @@ -120,7 +120,7 @@ func (s *Server) configureAudit(adt *audit.Audit, bAllowAdvancedLogging bool) er } // ExperimentalAuditSettings provides basic file audit (E0, E10); logConfigSrc provides advanced config (E20). - cfg, err := config.MloggerConfigFromAuditConfig(s.Config().ExperimentalAuditSettings, logConfigSrc) + cfg, err := config.MloggerConfigFromAuditConfig(s.platform.Config().ExperimentalAuditSettings, logConfigSrc) if err != nil { return fmt.Errorf("invalid config for audit, %w", err) } diff --git a/app/authorization_test.go b/app/authorization_test.go index c115fa8e64..9d3cc45264 100644 --- a/app/authorization_test.go +++ b/app/authorization_test.go @@ -7,7 +7,7 @@ import ( "context" "encoding/csv" "fmt" - "io/ioutil" + "io" "os" "strconv" "strings" @@ -133,7 +133,7 @@ func TestSessionHasPermissionToGroup(t *testing.T) { require.NoError(t, e) defer file.Close() - b, e := ioutil.ReadAll(file) + b, e := io.ReadAll(file) require.NoError(t, e) r := csv.NewReader(strings.NewReader(string(b))) diff --git a/app/channel.go b/app/channel.go index e5f0c7aefc..74dd77938f 100644 --- a/app/channel.go +++ b/app/channel.go @@ -641,11 +641,11 @@ func (a *App) UpdateChannel(c request.CTX, channel *model.Channel) (*model.Chann var invErr *store.ErrInvalidInput switch { case errors.As(err, &invErr): - return nil, model.NewAppError("UpdateChannel", "app.channel.update.bad_id", nil, invErr.Error(), http.StatusBadRequest) + return nil, model.NewAppError("UpdateChannel", "app.channel.update.bad_id", nil, "", http.StatusBadRequest).Wrap(invErr) case errors.As(err, &appErr): return nil, appErr default: - return nil, model.NewAppError("UpdateChannel", "app.channel.update_channel.internal_error", nil, err.Error(), http.StatusInternalServerError) + return nil, model.NewAppError("UpdateChannel", "app.channel.update_channel.internal_error", nil, "", http.StatusInternalServerError).Wrap(err) } } @@ -1267,9 +1267,9 @@ func (a *App) UpdateChannelMemberNotifyProps(c request.CTX, data map[string]stri case errors.As(err, &appErr): return nil, appErr case errors.As(err, &nfErr): - return nil, model.NewAppError("updateMemberNotifyProps", MissingChannelMemberError, nil, nfErr.Error(), http.StatusNotFound) + return nil, model.NewAppError("updateMemberNotifyProps", MissingChannelMemberError, nil, "", http.StatusNotFound).Wrap(nfErr) default: - return nil, model.NewAppError("updateMemberNotifyProps", "app.channel.get_member.app_error", nil, err.Error(), http.StatusInternalServerError) + return nil, model.NewAppError("updateMemberNotifyProps", "app.channel.get_member.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } } @@ -1289,17 +1289,17 @@ func (a *App) UpdateChannelMemberNotifyProps(c request.CTX, data map[string]stri } func (a *App) updateChannelMember(c request.CTX, member *model.ChannelMember) (*model.ChannelMember, *model.AppError) { - member, nErr := a.Srv().Store.Channel().UpdateMember(member) - if nErr != nil { + member, err := a.Srv().Store.Channel().UpdateMember(member) + if err != nil { var appErr *model.AppError var nfErr *store.ErrNotFound switch { - case errors.As(nErr, &appErr): + case errors.As(err, &appErr): return nil, appErr - case errors.As(nErr, &nfErr): - return nil, model.NewAppError("updateChannelMember", MissingChannelMemberError, nil, nfErr.Error(), http.StatusNotFound) + case errors.As(err, &nfErr): + return nil, model.NewAppError("updateChannelMember", MissingChannelMemberError, nil, "", http.StatusNotFound).Wrap(nfErr) default: - return nil, model.NewAppError("updateChannelMember", "app.channel.get_member.app_error", nil, nErr.Error(), http.StatusInternalServerError) + return nil, model.NewAppError("updateChannelMember", "app.channel.get_member.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } } @@ -2604,14 +2604,14 @@ func (a *App) MarkChannelAsUnreadFromPost(c request.CTX, postID string, userID s } func (a *App) markChannelAsUnreadFromPostCRTUnsupported(c request.CTX, postID string, userID string) (*model.ChannelUnreadAt, *model.AppError) { - post, err := a.GetSinglePost(postID, false) - if err != nil { - return nil, err + post, appErr := a.GetSinglePost(postID, false) + if appErr != nil { + return nil, appErr } - user, err := a.GetUser(userID) - if err != nil { - return nil, err + user, appErr := a.GetUser(userID) + if appErr != nil { + return nil, appErr } threadId := post.RootId @@ -2619,18 +2619,18 @@ func (a *App) markChannelAsUnreadFromPostCRTUnsupported(c request.CTX, postID st threadId = post.Id } - unreadMentions, unreadMentionsRoot, err := a.countMentionsFromPost(c, user, post) - if err != nil { - return nil, err + unreadMentions, unreadMentionsRoot, appErr := a.countMentionsFromPost(c, user, post) + if appErr != nil { + return nil, appErr } // if root post, // In CRT Supported Client: badge on channel only sums mentions in root posts including and below the post that was marked. // In CRT Unsupported Client: badge on channel sums mentions in all posts (root & replies) including and below the post that was marked unread. if post.RootId == "" { - channelUnread, nErr := a.Srv().Store.Channel().UpdateLastViewedAtPost(post, userID, unreadMentions, unreadMentionsRoot, true) - if nErr != nil { - return channelUnread, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, nErr.Error(), http.StatusInternalServerError) + channelUnread, err := a.Srv().Store.Channel().UpdateLastViewedAtPost(post, userID, unreadMentions, unreadMentionsRoot, true) + if err != nil { + return channelUnread, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } a.sendWebSocketPostUnreadEvent(c, channelUnread, postID, true) @@ -2643,21 +2643,21 @@ func (a *App) markChannelAsUnreadFromPostCRTUnsupported(c request.CTX, postID st // If there are replies with mentions below the marked reply in the thread, then sum the mentions for the threads mention badge. // In CRT Unsupported Client: Channel is marked as unread and new messages line inserted above the marked post. // Badge on channel sums mentions in all posts (root & replies) including and below the post that was marked unread. - rootPost, err := a.GetSinglePost(post.RootId, false) - if err != nil { - return nil, err + rootPost, appErr := a.GetSinglePost(post.RootId, false) + if appErr != nil { + return nil, appErr } - channel, nErr := a.Srv().Store.Channel().Get(post.ChannelId, true) - if nErr != nil { - return nil, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, nErr.Error(), http.StatusInternalServerError) + channel, err := a.Srv().Store.Channel().Get(post.ChannelId, true) + if err != nil { + return nil, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } if *a.Config().ServiceSettings.ThreadAutoFollow { - threadMembership, sErr := a.Srv().Store.Thread().GetMembershipForUser(user.Id, threadId) + threadMembership, mErr := a.Srv().Store.Thread().GetMembershipForUser(user.Id, threadId) var errNotFound *store.ErrNotFound - if sErr != nil && !errors.As(sErr, &errNotFound) { - return nil, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, sErr.Error(), http.StatusInternalServerError) + if mErr != nil && !errors.As(mErr, &errNotFound) { + return nil, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, "", http.StatusInternalServerError).Wrap(mErr) } // Follow thread if we're not already following it if threadMembership == nil { @@ -2668,25 +2668,25 @@ func (a *App) markChannelAsUnreadFromPostCRTUnsupported(c request.CTX, postID st UpdateViewedTimestamp: false, UpdateParticipants: false, } - threadMembership, sErr = a.Srv().Store.Thread().MaintainMembership(user.Id, threadId, opts) - if sErr != nil { - return nil, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, sErr.Error(), http.StatusInternalServerError) + threadMembership, mErr = a.Srv().Store.Thread().MaintainMembership(user.Id, threadId, opts) + if mErr != nil { + return nil, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, "", http.StatusInternalServerError).Wrap(mErr) } } // If threadmembership already exists but user had previously unfollowed the thread, then follow the thread again. threadMembership.Following = true threadMembership.LastViewed = post.CreateAt - 1 - threadMembership.UnreadMentions, err = a.countThreadMentions(c, user, rootPost, channel.TeamId, post.CreateAt-1) - if err != nil { - return nil, err + threadMembership.UnreadMentions, appErr = a.countThreadMentions(c, user, rootPost, channel.TeamId, post.CreateAt-1) + if appErr != nil { + return nil, appErr } - threadMembership, sErr = a.Srv().Store.Thread().UpdateMembership(threadMembership) - if sErr != nil { - return nil, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, sErr.Error(), http.StatusInternalServerError) + threadMembership, mErr = a.Srv().Store.Thread().UpdateMembership(threadMembership) + if mErr != nil { + return nil, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, "", http.StatusInternalServerError).Wrap(mErr) } - thread, sErr := a.Srv().Store.Thread().GetThreadForUser(channel.TeamId, threadMembership, true) - if sErr != nil { - return nil, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, sErr.Error(), http.StatusInternalServerError) + thread, mErr := a.Srv().Store.Thread().GetThreadForUser(channel.TeamId, threadMembership, true) + if mErr != nil { + return nil, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, "", http.StatusInternalServerError).Wrap(mErr) } a.sanitizeProfiles(thread.Participants, false) thread.Post.SanitizeProps() @@ -2702,9 +2702,9 @@ func (a *App) markChannelAsUnreadFromPostCRTUnsupported(c request.CTX, postID st } } - channelUnread, nErr := a.Srv().Store.Channel().UpdateLastViewedAtPost(post, userID, unreadMentions, 0, false) - if nErr != nil { - return channelUnread, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, nErr.Error(), http.StatusInternalServerError) + channelUnread, err := a.Srv().Store.Channel().UpdateLastViewedAtPost(post, userID, unreadMentions, 0, false) + if err != nil { + return channelUnread, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } a.sendWebSocketPostUnreadEvent(c, channelUnread, postID, false) a.UpdateMobileAppBadge(userID) @@ -3213,14 +3213,14 @@ func (a *App) ToggleMuteChannel(c request.CTX, channelID, userID string) (*model } func (a *App) setChannelsMuted(c request.CTX, channelIDs []string, userID string, muted bool) ([]*model.ChannelMember, *model.AppError) { - members, nErr := a.Srv().Store.Channel().GetMembersByChannelIds(channelIDs, userID) - if nErr != nil { + members, err := a.Srv().Store.Channel().GetMembersByChannelIds(channelIDs, userID) + if err != nil { var appErr *model.AppError switch { - case errors.As(nErr, &appErr): + case errors.As(err, &appErr): return nil, appErr default: - return nil, model.NewAppError("setChannelsMuted", "app.channel.get_member.app_error", nil, nErr.Error(), http.StatusInternalServerError) + return nil, model.NewAppError("setChannelsMuted", "app.channel.get_member.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } } @@ -3240,17 +3240,17 @@ func (a *App) setChannelsMuted(c request.CTX, channelIDs []string, userID string return nil, nil } - updated, nErr := a.Srv().Store.Channel().UpdateMultipleMembers(membersToUpdate) - if nErr != nil { + updated, err := a.Srv().Store.Channel().UpdateMultipleMembers(membersToUpdate) + if err != nil { var appErr *model.AppError var nfErr *store.ErrNotFound switch { - case errors.As(nErr, &appErr): + case errors.As(err, &appErr): return nil, appErr - case errors.As(nErr, &nfErr): - return nil, model.NewAppError("setChannelsMuted", MissingChannelMemberError, nil, nfErr.Error(), http.StatusNotFound) + case errors.As(err, &nfErr): + return nil, model.NewAppError("setChannelsMuted", MissingChannelMemberError, nil, "", http.StatusNotFound).Wrap(nfErr) default: - return nil, model.NewAppError("setChannelsMuted", "app.channel.get_member.app_error", nil, nErr.Error(), http.StatusInternalServerError) + return nil, model.NewAppError("setChannelsMuted", "app.channel.get_member.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } } @@ -3375,7 +3375,7 @@ func (a *App) ClearChannelMembersCache(c request.CTX, channelID string) error { return nil } if err := a.forEachChannelMember(c, channelID, clearSessionCache); err != nil { - return fmt.Errorf("error clearing cache for channel members: channel_id: %s, error: %v", channelID, err) + return fmt.Errorf("error clearing cache for channel members: channel_id: %s, error: %w", channelID, err) } return nil } @@ -3383,7 +3383,7 @@ func (a *App) ClearChannelMembersCache(c request.CTX, channelID string) error { func (a *App) GetMemberCountsByGroup(ctx context.Context, channelID string, includeTimezones bool) ([]*model.ChannelMemberCountByGroup, *model.AppError) { channelMemberCounts, err := a.Srv().Store.Channel().GetMemberCountsByGroup(ctx, channelID, includeTimezones) if err != nil { - return nil, model.NewAppError("GetMemberCountsByGroup", "app.channel.get_member_count.app_error", nil, err.Error(), http.StatusInternalServerError) + return nil, model.NewAppError("GetMemberCountsByGroup", "app.channel.get_member_count.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } return channelMemberCounts, nil diff --git a/app/channel_category.go b/app/channel_category.go index ff7ef067d8..972d80cc51 100644 --- a/app/channel_category.go +++ b/app/channel_category.go @@ -144,7 +144,7 @@ func (a *App) UpdateSidebarCategoryOrder(c request.CTX, userID, teamID string, c func (a *App) UpdateSidebarCategories(c request.CTX, userID, teamID string, categories []*model.SidebarCategoryWithChannels) ([]*model.SidebarCategoryWithChannels, *model.AppError) { updatedCategories, originalCategories, err := a.Srv().Store.Channel().UpdateSidebarCategories(userID, teamID, categories) if err != nil { - return nil, model.NewAppError("UpdateSidebarCategories", "app.channel.sidebar_categories.app_error", nil, err.Error(), http.StatusInternalServerError) + return nil, model.NewAppError("UpdateSidebarCategories", "app.channel.sidebar_categories.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } message := model.NewWebSocketEvent(model.WebsocketEventSidebarCategoryUpdated, teamID, "", userID, nil) diff --git a/app/channel_test.go b/app/channel_test.go index 459423ab29..72dc0db3e5 100644 --- a/app/channel_test.go +++ b/app/channel_test.go @@ -2056,7 +2056,7 @@ func TestMarkChannelsAsViewedPanic(t *testing.T) { UserStore: &mockUserStore, SessionStore: &mockSessionStore, OAuthStore: &mockOAuthStore, - ConfigFn: th.App.ch.srv.Config, + ConfigFn: th.App.ch.srv.platform.Config, LicenseFn: th.App.ch.srv.License, }) require.NoError(t, err) diff --git a/app/channels.go b/app/channels.go index 48aba3297c..ed3dea6c44 100644 --- a/app/channels.go +++ b/app/channels.go @@ -31,12 +31,6 @@ type licenseSvc interface { RequestTrialLicense(requesterID string, users int, termsAccepted bool, receiveEmailsAccepted bool) *model.AppError } -// namer is an interface which enforces that -// all services can return their names. -type namer interface { - Name() ServiceKey -} - // Channels contains all channels related state. type Channels struct { srv *Server @@ -107,7 +101,7 @@ func init() { func NewChannels(s *Server, services map[ServiceKey]any) (*Channels, error) { ch := &Channels{ srv: s, - imageProxy: imageproxy.MakeImageProxy(s, s.httpService, s.Log), + imageProxy: imageproxy.MakeImageProxy(s.platform, s.httpService, s.Log), uploadLockMap: map[string]bool{}, } @@ -133,10 +127,6 @@ func NewChannels(s *Server, services map[ServiceKey]any) (*Channels, error) { if !ok { return nil, errors.New("Config service did not satisfy ConfigSvc interface") } - _, ok = svc.(namer) - if !ok { - return nil, errors.New("Config service does not contain Name method") - } ch.cfgSvc = cfgSvc case FilestoreKey: filestore, ok := svc.(filestore.FileBackend) @@ -149,10 +139,6 @@ func NewChannels(s *Server, services map[ServiceKey]any) (*Channels, error) { if !ok { return nil, errors.New("License service did not satisfy licenseSvc interface") } - _, ok = svc.(namer) - if !ok { - return nil, errors.New("License service does not contain Name method") - } ch.licenseSvc = svc } } diff --git a/app/cluster_discovery.go b/app/cluster_discovery.go index 0a003e06a0..9ae26038d4 100644 --- a/app/cluster_discovery.go +++ b/app/cluster_discovery.go @@ -83,7 +83,7 @@ func (cds *ClusterDiscoveryService) Stop() { } func (s *Server) IsLeader() bool { - if s.License() != nil && *s.Config().ClusterSettings.Enable && s.Cluster != nil { + if s.License() != nil && *s.platform.Config().ClusterSettings.Enable && s.Cluster != nil { return s.Cluster.IsLeader() } return true diff --git a/app/command.go b/app/command.go index 7d4ac80551..31a3c01554 100644 --- a/app/command.go +++ b/app/command.go @@ -7,7 +7,6 @@ import ( "context" "errors" "io" - "io/ioutil" "net/http" "net/url" "regexp" @@ -521,7 +520,7 @@ func (a *App) DoCommandRequest(cmd *model.Command, p url.Values) (*model.Command if resp.StatusCode != http.StatusOK { // Ignore the error below because the resulting string will just be the empty string if bodyBytes is nil - bodyBytes, _ := ioutil.ReadAll(body) + bodyBytes, _ := io.ReadAll(body) return cmd, nil, model.NewAppError("command", "api.command.execute_command.failed_resp.app_error", map[string]any{"Trigger": cmd.Trigger, "Status": resp.Status}, string(bodyBytes), http.StatusInternalServerError) } diff --git a/app/command_autocomplete.go b/app/command_autocomplete.go index 56fd45d6f5..43468ee498 100644 --- a/app/command_autocomplete.go +++ b/app/command_autocomplete.go @@ -280,7 +280,7 @@ func (a *App) getDynamicListArgument(c *request.Context, commandArgs *model.Comm var listItems []model.AutocompleteListItem if jsonErr := json.NewDecoder(resp.Body).Decode(&listItems); jsonErr != nil { - mlog.Warn("Failed to decode from JSON", mlog.Err(jsonErr)) + c.Logger().Warn("Failed to decode from JSON", mlog.Err(jsonErr)) } return parseListItems(listItems, parsed, toBeParsed) diff --git a/app/compliance.go b/app/compliance.go index a79ff37d31..0a398c6693 100644 --- a/app/compliance.go +++ b/app/compliance.go @@ -5,8 +5,8 @@ package app import ( "errors" - "io/ioutil" "net/http" + "os" "github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/mattermost-server/v6/shared/mlog" @@ -75,7 +75,7 @@ func (a *App) GetComplianceReport(reportId string) (*model.Compliance, *model.Ap } func (a *App) GetComplianceFile(job *model.Compliance) ([]byte, *model.AppError) { - f, err := ioutil.ReadFile(*a.Config().ComplianceSettings.Directory + "compliance/" + job.JobName() + ".zip") + f, err := os.ReadFile(*a.Config().ComplianceSettings.Directory + "compliance/" + job.JobName() + ".zip") if err != nil { return nil, model.NewAppError("readFile", "api.file.read_file.reading_local.app_error", nil, err.Error(), http.StatusNotImplemented) } diff --git a/app/config.go b/app/config.go index 6aacab9405..1c66654039 100644 --- a/app/config.go +++ b/app/config.go @@ -12,7 +12,6 @@ import ( "encoding/base64" "encoding/json" "fmt" - "net/http" "net/url" "reflect" "strconv" @@ -22,7 +21,6 @@ import ( "github.com/mattermost/mattermost-server/v6/config" "github.com/mattermost/mattermost-server/v6/model" - "github.com/mattermost/mattermost-server/v6/product" "github.com/mattermost/mattermost-server/v6/shared/mail" "github.com/mattermost/mattermost-server/v6/shared/mlog" "github.com/mattermost/mattermost-server/v6/utils" @@ -32,113 +30,24 @@ const ( ErrorTermsOfServiceNoRowsFound = "app.terms_of_service.get.no_rows.app_error" ) -// ensure the config wrapper implements `product.ConfigService` -var _ product.ConfigService = (*configWrapper)(nil) - -// configWrapper is an adapter struct that only exposes the -// config related functionality to be passed down to other products. -type configWrapper struct { - srv *Server - *config.Store -} - -func (w *configWrapper) Name() ServiceKey { - return ConfigKey -} - -func (w *configWrapper) Config() *model.Config { - return w.Store.Get() -} - -func (w *configWrapper) AddConfigListener(listener func(*model.Config, *model.Config)) string { - return w.Store.AddListener(listener) -} - -func (w *configWrapper) RemoveConfigListener(id string) { - w.Store.RemoveListener(id) -} - -func (w *configWrapper) UpdateConfig(f func(*model.Config)) { - if w.Store.IsReadOnly() { - return - } - old := w.Config() - updated := old.Clone() - f(updated) - if _, _, err := w.Store.Set(updated); err != nil { - mlog.Error("Failed to update config", mlog.Err(err)) - } -} - -func (w *configWrapper) SaveConfig(newCfg *model.Config, sendConfigChangeClusterMessage bool) (*model.Config, *model.Config, *model.AppError) { - oldCfg, newCfg, err := w.Store.Set(newCfg) - if errors.Cause(err) == config.ErrReadOnlyConfiguration { - return nil, nil, model.NewAppError("saveConfig", "ent.cluster.save_config.error", nil, err.Error(), http.StatusForbidden) - } else if err != nil { - return nil, nil, model.NewAppError("saveConfig", "app.save_config.app_error", nil, err.Error(), http.StatusInternalServerError) - } - - if w.srv.startMetrics && *w.Config().MetricsSettings.Enable { - if w.srv.GetMetrics() != nil { - w.srv.GetMetrics().Register() - } - w.srv.platform.RestartMetrics() // TODO: remove when this moved to the platform service - } else { - w.srv.platform.ShutdownMetrics() // TODO: remove when this moved to the platform service - } - - if w.srv.Cluster != nil { - err := w.srv.Cluster.ConfigChanged(w.Store.RemoveEnvironmentOverrides(oldCfg), - w.Store.RemoveEnvironmentOverrides(newCfg), sendConfigChangeClusterMessage) - if err != nil { - return nil, nil, err - } - } - - return oldCfg, newCfg, nil -} - -func (w *configWrapper) ReloadConfig() error { - if err := w.Store.Load(); err != nil { - return err - } - return nil -} - func (s *Server) Config() *model.Config { - return s.configStore.Config() -} - -func (s *Server) ConfigStore() *configWrapper { - return s.configStore + return s.platform.Config() } func (a *App) Config() *model.Config { return a.ch.cfgSvc.Config() } -func (s *Server) EnvironmentConfig(filter func(reflect.StructField) bool) map[string]any { - return s.configStore.GetEnvironmentOverridesWithFilter(filter) -} - func (a *App) EnvironmentConfig(filter func(reflect.StructField) bool) map[string]any { - return a.Srv().EnvironmentConfig(filter) -} - -func (s *Server) UpdateConfig(f func(*model.Config)) { - s.configStore.UpdateConfig(f) + return a.Srv().platform.GetEnvironmentOverridesWithFilter(filter) } func (a *App) UpdateConfig(f func(*model.Config)) { - a.Srv().UpdateConfig(f) -} - -func (s *Server) ReloadConfig() error { - return s.configStore.ReloadConfig() + a.Srv().platform.UpdateConfig(f) } func (a *App) ReloadConfig() error { - return a.Srv().ReloadConfig() + return a.Srv().platform.ReloadConfig() } func (a *App) ClientConfig() map[string]string { @@ -153,24 +62,13 @@ func (a *App) LimitedClientConfig() map[string]string { return a.ch.limitedClientConfig.Load().(map[string]string) } -// Registers a function with a given listener to be called when the config is reloaded and may have changed. The function -// will be called with two arguments: the old config and the new config. AddConfigListener returns a unique ID -// for the listener that can later be used to remove it. -func (s *Server) AddConfigListener(listener func(*model.Config, *model.Config)) string { - return s.configStore.AddConfigListener(listener) -} - func (a *App) AddConfigListener(listener func(*model.Config, *model.Config)) string { - return a.Srv().AddConfigListener(listener) + return a.Srv().platform.AddConfigListener(listener) } // Removes a listener function by the unique ID returned when AddConfigListener was called -func (s *Server) RemoveConfigListener(id string) { - s.configStore.RemoveConfigListener(id) -} - func (a *App) RemoveConfigListener(id string) { - a.Srv().RemoveConfigListener(id) + a.Srv().platform.RemoveConfigListener(id) } // ensurePostActionCookieSecret ensures that the key for encrypting PostActionCookie exists @@ -449,7 +347,7 @@ func (a *App) LimitedClientConfigWithComputed() map[string]string { // GetConfigFile proxies access to the given configuration file to the underlying config store. func (a *App) GetConfigFile(name string) ([]byte, error) { - data, err := a.Srv().configStore.GetFile(name) + data, err := a.Srv().platform.GetConfigFile(name) if err != nil { return nil, errors.Wrapf(err, "failed to get config file %s", name) } @@ -471,15 +369,9 @@ func (a *App) GetEnvironmentConfig(filter func(reflect.StructField) bool) map[st return a.EnvironmentConfig(filter) } -// SaveConfig replaces the active configuration, optionally notifying cluster peers. -// It returns both the previous and current configs. -func (s *Server) SaveConfig(newCfg *model.Config, sendConfigChangeClusterMessage bool) (*model.Config, *model.Config, *model.AppError) { - return s.configStore.SaveConfig(newCfg, sendConfigChangeClusterMessage) -} - // SaveConfig replaces the active configuration, optionally notifying cluster peers. func (a *App) SaveConfig(newCfg *model.Config, sendConfigChangeClusterMessage bool) (*model.Config, *model.Config, *model.AppError) { - return a.Srv().SaveConfig(newCfg, sendConfigChangeClusterMessage) + return a.Srv().platform.SaveConfig(newCfg, sendConfigChangeClusterMessage) } func (a *App) HandleMessageExportConfig(cfg *model.Config, appCfg *model.Config) { @@ -499,8 +391,8 @@ func (a *App) HandleMessageExportConfig(cfg *model.Config, appCfg *model.Config) } func (s *Server) MailServiceConfig() *mail.SMTPConfig { - emailSettings := s.Config().EmailSettings - hostname := utils.GetHostnameFromSiteURL(*s.Config().ServiceSettings.SiteURL) + emailSettings := s.platform.Config().EmailSettings + hostname := utils.GetHostnameFromSiteURL(*s.platform.Config().ServiceSettings.SiteURL) cfg := mail.SMTPConfig{ Hostname: hostname, ConnectionSecurity: *emailSettings.ConnectionSecurity, diff --git a/app/config_test.go b/app/config_test.go index fcca2889a4..aa019e4281 100644 --- a/app/config_test.go +++ b/app/config_test.go @@ -16,41 +16,6 @@ import ( "github.com/mattermost/mattermost-server/v6/utils" ) -func TestConfigListener(t *testing.T) { - th := Setup(t) - defer th.TearDown() - - originalSiteName := th.App.Config().TeamSettings.SiteName - - listenerCalled := false - listener := func(oldConfig *model.Config, newConfig *model.Config) { - assert.False(t, listenerCalled, "listener called twice") - - assert.Equal(t, *originalSiteName, *oldConfig.TeamSettings.SiteName, "old config contains incorrect site name") - assert.Equal(t, "test123", *newConfig.TeamSettings.SiteName, "new config contains incorrect site name") - - listenerCalled = true - } - listenerId := th.App.AddConfigListener(listener) - defer th.App.RemoveConfigListener(listenerId) - - listener2Called := false - listener2 := func(oldConfig *model.Config, newConfig *model.Config) { - assert.False(t, listener2Called, "listener2 called twice") - - listener2Called = true - } - listener2Id := th.App.AddConfigListener(listener2) - defer th.App.RemoveConfigListener(listener2Id) - - th.App.UpdateConfig(func(cfg *model.Config) { - *cfg.TeamSettings.SiteName = "test123" - }) - - assert.True(t, listenerCalled, "listener should've been called") - assert.True(t, listener2Called, "listener 2 should've been called") -} - func TestAsymmetricSigningKey(t *testing.T) { th := SetupWithStoreMock(t) defer th.TearDown() diff --git a/app/download.go b/app/download.go index ac9ac68466..449f787c46 100644 --- a/app/download.go +++ b/app/download.go @@ -5,7 +5,6 @@ package app import ( "io" - "io/ioutil" "net/http" "net/url" "time" @@ -35,7 +34,7 @@ func (s *Server) downloadFromURL(downloadURL string) ([]byte, error) { if err != nil { return nil, errors.Errorf("failed to parse url %s", downloadURL) } - if !*s.Config().PluginSettings.AllowInsecureDownloadURL && u.Scheme != "https" { + if !*s.platform.Config().PluginSettings.AllowInsecureDownloadURL && u.Scheme != "https" { return nil, errors.Errorf("insecure url not allowed %s", downloadURL) } @@ -64,5 +63,5 @@ func (s *Server) downloadFromURL(downloadURL string) ([]byte, error) { defer resp.Body.Close() - return ioutil.ReadAll(resp.Body) + return io.ReadAll(resp.Body) } diff --git a/app/email/helper_test.go b/app/email/helper_test.go index 2aabf04a3e..75fa7605b1 100644 --- a/app/email/helper_test.go +++ b/app/email/helper_test.go @@ -5,7 +5,6 @@ package email import ( "bytes" - "io/ioutil" "os" "path/filepath" "testing" @@ -64,7 +63,7 @@ func SetupWithStoreMock(tb testing.TB) *TestHelper { } func setupTestHelper(s store.Store, tb testing.TB) *TestHelper { - tempWorkspace, err := ioutil.TempDir("", "userservicetest") + tempWorkspace, err := os.MkdirTemp("", "userservicetest") if err != nil { panic(err) } diff --git a/app/emoji.go b/app/emoji.go index 496868dff3..5653ecacbc 100644 --- a/app/emoji.go +++ b/app/emoji.go @@ -39,11 +39,11 @@ const ( func (a *App) CreateEmoji(sessionUserId string, emoji *model.Emoji, multiPartImageData *multipart.Form) (*model.Emoji, *model.AppError) { if !*a.Config().ServiceSettings.EnableCustomEmoji { - return nil, model.NewAppError("UploadEmojiImage", "api.emoji.disabled.app_error", nil, "", http.StatusNotImplemented) + return nil, model.NewAppError("UploadEmojiImage", "api.emoji.disabled.app_error", nil, "", http.StatusForbidden) } if *a.Config().FileSettings.DriverName == "" { - return nil, model.NewAppError("GetEmoji", "api.emoji.storage.app_error", nil, "", http.StatusNotImplemented) + return nil, model.NewAppError("GetEmoji", "api.emoji.storage.app_error", nil, "", http.StatusForbidden) } // wipe the emoji id so that existing emojis can't get overwritten @@ -52,8 +52,8 @@ func (a *App) CreateEmoji(sessionUserId string, emoji *model.Emoji, multiPartIma // do our best to validate the emoji before committing anything to the DB so that we don't have to clean up // orphaned files left over when validation fails later on emoji.PreSave() - if err := emoji.IsValid(); err != nil { - return nil, err + if appErr := emoji.IsValid(); appErr != nil { + return nil, appErr } if emoji.CreatorId != sessionUserId { @@ -61,22 +61,21 @@ func (a *App) CreateEmoji(sessionUserId string, emoji *model.Emoji, multiPartIma } if existingEmoji, err := a.Srv().Store.Emoji().GetByName(context.Background(), emoji.Name, true); err == nil && existingEmoji != nil { - return nil, model.NewAppError("createEmoji", "api.emoji.create.duplicate.app_error", nil, "", http.StatusBadRequest) + return nil, model.NewAppError("createEmoji", "api.emoji.create.duplicate.app_error", nil, "", http.StatusBadRequest).Wrap(err) } imageData := multiPartImageData.File["image"] if len(imageData) == 0 { - err := model.NewAppError("Context", "api.context.invalid_body_param.app_error", map[string]any{"Name": "createEmoji"}, "", http.StatusBadRequest) - return nil, err + return nil, model.NewAppError("Context", "api.context.invalid_body_param.app_error", map[string]any{"Name": "createEmoji"}, "", http.StatusBadRequest) } - if err := a.UploadEmojiImage(emoji.Id, imageData[0]); err != nil { - return nil, err + if appErr := a.UploadEmojiImage(emoji.Id, imageData[0]); appErr != nil { + return nil, appErr } emoji, err := a.Srv().Store.Emoji().Save(emoji) if err != nil { - return nil, model.NewAppError("CreateEmoji", "app.emoji.create.internal_error", nil, err.Error(), http.StatusInternalServerError) + return nil, model.NewAppError("CreateEmoji", "app.emoji.create.internal_error", nil, "", http.StatusInternalServerError).Wrap(err) } message := model.NewWebSocketEvent(model.WebsocketEventEmojiAdded, "", "", "", nil) @@ -100,11 +99,11 @@ func (a *App) GetEmojiList(page, perPage int, sort string) ([]*model.Emoji, *mod func (a *App) UploadEmojiImage(id string, imageData *multipart.FileHeader) *model.AppError { if !*a.Config().ServiceSettings.EnableCustomEmoji { - return model.NewAppError("UploadEmojiImage", "api.emoji.disabled.app_error", nil, "", http.StatusNotImplemented) + return model.NewAppError("UploadEmojiImage", "api.emoji.disabled.app_error", nil, "", http.StatusForbidden) } if *a.Config().FileSettings.DriverName == "" { - return model.NewAppError("UploadEmojiImage", "api.emoji.storage.app_error", nil, "", http.StatusNotImplemented) + return model.NewAppError("UploadEmojiImage", "api.emoji.storage.app_error", nil, "", http.StatusForbidden) } file, err := imageData.Open() @@ -185,11 +184,11 @@ func (a *App) DeleteEmoji(emoji *model.Emoji) *model.AppError { func (a *App) GetEmoji(emojiId string) (*model.Emoji, *model.AppError) { if !*a.Config().ServiceSettings.EnableCustomEmoji { - return nil, model.NewAppError("GetEmoji", "api.emoji.disabled.app_error", nil, "", http.StatusNotImplemented) + return nil, model.NewAppError("GetEmoji", "api.emoji.disabled.app_error", nil, "", http.StatusForbidden) } if *a.Config().FileSettings.DriverName == "" { - return nil, model.NewAppError("GetEmoji", "api.emoji.storage.app_error", nil, "", http.StatusNotImplemented) + return nil, model.NewAppError("GetEmoji", "api.emoji.storage.app_error", nil, "", http.StatusForbidden) } emoji, err := a.Srv().Store.Emoji().Get(context.Background(), emojiId, true) @@ -208,11 +207,11 @@ func (a *App) GetEmoji(emojiId string) (*model.Emoji, *model.AppError) { func (a *App) GetEmojiByName(emojiName string) (*model.Emoji, *model.AppError) { if !*a.Config().ServiceSettings.EnableCustomEmoji { - return nil, model.NewAppError("GetEmojiByName", "api.emoji.disabled.app_error", nil, "", http.StatusNotImplemented) + return nil, model.NewAppError("GetEmojiByName", "api.emoji.disabled.app_error", nil, "", http.StatusForbidden) } if *a.Config().FileSettings.DriverName == "" { - return nil, model.NewAppError("GetEmojiByName", "api.emoji.storage.app_error", nil, "", http.StatusNotImplemented) + return nil, model.NewAppError("GetEmojiByName", "api.emoji.storage.app_error", nil, "", http.StatusForbidden) } emoji, err := a.Srv().Store.Emoji().GetByName(context.Background(), emojiName, true) @@ -231,7 +230,7 @@ func (a *App) GetEmojiByName(emojiName string) (*model.Emoji, *model.AppError) { func (a *App) GetMultipleEmojiByName(names []string) ([]*model.Emoji, *model.AppError) { if !*a.Config().ServiceSettings.EnableCustomEmoji { - return nil, model.NewAppError("GetMultipleEmojiByName", "api.emoji.disabled.app_error", nil, "", http.StatusNotImplemented) + return nil, model.NewAppError("GetMultipleEmojiByName", "api.emoji.disabled.app_error", nil, "", http.StatusForbidden) } emoji, err := a.Srv().Store.Emoji().GetMultipleByName(names) @@ -269,7 +268,7 @@ func (a *App) GetEmojiImage(emojiId string) ([]byte, string, *model.AppError) { func (a *App) SearchEmoji(name string, prefixOnly bool, limit int) ([]*model.Emoji, *model.AppError) { if !*a.Config().ServiceSettings.EnableCustomEmoji { - return nil, model.NewAppError("SearchEmoji", "api.emoji.disabled.app_error", nil, "", http.StatusNotImplemented) + return nil, model.NewAppError("SearchEmoji", "api.emoji.disabled.app_error", nil, "", http.StatusForbidden) } list, err := a.Srv().Store.Emoji().Search(name, prefixOnly, limit) diff --git a/app/enterprise.go b/app/enterprise.go index bb34bb1d8e..db826a873f 100644 --- a/app/enterprise.go +++ b/app/enterprise.go @@ -87,9 +87,9 @@ func RegisterCloudInterface(f func(*Server) einterfaces.CloudInterface) { cloudInterface = f } -var metricsInterface func(*Server) einterfaces.MetricsInterface +var metricsInterface func(*Server, string, string) einterfaces.MetricsInterface -func RegisterMetricsInterface(f func(*Server) einterfaces.MetricsInterface) { +func RegisterMetricsInterface(f func(*Server, string, string) einterfaces.MetricsInterface) { metricsInterface = f } diff --git a/app/export.go b/app/export.go index 7aad4a597d..553e1d41b7 100644 --- a/app/export.go +++ b/app/export.go @@ -141,14 +141,14 @@ func (a *App) BulkExport(ctx request.CTX, writer io.Writer, outPath string, opts return nil } -func (a *App) exportWriteLine(writer io.Writer, line *LineImportData) *model.AppError { +func (a *App) exportWriteLine(w io.Writer, line *LineImportData) *model.AppError { b, err := json.Marshal(line) if err != nil { - return model.NewAppError("BulkExport", "app.export.export_write_line.json_marshall.error", nil, "err="+err.Error(), http.StatusBadRequest) + return model.NewAppError("BulkExport", "app.export.export_write_line.json_marshall.error", nil, "", http.StatusBadRequest).Wrap(err) } - if _, err := writer.Write(append(b, '\n')); err != nil { - return model.NewAppError("BulkExport", "app.export.export_write_line.io_writer.error", nil, "err="+err.Error(), http.StatusBadRequest) + if _, err := w.Write(append(b, '\n')); err != nil { + return model.NewAppError("BulkExport", "app.export.export_write_line.io_writer.error", nil, "", http.StatusBadRequest).Wrap(err) } return nil diff --git a/app/export_test.go b/app/export_test.go index e9231a3af4..3ed17d9547 100644 --- a/app/export_test.go +++ b/app/export_test.go @@ -6,7 +6,6 @@ package app import ( "bytes" "fmt" - "io/ioutil" "os" "path/filepath" "sort" @@ -590,7 +589,7 @@ func TestBulkExport(t *testing.T) { th := Setup(t) testsDir, _ := fileutils.FindDir("tests") - dir, err := ioutil.TempDir("", "import_test") + dir, err := os.MkdirTemp("", "import_test") require.NoError(t, err) defer os.RemoveAll(dir) diff --git a/app/extract_plugin_tar_test.go b/app/extract_plugin_tar_test.go index 3cacff7272..f1662fafa0 100644 --- a/app/extract_plugin_tar_test.go +++ b/app/extract_plugin_tar_test.go @@ -8,7 +8,6 @@ import ( "bytes" "compress/gzip" "fmt" - "io/ioutil" "os" "path/filepath" "sort" @@ -81,7 +80,7 @@ func TestExtractTarGz(t *testing.T) { }) } - dst, err := ioutil.TempDir("", "TestExtractTarGz") + dst, err := os.MkdirTemp("", "TestExtractTarGz") require.NoError(t, err) defer os.RemoveAll(dst) @@ -175,7 +174,7 @@ func TestExtractTarGz(t *testing.T) { for i, testCase := range testCases { t.Run(fmt.Sprintf("test-%d", i), func(t *testing.T) { - dst, err := ioutil.TempDir("", "TestExtractTarGz") + dst, err := os.MkdirTemp("", "TestExtractTarGz") require.NoError(t, err) defer os.RemoveAll(dst) diff --git a/app/feature_flags.go b/app/feature_flags.go deleted file mode 100644 index efb517eca3..0000000000 --- a/app/feature_flags.go +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package app - -import ( - "encoding/json" - "os" - "time" - - "github.com/mattermost/mattermost-server/v6/app/featureflag" - "github.com/mattermost/mattermost-server/v6/shared/mlog" -) - -// setupFeatureFlags called on startup and when the cluster leader changes. -// Starts or stops the synchronization of feature flags from upstream management. -func (s *Server) setupFeatureFlags() { - s.featureFlagSynchronizerMutex.Lock() - defer s.featureFlagSynchronizerMutex.Unlock() - splitKey := *s.Config().ServiceSettings.SplitKey - splitConfigured := splitKey != "" - syncFeatureFlags := splitConfigured && s.IsLeader() - - s.configStore.SetReadOnlyFF(!splitConfigured) - - if syncFeatureFlags { - if err := s.startFeatureFlagUpdateJob(); err != nil { - s.Log.Warn("Unable to setup synchronization with feature flag management. Will fallback to cache.", mlog.Err(err)) - } - } else { - s.stopFeatureFlagUpdateJob() - } - - if err := s.configStore.Load(); err != nil { - s.Log.Warn("Unable to load config store after feature flag setup.", mlog.Err(err)) - } -} - -func (s *Server) updateFeatureFlagValuesFromManagement() { - newCfg := s.configStore.GetNoEnv().Clone() - oldFlags := *newCfg.FeatureFlags - newFlags := s.featureFlagSynchronizer.UpdateFeatureFlagValues(oldFlags) - oldFlagsBytes, _ := json.Marshal(oldFlags) - newFlagsBytes, _ := json.Marshal(newFlags) - s.Log.Debug("Checking feature flags from management service", mlog.String("old_flags", string(oldFlagsBytes)), mlog.String("new_flags", string(newFlagsBytes))) - if oldFlags != newFlags { - s.Log.Debug("Feature flag change detected, updating config") - *newCfg.FeatureFlags = newFlags - s.SaveConfig(newCfg, true) - } -} - -func (s *Server) startFeatureFlagUpdateJob() error { - // Can be run multiple times - if s.featureFlagSynchronizer != nil { - return nil - } - - var log *mlog.Logger - if *s.Config().ServiceSettings.DebugSplit { - log = s.Log - } - - attributes := map[string]any{} - - // if we are part of a cloud installation, add its installation and group id - if installationId := os.Getenv("MM_CLOUD_INSTALLATION_ID"); installationId != "" { - attributes["installation_id"] = installationId - } - if groupId := os.Getenv("MM_CLOUD_GROUP_ID"); groupId != "" { - attributes["group_id"] = groupId - } - - synchronizer, err := featureflag.NewSynchronizer(featureflag.SyncParams{ - ServerID: s.TelemetryId(), - SplitKey: *s.Config().ServiceSettings.SplitKey, - Log: log, - Attributes: attributes, - }) - if err != nil { - return err - } - - s.featureFlagStop = make(chan struct{}) - s.featureFlagStopped = make(chan struct{}) - s.featureFlagSynchronizer = synchronizer - syncInterval := *s.Config().ServiceSettings.FeatureFlagSyncIntervalSeconds - - go func() { - ticker := time.NewTicker(time.Duration(syncInterval) * time.Second) - defer ticker.Stop() - defer close(s.featureFlagStopped) - if err := synchronizer.EnsureReady(); err != nil { - s.Log.Warn("Problem connecting to feature flag management. Will fallback to cloud cache.", mlog.Err(err)) - return - } - s.updateFeatureFlagValuesFromManagement() - for { - select { - case <-s.featureFlagStop: - return - case <-ticker.C: - s.updateFeatureFlagValuesFromManagement() - } - } - }() - - return nil -} - -func (s *Server) stopFeatureFlagUpdateJob() { - if s.featureFlagSynchronizer != nil { - close(s.featureFlagStop) - <-s.featureFlagStopped - s.featureFlagSynchronizer.Close() - s.featureFlagSynchronizer = nil - } -} diff --git a/app/group.go b/app/group.go index 686c2d6c0c..7f44487d5a 100644 --- a/app/group.go +++ b/app/group.go @@ -122,9 +122,9 @@ func (a *App) isUniqueToUsernames(val string) *model.AppError { } func (a *App) CreateGroupWithUserIds(group *model.GroupWithUserIds) (*model.Group, *model.AppError) { - if err := a.isUniqueToUsernames(group.GetName()); err != nil { - err.Where = "CreateGroupWithUserIds" - return nil, err + if appErr := a.isUniqueToUsernames(group.GetName()); appErr != nil { + appErr.Where = "CreateGroupWithUserIds" + return nil, appErr } newGroup, err := a.Srv().Store.Group().CreateWithUserIds(group) @@ -136,18 +136,18 @@ func (a *App) CreateGroupWithUserIds(group *model.GroupWithUserIds) (*model.Grou case errors.As(err, &appErr): return nil, appErr case errors.As(err, &invErr): - return nil, model.NewAppError("CreateGroupWithUserIds", "app.group.id.app_error", nil, invErr.Error(), http.StatusBadRequest) + return nil, model.NewAppError("CreateGroupWithUserIds", "app.group.id.app_error", nil, "", http.StatusBadRequest).Wrap(invErr) case errors.As(err, &dupKey): - return nil, model.NewAppError("CreateGroupWithUserIds", "app.custom_group.unique_name", nil, dupKey.Error(), http.StatusBadRequest) + return nil, model.NewAppError("CreateGroupWithUserIds", "app.custom_group.unique_name", nil, "", http.StatusBadRequest).Wrap(dupKey) default: - return nil, model.NewAppError("CreateGroupWithUserIds", "app.insert_error", nil, err.Error(), http.StatusInternalServerError) + return nil, model.NewAppError("CreateGroupWithUserIds", "app.insert_error", nil, "", http.StatusInternalServerError).Wrap(err) } } messageWs := model.NewWebSocketEvent(model.WebsocketEventReceivedGroup, "", "", "", nil) count, err := a.Srv().Store.Group().GetMemberCount(newGroup.Id) if err != nil { - return nil, model.NewAppError("CreateGroupWithUserIds", "app.group.id.app_error", nil, err.Error(), http.StatusBadRequest) + return nil, model.NewAppError("CreateGroupWithUserIds", "app.group.id.app_error", nil, "", http.StatusBadRequest).Wrap(err) } group.MemberCount = model.NewInt(int(count)) groupJSON, jsonErr := json.Marshal(newGroup) @@ -161,28 +161,12 @@ func (a *App) CreateGroupWithUserIds(group *model.GroupWithUserIds) (*model.Grou } func (a *App) UpdateGroup(group *model.Group) (*model.Group, *model.AppError) { - if err := a.isUniqueToUsernames(group.GetName()); err != nil { - err.Where = "UpdateGroup" - return nil, err + if appErr := a.isUniqueToUsernames(group.GetName()); appErr != nil { + appErr.Where = "UpdateGroup" + return nil, appErr } updatedGroup, err := a.Srv().Store.Group().Update(group) - - if err == nil { - count, countErr := a.Srv().Store.Group().GetMemberCount(updatedGroup.Id) - if countErr != nil { - return nil, model.NewAppError("UpdateGroup", "app.group.id.app_error", nil, countErr.Error(), http.StatusBadRequest) - } - updatedGroup.MemberCount = model.NewInt(int(count)) - messageWs := model.NewWebSocketEvent(model.WebsocketEventReceivedGroup, "", "", "", nil) - groupJSON, jsonErr := json.Marshal(updatedGroup) - if jsonErr != nil { - return nil, model.NewAppError("UpdateGroup", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr) - } - messageWs.Add("group", string(groupJSON)) - a.Publish(messageWs) - } - if err != nil { var nfErr *store.ErrNotFound var appErr *model.AppError @@ -191,14 +175,29 @@ func (a *App) UpdateGroup(group *model.Group) (*model.Group, *model.AppError) { case errors.As(err, &appErr): return nil, appErr case errors.As(err, &nfErr): - return nil, model.NewAppError("UpdateGroup", "app.group.no_rows", nil, nfErr.Error(), http.StatusNotFound) + return nil, model.NewAppError("UpdateGroup", "app.group.no_rows", nil, "", http.StatusNotFound).Wrap(nfErr) case errors.As(err, &dupKey): - return nil, model.NewAppError("CreateGroup", "app.custom_group.unique_name", nil, dupKey.Error(), http.StatusBadRequest) + return nil, model.NewAppError("CreateGroup", "app.custom_group.unique_name", nil, "", http.StatusBadRequest).Wrap(dupKey) default: - return nil, model.NewAppError("UpdateGroup", "app.select_error", nil, err.Error(), http.StatusInternalServerError) + return nil, model.NewAppError("UpdateGroup", "app.select_error", nil, "", http.StatusInternalServerError).Wrap(err) } } + count, err := a.Srv().Store.Group().GetMemberCount(updatedGroup.Id) + if err != nil { + return nil, model.NewAppError("UpdateGroup", "app.group.id.app_error", nil, "", http.StatusBadRequest).Wrap(err) + } + + updatedGroup.MemberCount = model.NewInt(int(count)) + messageWs := model.NewWebSocketEvent(model.WebsocketEventReceivedGroup, "", "", "", nil) + + groupJSON, err := json.Marshal(updatedGroup) + if err != nil { + return nil, model.NewAppError("UpdateGroup", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) + } + messageWs.Add("group", string(groupJSON)) + a.Publish(messageWs) + return updatedGroup, nil } @@ -763,9 +762,9 @@ func (a *App) DeleteGroupMembers(groupID string, userIDs []string) ([]*model.Gro case errors.As(err, &appErr): return nil, appErr case errors.As(err, &invErr): - return nil, model.NewAppError("DeleteGroupMember", "app.group.uniqueness_error", nil, invErr.Error(), http.StatusBadRequest) + return nil, model.NewAppError("DeleteGroupMember", "app.group.uniqueness_error", nil, "", http.StatusBadRequest).Wrap(invErr) default: - return nil, model.NewAppError("DeleteGroupMember", "app.update_error", nil, err.Error(), http.StatusInternalServerError) + return nil, model.NewAppError("DeleteGroupMember", "app.update_error", nil, "", http.StatusInternalServerError).Wrap(err) } } diff --git a/app/helper_test.go b/app/helper_test.go index 3cbaa72497..5b15d3f519 100644 --- a/app/helper_test.go +++ b/app/helper_test.go @@ -5,7 +5,6 @@ package app import ( "context" - "io/ioutil" "os" "path/filepath" "strings" @@ -48,7 +47,7 @@ type TestHelper struct { } func setupTestHelper(dbStore store.Store, enterprise bool, includeCacheLayer bool, options []Option, tb testing.TB) *TestHelper { - tempWorkspace, err := ioutil.TempDir("", "apptest") + tempWorkspace, err := os.MkdirTemp("", "apptest") if err != nil { panic(err) } diff --git a/app/imaging/utils_test.go b/app/imaging/utils_test.go index cdd81db44d..6d0c5383ae 100644 --- a/app/imaging/utils_test.go +++ b/app/imaging/utils_test.go @@ -6,7 +6,6 @@ package imaging import ( "bytes" "image/color" - "io/ioutil" "os" "testing" @@ -77,7 +76,7 @@ func TestFillImageTransparency(t *testing.T) { require.NotNil(t, inputImg) require.Equal(t, "png", format) - expectedBytes, err := ioutil.ReadFile(imgDir + "/" + tc.outputName) + expectedBytes, err := os.ReadFile(imgDir + "/" + tc.outputName) require.NoError(t, err) FillImageTransparency(inputImg, tc.fillColor) diff --git a/app/import_functions.go b/app/import_functions.go index 44f89737a5..f84af9e500 100644 --- a/app/import_functions.go +++ b/app/import_functions.go @@ -10,7 +10,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "net/http" "os" "path" @@ -1217,7 +1216,7 @@ func (a *App) importAttachment(c *request.Context, data *AttachmentImportData, p timestamp := utils.TimeFromMillis(post.CreateAt) - fileData, err := ioutil.ReadAll(file) + fileData, err := io.ReadAll(file) if err != nil { return nil, model.NewAppError("BulkImport", "app.import.attachment.read_file_data.error", map[string]any{"FilePath": *data.Path}, "", http.StatusBadRequest) } diff --git a/app/import_functions_test.go b/app/import_functions_test.go index c764e44c19..8ac8ff6e69 100644 --- a/app/import_functions_test.go +++ b/app/import_functions_test.go @@ -6,7 +6,6 @@ package app import ( "archive/zip" "context" - "io/ioutil" "os" "path/filepath" "strings" @@ -3100,7 +3099,6 @@ func TestImportImportPost(t *testing.T) { }) t.Run("Reply CreateAt before parent post CreateAt", func(t *testing.T) { - t.Skip("MM-44922") now := model.GetMillis() before := now - 10 data := LineImportWorkerData{ @@ -3128,6 +3126,7 @@ func TestImportImportPost(t *testing.T) { posts, nErr := th.App.Srv().Store.Post().GetPostsCreatedAt(channel.Id, now) require.NoError(t, nErr) require.Len(t, posts, 2, "Unexpected number of posts found.") + require.NoError(t, th.TestLogger.Flush()) testlib.AssertLog(t, th.LogBuffer, mlog.LvlWarn.Name, "Reply CreateAt is before parent post CreateAt, setting it to parent post CreateAt") rootPost := posts[0] @@ -4378,11 +4377,11 @@ func TestImportDirectPostWithAttachments(t *testing.T) { testImage := filepath.Join(testsDir, "test.png") testImage2 := filepath.Join(testsDir, "test.svg") // create a temp file with same name as original but with a different first byte - tmpFolder, _ := ioutil.TempDir("", "imgFake") + tmpFolder, _ := os.MkdirTemp("", "imgFake") testImageFake := filepath.Join(tmpFolder, "test.png") - fakeFileData, _ := ioutil.ReadFile(testImage) + fakeFileData, _ := os.ReadFile(testImage) fakeFileData[0] = 0 - _ = ioutil.WriteFile(testImageFake, fakeFileData, 0644) + _ = os.WriteFile(testImageFake, fakeFileData, 0644) defer os.RemoveAll(tmpFolder) // Create a user. diff --git a/app/import_test.go b/app/import_test.go index 3286f3f03a..f3676b6e10 100644 --- a/app/import_test.go +++ b/app/import_test.go @@ -6,7 +6,6 @@ package app import ( "archive/zip" "io" - "io/ioutil" "net/http" "os" "path/filepath" @@ -439,7 +438,7 @@ func BenchmarkBulkImport(b *testing.B) { info, err := importFile.Stat() require.NoError(b, err) - dir, err := ioutil.TempDir("", "testimport") + dir, err := os.MkdirTemp("", "testimport") require.NoError(b, err) defer os.RemoveAll(dir) diff --git a/app/import_validators.go b/app/import_validators.go index 3be6b8fabd..c2dc34b5d0 100644 --- a/app/import_validators.go +++ b/app/import_validators.go @@ -332,10 +332,10 @@ func validateUserTeamsImportData(data *[]UserTeamImportData) *model.AppError { } } - if tdata.Theme != nil && 0 < len(strings.Trim(*tdata.Theme, " \t\r")) { + if tdata.Theme != nil && strings.Trim(*tdata.Theme, " \t\r") != "" { var unused map[string]string if err := json.NewDecoder(strings.NewReader(*tdata.Theme)).Decode(&unused); err != nil { - return model.NewAppError("BulkImport", "app.import.validate_user_teams_import_data.invalid_team_theme.error", nil, err.Error(), http.StatusBadRequest) + return model.NewAppError("BulkImport", "app.import.validate_user_teams_import_data.invalid_team_theme.error", nil, "", http.StatusBadRequest).Wrap(err) } } } diff --git a/app/integration_action.go b/app/integration_action.go index 6f3d703808..35b93a956f 100644 --- a/app/integration_action.go +++ b/app/integration_action.go @@ -23,7 +23,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "net/http" "net/url" "path" @@ -98,9 +98,9 @@ func (a *App) DoPostActionWithCookie(c *request.Context, postID, actionId, userI var nfErr *store.ErrNotFound switch { case errors.As(result.NErr, &nfErr): - return "", model.NewAppError("DoPostActionWithCookie", "app.post.get.app_error", nil, nfErr.Error(), http.StatusNotFound) + return "", model.NewAppError("DoPostActionWithCookie", "app.post.get.app_error", nil, "", http.StatusNotFound).Wrap(nfErr) default: - return "", model.NewAppError("DoPostActionWithCookie", "app.post.get.app_error", nil, result.NErr.Error(), http.StatusInternalServerError) + return "", model.NewAppError("DoPostActionWithCookie", "app.post.get.app_error", nil, "", http.StatusInternalServerError).Wrap(result.NErr) } } if cookie.Integration == nil { @@ -116,9 +116,9 @@ func (a *App) DoPostActionWithCookie(c *request.Context, postID, actionId, userI var nfErr *store.ErrNotFound switch { case errors.As(err, &nfErr): - return "", model.NewAppError("DoPostActionWithCookie", "app.channel.get.existing.app_error", nil, nfErr.Error(), http.StatusNotFound) + return "", model.NewAppError("DoPostActionWithCookie", "app.channel.get.existing.app_error", nil, "", http.StatusNotFound).Wrap(nfErr) default: - return "", model.NewAppError("DoPostActionWithCookie", "app.channel.get.find.app_error", nil, err.Error(), http.StatusInternalServerError) + return "", model.NewAppError("DoPostActionWithCookie", "app.channel.get.find.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } } @@ -137,7 +137,7 @@ func (a *App) DoPostActionWithCookie(c *request.Context, postID, actionId, userI post := result.Data.(*model.Post) result = <-cchan if result.NErr != nil { - return "", model.NewAppError("DoPostActionWithCookie", "app.channel.get_for_post.app_error", nil, result.NErr.Error(), http.StatusInternalServerError) + return "", model.NewAppError("DoPostActionWithCookie", "app.channel.get_for_post.app_error", nil, "", http.StatusInternalServerError).Wrap(result.NErr) } channel := result.Data.(*model.Channel) @@ -195,9 +195,9 @@ func (a *App) DoPostActionWithCookie(c *request.Context, postID, actionId, userI var nfErr *store.ErrNotFound switch { case errors.As(ur.NErr, &nfErr): - return "", model.NewAppError("DoPostActionWithCookie", MissingAccountError, nil, nfErr.Error(), http.StatusNotFound) + return "", model.NewAppError("DoPostActionWithCookie", MissingAccountError, nil, "", http.StatusNotFound).Wrap(nfErr) default: - return "", model.NewAppError("DoPostActionWithCookie", "app.user.get.app_error", nil, ur.NErr.Error(), http.StatusInternalServerError) + return "", model.NewAppError("DoPostActionWithCookie", "app.user.get.app_error", nil, "", http.StatusInternalServerError).Wrap(ur.NErr) } } user := ur.Data.(*model.User) @@ -209,9 +209,9 @@ func (a *App) DoPostActionWithCookie(c *request.Context, postID, actionId, userI var nfErr *store.ErrNotFound switch { case errors.As(tr.NErr, &nfErr): - return "", model.NewAppError("DoPostActionWithCookie", "app.team.get.find.app_error", nil, nfErr.Error(), http.StatusNotFound) + return "", model.NewAppError("DoPostActionWithCookie", "app.team.get.find.app_error", nil, "", http.StatusNotFound).Wrap(nfErr) default: - return "", model.NewAppError("DoPostActionWithCookie", "app.team.get.finding.app_error", nil, tr.NErr.Error(), http.StatusInternalServerError) + return "", model.NewAppError("DoPostActionWithCookie", "app.team.get.finding.app_error", nil, "", http.StatusInternalServerError).Wrap(tr.NErr) } } @@ -234,7 +234,6 @@ func (a *App) DoPostActionWithCookie(c *request.Context, postID, actionId, userI return "", appErr } - var resp *http.Response if strings.HasPrefix(upstreamURL, "/warn_metrics/") { appErr = a.doLocalWarnMetricsRequest(c, upstreamURL, upstreamRequest) if appErr != nil { @@ -242,25 +241,26 @@ func (a *App) DoPostActionWithCookie(c *request.Context, postID, actionId, userI } return "", nil } - requestJSON, jsonErr := json.Marshal(upstreamRequest) - if jsonErr != nil { - return "", model.NewAppError("DoPostActionWithCookie", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + + requestJSON, err := json.Marshal(upstreamRequest) + if err != nil { + return "", model.NewAppError("DoPostActionWithCookie", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } - resp, appErr = a.DoActionRequest(c, upstreamURL, requestJSON) + resp, appErr := a.DoActionRequest(c, upstreamURL, requestJSON) if appErr != nil { return "", appErr } defer resp.Body.Close() var response model.PostActionIntegrationResponse - respBytes, err := ioutil.ReadAll(resp.Body) + respBytes, err := io.ReadAll(resp.Body) if err != nil { - return "", model.NewAppError("DoPostActionWithCookie", "api.post.do_action.action_integration.app_error", nil, "err="+err.Error(), http.StatusBadRequest) + return "", model.NewAppError("DoPostActionWithCookie", "api.post.do_action.action_integration.app_error", nil, "", http.StatusBadRequest).Wrap(err) } if len(respBytes) > 0 { if err = json.Unmarshal(respBytes, &response); err != nil { - return "", model.NewAppError("DoPostActionWithCookie", "api.post.do_action.action_integration.app_error", nil, "err="+err.Error(), http.StatusBadRequest) + return "", model.NewAppError("DoPostActionWithCookie", "api.post.do_action.action_integration.app_error", nil, "", http.StatusBadRequest).Wrap(err) } } @@ -435,7 +435,7 @@ func (ch *Channels) doPluginRequest(c *request.Context, method, rawURL string, v ProtoMajor: 1, ProtoMinor: 1, Header: w.headers, - Body: ioutil.NopCloser(bytes.NewReader(w.data)), + Body: io.NopCloser(bytes.NewReader(w.data)), } if resp.StatusCode == 0 { resp.StatusCode = http.StatusOK @@ -585,14 +585,17 @@ func (a *App) DoLocalRequest(c *request.Context, rawURL string, body []byte) (*h } func (a *App) OpenInteractiveDialog(request model.OpenDialogRequest) *model.AppError { - clientTriggerId, userID, err := request.DecodeAndVerifyTriggerId(a.AsymmetricSigningKey()) - if err != nil { - return err + clientTriggerId, userID, appErr := request.DecodeAndVerifyTriggerId(a.AsymmetricSigningKey()) + if appErr != nil { + return appErr } request.TriggerId = clientTriggerId - jsonRequest, _ := json.Marshal(request) + jsonRequest, err := json.Marshal(request) + if err != nil { + a.ch.srv.GetLogger().Warn("Error encoding request", mlog.Err(err)) + } message := model.NewWebSocketEvent(model.WebsocketEventOpenDialog, "", "", userID, nil) message.Add("dialog", string(jsonRequest)) @@ -606,23 +609,19 @@ func (a *App) SubmitInteractiveDialog(c *request.Context, request model.SubmitDi request.URL = "" request.Type = "dialog_submission" - b, jsonErr := json.Marshal(request) - if jsonErr != nil { - return nil, model.NewAppError("SubmitInteractiveDialog", "app.submit_interactive_dialog.json_error", nil, jsonErr.Error(), http.StatusBadRequest) - } - - resp, err := a.DoActionRequest(c, url, b) + b, err := json.Marshal(request) if err != nil { - return nil, err + return nil, model.NewAppError("SubmitInteractiveDialog", "app.submit_interactive_dialog.json_error", nil, "", http.StatusBadRequest).Wrap(err) } + resp, appErr := a.DoActionRequest(c, url, b) + if appErr != nil { + return nil, appErr + } defer resp.Body.Close() var response model.SubmitDialogResponse - if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { - // Don't fail, an empty response is acceptable - return &response, nil - } + json.NewDecoder(resp.Body).Decode(&response) // Don't fail, an empty response is acceptable return &response, nil } diff --git a/app/integration_action_test.go b/app/integration_action_test.go index 6dde72a2be..8fa6debe5d 100644 --- a/app/integration_action_test.go +++ b/app/integration_action_test.go @@ -6,7 +6,7 @@ package app import ( "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "net/http/httptest" "net/url" @@ -1079,47 +1079,47 @@ func TestDoPluginRequest(t *testing.T) { resp, err := th.App.doPluginRequest(th.Context, "GET", "/plugins/myplugin", nil, nil) assert.Nil(t, err) require.NotNil(t, resp) - body, _ := ioutil.ReadAll(resp.Body) + body, _ := io.ReadAll(resp.Body) assert.Equal(t, "could not find param abc=xyz", string(body)) resp, err = th.App.doPluginRequest(th.Context, "GET", "/plugins/myplugin?abc=xyz", nil, nil) assert.Nil(t, err) require.NotNil(t, resp) - body, _ = ioutil.ReadAll(resp.Body) + body, _ = io.ReadAll(resp.Body) assert.Equal(t, "param multiple should have 3 values", string(body)) resp, err = th.App.doPluginRequest(th.Context, "GET", "/plugins/myplugin", url.Values{"abc": []string{"xyz"}, "multiple": []string{"1 first", "2 second", "3 third"}}, nil) assert.Nil(t, err) require.NotNil(t, resp) - body, _ = ioutil.ReadAll(resp.Body) + body, _ = io.ReadAll(resp.Body) assert.Equal(t, "OK", string(body)) resp, err = th.App.doPluginRequest(th.Context, "GET", "/plugins/myplugin?abc=xyz&multiple=1%20first", url.Values{"multiple": []string{"2 second", "3 third"}}, nil) assert.Nil(t, err) require.NotNil(t, resp) - body, _ = ioutil.ReadAll(resp.Body) + body, _ = io.ReadAll(resp.Body) assert.Equal(t, "OK", string(body)) resp, err = th.App.doPluginRequest(th.Context, "GET", "/plugins/myplugin?abc=xyz&multiple=1%20first&multiple=3%20third", url.Values{"multiple": []string{"2 second"}}, nil) assert.Nil(t, err) require.NotNil(t, resp) - body, _ = ioutil.ReadAll(resp.Body) + body, _ = io.ReadAll(resp.Body) assert.Equal(t, "OK", string(body)) resp, err = th.App.doPluginRequest(th.Context, "GET", "/plugins/myplugin?multiple=1%20first&multiple=3%20third", url.Values{"multiple": []string{"2 second"}, "abc": []string{"xyz"}}, nil) assert.Nil(t, err) require.NotNil(t, resp) - body, _ = ioutil.ReadAll(resp.Body) + body, _ = io.ReadAll(resp.Body) assert.Equal(t, "OK", string(body)) resp, err = th.App.doPluginRequest(th.Context, "GET", "/plugins/myplugin?multiple=1%20first&multiple=3%20third", url.Values{"multiple": []string{"4 fourth"}, "abc": []string{"xyz"}}, nil) assert.Nil(t, err) require.NotNil(t, resp) - body, _ = ioutil.ReadAll(resp.Body) + body, _ = io.ReadAll(resp.Body) assert.Equal(t, "param multiple not correct", string(body)) } diff --git a/app/layer_generators/main.go b/app/layer_generators/main.go index 4fe3586f06..1a15ff4318 100644 --- a/app/layer_generators/main.go +++ b/app/layer_generators/main.go @@ -10,7 +10,7 @@ import ( "go/ast" "go/parser" "go/token" - "io/ioutil" + "io" "log" "os" "path" @@ -58,7 +58,7 @@ func main() { log.Fatal(err) } - err = ioutil.WriteFile(outputFile, formattedCode, 0644) + err = os.WriteFile(outputFile, formattedCode, 0644) if err != nil { log.Fatal(err) } @@ -162,7 +162,7 @@ func extractStoreMetadata() (*storeMetadata, error) { if err != nil { return nil, fmt.Errorf("unable to open %s file: %w", inputFile, err) } - src, err := ioutil.ReadAll(file) + src, err := io.ReadAll(file) if err != nil { return nil, err } diff --git a/app/ldap.go b/app/ldap.go index 20f4fdf752..a782b4715c 100644 --- a/app/ldap.go +++ b/app/ldap.go @@ -4,7 +4,7 @@ package app import ( - "io/ioutil" + "io" "mime/multipart" "net/http" @@ -186,12 +186,12 @@ func (a *App) writeLdapFile(filename string, fileData *multipart.FileHeader) *mo } defer file.Close() - data, err := ioutil.ReadAll(file) + data, err := io.ReadAll(file) if err != nil { return model.NewAppError("AddLdapCertificate", "api.admin.add_certificate.saving.app_error", nil, err.Error(), http.StatusInternalServerError) } - err = a.Srv().configStore.SetFile(filename, data) + err = a.Srv().platform.SetConfigFile(filename, data) if err != nil { return model.NewAppError("AddLdapCertificate", "api.admin.add_certificate.saving.app_error", nil, err.Error(), http.StatusInternalServerError) } @@ -234,7 +234,7 @@ func (a *App) AddLdapPrivateCertificate(fileData *multipart.FileHeader) *model.A } func (a *App) removeLdapFile(filename string) *model.AppError { - if err := a.Srv().configStore.RemoveFile(filename); err != nil { + if err := a.Srv().platform.RemoveConfigFile(filename); err != nil { return model.NewAppError("RemoveLdapFile", "api.admin.remove_certificate.delete.app_error", map[string]any{"Filename": filename}, err.Error(), http.StatusInternalServerError) } return nil diff --git a/app/license.go b/app/license.go index c6617bd76f..bf359752cf 100644 --- a/app/license.go +++ b/app/license.go @@ -48,7 +48,7 @@ func (w *licenseWrapper) GetLicense() *model.License { } func (w *licenseWrapper) RequestTrialLicense(requesterID string, users int, termsAccepted bool, receiveEmailsAccepted bool) *model.AppError { - if *w.srv.Config().ExperimentalSettings.RestrictSystemAdmin { + if *w.srv.platform.Config().ExperimentalSettings.RestrictSystemAdmin { return model.NewAppError("RequestTrialLicense", "api.restricted_system_admin", nil, "", http.StatusForbidden) } @@ -75,8 +75,8 @@ func (w *licenseWrapper) RequestTrialLicense(requesterID string, users int, term ServerID: w.srv.TelemetryId(), Name: requester.GetDisplayName(model.ShowFullName), Email: requester.Email, - SiteName: *w.srv.Config().TeamSettings.SiteName, - SiteURL: *w.srv.Config().ServiceSettings.SiteURL, + SiteName: *w.srv.platform.Config().TeamSettings.SiteName, + SiteURL: *w.srv.platform.Config().ServiceSettings.SiteURL, Users: users, TermsAccepted: termsAccepted, ReceiveEmailsAccepted: receiveEmailsAccepted, @@ -93,6 +93,11 @@ type JWTClaims struct { jwt.StandardClaims } +func (s *Server) License() *model.License { + license, _ := s.licenseValue.Load().(*model.License) + return license +} + func (s *Server) LoadLicense() { // ENV var overrides all other sources of license. licenseStr := os.Getenv(LicenseEnv) @@ -131,7 +136,7 @@ func (s *Server) LoadLicense() { if !model.IsValidId(licenseId) { // Lets attempt to load the file from disk since it was missing from the DB - license, licenseBytes := utils.GetAndValidateLicenseFileFromDisk(*s.Config().ServiceSettings.LicenseFileLocation) + license, licenseBytes := utils.GetAndValidateLicenseFileFromDisk(*s.platform.Config().ServiceSettings.LicenseFileLocation) if license != nil { if _, err := s.SaveLicense(licenseBytes); err != nil { @@ -177,13 +182,13 @@ func (s *Server) SaveLicense(licenseBytes []byte) (*model.License, *model.AppErr return nil, model.NewAppError("addLicense", model.ExpiredLicenseError, nil, "", http.StatusBadRequest) } - if *s.Config().JobSettings.RunJobs && s.Jobs != nil { + if *s.platform.Config().JobSettings.RunJobs && s.Jobs != nil { if err := s.Jobs.StopWorkers(); err != nil && !errors.Is(err, jobs.ErrWorkersNotRunning) { mlog.Warn("Stopping job server workers failed", mlog.Err(err)) } } - if *s.Config().JobSettings.RunScheduler && s.Jobs != nil { + if *s.platform.Config().JobSettings.RunScheduler && s.Jobs != nil { if err := s.Jobs.StopSchedulers(); err != nil && !errors.Is(err, jobs.ErrSchedulersNotRunning) { mlog.Error("Stopping job server schedulers failed", mlog.Err(err)) } @@ -193,12 +198,12 @@ func (s *Server) SaveLicense(licenseBytes []byte) (*model.License, *model.AppErr // restart job server workers - this handles the edge case where a license file is uploaded, but the job server // doesn't start until the server is restarted, which prevents the 'run job now' buttons in system console from // functioning as expected - if *s.Config().JobSettings.RunJobs && s.Jobs != nil { + if *s.platform.Config().JobSettings.RunJobs && s.Jobs != nil { if err := s.Jobs.StartWorkers(); err != nil { mlog.Error("Starting job server workers failed", mlog.Err(err)) } } - if *s.Config().JobSettings.RunScheduler && s.Jobs != nil { + if *s.platform.Config().JobSettings.RunScheduler && s.Jobs != nil { if err := s.Jobs.StartSchedulers(); err != nil && !errors.Is(err, jobs.ErrSchedulersRunning) { mlog.Error("Starting job server schedulers failed", mlog.Err(err)) } @@ -233,7 +238,7 @@ func (s *Server) SaveLicense(licenseBytes []byte) (*model.License, *model.AppErr return nil, model.NewAppError("addLicense", "api.license.add_license.save_active.app_error", nil, "", http.StatusInternalServerError) } - s.ReloadConfig() + s.platform.ReloadConfig() s.InvalidateAllCaches() return &license, nil @@ -256,12 +261,20 @@ func (s *Server) SetLicense(license *model.License) bool { license.Features.SetDefaults() s.licenseValue.Store(license) + if s.platform != nil { + s.platform.SetLicense(license) + } + s.clientLicenseValue.Store(utils.GetClientLicense(license)) return true } s.licenseValue.Store((*model.License)(nil)) s.clientLicenseValue.Store(map[string]string(nil)) + if s.platform != nil { + s.platform.SetLicense((*model.License)(nil)) + } + return false } @@ -307,7 +320,7 @@ func (s *Server) RemoveLicense() *model.AppError { } s.SetLicense(nil) - s.ReloadConfig() + s.platform.ReloadConfig() s.InvalidateAllCaches() return nil @@ -329,14 +342,14 @@ func (s *Server) GetSanitizedClientLicense() map[string]string { // RequestTrialLicense request a trial license from the mattermost official license server func (s *Server) RequestTrialLicense(trialRequest *model.TrialLicenseRequest) *model.AppError { - trialRequestJSON, jsonErr := json.Marshal(trialRequest) - if jsonErr != nil { - return model.NewAppError("RequestTrialLicense", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + trialRequestJSON, err := json.Marshal(trialRequest) + if err != nil { + return model.NewAppError("RequestTrialLicense", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } resp, err := http.Post(RequestTrialURL, "application/json", bytes.NewBuffer(trialRequestJSON)) if err != nil { - return model.NewAppError("RequestTrialLicense", "api.license.request_trial_license.app_error", nil, err.Error(), http.StatusBadRequest) + return model.NewAppError("RequestTrialLicense", "api.license.request_trial_license.app_error", nil, "", http.StatusBadRequest).Wrap(err) } defer resp.Body.Close() @@ -350,7 +363,11 @@ func (s *Server) RequestTrialLicense(trialRequest *model.TrialLicenseRequest) *m fmt.Sprintf("Unexpected HTTP status code %q returned by server", resp.Status), http.StatusInternalServerError) } - licenseResponse := model.MapFromJSON(resp.Body) + var licenseResponse map[string]string + err = json.NewDecoder(resp.Body).Decode(&licenseResponse) + if err != nil { + s.GetLogger().Warn("Error decoding license response", mlog.Err(err)) + } if _, ok := licenseResponse["license"]; !ok { return model.NewAppError("RequestTrialLicense", "api.license.request_trial_license.app_error", nil, licenseResponse["message"], http.StatusBadRequest) @@ -360,7 +377,7 @@ func (s *Server) RequestTrialLicense(trialRequest *model.TrialLicenseRequest) *m return err } - s.ReloadConfig() + s.platform.ReloadConfig() s.InvalidateAllCaches() return nil diff --git a/app/migrations.go b/app/migrations.go index aba545c443..36d12302c1 100644 --- a/app/migrations.go +++ b/app/migrations.go @@ -69,9 +69,9 @@ func (s *Server) doAdvancedPermissionsMigration() { return } - config := s.Config() + config := s.platform.Config() *config.ServiceSettings.PostEditTimeLimit = -1 - if _, _, err := s.SaveConfig(config, true); err != nil { + if _, _, err := s.platform.SaveConfig(config, true); err != nil { mlog.Error("Failed to update config in Advanced Permissions Phase 1 Migration.", mlog.Err(err)) } @@ -327,7 +327,7 @@ func (s *Server) doContentExtractionConfigDefaultTrueMigration() { return } - s.UpdateConfig(func(config *model.Config) { + s.platform.UpdateConfig(func(config *model.Config) { config.FileSettings.ExtractContent = model.NewBool(true) }) @@ -474,7 +474,7 @@ const existingInstallationPostsThreshold = 10 func (s *Server) doFirstAdminSetupCompleteMigration() { // Don't run the migration until the flag is turned on. - if !s.Config().FeatureFlags.UseCaseOnboarding { + if !s.platform.Config().FeatureFlags.UseCaseOnboarding { return } diff --git a/app/notification_push.go b/app/notification_push.go index e10b716c7d..1065dbf1fe 100644 --- a/app/notification_push.go +++ b/app/notification_push.go @@ -6,14 +6,14 @@ package app import ( "bytes" "encoding/json" + "errors" + "fmt" "io" "net/http" "runtime" "strings" "sync" - "github.com/pkg/errors" - "github.com/mattermost/mattermost-server/v6/app/request" "github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/mattermost-server/v6/shared/i18n" @@ -290,7 +290,7 @@ func (a *App) UpdateMobileAppBadge(userID string) { } func (s *Server) createPushNotificationsHub(c request.CTX) { - buffer := *s.Config().EmailSettings.PushNotificationBuffer + buffer := *s.platform.Config().EmailSettings.PushNotificationBuffer hub := PushNotificationsHub{ notificationsChan: make(chan PushNotification, buffer), app: New(ServerConnector(s.Channels())), @@ -382,9 +382,9 @@ func (s *Server) StopPushNotificationsHubWorkers() { } func (a *App) rawSendToPushProxy(msg *model.PushNotification) (model.PushResponse, error) { - msgJSON, jsonErr := json.Marshal(msg) - if jsonErr != nil { - return nil, errors.Wrap(jsonErr, "failed to encode to JSON") + msgJSON, err := json.Marshal(msg) + if err != nil { + return nil, fmt.Errorf("failed to encode to JSON: %w", err) } url := strings.TrimRight(*a.Config().EmailSettings.PushNotificationServer, "/") + model.APIURLSuffixV1 + "/send_push" @@ -400,8 +400,8 @@ func (a *App) rawSendToPushProxy(msg *model.PushNotification) (model.PushRespons defer resp.Body.Close() var pushResponse model.PushResponse - if jsonErr := json.NewDecoder(resp.Body).Decode(&pushResponse); jsonErr != nil { - return nil, errors.Wrap(jsonErr, "failed to decode from JSON") + if err := json.NewDecoder(resp.Body).Decode(&pushResponse); err != nil { + return nil, fmt.Errorf("failed to decode from JSON: %w", err) } return pushResponse, nil @@ -427,7 +427,7 @@ func (a *App) sendToPushProxy(msg *model.PushNotification, session *model.Sessio case model.PushStatusRemove: a.AttachDeviceId(session.Id, "", session.ExpiresAt) a.ClearSessionCacheForUser(session.UserId) - return errors.New("Device was reported as removed") + return errors.New("device was reported as removed") case model.PushStatusFail: return errors.New(pushResponse[model.PushStatusErrorMsg]) } @@ -447,9 +447,9 @@ func (a *App) SendAckToPushProxy(ack *model.PushNotificationAck) error { mlog.String("status", model.PushReceived), ) - ackJSON, jsonErr := json.Marshal(ack) - if jsonErr != nil { - return errors.Wrap(jsonErr, "failed to encode to JSON") + ackJSON, err := json.Marshal(ack) + if err != nil { + return fmt.Errorf("failed to encode to JSON: %w", err) } request, err := http.NewRequest( @@ -457,7 +457,6 @@ func (a *App) SendAckToPushProxy(ack *model.PushNotificationAck) error { strings.TrimRight(*a.Config().EmailSettings.PushNotificationServer, "/")+model.APIURLSuffixV1+"/ack", bytes.NewReader(ackJSON), ) - if err != nil { return err } @@ -467,19 +466,16 @@ func (a *App) SendAckToPushProxy(ack *model.PushNotificationAck) error { return err } defer resp.Body.Close() + // Reading the body to completion. _, err = io.Copy(io.Discard, resp.Body) - if err != nil { - return err - } - - return nil + return err } func (a *App) getMobileAppSessions(userID string) ([]*model.Session, *model.AppError) { sessions, err := a.Srv().Store.Session().GetSessionsWithActiveDeviceIds(userID) if err != nil { - return nil, model.NewAppError("getMobileAppSessions", "app.session.get_sessions.app_error", nil, err.Error(), http.StatusInternalServerError) + return nil, model.NewAppError("getMobileAppSessions", "app.session.get_sessions.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } return sessions, nil @@ -572,7 +568,7 @@ func (a *App) BuildPushNotificationMessage(c request.CTX, contentsConfig string, unreadCount, err := a.Srv().Store.User().GetUnreadCount(user.Id) if err != nil { - return nil, model.NewAppError("BuildPushNotificationMessage", "app.user.get_unread_count.app_error", nil, err.Error(), http.StatusInternalServerError) + return nil, model.NewAppError("BuildPushNotificationMessage", "app.user.get_unread_count.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } msg.Badge = int(unreadCount) diff --git a/app/notification_push_test.go b/app/notification_push_test.go index 53ac88db13..0f3e8a157f 100644 --- a/app/notification_push_test.go +++ b/app/notification_push_test.go @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/mattermost/mattermost-server/v6/app/platform" "github.com/mattermost/mattermost-server/v6/config" "github.com/mattermost/mattermost-server/v6/model" fmocks "github.com/mattermost/mattermost-server/v6/shared/filestore/mocks" @@ -1443,9 +1444,13 @@ func TestPushNotificationRace(t *testing.T) { Router: mux.NewRouter(), filestore: &fmocks.FileBackend{}, } - s.configStore = &configWrapper{srv: s, Store: memoryStore} + var err error + s.platform, err = platform.New(platform.ServiceConfig{ + ConfigStore: memoryStore, + }) + require.NoError(t, err) serviceMap := map[ServiceKey]any{ - ConfigKey: s.configStore, + ConfigKey: s.platform, LicenseKey: &licenseWrapper{s}, FilestoreKey: s.filestore, } diff --git a/app/oauth.go b/app/oauth.go index 104fe654c6..e205641522 100644 --- a/app/oauth.go +++ b/app/oauth.go @@ -11,7 +11,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "net/http" "net/url" "strconv" @@ -853,7 +852,7 @@ func (a *App) AuthorizeOAuthUser(w http.ResponseWriter, r *http.Request, service var ar *model.AccessResponse err = json.NewDecoder(tee).Decode(&ar) if err != nil || resp.StatusCode != http.StatusOK { - return nil, "", stateProps, nil, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.bad_response.app_error", nil, fmt.Sprintf("response_body=%s, status_code=%d, error=%v", buf.String(), resp.StatusCode, err), http.StatusInternalServerError) + return nil, "", stateProps, nil, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.bad_response.app_error", nil, fmt.Sprintf("response_body=%s, status_code=%d, error=%v", buf.String(), resp.StatusCode, err), http.StatusInternalServerError).Wrap(err) } if strings.ToLower(ar.TokenType) != model.AccessTokenType { @@ -891,7 +890,7 @@ func (a *App) AuthorizeOAuthUser(w http.ResponseWriter, r *http.Request, service defer resp.Body.Close() // Ignore the error below because the resulting string will just be the empty string if bodyBytes is nil - bodyBytes, _ := ioutil.ReadAll(resp.Body) + bodyBytes, _ := io.ReadAll(resp.Body) bodyString := string(bodyBytes) mlog.Error("Error getting OAuth user", mlog.Int("response", resp.StatusCode), mlog.String("body_string", bodyString)) diff --git a/app/oauth_test.go b/app/oauth_test.go index 1d7807fa3b..57a394a710 100644 --- a/app/oauth_test.go +++ b/app/oauth_test.go @@ -7,7 +7,7 @@ import ( "encoding/base64" "encoding/json" "errors" - "io/ioutil" + "io" "net/http" "net/http/httptest" "testing" @@ -517,7 +517,7 @@ func TestAuthorizeOAuthUser(t *testing.T) { body, receivedTeamId, receivedStateProps, _, err := th.App.AuthorizeOAuthUser(&recorder, request, model.ServiceGitlab, "", state, "") require.NotNil(t, body) - bodyBytes, bodyErr := ioutil.ReadAll(body) + bodyBytes, bodyErr := io.ReadAll(body) require.NoError(t, bodyErr) assert.Equal(t, userData, string(bodyBytes)) diff --git a/app/options.go b/app/options.go index 4c35cd0478..6452fd9092 100644 --- a/app/options.go +++ b/app/options.go @@ -6,6 +6,7 @@ package app import ( "github.com/pkg/errors" + "github.com/mattermost/mattermost-server/v6/app/platform" "github.com/mattermost/mattermost-server/v6/config" "github.com/mattermost/mattermost-server/v6/einterfaces" "github.com/mattermost/mattermost-server/v6/model" @@ -52,7 +53,22 @@ func Config(dsn string, readOnly bool, configDefaults *model.Config) Option { return errors.Wrap(err, "failed to apply Config option") } - s.configStore = &configWrapper{srv: s, Store: configStore} + platformCfg := platform.ServiceConfig{ + ConfigStore: configStore, + Logger: s.Log, + StartMetrics: s.startMetrics, + Cluster: s.Cluster, + } + if metricsInterface != nil { + platformCfg.Metrics = metricsInterface(s, *configStore.Get().SqlSettings.DriverName, *configStore.Get().SqlSettings.DataSource) + } + + ps, sErr := platform.New(platformCfg) + if sErr != nil { + return errors.Wrap(sErr, "failed to initialize platform") + } + s.platform = ps + return nil } } @@ -60,7 +76,21 @@ func Config(dsn string, readOnly bool, configDefaults *model.Config) Option { // ConfigStore applies the given config store, typically to replace the traditional sources with a memory store for testing. func ConfigStore(configStore *config.Store) Option { return func(s *Server) error { - s.configStore = &configWrapper{srv: s, Store: configStore} + platformCfg := platform.ServiceConfig{ + ConfigStore: configStore, + Logger: s.Log, + StartMetrics: s.startMetrics, + Cluster: s.Cluster, + } + if metricsInterface != nil { + platformCfg.Metrics = metricsInterface(s, *configStore.Get().SqlSettings.DriverName, *configStore.Get().SqlSettings.DataSource) + } + + ps, sErr := platform.New(platformCfg) + if sErr != nil { + return errors.Wrap(sErr, "failed to initialize platform") + } + s.platform = ps return nil } diff --git a/app/platform/cluster.go b/app/platform/cluster.go new file mode 100644 index 0000000000..75fe329cea --- /dev/null +++ b/app/platform/cluster.go @@ -0,0 +1,12 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +package platform + +func (ps *PlatformService) IsLeader() bool { + if ps.License() != nil && *ps.Config().ClusterSettings.Enable && ps.cluster != nil { + return ps.cluster.IsLeader() + } + + return true +} diff --git a/app/platform/config.go b/app/platform/config.go index 20c5a823d5..fc13aa3761 100644 --- a/app/platform/config.go +++ b/app/platform/config.go @@ -5,9 +5,14 @@ package platform import ( "errors" + "fmt" + "net/http" + "reflect" "github.com/mattermost/mattermost-server/v6/config" "github.com/mattermost/mattermost-server/v6/einterfaces" + "github.com/mattermost/mattermost-server/v6/model" + "github.com/mattermost/mattermost-server/v6/product" "github.com/mattermost/mattermost-server/v6/shared/mlog" ) @@ -30,7 +35,145 @@ func (c *ServiceConfig) validate() error { } if c.Logger == nil { - return errors.New("Logger is required") + var err error + // If Logger is not set, use a default logger temporarily. + // this should be removed once the logger is properly configured with the service config. + // MM-45841 + c.Logger, err = mlog.NewLogger() + if err != nil { + return err + } } return nil } + +// ensure the config wrapper implements `product.ConfigService` +var _ product.ConfigService = (*PlatformService)(nil) + +func (ps *PlatformService) Config() *model.Config { + return ps.configStore.Get() +} + +// Registers a function with a given listener to be called when the config is reloaded and may have changed. The function +// will be called with two arguments: the old config and the new config. AddConfigListener returns a unique ID +// for the listener that can later be used to remove it. +func (ps *PlatformService) AddConfigListener(listener func(*model.Config, *model.Config)) string { + return ps.configStore.AddListener(listener) +} + +func (ps *PlatformService) RemoveConfigListener(id string) { + ps.configStore.RemoveListener(id) +} + +func (ps *PlatformService) UpdateConfig(f func(*model.Config)) { + if ps.configStore.IsReadOnly() { + return + } + old := ps.Config() + updated := old.Clone() + f(updated) + if _, _, err := ps.configStore.Set(updated); err != nil { + ps.logger.Error("Failed to update config", mlog.Err(err)) + } +} + +// SaveConfig replaces the active configuration, optionally notifying cluster peers. +// It returns both the previous and current configs. +func (ps *PlatformService) SaveConfig(newCfg *model.Config, sendConfigChangeClusterMessage bool) (*model.Config, *model.Config, *model.AppError) { + oldCfg, newCfg, err := ps.configStore.Set(newCfg) + if errors.Is(err, config.ErrReadOnlyConfiguration) { + return nil, nil, model.NewAppError("saveConfig", "ent.cluster.save_config.error", nil, err.Error(), http.StatusForbidden) + } else if err != nil { + return nil, nil, model.NewAppError("saveConfig", "app.save_config.app_error", nil, err.Error(), http.StatusInternalServerError) + } + + if ps.serviceConfig.StartMetrics && *ps.Config().MetricsSettings.Enable { + ps.RestartMetrics() + } else { + ps.ShutdownMetrics() + } + + if ps.cluster != nil { + err := ps.cluster.ConfigChanged(ps.configStore.RemoveEnvironmentOverrides(oldCfg), + ps.configStore.RemoveEnvironmentOverrides(newCfg), sendConfigChangeClusterMessage) + if err != nil { + return nil, nil, err + } + } + + return oldCfg, newCfg, nil +} + +func (ps *PlatformService) ReloadConfig() error { + if err := ps.configStore.Load(); err != nil { + return err + } + return nil +} + +func (ps *PlatformService) GetEnvironmentOverridesWithFilter(filter func(reflect.StructField) bool) map[string]interface{} { + return ps.configStore.GetEnvironmentOverridesWithFilter(filter) +} + +func (ps *PlatformService) GetEnvironmentOverrides() map[string]interface{} { + return ps.configStore.GetEnvironmentOverrides() +} + +func (ps *PlatformService) DescribeConfig() string { + return ps.configStore.String() +} + +func (ps *PlatformService) CleanUpConfig() error { + return ps.configStore.CleanUp() +} + +// ConfigureLogger applies the specified configuration to a logger. +func (ps *PlatformService) ConfigureLogger(name string, logger *mlog.Logger, logSettings *model.LogSettings, getPath func(string) string) error { + // Advanced logging is E20 only, however logging must be initialized before the license + // file is loaded. If no valid E20 license exists then advanced logging will be + // shutdown once license is loaded/checked. + var err error + dsn := *logSettings.AdvancedLoggingConfig + var logConfigSrc config.LogConfigSrc + if dsn != "" { + logConfigSrc, err = config.NewLogConfigSrc(dsn, ps.configStore) + if err != nil { + return fmt.Errorf("invalid config source for %s, %w", name, err) + } + ps.logger.Info("Loaded configuration for "+name, mlog.String("source", dsn)) + } + + cfg, err := config.MloggerConfigFromLoggerConfig(logSettings, logConfigSrc, getPath) + if err != nil { + return fmt.Errorf("invalid config source for %s, %w", name, err) + } + + if err := logger.ConfigureTargets(cfg, nil); err != nil { + return fmt.Errorf("invalid config for %s, %w", name, err) + } + return nil +} + +func (ps *PlatformService) GetConfigStore() *config.Store { + return ps.configStore +} + +func (ps *PlatformService) GetConfigFile(name string) ([]byte, error) { + return ps.configStore.GetFile(name) +} + +func (ps *PlatformService) SetConfigFile(name string, data []byte) error { + return ps.configStore.SetFile(name, data) +} + +func (ps *PlatformService) RemoveConfigFile(name string) error { + return ps.configStore.RemoveFile(name) +} + +func (ps *PlatformService) HasConfigFile(name string) (bool, error) { + return ps.configStore.HasFile(name) +} + +func (ps *PlatformService) SetConfigReadOnlyFF(readOnly bool) { + ps.configStore.SetReadOnlyFF(readOnly) +} diff --git a/app/platform/config_test.go b/app/platform/config_test.go new file mode 100644 index 0000000000..62ecbce482 --- /dev/null +++ b/app/platform/config_test.go @@ -0,0 +1,47 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +package platform + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/mattermost/mattermost-server/v6/model" +) + +func TestConfigListener(t *testing.T) { + th := Setup(t) + defer th.TearDown() + + originalSiteName := th.Service.Config().TeamSettings.SiteName + + listenerCalled := false + listener := func(oldConfig *model.Config, newConfig *model.Config) { + assert.False(t, listenerCalled, "listener called twice") + + assert.Equal(t, *originalSiteName, *oldConfig.TeamSettings.SiteName, "old config contains incorrect site name") + assert.Equal(t, "test123", *newConfig.TeamSettings.SiteName, "new config contains incorrect site name") + + listenerCalled = true + } + listenerId := th.Service.AddConfigListener(listener) + defer th.Service.RemoveConfigListener(listenerId) + + listener2Called := false + listener2 := func(oldConfig *model.Config, newConfig *model.Config) { + assert.False(t, listener2Called, "listener2 called twice") + + listener2Called = true + } + listener2Id := th.Service.AddConfigListener(listener2) + defer th.Service.RemoveConfigListener(listener2Id) + + th.Service.UpdateConfig(func(cfg *model.Config) { + *cfg.TeamSettings.SiteName = "test123" + }) + + assert.True(t, listenerCalled, "listener should've been called") + assert.True(t, listener2Called, "listener 2 should've been called") +} diff --git a/app/platform/feature_flags.go b/app/platform/feature_flags.go new file mode 100644 index 0000000000..8bcc8843d5 --- /dev/null +++ b/app/platform/feature_flags.go @@ -0,0 +1,118 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +package platform + +import ( + "encoding/json" + "os" + "time" + + "github.com/mattermost/mattermost-server/v6/app/featureflag" + "github.com/mattermost/mattermost-server/v6/shared/mlog" +) + +// SetupFeatureFlags called on startup and when the cluster leader changes. +// Starts or stops the synchronization of feature flags from upstream management. +func (ps *PlatformService) SetupFeatureFlags() { + ps.featureFlagSynchronizerMutex.Lock() + defer ps.featureFlagSynchronizerMutex.Unlock() + splitKey := *ps.Config().ServiceSettings.SplitKey + splitConfigured := splitKey != "" + syncFeatureFlags := splitConfigured && ps.IsLeader() + + ps.configStore.SetReadOnlyFF(!splitConfigured) + + if syncFeatureFlags { + if err := ps.startFeatureFlagUpdateJob(); err != nil { + ps.logger.Warn("Unable to setup synchronization with feature flag management. Will fallback to cache.", mlog.Err(err)) + } + } else { + ps.StopFeatureFlagUpdateJob() + } + + if err := ps.configStore.Load(); err != nil { + ps.logger.Warn("Unable to load config store after feature flag setup.", mlog.Err(err)) + } +} + +func (ps *PlatformService) updateFeatureFlagValuesFromManagement() { + newCfg := ps.configStore.GetNoEnv().Clone() + oldFlags := *newCfg.FeatureFlags + newFlags := ps.featureFlagSynchronizer.UpdateFeatureFlagValues(oldFlags) + oldFlagsBytes, _ := json.Marshal(oldFlags) + newFlagsBytes, _ := json.Marshal(newFlags) + ps.logger.Debug("Checking feature flags from management service", mlog.String("old_flags", string(oldFlagsBytes)), mlog.String("new_flags", string(newFlagsBytes))) + if oldFlags != newFlags { + ps.logger.Debug("Feature flag change detected, updating config") + *newCfg.FeatureFlags = newFlags + ps.SaveConfig(newCfg, true) + } +} + +func (ps *PlatformService) startFeatureFlagUpdateJob() error { + // Can be run multiple times + if ps.featureFlagSynchronizer != nil { + return nil + } + + var log *mlog.Logger + if *ps.Config().ServiceSettings.DebugSplit { + log = ps.logger + } + + attributes := map[string]any{} + + // if we are part of a cloud installation, add its installation and group id + if installationId := os.Getenv("MM_CLOUD_INSTALLATION_ID"); installationId != "" { + attributes["installation_id"] = installationId + } + if groupId := os.Getenv("MM_CLOUD_GROUP_ID"); groupId != "" { + attributes["group_id"] = groupId + } + + synchronizer, err := featureflag.NewSynchronizer(featureflag.SyncParams{ + ServerID: ps.telemetryId, + SplitKey: *ps.Config().ServiceSettings.SplitKey, + Log: log, + Attributes: attributes, + }) + if err != nil { + return err + } + + ps.featureFlagStop = make(chan struct{}) + ps.featureFlagStopped = make(chan struct{}) + ps.featureFlagSynchronizer = synchronizer + syncInterval := *ps.Config().ServiceSettings.FeatureFlagSyncIntervalSeconds + + go func() { + ticker := time.NewTicker(time.Duration(syncInterval) * time.Second) + defer ticker.Stop() + defer close(ps.featureFlagStopped) + if err := synchronizer.EnsureReady(); err != nil { + ps.logger.Warn("Problem connecting to feature flag management. Will fallback to cloud cache.", mlog.Err(err)) + return + } + ps.updateFeatureFlagValuesFromManagement() + for { + select { + case <-ps.featureFlagStop: + return + case <-ticker.C: + ps.updateFeatureFlagValuesFromManagement() + } + } + }() + + return nil +} + +func (ps *PlatformService) StopFeatureFlagUpdateJob() { + if ps.featureFlagSynchronizer != nil { + close(ps.featureFlagStop) + <-ps.featureFlagStopped + ps.featureFlagSynchronizer.Close() + ps.featureFlagSynchronizer = nil + } +} diff --git a/app/platform/helper_test.go b/app/platform/helper_test.go new file mode 100644 index 0000000000..17b053093f --- /dev/null +++ b/app/platform/helper_test.go @@ -0,0 +1,87 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +package platform + +import ( + "io/ioutil" + "path/filepath" + "testing" + + "github.com/mattermost/mattermost-server/v6/config" + "github.com/mattermost/mattermost-server/v6/model" + "github.com/mattermost/mattermost-server/v6/store" +) + +type TestHelper struct { + Service *PlatformService +} + +func Setup(tb testing.TB) *TestHelper { + if testing.Short() { + tb.SkipNow() + } + dbStore := mainHelper.GetStore() + dbStore.DropAllTables() + dbStore.MarkSystemRanUnitTests() + mainHelper.PreloadMigrations() + + return setupTestHelper(dbStore, false, true, tb) +} + +func setupTestHelper(dbStore store.Store, enterprise bool, includeCacheLayer bool, tb testing.TB) *TestHelper { + tempWorkspace, err := ioutil.TempDir("", "apptest") + if err != nil { + panic(err) + } + + configStore := config.NewTestMemoryStore() + + memoryConfig := configStore.Get() + *memoryConfig.PluginSettings.Directory = filepath.Join(tempWorkspace, "plugins") + *memoryConfig.PluginSettings.ClientDirectory = filepath.Join(tempWorkspace, "webapp") + *memoryConfig.PluginSettings.AutomaticPrepackagedPlugins = false + *memoryConfig.LogSettings.EnableSentry = false // disable error reporting during tests + *memoryConfig.AnnouncementSettings.AdminNoticesEnabled = false + *memoryConfig.AnnouncementSettings.UserNoticesEnabled = false + configStore.Set(memoryConfig) + + ps, err := New(ServiceConfig{ + ConfigStore: configStore, + }) + if err != nil { + panic(err) + } + + th := &TestHelper{ + Service: ps, + } + + // Share same configuration with app.TestHelper + th.Service.UpdateConfig(func(cfg *model.Config) { + *cfg.TeamSettings.MaxUsersPerTeam = 50 + *cfg.RateLimitSettings.Enable = false + *cfg.TeamSettings.EnableOpenServer = true + }) + + // Disable strict password requirements for test + th.Service.UpdateConfig(func(cfg *model.Config) { + *cfg.PasswordSettings.MinimumLength = 5 + *cfg.PasswordSettings.Lowercase = false + *cfg.PasswordSettings.Uppercase = false + *cfg.PasswordSettings.Symbol = false + *cfg.PasswordSettings.Number = false + }) + + if enterprise { + th.Service.SetLicense(model.NewTestLicense()) + } else { + th.Service.SetLicense(nil) + } + + return th +} + +func (th *TestHelper) TearDown() { + // Add cleaning code here +} diff --git a/app/platform/main_test.go b/app/platform/main_test.go new file mode 100644 index 0000000000..e2e91836f5 --- /dev/null +++ b/app/platform/main_test.go @@ -0,0 +1,32 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +package platform + +import ( + "flag" + "testing" + + "github.com/mattermost/mattermost-server/v6/testlib" +) + +var mainHelper *testlib.MainHelper +var replicaFlag bool + +func TestMain(m *testing.M) { + if f := flag.Lookup("mysql-replica"); f == nil { + flag.BoolVar(&replicaFlag, "mysql-replica", false, "") + flag.Parse() + } + + var options = testlib.HelperOptions{ + EnableStore: true, + EnableResources: true, + WithReadReplica: replicaFlag, + } + + mainHelper = testlib.NewMainHelperWithOptions(&options) + defer mainHelper.Close() + + mainHelper.Main(m) +} diff --git a/app/platform/server_license.go b/app/platform/server_license.go new file mode 100644 index 0000000000..3ccc95999b --- /dev/null +++ b/app/platform/server_license.go @@ -0,0 +1,19 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +package platform + +import ( + "github.com/mattermost/mattermost-server/v6/model" +) + +// License returns the license stored in the server struct. +// This should be removed with MM-45839 +func (ps *PlatformService) License() *model.License { + license, _ := ps.licenseValue.Load().(*model.License) + return license +} + +func (ps *PlatformService) SetLicense(license *model.License) { + ps.licenseValue.Store(license) +} diff --git a/app/platform/service.go b/app/platform/service.go index baa4b1362e..2db592adc2 100644 --- a/app/platform/service.go +++ b/app/platform/service.go @@ -4,6 +4,11 @@ package platform import ( + "fmt" + "sync" + "sync/atomic" + + "github.com/mattermost/mattermost-server/v6/app/featureflag" "github.com/mattermost/mattermost-server/v6/config" "github.com/mattermost/mattermost-server/v6/einterfaces" "github.com/mattermost/mattermost-server/v6/shared/mlog" @@ -19,6 +24,14 @@ type PlatformService struct { metrics *platformMetrics + featureFlagSynchronizerMutex sync.Mutex + featureFlagSynchronizer *featureflag.Synchronizer + featureFlagStop chan struct{} + featureFlagStopped chan struct{} + + licenseValue atomic.Value + telemetryId string + cluster einterfaces.ClusterInterface } @@ -49,3 +62,18 @@ func (ps *PlatformService) ShutdownMetrics() error { return nil } + +func (ps *PlatformService) ShutdownConfig() error { + if ps.configStore != nil { + err := ps.configStore.Close() + if err != nil { + return fmt.Errorf("failed to close config store: %w", err) + } + } + + return nil +} + +func (ps *PlatformService) SetTelemetryId(id string) { + ps.telemetryId = id +} diff --git a/app/plugin.go b/app/plugin.go index 38be469d17..2775eb0d86 100644 --- a/app/plugin.go +++ b/app/plugin.go @@ -7,7 +7,6 @@ import ( "encoding/base64" "fmt" "io" - "io/ioutil" "net/http" "os" "path/filepath" @@ -39,7 +38,7 @@ type pluginSignaturePath struct { signaturePath string } -//Ensure routerService implements `product.RouterService` +// Ensure routerService implements `product.RouterService` var _ product.RouterService = (*routerService)(nil) type routerService struct { @@ -976,7 +975,7 @@ func (ch *Channels) processPrepackagedPlugin(pluginPath *pluginSignaturePath) (* } defer fileReader.Close() - tmpDir, err := ioutil.TempDir("", "plugintmp") + tmpDir, err := os.MkdirTemp("", "plugintmp") if err != nil { return nil, errors.Wrap(err, "Failed to create temp dir plugintmp") } @@ -1086,7 +1085,7 @@ func getPrepackagedPlugin(pluginPath *pluginSignaturePath, pluginFile io.ReadSee if sigErr != nil { return nil, "", errors.Wrapf(sigErr, "Failed to open prepackaged plugin signature %s", sig) } - bytes, sigErr := ioutil.ReadAll(sigReader) + bytes, sigErr := io.ReadAll(sigReader) if sigErr != nil { return nil, "", errors.Wrapf(sigErr, "Failed to read prepackaged plugin signature %s", sig) } @@ -1105,7 +1104,7 @@ func getPrepackagedPlugin(pluginPath *pluginSignaturePath, pluginFile io.ReadSee } func getIcon(iconPath string) (string, error) { - icon, err := ioutil.ReadFile(iconPath) + icon, err := os.ReadFile(iconPath) if err != nil { return "", errors.Wrapf(err, "failed to open icon at path %s", iconPath) } diff --git a/app/plugin_api.go b/app/plugin_api.go index d42d08613d..f2afc5e7ce 100644 --- a/app/plugin_api.go +++ b/app/plugin_api.go @@ -8,7 +8,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "net/http" "net/url" "path/filepath" @@ -897,7 +896,7 @@ func (api *PluginAPI) InstallPlugin(file io.Reader, replace bool) (*model.Manife return nil, model.NewAppError("installPlugin", "app.plugin.upload_disabled.app_error", nil, "", http.StatusNotImplemented) } - fileBuffer, err := ioutil.ReadAll(file) + fileBuffer, err := io.ReadAll(file) if err != nil { return nil, model.NewAppError("InstallPlugin", "api.plugin.upload.file.app_error", nil, "", http.StatusBadRequest) } @@ -1029,7 +1028,7 @@ func (api *PluginAPI) PluginHTTP(request *http.Request) *http.Response { if len(split) != 3 { return &http.Response{ StatusCode: http.StatusBadRequest, - Body: ioutil.NopCloser(bytes.NewBufferString("Not enough URL. Form of URL should be //*")), + Body: io.NopCloser(bytes.NewBufferString("Not enough URL. Form of URL should be //*")), } } destinationPluginId := split[1] @@ -1043,7 +1042,7 @@ func (api *PluginAPI) PluginHTTP(request *http.Request) *http.Response { } return &http.Response{ StatusCode: http.StatusBadRequest, - Body: ioutil.NopCloser(bytes.NewBufferString(message)), + Body: io.NopCloser(bytes.NewBufferString(message)), } } responseTransfer := &PluginResponseWriter{} diff --git a/app/plugin_api_test.go b/app/plugin_api_test.go index 6bb40a78cd..541d0f3a18 100644 --- a/app/plugin_api_test.go +++ b/app/plugin_api_test.go @@ -11,7 +11,7 @@ import ( "image" "image/color" "image/png" - "io/ioutil" + "io" "net/http" "net/http/httptest" "os" @@ -70,7 +70,7 @@ func setDefaultPluginConfig(th *TestHelper, pluginID string) { } func setupMultiPluginAPITest(t *testing.T, pluginCodes []string, pluginManifests []string, pluginIDs []string, asMain bool, app *App, c *request.Context) string { - pluginDir, err := ioutil.TempDir("", "") + pluginDir, err := os.MkdirTemp("", "") require.NoError(t, err) t.Cleanup(func() { err = os.RemoveAll(pluginDir) @@ -79,7 +79,7 @@ func setupMultiPluginAPITest(t *testing.T, pluginCodes []string, pluginManifests } }) - webappPluginDir, err := ioutil.TempDir("", "") + webappPluginDir, err := os.MkdirTemp("", "") require.NoError(t, err) t.Cleanup(func() { err = os.RemoveAll(webappPluginDir) @@ -106,7 +106,7 @@ func setupMultiPluginAPITest(t *testing.T, pluginCodes []string, pluginManifests utils.CompileGoTest(t, pluginCodes[i], backend) } - ioutil.WriteFile(filepath.Join(pluginDir, pluginID, "plugin.json"), []byte(pluginManifests[i]), 0600) + os.WriteFile(filepath.Join(pluginDir, pluginID, "plugin.json"), []byte(pluginManifests[i]), 0600) manifest, activated, reterr := env.Activate(pluginID) require.NoError(t, reterr) require.NotNil(t, manifest) @@ -841,9 +841,9 @@ func TestPluginAPIGetPlugins(t *testing.T) { } ` - pluginDir, err := ioutil.TempDir("", "") + pluginDir, err := os.MkdirTemp("", "") require.NoError(t, err) - webappPluginDir, err := ioutil.TempDir("", "") + webappPluginDir, err := os.MkdirTemp("", "") require.NoError(t, err) defer os.RemoveAll(pluginDir) defer os.RemoveAll(webappPluginDir) @@ -857,7 +857,7 @@ func TestPluginAPIGetPlugins(t *testing.T) { backend := filepath.Join(pluginDir, pluginID, "backend.exe") utils.CompileGo(t, pluginCode, backend) - ioutil.WriteFile(filepath.Join(pluginDir, pluginID, "plugin.json"), []byte(fmt.Sprintf(`{"id": "%s", "server": {"executable": "backend.exe"}}`, pluginID)), 0600) + os.WriteFile(filepath.Join(pluginDir, pluginID, "plugin.json"), []byte(fmt.Sprintf(`{"id": "%s", "server": {"executable": "backend.exe"}}`, pluginID)), 0600) manifest, activated, reterr := env.Activate(pluginID) require.NoError(t, reterr) @@ -884,7 +884,7 @@ func TestPluginAPIInstallPlugin(t *testing.T) { api := th.SetupPluginAPI() path, _ := fileutils.FindDir("tests") - tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin.tar.gz")) + tarData, err := os.ReadFile(filepath.Join(path, "testplugin.tar.gz")) require.NoError(t, err) _, appErr := api.InstallPlugin(bytes.NewReader(tarData), true) @@ -922,9 +922,9 @@ func TestInstallPlugin(t *testing.T) { // since it removes plugin dirs right after it returns, does not update App configs with the plugin // dirs and this behavior tends to break this test as a result. setupTest := func(t *testing.T, pluginCode string, pluginManifest string, pluginID string, app *App, c *request.Context) (func(), string) { - pluginDir, err := ioutil.TempDir("", "") + pluginDir, err := os.MkdirTemp("", "") require.NoError(t, err) - webappPluginDir, err := ioutil.TempDir("", "") + webappPluginDir, err := os.MkdirTemp("", "") require.NoError(t, err) app.UpdateConfig(func(cfg *model.Config) { @@ -944,7 +944,7 @@ func TestInstallPlugin(t *testing.T) { backend := filepath.Join(pluginDir, pluginID, "backend.exe") utils.CompileGo(t, pluginCode, backend) - ioutil.WriteFile(filepath.Join(pluginDir, pluginID, "plugin.json"), []byte(pluginManifest), 0600) + os.WriteFile(filepath.Join(pluginDir, pluginID, "plugin.json"), []byte(pluginManifest), 0600) manifest, activated, reterr := env.Activate(pluginID) require.NoError(t, reterr) require.NotNil(t, manifest) @@ -1126,7 +1126,7 @@ func TestPluginAPIRemoveTeamIcon(t *testing.T) { } func pluginAPIHookTest(t *testing.T, th *TestHelper, fileName string, id string, settingsSchema string) error { - data, err := ioutil.ReadFile(fileName) + data, err := os.ReadFile(fileName) if err != nil { return err } @@ -1161,7 +1161,7 @@ func TestBasicAPIPlugins(t *testing.T) { defaultSchema := getDefaultPluginSettingsSchema() testFolder, found := fileutils.FindDir("mattermost-server/app/plugin_api_tests") require.True(t, found, "Cannot read find app folder") - dirs, err := ioutil.ReadDir(testFolder) + dirs, err := os.ReadDir(testFolder) require.NoError(t, err, "Cannot read test folder %v", testFolder) for _, dir := range dirs { d := dir.Name() @@ -1523,7 +1523,7 @@ func TestInterpluginPluginHTTP(t *testing.T) { "github.com/mattermost/mattermost-server/v6/model" "bytes" "net/http" - "io/ioutil" + "io" ) type MyPlugin struct { @@ -1545,7 +1545,7 @@ func TestInterpluginPluginHTTP(t *testing.T) { if resp.Body == nil { return nil, "Nil body" } - respbody, err := ioutil.ReadAll(resp.Body) + respbody, err := io.ReadAll(resp.Body) if err != nil { return nil, err.Error() } @@ -1605,9 +1605,9 @@ func TestAPIMetrics(t *testing.T) { t.Run("", func(t *testing.T) { metricsMock := &mocks.MetricsInterface{} - pluginDir, err := ioutil.TempDir("", "") + pluginDir, err := os.MkdirTemp("", "") require.NoError(t, err) - webappPluginDir, err := ioutil.TempDir("", "") + webappPluginDir, err := os.MkdirTemp("", "") require.NoError(t, err) defer os.RemoveAll(pluginDir) defer os.RemoveAll(webappPluginDir) @@ -1642,7 +1642,7 @@ func TestAPIMetrics(t *testing.T) { } ` utils.CompileGo(t, code, backend) - ioutil.WriteFile(filepath.Join(pluginDir, pluginID, "plugin.json"), []byte(`{"id": "`+pluginID+`", "server": {"executable": "backend.exe"}}`), 0600) + os.WriteFile(filepath.Join(pluginDir, pluginID, "plugin.json"), []byte(`{"id": "`+pluginID+`", "server": {"executable": "backend.exe"}}`), 0600) // Don't care about these mocks metricsMock.On("ObservePluginHookDuration", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return() @@ -1730,7 +1730,7 @@ func TestPluginHTTPConnHijack(t *testing.T) { require.True(t, found, "Cannot find tests folder") fullPath := path.Join(testFolder, "manual.test_http_hijack_plugin", "main.go") - pluginCode, err := ioutil.ReadFile(fullPath) + pluginCode, err := os.ReadFile(fullPath) require.NoError(t, err) require.NotEmpty(t, pluginCode) @@ -1752,7 +1752,7 @@ func TestPluginHTTPConnHijack(t *testing.T) { defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) require.NoError(t, err) require.Equal(t, "OK", string(body)) } @@ -1765,7 +1765,7 @@ func TestPluginHTTPUpgradeWebSocket(t *testing.T) { require.True(t, found, "Cannot find tests folder") fullPath := path.Join(testFolder, "manual.test_http_upgrade_websocket_plugin", "main.go") - pluginCode, err := ioutil.ReadFile(fullPath) + pluginCode, err := os.ReadFile(fullPath) require.NoError(t, err) require.NotEmpty(t, pluginCode) diff --git a/app/plugin_hooks_test.go b/app/plugin_hooks_test.go index e4eaa4d23e..b6e26b562f 100644 --- a/app/plugin_hooks_test.go +++ b/app/plugin_hooks_test.go @@ -7,7 +7,6 @@ import ( "bytes" "context" "io" - "io/ioutil" "net/http" "net/http/httptest" "os" @@ -29,9 +28,9 @@ import ( ) func SetAppEnvironmentWithPlugins(t *testing.T, pluginCode []string, app *App, apiFunc func(*model.Manifest) plugin.API) (func(), []string, []error) { - pluginDir, err := ioutil.TempDir("", "") + pluginDir, err := os.MkdirTemp("", "") require.NoError(t, err) - webappPluginDir, err := ioutil.TempDir("", "") + webappPluginDir, err := os.MkdirTemp("", "") require.NoError(t, err) env, err := plugin.NewEnvironment(apiFunc, NewDriverImpl(app.Srv()), pluginDir, webappPluginDir, app.Log(), nil) @@ -45,7 +44,7 @@ func SetAppEnvironmentWithPlugins(t *testing.T, pluginCode []string, app *App, a backend := filepath.Join(pluginDir, pluginID, "backend.exe") utils.CompileGo(t, code, backend) - ioutil.WriteFile(filepath.Join(pluginDir, pluginID, "plugin.json"), []byte(`{"id": "`+pluginID+`", "server": {"executable": "backend.exe"}}`), 0600) + os.WriteFile(filepath.Join(pluginDir, pluginID, "plugin.json"), []byte(`{"id": "`+pluginID+`", "server": {"executable": "backend.exe"}}`), 0600) _, _, activationErr := env.Activate(pluginID) pluginIDs = append(pluginIDs, pluginID) activationErrors = append(activationErrors, activationErr) @@ -1024,9 +1023,9 @@ func TestHookMetrics(t *testing.T) { t.Run("", func(t *testing.T) { metricsMock := &mocks.MetricsInterface{} - pluginDir, err := ioutil.TempDir("", "") + pluginDir, err := os.MkdirTemp("", "") require.NoError(t, err) - webappPluginDir, err := ioutil.TempDir("", "") + webappPluginDir, err := os.MkdirTemp("", "") require.NoError(t, err) defer os.RemoveAll(pluginDir) defer os.RemoveAll(webappPluginDir) @@ -1069,7 +1068,7 @@ func TestHookMetrics(t *testing.T) { } ` utils.CompileGo(t, code, backend) - ioutil.WriteFile(filepath.Join(pluginDir, pluginID, "plugin.json"), []byte(`{"id": "`+pluginID+`", "server": {"executable": "backend.exe"}}`), 0600) + os.WriteFile(filepath.Join(pluginDir, pluginID, "plugin.json"), []byte(`{"id": "`+pluginID+`", "server": {"executable": "backend.exe"}}`), 0600) // Setup mocks before activating metricsMock.On("ObservePluginHookDuration", pluginID, "Implemented", true, mock.Anything).Return() diff --git a/app/plugin_install.go b/app/plugin_install.go index 73d6a9e20f..12eb1f3046 100644 --- a/app/plugin_install.go +++ b/app/plugin_install.go @@ -33,14 +33,12 @@ // Prepackaged plugins are included with the server. They otherwise follow the above flow, except do not get uploaded // to the filestore. Prepackaged plugins override all other plugins with the same plugin id, but only when the prepackaged // plugin is newer. Managed plugins unconditionally override unmanaged plugins with the same plugin id. -// package app import ( "bytes" "fmt" "io" - "io/ioutil" "net/http" "os" "path/filepath" @@ -280,7 +278,7 @@ func (ch *Channels) installPluginLocally(pluginFile, signature io.ReadSeeker, in } } - tmpDir, err := ioutil.TempDir("", "plugintmp") + tmpDir, err := os.MkdirTemp("", "plugintmp") if err != nil { return nil, model.NewAppError("installPluginLocally", "app.plugin.filesystem.app_error", nil, err.Error(), http.StatusInternalServerError) } @@ -305,7 +303,7 @@ func extractPlugin(pluginFile io.ReadSeeker, extractDir string) (*model.Manifest return nil, "", model.NewAppError("extractPlugin", "app.plugin.extract.app_error", nil, err.Error(), http.StatusBadRequest) } - dir, err := ioutil.ReadDir(extractDir) + dir, err := os.ReadDir(extractDir) if err != nil { return nil, "", model.NewAppError("extractPlugin", "app.plugin.filesystem.app_error", nil, err.Error(), http.StatusInternalServerError) } diff --git a/app/plugin_requests.go b/app/plugin_requests.go index 17301c54ce..5e75a10457 100644 --- a/app/plugin_requests.go +++ b/app/plugin_requests.go @@ -6,7 +6,7 @@ package app import ( "bytes" "fmt" - "io/ioutil" + "io" "net/http" "path" "path/filepath" @@ -157,11 +157,11 @@ func (ch *Channels) servePluginRequest(w http.ResponseWriter, r *http.Request, h sentToken := "" if r.Header.Get(model.HeaderCsrfToken) == "" { - bodyBytes, _ := ioutil.ReadAll(r.Body) - r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes)) + bodyBytes, _ := io.ReadAll(r.Body) + r.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) r.ParseForm() sentToken = r.FormValue("csrf") - r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes)) + r.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) } else { sentToken = r.Header.Get(model.HeaderCsrfToken) } diff --git a/app/plugin_signature.go b/app/plugin_signature.go index 6dab66efb8..bedb6946a1 100644 --- a/app/plugin_signature.go +++ b/app/plugin_signature.go @@ -6,7 +6,6 @@ package app import ( "bytes" "io" - "io/ioutil" "net/http" "path/filepath" @@ -25,7 +24,7 @@ func (a *App) GetPublicKey(name string) ([]byte, *model.AppError) { } func (s *Server) getPublicKey(name string) ([]byte, *model.AppError) { - data, err := s.configStore.GetFile(name) + data, err := s.platform.GetConfigFile(name) if err != nil { return nil, model.NewAppError("GetPublicKey", "app.plugin.get_public_key.get_file.app_error", nil, err.Error(), http.StatusInternalServerError) } @@ -37,11 +36,11 @@ func (a *App) AddPublicKey(name string, key io.Reader) *model.AppError { if isSamlFile(&a.Config().SamlSettings, name) { return model.NewAppError("AddPublicKey", "app.plugin.modify_saml.app_error", nil, "", http.StatusInternalServerError) } - data, err := ioutil.ReadAll(key) + data, err := io.ReadAll(key) if err != nil { return model.NewAppError("AddPublicKey", "app.plugin.write_file.read.app_error", nil, err.Error(), http.StatusInternalServerError) } - err = a.Srv().configStore.SetFile(name, data) + err = a.Srv().platform.SetConfigFile(name, data) if err != nil { return model.NewAppError("AddPublicKey", "app.plugin.write_file.saving.app_error", nil, err.Error(), http.StatusInternalServerError) } @@ -61,7 +60,7 @@ func (a *App) DeletePublicKey(name string) *model.AppError { return model.NewAppError("AddPublicKey", "app.plugin.modify_saml.app_error", nil, "", http.StatusInternalServerError) } filename := filepath.Base(name) - if err := a.Srv().configStore.RemoveFile(filename); err != nil { + if err := a.Srv().platform.RemoveConfigFile(filename); err != nil { return model.NewAppError("DeletePublicKey", "app.plugin.delete_public_key.delete.app_error", nil, err.Error(), http.StatusInternalServerError) } @@ -122,7 +121,7 @@ func verifyBinarySignature(publicKey, signedFile, signature io.Reader) error { } func decodeIfArmored(reader io.Reader) (io.Reader, error) { - readBytes, err := ioutil.ReadAll(reader) + readBytes, err := io.ReadAll(reader) if err != nil { return nil, errors.Wrap(err, "can't read the file") } diff --git a/app/plugin_signature_test.go b/app/plugin_signature_test.go index f1b0d31d1d..20e50bc414 100644 --- a/app/plugin_signature_test.go +++ b/app/plugin_signature_test.go @@ -4,7 +4,6 @@ package app import ( - "io/ioutil" "os" "path/filepath" "testing" @@ -38,7 +37,7 @@ func TestPluginPublicKeys(t *testing.T) { path, _ := fileutils.FindDir("tests") publicKeyFilename := "test-public-key.plugin.gpg" - publicKey, err := ioutil.ReadFile(filepath.Join(path, publicKeyFilename)) + publicKey, err := os.ReadFile(filepath.Join(path, publicKeyFilename)) require.NoError(t, err) fileReader, err := os.Open(filepath.Join(path, publicKeyFilename)) require.NoError(t, err) diff --git a/app/plugin_test.go b/app/plugin_test.go index d5b21aefe5..47f7a2a86a 100644 --- a/app/plugin_test.go +++ b/app/plugin_test.go @@ -9,7 +9,7 @@ import ( "encoding/base64" "errors" "fmt" - "io/ioutil" + "io" "net/http" "net/http/httptest" "os" @@ -384,7 +384,7 @@ func TestPrivateServePluginRequest(t *testing.T) { handler := func(context *plugin.Context, w http.ResponseWriter, r *http.Request) { assert.Equal(t, testCase.ExpectedURL, r.URL.Path) - body, _ := ioutil.ReadAll(r.Body) + body, _ := io.ReadAll(r.Body) assert.Equal(t, expectedBody, body) } @@ -827,7 +827,7 @@ func TestProcessPrepackagedPlugins(t *testing.T) { t.Run("automatic, enabled plugin, no signature", func(t *testing.T) { // Install the plugin and enable - pluginBytes, err := ioutil.ReadFile(testPluginPath) + pluginBytes, err := os.ReadFile(testPluginPath) require.NoError(t, err) require.NotNil(t, pluginBytes) @@ -935,7 +935,7 @@ func TestProcessPrepackagedPlugins(t *testing.T) { require.NoError(t, err) // Install first plugin and enable - pluginBytes, err := ioutil.ReadFile(testPluginPath) + pluginBytes, err := os.ReadFile(testPluginPath) require.NoError(t, err) require.NotNil(t, pluginBytes) diff --git a/app/post.go b/app/post.go index beabd25da0..51a097933a 100644 --- a/app/post.go +++ b/app/post.go @@ -251,7 +251,7 @@ func (a *App) CreatePost(c request.CTX, post *model.Post, channel *model.Channel post.AddProp("attachments", attachmentsInterface) } if err != nil { - mlog.Warn("Could not convert post attachments to map interface.", mlog.Err(err)) + c.Logger().Warn("Could not convert post attachments to map interface.", mlog.Err(err)) } } @@ -329,7 +329,7 @@ func (a *App) CreatePost(c request.CTX, post *model.Post, channel *model.Channel if len(post.FileIds) > 0 { if err = a.attachFilesToPost(post); err != nil { - mlog.Warn("Encountered error attaching files to post", mlog.String("post_id", post.Id), mlog.Any("file_ids", post.FileIds), mlog.Err(err)) + c.Logger().Warn("Encountered error attaching files to post", mlog.String("post_id", post.Id), mlog.Any("file_ids", post.FileIds), mlog.Err(err)) } if a.Metrics() != nil { @@ -348,12 +348,12 @@ func (a *App) CreatePost(c request.CTX, post *model.Post, channel *model.Channel UpdateFollowing: true, }) if err != nil { - mlog.Warn("Failed to update thread membership", mlog.Err(err)) + c.Logger().Warn("Failed to update thread membership", mlog.Err(err)) } } if err := a.handlePostEvents(c, rpost, user, channel, triggerWebhooks, parentPostList, setOnline); err != nil { - mlog.Warn("Failed to handle post events", mlog.Err(err)) + c.Logger().Warn("Failed to handle post events", mlog.Err(err)) } // Send any ephemeral posts after the post is created to ensure it shows up after the latest post created @@ -1224,34 +1224,35 @@ func (a *App) GetPostsForChannelAroundLastUnread(c request.CTX, channelID, userI } func (a *App) DeletePost(c request.CTX, postID, deleteByID string) (*model.Post, *model.AppError) { - post, nErr := a.Srv().Store.Post().GetSingle(postID, false) - if nErr != nil { - return nil, model.NewAppError("DeletePost", "app.post.get.app_error", nil, nErr.Error(), http.StatusBadRequest) + post, err := a.Srv().Store.Post().GetSingle(postID, false) + if err != nil { + return nil, model.NewAppError("DeletePost", "app.post.get.app_error", nil, err.Error(), http.StatusBadRequest) } - channel, err := a.GetChannel(c, post.ChannelId) - if err != nil { - return nil, err + channel, appErr := a.GetChannel(c, post.ChannelId) + if appErr != nil { + return nil, appErr } if channel.DeleteAt != 0 { - err := model.NewAppError("DeletePost", "api.post.delete_post.can_not_delete_post_in_deleted.error", nil, "", http.StatusBadRequest) - return nil, err + appErr := model.NewAppError("DeletePost", "api.post.delete_post.can_not_delete_post_in_deleted.error", nil, "", http.StatusBadRequest) + return nil, appErr } - if err := a.Srv().Store.Post().Delete(postID, model.GetMillis(), deleteByID); err != nil { + err = a.Srv().Store.Post().Delete(postID, model.GetMillis(), deleteByID) + if err != nil { var nfErr *store.ErrNotFound switch { case errors.As(err, &nfErr): - return nil, model.NewAppError("DeletePost", "app.post.delete.app_error", nil, nfErr.Error(), http.StatusNotFound) + return nil, model.NewAppError("DeletePost", "app.post.delete.app_error", nil, "", http.StatusNotFound).Wrap(nfErr) default: - return nil, model.NewAppError("DeletePost", "app.post.delete.app_error", nil, err.Error(), http.StatusInternalServerError) + return nil, model.NewAppError("DeletePost", "app.post.delete.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } } - postJSON, jsonErr := json.Marshal(post) - if jsonErr != nil { - return nil, model.NewAppError("DeletePost", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr) + postJSON, err := json.Marshal(post) + if err != nil { + return nil, model.NewAppError("DeletePost", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } userMessage := model.NewWebSocketEvent(model.WebsocketEventPostDeleted, "", post.ChannelId, "", nil) @@ -1283,14 +1284,14 @@ func (a *App) DeletePost(c request.CTX, postID, deleteByID string) (*model.Post, func (a *App) deleteFlaggedPosts(postID string) { if err := a.Srv().Store.Preference().DeleteCategoryAndName(model.PreferenceCategoryFlaggedPost, postID); err != nil { - mlog.Warn("Unable to delete flagged post preference when deleting post.", mlog.Err(err)) + a.Log().Warn("Unable to delete flagged post preference when deleting post.", mlog.Err(err)) return } } func (a *App) deletePostFiles(postID string) { if _, err := a.Srv().Store.FileInfo().DeleteForPost(postID); err != nil { - mlog.Warn("Encountered error when deleting files for post", mlog.String("post_id", postID), mlog.Err(err)) + a.Log().Warn("Encountered error when deleting files for post", mlog.String("post_id", postID), mlog.Err(err)) } } @@ -1358,7 +1359,7 @@ func (a *App) searchPostsInTeam(teamID string, userID string, paramsList []*mode for result := range pchan { if result.NErr != nil { - return nil, model.NewAppError("searchPostsInTeam", "app.post.search.app_error", nil, result.NErr.Error(), http.StatusInternalServerError) + return nil, model.NewAppError("searchPostsInTeam", "app.post.search.app_error", nil, "", http.StatusInternalServerError).Wrap(result.NErr) } data := result.Data.(*model.PostList) posts.Extend(data) @@ -1375,7 +1376,7 @@ func (a *App) convertChannelNamesToChannelIds(c *request.Context, channels []str for idx, channelName := range channels { channel, err := a.parseAndFetchChannelIdByNameFromInFilter(c, channelName, userID, teamID, includeDeletedChannels) if err != nil { - mlog.Warn("error getting channel id by name from in filter", mlog.Err(err)) + a.Log().Warn("error getting channel id by name from in filter", mlog.Err(err)) continue } channels[idx] = channel.Id @@ -1387,7 +1388,7 @@ func (a *App) convertUserNameToUserIds(usernames []string) []string { for idx, username := range usernames { user, err := a.GetUserByUsername(username) if err != nil { - mlog.Warn("error getting user by username", mlog.String("user_name", username), mlog.Err(err)) + a.Log().Warn("error getting user by username", mlog.String("user_name", username), mlog.Err(err)) continue } usernames[idx] = user.Id @@ -1410,13 +1411,13 @@ func (a *App) GetLastAccessiblePostTime() (int64, *model.AppError) { // All posts are accessible return 0, nil default: - return 0, model.NewAppError("GetLastAccessiblePostTime", "app.system.get_by_name.app_error", nil, err.Error(), http.StatusInternalServerError) + return 0, model.NewAppError("GetLastAccessiblePostTime", "app.system.get_by_name.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } } lastAccessiblePostTime, err := strconv.ParseInt(system.Value, 10, 64) if err != nil { - return 0, model.NewAppError("GetLastAccessiblePostTime", "common.parse_error_int64", map[string]interface{}{"Value": system.Value}, err.Error(), http.StatusInternalServerError) + return 0, model.NewAppError("GetLastAccessiblePostTime", "common.parse_error_int64", map[string]interface{}{"Value": system.Value}, "", http.StatusInternalServerError).Wrap(err) } return lastAccessiblePostTime, nil @@ -1434,7 +1435,7 @@ func (a *App) ComputeLastAccessiblePostTime() error { if err != nil { var nfErr *store.ErrNotFound if !errors.As(err, &nfErr) { - return model.NewAppError("ComputeLastAccessiblePostTime", "app.last_accessible_post.app_error", nil, err.Error(), http.StatusInternalServerError) + return model.NewAppError("ComputeLastAccessiblePostTime", "app.last_accessible_post.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } } @@ -1444,7 +1445,7 @@ func (a *App) ComputeLastAccessiblePostTime() error { Value: strconv.FormatInt(createdAt, 10), }) if err != nil { - return model.NewAppError("ComputeLastAccessiblePostTime", "app.system.save.app_error", nil, err.Error(), http.StatusInternalServerError) + return model.NewAppError("ComputeLastAccessiblePostTime", "app.system.save.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } return nil @@ -1458,7 +1459,7 @@ func (a *App) getCloudMessagesHistoryLimit() (int64, *model.AppError) { limits, err := a.Cloud().GetCloudLimits("") if err != nil { - return 0, model.NewAppError("getCloudMessagesHistoryLimit", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + return 0, model.NewAppError("getCloudMessagesHistoryLimit", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } if limits == nil || limits.Messages == nil || limits.Messages.History == nil { @@ -1516,14 +1517,14 @@ func (a *App) SearchPostsForUser(c *request.Context, terms string, userID string return model.MakePostSearchResults(model.NewPostList(), nil), nil } - postSearchResults, nErr := a.Srv().Store.Post().SearchPostsForUser(finalParamsList, userID, teamID, page, perPage) - if nErr != nil { + postSearchResults, err := a.Srv().Store.Post().SearchPostsForUser(finalParamsList, userID, teamID, page, perPage) + if err != nil { var appErr *model.AppError switch { - case errors.As(nErr, &appErr): + case errors.As(err, &appErr): return nil, appErr default: - return nil, model.NewAppError("SearchPostsForUser", "app.post.search.app_error", nil, nErr.Error(), http.StatusInternalServerError) + return nil, model.NewAppError("SearchPostsForUser", "app.post.search.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } } @@ -1535,9 +1536,9 @@ func (a *App) SearchPostsForUser(c *request.Context, terms string, userID string } func (a *App) GetRecentSearchesForUser(userID string) ([]*model.SearchParams, *model.AppError) { - searchParams, nErr := a.Srv().Store.Post().GetRecentSearchesForUser(userID) - if nErr != nil { - return nil, model.NewAppError("GetRecentSearchesForUser", "app.recent_searches.app_error", nil, nErr.Error(), http.StatusInternalServerError) + searchParams, err := a.Srv().Store.Post().GetRecentSearchesForUser(userID) + if err != nil { + return nil, model.NewAppError("GetRecentSearchesForUser", "app.recent_searches.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } return searchParams, nil diff --git a/app/post_metadata.go b/app/post_metadata.go index 05996e9b0a..f7155e0a7c 100644 --- a/app/post_metadata.go +++ b/app/post_metadata.go @@ -41,7 +41,7 @@ var linkCache = cache.NewLRU(cache.LRUOptions{ func (s *Server) initPostMetadata() { // Dump any cached links if the proxy settings have changed so image URLs can be updated - s.AddConfigListener(func(before, after *model.Config) { + s.platform.AddConfigListener(func(before, after *model.Config) { if (before.ImageProxySettings.Enable != after.ImageProxySettings.Enable) || (before.ImageProxySettings.ImageProxyType != after.ImageProxySettings.ImageProxyType) || (before.ImageProxySettings.RemoteImageProxyURL != after.ImageProxySettings.RemoteImageProxyURL) || diff --git a/app/post_metadata_test.go b/app/post_metadata_test.go index 3bf8ebf334..63ee5c99d6 100644 --- a/app/post_metadata_test.go +++ b/app/post_metadata_test.go @@ -796,7 +796,7 @@ func TestPreparePostForClientWithImageProxy(t *testing.T) { *cfg.ImageProxySettings.RemoteImageProxyOptions = "foo" }) - th.App.ch.imageProxy = imageproxy.MakeImageProxy(th.Server, th.Server.HTTPService(), th.Server.Log) + th.App.ch.imageProxy = imageproxy.MakeImageProxy(th.Server.platform, th.Server.HTTPService(), th.Server.Log) return th } diff --git a/app/post_test.go b/app/post_test.go index f8b12ed746..f144b894ca 100644 --- a/app/post_test.go +++ b/app/post_test.go @@ -472,7 +472,7 @@ func TestImageProxy(t *testing.T) { *cfg.ServiceSettings.SiteURL = "http://mymattermost.com" }) - th.App.ch.imageProxy = imageproxy.MakeImageProxy(th.Server, th.Server.HTTPService(), th.Server.Log) + th.App.ch.imageProxy = imageproxy.MakeImageProxy(th.Server.platform, th.Server.HTTPService(), th.Server.Log) for name, tc := range map[string]struct { ProxyType string @@ -686,7 +686,7 @@ func TestCreatePost(t *testing.T) { *cfg.ImageProxySettings.RemoteImageProxyOptions = "foo" }) - th.App.ch.imageProxy = imageproxy.MakeImageProxy(th.Server, th.Server.HTTPService(), th.Server.Log) + th.App.ch.imageProxy = imageproxy.MakeImageProxy(th.Server.platform, th.Server.HTTPService(), th.Server.Log) imageURL := "http://mydomain.com/myimage" proxiedImageURL := "http://mymattermost.com/api/v4/image?url=http%3A%2F%2Fmydomain.com%2Fmyimage" @@ -956,7 +956,7 @@ func TestPatchPost(t *testing.T) { *cfg.ImageProxySettings.RemoteImageProxyOptions = "foo" }) - th.App.ch.imageProxy = imageproxy.MakeImageProxy(th.Server, th.Server.HTTPService(), th.Server.Log) + th.App.ch.imageProxy = imageproxy.MakeImageProxy(th.Server.platform, th.Server.HTTPService(), th.Server.Log) imageURL := "http://mydomain.com/myimage" proxiedImageURL := "http://mymattermost.com/api/v4/image?url=http%3A%2F%2Fmydomain.com%2Fmyimage" @@ -1252,7 +1252,7 @@ func TestUpdatePost(t *testing.T) { *cfg.ImageProxySettings.RemoteImageProxyOptions = "foo" }) - th.App.ch.imageProxy = imageproxy.MakeImageProxy(th.Server, th.Server.HTTPService(), th.Server.Log) + th.App.ch.imageProxy = imageproxy.MakeImageProxy(th.Server.platform, th.Server.HTTPService(), th.Server.Log) imageURL := "http://mydomain.com/myimage" proxiedImageURL := "http://mymattermost.com/api/v4/image?url=http%3A%2F%2Fmydomain.com%2Fmyimage" diff --git a/app/preference.go b/app/preference.go index 843976d122..4f470dd108 100644 --- a/app/preference.go +++ b/app/preference.go @@ -53,12 +53,12 @@ func (a *App) UpdatePreferences(userID string, preferences model.Preferences) *m case errors.As(err, &appErr): return appErr default: - return model.NewAppError("UpdatePreferences", "app.preference.save.updating.app_error", nil, err.Error(), http.StatusBadRequest) + return model.NewAppError("UpdatePreferences", "app.preference.save.updating.app_error", nil, "", http.StatusBadRequest).Wrap(err) } } if err := a.Srv().Store.Channel().UpdateSidebarChannelsByPreferences(preferences); err != nil { - return model.NewAppError("UpdatePreferences", "api.preference.update_preferences.update_sidebar.app_error", nil, err.Error(), http.StatusInternalServerError) + return model.NewAppError("UpdatePreferences", "api.preference.update_preferences.update_sidebar.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } message := model.NewWebSocketEvent(model.WebsocketEventSidebarCategoryUpdated, "", "", userID, nil) @@ -87,12 +87,12 @@ func (a *App) DeletePreferences(userID string, preferences model.Preferences) *m for _, preference := range preferences { if err := a.Srv().Store.Preference().Delete(userID, preference.Category, preference.Name); err != nil { - return model.NewAppError("DeletePreferences", "app.preference.delete.app_error", nil, err.Error(), http.StatusBadRequest) + return model.NewAppError("DeletePreferences", "app.preference.delete.app_error", nil, "", http.StatusBadRequest).Wrap(err) } } if err := a.Srv().Store.Channel().DeleteSidebarChannelsByPreferences(preferences); err != nil { - return model.NewAppError("DeletePreferences", "api.preference.delete_preferences.update_sidebar.app_error", nil, err.Error(), http.StatusInternalServerError) + return model.NewAppError("DeletePreferences", "api.preference.delete_preferences.update_sidebar.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } message := model.NewWebSocketEvent(model.WebsocketEventSidebarCategoryUpdated, "", "", userID, nil) diff --git a/app/reaction.go b/app/reaction.go index 26aa7d8414..7451677f2c 100644 --- a/app/reaction.go +++ b/app/reaction.go @@ -162,9 +162,9 @@ func (a *App) DeleteReactionForPost(c *request.Context, reaction *model.Reaction func (a *App) sendReactionEvent(event string, reaction *model.Reaction, post *model.Post) { // send out that a reaction has been added/removed message := model.NewWebSocketEvent(event, "", post.ChannelId, "", nil) - reactionJSON, jsonErr := json.Marshal(reaction) - if jsonErr != nil { - mlog.Warn("Failed to encode reaction to JSON") + reactionJSON, err := json.Marshal(reaction) + if err != nil { + a.Log().Warn("Failed to encode reaction to JSON", mlog.Err(err)) } message.Add("reaction", string(reactionJSON)) a.Publish(message) diff --git a/app/reaction_test.go b/app/reaction_test.go index e0d536d775..3e60208b84 100644 --- a/app/reaction_test.go +++ b/app/reaction_test.go @@ -90,8 +90,8 @@ func TestGetTopReactionsForTeamSince(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() - th.Server.configStore.SetReadOnlyFF(false) - defer th.Server.configStore.SetReadOnlyFF(true) + th.Server.platform.SetConfigReadOnlyFF(false) + defer th.Server.platform.SetConfigReadOnlyFF(true) userId := th.BasicUser.Id user2Id := th.BasicUser2.Id @@ -261,8 +261,8 @@ func TestGetTopReactionsForUserSince(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() - th.Server.configStore.SetReadOnlyFF(false) - defer th.Server.configStore.SetReadOnlyFF(true) + th.Server.platform.SetConfigReadOnlyFF(false) + defer th.Server.platform.SetConfigReadOnlyFF(true) userId := th.BasicUser.Id diff --git a/app/response_transfer.go b/app/response_transfer.go index 624d940a3f..e3acf3b527 100644 --- a/app/response_transfer.go +++ b/app/response_transfer.go @@ -6,7 +6,7 @@ package app import ( "bytes" "fmt" - "io/ioutil" + "io" "net/http" "strconv" "strings" @@ -59,7 +59,7 @@ func (rt *PluginResponseWriter) GenerateResponse() *http.Response { res.Status = fmt.Sprintf("%03d %s", res.StatusCode, http.StatusText(res.StatusCode)) if rt.Len() > 0 { - res.Body = ioutil.NopCloser(rt) + res.Body = io.NopCloser(rt) } else { res.Body = http.NoBody } diff --git a/app/role_test.go b/app/role_test.go index 2e10c0d3c0..1bf9420ae4 100644 --- a/app/role_test.go +++ b/app/role_test.go @@ -6,7 +6,7 @@ package app import ( "context" "encoding/csv" - "io/ioutil" + "io" "os" "strconv" "strings" @@ -130,7 +130,7 @@ func testPermissionInheritance(t *testing.T, testCallback func(t *testing.T, th require.NoError(t, e) defer file.Close() - b, e := ioutil.ReadAll(file) + b, e := io.ReadAll(file) require.NoError(t, e) r := csv.NewReader(strings.NewReader(string(b))) diff --git a/app/saml.go b/app/saml.go index 58787bf08a..b0b83ba159 100644 --- a/app/saml.go +++ b/app/saml.go @@ -8,7 +8,7 @@ import ( "encoding/pem" "encoding/xml" "fmt" - "io/ioutil" + "io" "mime/multipart" "net/http" "strings" @@ -42,12 +42,12 @@ func (a *App) writeSamlFile(filename string, fileData *multipart.FileHeader) *mo } defer file.Close() - data, err := ioutil.ReadAll(file) + data, err := io.ReadAll(file) if err != nil { return model.NewAppError("AddSamlCertificate", "api.admin.add_certificate.saving.app_error", nil, err.Error(), http.StatusInternalServerError) } - err = a.Srv().configStore.SetFile(filename, data) + err = a.Srv().platform.SetConfigFile(filename, data) if err != nil { return model.NewAppError("AddSamlCertificate", "api.admin.add_certificate.saving.app_error", nil, err.Error(), http.StatusInternalServerError) } @@ -107,7 +107,7 @@ func (a *App) AddSamlIdpCertificate(fileData *multipart.FileHeader) *model.AppEr } func (a *App) removeSamlFile(filename string) *model.AppError { - if err := a.Srv().configStore.RemoveFile(filename); err != nil { + if err := a.Srv().platform.RemoveConfigFile(filename); err != nil { return model.NewAppError("RemoveSamlFile", "api.admin.remove_certificate.delete.app_error", map[string]any{"Filename": filename}, err.Error(), http.StatusInternalServerError) } @@ -171,9 +171,9 @@ func (a *App) RemoveSamlIdpCertificate() *model.AppError { func (a *App) GetSamlCertificateStatus() *model.SamlCertificateStatus { status := &model.SamlCertificateStatus{} - status.IdpCertificateFile, _ = a.Srv().configStore.HasFile(*a.Config().SamlSettings.IdpCertificateFile) - status.PrivateKeyFile, _ = a.Srv().configStore.HasFile(*a.Config().SamlSettings.PrivateKeyFile) - status.PublicCertificateFile, _ = a.Srv().configStore.HasFile(*a.Config().SamlSettings.PublicCertificateFile) + status.IdpCertificateFile, _ = a.Srv().platform.HasConfigFile(*a.Config().SamlSettings.IdpCertificateFile) + status.PrivateKeyFile, _ = a.Srv().platform.HasConfigFile(*a.Config().SamlSettings.PrivateKeyFile) + status.PublicCertificateFile, _ = a.Srv().platform.HasConfigFile(*a.Config().SamlSettings.PublicCertificateFile) return status } @@ -212,7 +212,7 @@ func (a *App) FetchSamlMetadataFromIdp(url string) ([]byte, *model.AppError) { } defer resp.Body.Close() - bodyXML, err := ioutil.ReadAll(resp.Body) + bodyXML, err := io.ReadAll(resp.Body) if err != nil { return nil, model.NewAppError("FetchSamlMetadataFromIdp", "app.admin.saml.failure_read_response_body_from_idp.app_error", nil, err.Error(), http.StatusInternalServerError) } @@ -267,7 +267,7 @@ func (a *App) SetSamlIdpCertificateFromMetadata(data []byte) *model.AppError { Bytes: block.Bytes, }) - if err := a.Srv().configStore.SetFile(SamlIdpCertificateName, data); err != nil { + if err := a.Srv().platform.SetConfigFile(SamlIdpCertificateName, data); err != nil { return model.NewAppError("SetSamlIdpCertificateFromMetadata", "api.admin.saml.failure_save_idp_certificate_file.app_error", nil, err.Error(), http.StatusInternalServerError) } diff --git a/app/security_update_check.go b/app/security_update_check.go index 3712465ed7..258ef03f0e 100644 --- a/app/security_update_check.go +++ b/app/security_update_check.go @@ -5,7 +5,7 @@ package app import ( "encoding/json" - "io/ioutil" + "io" "net/http" "net/url" "runtime" @@ -33,7 +33,7 @@ const ( ) func (s *Server) DoSecurityUpdateCheck() { - if !*s.Config().ServiceSettings.EnableSecurityFixAlert { + if !*s.platform.Config().ServiceSettings.EnableSecurityFixAlert { return } @@ -53,7 +53,7 @@ func (s *Server) DoSecurityUpdateCheck() { v.Set(PropSecurityID, s.TelemetryId()) v.Set(PropSecurityBuild, model.CurrentVersion+"."+model.BuildNumber) v.Set(PropSecurityEnterpriseReady, model.BuildEnterpriseReady) - v.Set(PropSecurityDatabase, *s.Config().SqlSettings.DriverName) + v.Set(PropSecurityDatabase, *s.platform.Config().SqlSettings.DriverName) v.Set(PropSecurityOS, runtime.GOOS) if props[model.SystemRanUnitTests] != "" { @@ -91,7 +91,7 @@ func (s *Server) DoSecurityUpdateCheck() { var bulletins model.SecurityBulletins if jsonErr := json.NewDecoder(res.Body).Decode(&bulletins); jsonErr != nil { - mlog.Error("Failed to decode JSON", mlog.Err(jsonErr)) + s.Log.Error("Failed to decode JSON", mlog.Err(jsonErr)) return } @@ -110,7 +110,7 @@ func (s *Server) DoSecurityUpdateCheck() { return } - body, err := ioutil.ReadAll(resBody.Body) + body, err := io.ReadAll(resBody.Body) resBody.Body.Close() if err != nil || resBody.StatusCode != 200 { mlog.Error("Failed to read security bulletin details") diff --git a/app/server.go b/app/server.go index 48b99eea35..8f641e8c7c 100644 --- a/app/server.go +++ b/app/server.go @@ -31,7 +31,6 @@ import ( "golang.org/x/crypto/acme/autocert" "github.com/mattermost/mattermost-server/v6/app/email" - "github.com/mattermost/mattermost-server/v6/app/featureflag" "github.com/mattermost/mattermost-server/v6/app/platform" "github.com/mattermost/mattermost-server/v6/app/request" "github.com/mattermost/mattermost-server/v6/app/teams" @@ -168,7 +167,6 @@ type Server struct { searchConfigListenerId string searchLicenseListenerId string loggerLicenseListenerId string - configStore *configWrapper filestore filestore.FileBackend platform *platform.PlatformService @@ -201,11 +199,6 @@ type Server struct { tracer *tracing.Tracer - featureFlagSynchronizer *featureflag.Synchronizer - featureFlagStop chan struct{} - featureFlagStopped chan struct{} - featureFlagSynchronizerMutex sync.Mutex - products map[string]Product } @@ -237,7 +230,7 @@ func NewServer(options ...Option) (*Server, error) { // and has dependency requirements with the previous step. // // Step 1: Config. - if s.configStore == nil { + if s.platform == nil { innerStore, err := config.NewFileStore("config.json", true) if err != nil { return nil, errors.Wrap(err, "failed to load config") @@ -247,7 +240,25 @@ func NewServer(options ...Option) (*Server, error) { return nil, errors.Wrap(err, "failed to load config") } - s.configStore = &configWrapper{srv: s, Store: configStore} + platformCfg := platform.ServiceConfig{ + ConfigStore: configStore, + Logger: s.Log, + StartMetrics: s.startMetrics, + Cluster: s.Cluster, + } + if metricsInterface != nil { + platformCfg.Metrics = metricsInterface(s, *configStore.Get().SqlSettings.DriverName, *configStore.Get().SqlSettings.DataSource) + } + + ps, sErr := platform.New(platformCfg) + if sErr != nil { + return nil, errors.Wrap(sErr, "failed to initialize platform") + } + s.platform = ps + + if s.licenseValue.Load() != nil { + ps.SetLicense(s.licenseValue.Load().(*model.License)) // in case license is set in server options + } } // Step 2: Logging @@ -255,7 +266,7 @@ func NewServer(options ...Option) (*Server, error) { mlog.Error("Could not initiate logging", mlog.Err(err)) } - subpath, err := utils.GetSubpathFromConfig(s.Config()) + subpath, err := utils.GetSubpathFromConfig(s.platform.Config()) if err != nil { return nil, errors.Wrap(err, "failed to parse SiteURL subpath") } @@ -264,12 +275,12 @@ func NewServer(options ...Option) (*Server, error) { // This is called after initLogging() to avoid a race condition. mlog.Info("Server is initializing...", mlog.String("go_version", runtime.Version())) - s.httpService = httpservice.MakeHTTPService(s) + s.httpService = httpservice.MakeHTTPService(s.platform) // Step 3: Search Engine // Depends on Step 1 (config). - searchEngine := searchengine.NewBroker(s.Config()) - bleveEngine := bleveengine.NewBleveEngine(s.Config()) + searchEngine := searchengine.NewBroker(s.platform.Config()) + bleveEngine := bleveengine.NewBleveEngine(s.platform.Config()) if err := bleveEngine.Start(); err != nil { return nil, err } @@ -280,22 +291,6 @@ func NewServer(options ...Option) (*Server, error) { // Depends on step 3 (s.SearchEngine must be non-nil) s.initEnterprise() - platformCfg := platform.ServiceConfig{ - ConfigStore: s.configStore.Store, - Logger: s.Log, - StartMetrics: s.startMetrics, - Cluster: s.Cluster, - } - if metricsInterface != nil { - platformCfg.Metrics = metricsInterface(s) - } - - ps, sErr := platform.New(platformCfg) - if sErr != nil { - return nil, errors.Wrap(sErr, "failed to initialize platform") - } - s.platform = ps - // Step 5: Cache provider. // At the moment we only have this implementation // in the future the cache provider will be built based on the loaded config @@ -308,7 +303,7 @@ func NewServer(options ...Option) (*Server, error) { // Depends on Step 1 (config), 4 (metrics, cluster) and 5 (cacheProvider). if s.newStore == nil { s.newStore = func() (store.Store, error) { - s.sqlStore = sqlstore.New(s.Config().SqlSettings, s.GetMetrics()) + s.sqlStore = sqlstore.New(s.platform.Config().SqlSettings, s.GetMetrics()) lcl, err2 := localcachelayer.NewLocalCacheLayer( retrylayer.New(s.sqlStore), @@ -323,10 +318,10 @@ func NewServer(options ...Option) (*Server, error) { searchStore := searchlayer.NewSearchLayer( lcl, s.SearchEngine, - s.Config(), + s.platform.Config(), ) - s.AddConfigListener(func(prevCfg, cfg *model.Config) { + s.platform.AddConfigListener(func(prevCfg, cfg *model.Config) { searchStore.UpdateConfig(cfg) }) @@ -352,7 +347,7 @@ func NewServer(options ...Option) (*Server, error) { UserStore: s.Store.User(), SessionStore: s.Store.Session(), OAuthStore: s.Store.OAuth(), - ConfigFn: s.Config, + ConfigFn: s.platform.Config, Metrics: s.GetMetrics(), Cluster: s.Cluster, LicenseFn: s.License, @@ -376,9 +371,9 @@ func NewServer(options ...Option) (*Server, error) { } license := s.License() - insecure := s.Config().ServiceSettings.EnableInsecureOutgoingConnections + insecure := s.platform.Config().ServiceSettings.EnableInsecureOutgoingConnections // Step 7: Initialize filestore - backend, err := filestore.NewFileBackend(s.Config().FileSettings.ToFileBackendSettings(license != nil && *license.Features.Compliance, insecure != nil && *insecure)) + backend, err := filestore.NewFileBackend(s.platform.Config().FileSettings.ToFileBackendSettings(license != nil && *license.Features.Compliance, insecure != nil && *insecure)) if err != nil { return nil, errors.Wrap(err, "failed to initialize filebackend") } @@ -398,7 +393,7 @@ func NewServer(options ...Option) (*Server, error) { GroupStore: s.Store.Group(), Users: s.userService, WebHub: s, - ConfigFn: s.Config, + ConfigFn: s.platform.Config, LicenseFn: s.License, }) if err != nil { @@ -410,7 +405,7 @@ func NewServer(options ...Option) (*Server, error) { serviceMap := map[ServiceKey]any{ ChannelKey: &channelsWrapper{srv: s}, - ConfigKey: s.configStore, + ConfigKey: s.platform, LicenseKey: s.licenseWrapper, FilestoreKey: s.filestore, FileInfoStoreKey: &fileInfoWrapper{srv: s}, @@ -441,7 +436,7 @@ func NewServer(options ...Option) (*Server, error) { // below this. Otherwise, please add it to Channels struct in app/channels.go. // ------------------------------------------------------------------------- - if *s.Config().LogSettings.EnableDiagnostics && *s.Config().LogSettings.EnableSentry { + if *s.platform.Config().LogSettings.EnableDiagnostics && *s.platform.Config().LogSettings.EnableSentry { if strings.Contains(SentryDSN, "placeholder") { mlog.Warn("Sentry reporting is enabled, but SENTRY_DSN is not set. Disabling reporting.") } else { @@ -468,7 +463,7 @@ func NewServer(options ...Option) (*Server, error) { } } - if *s.Config().ServiceSettings.EnableOpenTracing { + if *s.platform.Config().ServiceSettings.EnableOpenTracing { tracer, err2 := tracing.New() if err2 != nil { return nil, err2 @@ -496,7 +491,7 @@ func NewServer(options ...Option) (*Server, error) { s.createPushNotificationsHub(request.EmptyContext(s.GetLogger())) - if err2 := i18n.InitTranslations(*s.Config().LocalizationSettings.DefaultServerLocale, *s.Config().LocalizationSettings.DefaultClientLocale); err2 != nil { + if err2 := i18n.InitTranslations(*s.platform.Config().LocalizationSettings.DefaultServerLocale, *s.platform.Config().LocalizationSettings.DefaultClientLocale); err2 != nil { return nil, errors.Wrapf(err2, "unable to load Mattermost translation files") } @@ -515,7 +510,7 @@ func NewServer(options ...Option) (*Server, error) { }) s.htmlTemplateWatcher = htmlTemplateWatcher - s.configListenerId = s.AddConfigListener(func(_, _ *model.Config) { + s.configListenerId = s.platform.AddConfigListener(func(_, _ *model.Config) { ch := s.Channels() ch.regenerateClientConfig() @@ -544,9 +539,10 @@ func NewServer(options ...Option) (*Server, error) { }) s.telemetryService = telemetry.New(New(ServerConnector(s.Channels())), s.Store, s.SearchEngine, s.Log) + s.platform.SetTelemetryId(s.TelemetryId()) // TODO: move this into platform once telemetry service moved to platform. emailService, err := email.NewService(email.ServiceConfig{ - ConfigFn: s.Config, + ConfigFn: s.platform.Config, LicenseFn: s.License, GoFn: s.Go, TemplatesContainer: s.TemplatesContainer(), @@ -558,7 +554,7 @@ func NewServer(options ...Option) (*Server, error) { } s.EmailService = emailService - s.setupFeatureFlags() + s.platform.SetupFeatureFlags() s.initJobs() @@ -567,7 +563,7 @@ func NewServer(options ...Option) (*Server, error) { if s.Jobs != nil { s.Jobs.HandleClusterLeaderChange(s.IsLeader()) } - s.setupFeatureFlags() + s.platform.SetupFeatureFlags() }) // If configured with a subpath, redirect 404s at the root back into the subpath. @@ -578,12 +574,12 @@ func NewServer(options ...Option) (*Server, error) { }) } - if _, err = url.ParseRequestURI(*s.Config().ServiceSettings.SiteURL); err != nil { + if _, err = url.ParseRequestURI(*s.platform.Config().ServiceSettings.SiteURL); err != nil { mlog.Error("SiteURL must be set. Some features will operate incorrectly if the SiteURL is not set. See documentation for details: https://docs.mattermost.com/configure/configuration-settings.html#site-url") } // Start email batching because it's not like the other jobs - s.AddConfigListener(func(_, _ *model.Config) { + s.platform.AddConfigListener(func(_, _ *model.Config) { s.EmailService.InitEmailBatching() }) @@ -604,7 +600,7 @@ func NewServer(options ...Option) (*Server, error) { pwd, _ := os.Getwd() mlog.Info("Printing current working", mlog.String("directory", pwd)) - mlog.Info("Loaded config", mlog.String("source", s.configStore.String())) + mlog.Info("Loaded config", mlog.String("source", s.platform.DescribeConfig())) allowAdvancedLogging := license != nil && *license.Features.AdvancedLogging @@ -626,7 +622,7 @@ func NewServer(options ...Option) (*Server, error) { // Enable developer settings if this is a "dev" build if model.BuildNumber == "dev" { - s.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableDeveloper = true }) + s.platform.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableDeveloper = true }) } if s.startMetrics { @@ -649,13 +645,13 @@ func NewServer(options ...Option) (*Server, error) { } }) - s.SearchEngine.UpdateConfig(s.Config()) + s.SearchEngine.UpdateConfig(s.platform.Config()) searchConfigListenerId, searchLicenseListenerId := s.StartSearchEngine() s.searchConfigListenerId = searchConfigListenerId s.searchLicenseListenerId = searchLicenseListenerId // if enabled - perform initial product notices fetch - if *s.Config().AnnouncementSettings.AdminNoticesEnabled || *s.Config().AnnouncementSettings.UserNoticesEnabled { + if *s.platform.Config().AnnouncementSettings.AdminNoticesEnabled || *s.platform.Config().AnnouncementSettings.UserNoticesEnabled { go func() { appInstance := New(ServerConnector(s.Channels())) if err := appInstance.UpdateProductNotices(); err != nil { @@ -668,7 +664,7 @@ func NewServer(options ...Option) (*Server, error) { return s, nil } - s.AddConfigListener(func(old, new *model.Config) { + s.platform.AddConfigListener(func(old, new *model.Config) { appInstance := New(ServerConnector(s.Channels())) if *old.GuestAccountsSettings.Enable && !*new.GuestAccountsSettings.Enable { c := request.EmptyContext(s.GetLogger()) @@ -679,7 +675,7 @@ func NewServer(options ...Option) (*Server, error) { }) // Disable active guest accounts on first run if guest accounts are disabled - if !*s.Config().GuestAccountsSettings.Enable { + if !*s.platform.Config().GuestAccountsSettings.Enable { appInstance := New(ServerConnector(s.Channels())) c := request.EmptyContext(s.GetLogger()) if appErr := appInstance.DeactivateGuests(c); appErr != nil { @@ -703,7 +699,7 @@ func NewServer(options ...Option) (*Server, error) { s.initPostMetadata() // Dump the image cache if the proxy settings have changed. (need switch URLs to the correct proxy) - s.AddConfigListener(func(oldCfg, newCfg *model.Config) { + s.platform.AddConfigListener(func(oldCfg, newCfg *model.Config) { if (oldCfg.ImageProxySettings.Enable != newCfg.ImageProxySettings.Enable) || (oldCfg.ImageProxySettings.ImageProxyType != newCfg.ImageProxySettings.ImageProxyType) || (oldCfg.ImageProxySettings.RemoteImageProxyURL != newCfg.ImageProxySettings.RemoteImageProxyURL) || @@ -755,18 +751,18 @@ func (s *Server) runJobs() { complianceI.StartComplianceDailyJob() } - if *s.Config().JobSettings.RunJobs && s.Jobs != nil { + if *s.platform.Config().JobSettings.RunJobs && s.Jobs != nil { if err := s.Jobs.StartWorkers(); err != nil { mlog.Error("Failed to start job server workers", mlog.Err(err)) } } - if *s.Config().JobSettings.RunScheduler && s.Jobs != nil { + if *s.platform.Config().JobSettings.RunScheduler && s.Jobs != nil { if err := s.Jobs.StartSchedulers(); err != nil { mlog.Error("Failed to start job server schedulers", mlog.Err(err)) } } - if *s.Config().ServiceSettings.EnableAWSMetering { + if *s.platform.Config().ServiceSettings.EnableAWSMetering { runReportToAWSMeterJob(s) } } @@ -786,7 +782,7 @@ func (s *Server) Channels() *Channels { // Return Database type (postgres or mysql) and current version of the schema func (s *Server) DatabaseTypeAndSchemaVersion() (string, string) { schemaVersion, _ := s.Store.GetDBSchemaVersion() - return *s.Config().SqlSettings.DriverName, strconv.Itoa(schemaVersion) + return *s.platform.Config().SqlSettings.DriverName, strconv.Itoa(schemaVersion) } // initLogging initializes and configures the logger(s). This may be called more than once. @@ -809,7 +805,7 @@ func (s *Server) initLogging() error { s.NotificationsLog = l.With(mlog.String("logSource", "notifications")) } - if err := s.configureLogger("logging", s.Log, &s.Config().LogSettings, s.configStore.Store, config.GetLogFileLocation); err != nil { + if err := s.platform.ConfigureLogger("logging", s.Log, &s.platform.Config().LogSettings, config.GetLogFileLocation); err != nil { // if the config is locked then a unit test has already configured and locked the logger; not an error. if !errors.Is(err, mlog.ErrConfigurationLock) { // revert to default logger if the config is invalid @@ -824,8 +820,8 @@ func (s *Server) initLogging() error { // Use the app logger as the global logger (eventually remove all instances of global logging). mlog.InitGlobalLogger(s.Log) - notificationLogSettings := config.GetLogSettingsFromNotificationsLogSettings(&s.Config().NotificationLogSettings) - if err := s.configureLogger("notification logging", s.NotificationsLog, notificationLogSettings, s.configStore.Store, config.GetNotificationsLogFileLocation); err != nil { + notificationLogSettings := config.GetLogSettingsFromNotificationsLogSettings(&s.platform.Config().NotificationLogSettings) + if err := s.platform.ConfigureLogger("notification logging", s.NotificationsLog, notificationLogSettings, config.GetNotificationsLogFileLocation); err != nil { if !errors.Is(err, mlog.ErrConfigurationLock) { mlog.Error("Error configuring notification logger", mlog.Err(err)) return err @@ -834,33 +830,6 @@ func (s *Server) initLogging() error { return nil } -// configureLogger applies the specified configuration to a logger. -func (s *Server) configureLogger(name string, logger *mlog.Logger, logSettings *model.LogSettings, configStore *config.Store, getPath func(string) string) error { - // Advanced logging is E20 only, however logging must be initialized before the license - // file is loaded. If no valid E20 license exists then advanced logging will be - // shutdown once license is loaded/checked. - var err error - dsn := *logSettings.AdvancedLoggingConfig - var logConfigSrc config.LogConfigSrc - if dsn != "" { - logConfigSrc, err = config.NewLogConfigSrc(dsn, configStore) - if err != nil { - return fmt.Errorf("invalid config source for %s, %w", name, err) - } - mlog.Info("Loaded configuration for "+name, mlog.String("source", dsn)) - } - - cfg, err := config.MloggerConfigFromLoggerConfig(logSettings, logConfigSrc, getPath) - if err != nil { - return fmt.Errorf("invalid config source for %s, %w", name, err) - } - - if err := logger.ConfigureTargets(cfg, nil); err != nil { - return fmt.Errorf("invalid config for %s, %w", name, err) - } - return nil -} - // removeUnlicensedLogTargets removes any unlicensed log target types. func (s *Server) removeUnlicensedLogTargets(license *model.License) { if license != nil && *license.Features.AdvancedLogging { @@ -895,7 +864,7 @@ func (s *Server) startInterClusterServices(license *model.License) error { } // Config check - if !*s.Config().ExperimentalSettings.EnableRemoteClusterService { + if !*s.platform.Config().ExperimentalSettings.EnableRemoteClusterService { mlog.Debug("Remote Cluster Service disabled via config") return nil } @@ -924,7 +893,7 @@ func (s *Server) startInterClusterServices(license *model.License) error { } // Config check - if !*s.Config().ExperimentalSettings.EnableSharedChannels { + if !*s.platform.Config().ExperimentalSettings.EnableSharedChannels { mlog.Debug("Shared Channels Service disabled via config") return nil } @@ -1029,14 +998,16 @@ func (s *Server) Shutdown() { s.WaitForGoroutines() - s.RemoveConfigListener(s.configListenerId) + s.platform.RemoveConfigListener(s.configListenerId) s.stopSearchEngine() s.Audit.Shutdown() - s.stopFeatureFlagUpdateJob() + s.platform.StopFeatureFlagUpdateJob() - s.configStore.Close() + if err = s.platform.ShutdownConfig(); err != nil { + s.Log.Warn("Failed to shut down config store", mlog.Err(err)) + } if s.Cluster != nil { s.Cluster.StopInterNodeCommunication() @@ -1239,23 +1210,23 @@ func (s *Server) Start() error { s.checkPushNotificationServerURL() - s.ReloadConfig() + s.platform.ReloadConfig() mlog.Info("Starting Server...") var handler http.Handler = s.RootRouter - if *s.Config().LogSettings.EnableDiagnostics && *s.Config().LogSettings.EnableSentry && !strings.Contains(SentryDSN, "placeholder") { + if *s.platform.Config().LogSettings.EnableDiagnostics && *s.platform.Config().LogSettings.EnableSentry && !strings.Contains(SentryDSN, "placeholder") { sentryHandler := sentryhttp.New(sentryhttp.Options{ Repanic: true, }) handler = sentryHandler.Handle(handler) } - if allowedOrigins := *s.Config().ServiceSettings.AllowCorsFrom; allowedOrigins != "" { - exposedCorsHeaders := *s.Config().ServiceSettings.CorsExposedHeaders - allowCredentials := *s.Config().ServiceSettings.CorsAllowCredentials - debug := *s.Config().ServiceSettings.CorsDebug + if allowedOrigins := *s.platform.Config().ServiceSettings.AllowCorsFrom; allowedOrigins != "" { + exposedCorsHeaders := *s.platform.Config().ServiceSettings.CorsExposedHeaders + allowCredentials := *s.platform.Config().ServiceSettings.CorsAllowCredentials + debug := *s.platform.Config().ServiceSettings.CorsDebug corsWrapper := cors.New(cors.Options{ AllowedOrigins: strings.Fields(allowedOrigins), AllowedMethods: corsAllowedMethods, @@ -1274,10 +1245,10 @@ func (s *Server) Start() error { handler = corsWrapper.Handler(handler) } - if *s.Config().RateLimitSettings.Enable { + if *s.platform.Config().RateLimitSettings.Enable { mlog.Info("RateLimiter is enabled") - rateLimiter, err2 := NewRateLimiter(&s.Config().RateLimitSettings, s.Config().ServiceSettings.TrustedProxyIPHeader) + rateLimiter, err2 := NewRateLimiter(&s.platform.Config().RateLimitSettings, s.platform.Config().ServiceSettings.TrustedProxyIPHeader) if err2 != nil { return err2 } @@ -1292,15 +1263,15 @@ func (s *Server) Start() error { s.Server = &http.Server{ Handler: handler, - ReadTimeout: time.Duration(*s.Config().ServiceSettings.ReadTimeout) * time.Second, - WriteTimeout: time.Duration(*s.Config().ServiceSettings.WriteTimeout) * time.Second, - IdleTimeout: time.Duration(*s.Config().ServiceSettings.IdleTimeout) * time.Second, + ReadTimeout: time.Duration(*s.platform.Config().ServiceSettings.ReadTimeout) * time.Second, + WriteTimeout: time.Duration(*s.platform.Config().ServiceSettings.WriteTimeout) * time.Second, + IdleTimeout: time.Duration(*s.platform.Config().ServiceSettings.IdleTimeout) * time.Second, ErrorLog: errStdLog, } - addr := *s.Config().ServiceSettings.ListenAddress + addr := *s.platform.Config().ServiceSettings.ListenAddress if addr == "" { - if *s.Config().ServiceSettings.ConnectionSecurity == model.ConnSecurityTLS { + if *s.platform.Config().ServiceSettings.ConnectionSecurity == model.ConnSecurityTLS { addr = ":https" } else { addr = ":http" @@ -1317,11 +1288,11 @@ func (s *Server) Start() error { mlog.Info(logListeningPort, mlog.String("address", listener.Addr().String())) m := &autocert.Manager{ - Cache: autocert.DirCache(*s.Config().ServiceSettings.LetsEncryptCertificateCacheFile), + Cache: autocert.DirCache(*s.platform.Config().ServiceSettings.LetsEncryptCertificateCacheFile), Prompt: autocert.AcceptTOS, } - if *s.Config().ServiceSettings.Forward80To443 { + if *s.platform.Config().ServiceSettings.Forward80To443 { if host, port, err := net.SplitHostPort(addr); err != nil { mlog.Error("Unable to setup forwarding", mlog.Err(err)) } else if port != "443" { @@ -1329,7 +1300,7 @@ func (s *Server) Start() error { } else { httpListenAddress := net.JoinHostPort(host, "http") - if *s.Config().ServiceSettings.UseLetsEncrypt { + if *s.platform.Config().ServiceSettings.UseLetsEncrypt { server := &http.Server{ Addr: httpListenAddress, Handler: m.HTTPHandler(nil), @@ -1353,21 +1324,21 @@ func (s *Server) Start() error { }() } } - } else if *s.Config().ServiceSettings.UseLetsEncrypt { + } else if *s.platform.Config().ServiceSettings.UseLetsEncrypt { return errors.New(i18n.T("api.server.start_server.forward80to443.disabled_while_using_lets_encrypt")) } s.didFinishListen = make(chan struct{}) go func() { var err error - if *s.Config().ServiceSettings.ConnectionSecurity == model.ConnSecurityTLS { + if *s.platform.Config().ServiceSettings.ConnectionSecurity == model.ConnSecurityTLS { tlsConfig := &tls.Config{ PreferServerCipherSuites: true, CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256}, } - switch *s.Config().ServiceSettings.TLSMinVer { + switch *s.platform.Config().ServiceSettings.TLSMinVer { case "1.0": tlsConfig.MinVersion = tls.VersionTLS10 case "1.1": @@ -1385,11 +1356,11 @@ func (s *Server) Start() error { tls.TLS_RSA_WITH_AES_256_GCM_SHA384, } - if len(s.Config().ServiceSettings.TLSOverwriteCiphers) == 0 { + if len(s.platform.Config().ServiceSettings.TLSOverwriteCiphers) == 0 { tlsConfig.CipherSuites = defaultCiphers } else { var cipherSuites []uint16 - for _, cipher := range s.Config().ServiceSettings.TLSOverwriteCiphers { + for _, cipher := range s.platform.Config().ServiceSettings.TLSOverwriteCiphers { value, ok := model.ServerTLSSupportedCiphers[cipher] if !ok { @@ -1411,12 +1382,12 @@ func (s *Server) Start() error { certFile := "" keyFile := "" - if *s.Config().ServiceSettings.UseLetsEncrypt { + if *s.platform.Config().ServiceSettings.UseLetsEncrypt { tlsConfig.GetCertificate = m.GetCertificate tlsConfig.NextProtos = append(tlsConfig.NextProtos, "h2") } else { - certFile = *s.Config().ServiceSettings.TLSCertFile - keyFile = *s.Config().ServiceSettings.TLSKeyFile + certFile = *s.platform.Config().ServiceSettings.TLSCertFile + keyFile = *s.platform.Config().ServiceSettings.TLSKeyFile } s.Server.TLSConfig = tlsConfig @@ -1433,7 +1404,7 @@ func (s *Server) Start() error { close(s.didFinishListen) }() - if *s.Config().ServiceSettings.EnableLocalMode { + if *s.platform.Config().ServiceSettings.EnableLocalMode { if err := s.startLocalModeServer(); err != nil { mlog.Critical(err.Error()) } @@ -1451,7 +1422,7 @@ func (s *Server) startLocalModeServer() error { Handler: s.LocalRouter, } - socket := *s.configStore.Get().ServiceSettings.LocalModeSocketLocation + socket := *s.platform.Config().ServiceSettings.LocalModeSocketLocation if err := os.RemoveAll(socket); err != nil { return errors.Wrapf(err, i18n.T("api.server.start_server.starting.critical"), err) } @@ -1495,7 +1466,7 @@ func (a *App) OriginChecker() func(*http.Request) bool { } func (s *Server) checkPushNotificationServerURL() { - notificationServer := *s.Config().EmailSettings.PushNotificationServer + notificationServer := *s.platform.Config().EmailSettings.PushNotificationServer if strings.HasPrefix(notificationServer, "http://") { mlog.Warn("Your push notification server is configured with HTTP. For improved security, update to HTTPS in your configuration.") } @@ -1563,7 +1534,7 @@ func runReportToAWSMeterJob(s *Server) { } func doReportUsageToAWSMeteringService(s *Server) { - awsMeter := awsmeter.New(s.Store, s.Config()) + awsMeter := awsmeter.New(s.Store, s.platform.Config()) if awsMeter == nil { mlog.Error("Cannot obtain instance of AWS Metering Service.") return @@ -1604,12 +1575,12 @@ func doSessionCleanup(s *Server) { } func doJobsCleanup(s *Server) { - if *s.Config().JobSettings.CleanupJobsThresholdDays < 0 { + if *s.platform.Config().JobSettings.CleanupJobsThresholdDays < 0 { return } mlog.Debug("Cleaning up jobs store.") - dur := time.Duration(*s.Config().JobSettings.CleanupJobsThresholdDays) * time.Hour * 24 + dur := time.Duration(*s.platform.Config().JobSettings.CleanupJobsThresholdDays) * time.Hour * 24 expiry := model.GetMillisForTime(time.Now().Add(-dur)) err := s.Store.Job().Cleanup(expiry, jobsCleanupBatchSize) if err != nil { @@ -1618,12 +1589,12 @@ func doJobsCleanup(s *Server) { } func doConfigCleanup(s *Server) { - if *s.Config().JobSettings.CleanupConfigThresholdDays < 0 || !config.IsDatabaseDSN(s.ConfigStore().Store.String()) { + if *s.platform.Config().JobSettings.CleanupConfigThresholdDays < 0 || !config.IsDatabaseDSN(s.platform.DescribeConfig()) { return } mlog.Info("Cleaning up configuration store.") - if err := s.ConfigStore().Store.CleanUp(); err != nil { + if err := s.platform.CleanUpConfig(); err != nil { mlog.Warn("Error while cleaning up configurations", mlog.Err(err)) } } @@ -1654,7 +1625,7 @@ func (s *Server) sendLicenseUpForRenewalEmail(users map[string]*model.User, lice if name == "" { name = user.Username } - if err := s.EmailService.SendLicenseUpForRenewalEmail(user.Email, name, user.Locale, *s.Config().ServiceSettings.SiteURL, renewalLink, daysToExpiration); err != nil { + if err := s.EmailService.SendLicenseUpForRenewalEmail(user.Email, name, user.Locale, *s.platform.Config().ServiceSettings.SiteURL, renewalLink, daysToExpiration); err != nil { mlog.Error("Error sending license up for renewal email to", mlog.String("user_email", user.Email), mlog.Err(err)) countNotOks++ } @@ -1735,7 +1706,7 @@ func (s *Server) doLicenseExpirationCheck() { mlog.Debug("Sending license expired email.", mlog.String("user_email", user.Email)) s.Go(func() { - if err := s.SendRemoveExpiredLicenseEmail(user.Email, renewalLink, user.Locale, *s.Config().ServiceSettings.SiteURL); err != nil { + if err := s.SendRemoveExpiredLicenseEmail(user.Email, renewalLink, user.Locale, *s.platform.Config().ServiceSettings.SiteURL); err != nil { mlog.Error("Error while sending the license expired email.", mlog.String("user_email", user.Email), mlog.Err(err)) } }) @@ -1765,7 +1736,7 @@ func (s *Server) StartSearchEngine() (string, string) { }) } - configListenerId := s.AddConfigListener(func(oldConfig *model.Config, newConfig *model.Config) { + configListenerId := s.platform.AddConfigListener(func(oldConfig *model.Config, newConfig *model.Config) { if s.SearchEngine == nil { return } @@ -1824,7 +1795,7 @@ func (s *Server) StartSearchEngine() (string, string) { } func (s *Server) stopSearchEngine() { - s.RemoveConfigListener(s.searchConfigListenerId) + s.platform.RemoveConfigListener(s.searchConfigListenerId) s.RemoveLicenseListener(s.searchLicenseListenerId) if s.SearchEngine != nil && s.SearchEngine.ElasticsearchEngine != nil && s.SearchEngine.ElasticsearchEngine.IsActive() { s.SearchEngine.ElasticsearchEngine.Stop() @@ -1858,7 +1829,7 @@ func (ch *Channels) ClientConfigHash() string { } func (s *Server) initJobs() { - s.Jobs = jobs.NewJobServer(s, s.Store, s.GetMetrics()) + s.Jobs = jobs.NewJobServer(s.platform, s.Store, s.GetMetrics()) if jobsDataRetentionJobInterface != nil { builder := jobsDataRetentionJobInterface(s) @@ -2031,7 +2002,7 @@ func (s *Server) SetSharedChannelSyncService(sharedChannelService SharedChannelS } func (s *Server) GetProfileImage(user *model.User) ([]byte, bool, *model.AppError) { - if *s.Config().FileSettings.DriverName == "" { + if *s.platform.Config().FileSettings.DriverName == "" { img, appErr := s.GetDefaultProfileImage(user) if appErr != nil { return nil, false, appErr @@ -2141,3 +2112,8 @@ func (a *App) GetAppliedSchemaMigrations() ([]model.AppliedMigration, *model.App } return table, nil } + +// Expose platform service from server, this should be replaced with server itself in time. +func (s *Server) Platform() *platform.PlatformService { + return s.platform +} diff --git a/app/server_inactivity.go b/app/server_inactivity.go index 3bb83e7f0c..4c5b0b7a01 100644 --- a/app/server_inactivity.go +++ b/app/server_inactivity.go @@ -17,17 +17,17 @@ const inactivityEmailSent = "INACTIVITY" func (s *Server) doInactivityCheck() { - if *s.Config().ServiceSettings.EnableDeveloper { + if *s.platform.Config().ServiceSettings.EnableDeveloper { mlog.Info("No activity check because developer mode is enabled") return } - if !*s.Config().EmailSettings.EnableInactivityEmail { + if !*s.platform.Config().EmailSettings.EnableInactivityEmail { mlog.Info("No activity check because EnableInactivityEmail is false") return } - if !s.Config().FeatureFlags.EnableInactivityCheckJob { + if !s.platform.Config().FeatureFlags.EnableInactivityCheckJob { mlog.Info("No activity check because EnableInactivityCheckJob feature flag is disabled") return } @@ -70,7 +70,7 @@ func (s *Server) doInactivityCheck() { } func (s *Server) takeInactivityAction() { - siteURL := *s.Config().ServiceSettings.SiteURL + siteURL := *s.platform.Config().ServiceSettings.SiteURL if siteURL == "" { mlog.Warn("No SiteURL configured") } diff --git a/app/server_license.go b/app/server_license.go deleted file mode 100644 index ffb0dc68ca..0000000000 --- a/app/server_license.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package app - -import ( - "github.com/mattermost/mattermost-server/v6/model" -) - -func (s *Server) License() *model.License { - license, _ := s.licenseValue.Load().(*model.License) - return license -} diff --git a/app/server_test.go b/app/server_test.go index 710aa302a1..c1e0cd8fec 100644 --- a/app/server_test.go +++ b/app/server_test.go @@ -23,6 +23,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/mattermost/mattermost-server/v6/app/platform" "github.com/mattermost/mattermost-server/v6/config" "github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/mattermost-server/v6/shared/filestore" @@ -83,54 +84,70 @@ func TestReadReplicaDisabledBasedOnLicense(t *testing.T) { s, err := NewServer(func(server *Server) error { configStore := config.NewTestMemoryStore() configStore.Set(&cfg) - server.configStore = &configWrapper{srv: server, Store: configStore} + var err error + server.platform, err = platform.New(platform.ServiceConfig{ + ConfigStore: configStore, + }) + require.NoError(t, err) return nil }) require.NoError(t, err) defer s.Shutdown() require.Same(t, s.sqlStore.GetMasterX(), s.sqlStore.GetReplicaX()) - require.Len(t, s.Config().SqlSettings.DataSourceReplicas, 1) + require.Len(t, s.platform.Config().SqlSettings.DataSourceReplicas, 1) }) t.Run("Read Replicas With License", func(t *testing.T) { s, err := NewServer(func(server *Server) error { configStore := config.NewTestMemoryStore() configStore.Set(&cfg) - server.configStore = &configWrapper{srv: server, Store: configStore} + var err error + server.platform, err = platform.New(platform.ServiceConfig{ + ConfigStore: configStore, + }) + require.NoError(t, err) server.licenseValue.Store(model.NewTestLicense()) return nil }) require.NoError(t, err) defer s.Shutdown() require.NotSame(t, s.sqlStore.GetMasterX(), s.sqlStore.GetReplicaX()) - require.Len(t, s.Config().SqlSettings.DataSourceReplicas, 1) + require.Len(t, s.platform.Config().SqlSettings.DataSourceReplicas, 1) }) t.Run("Search Replicas with no License", func(t *testing.T) { s, err := NewServer(func(server *Server) error { configStore := config.NewTestMemoryStore() configStore.Set(&cfg) - server.configStore = &configWrapper{srv: server, Store: configStore} + var err error + server.platform, err = platform.New(platform.ServiceConfig{ + ConfigStore: configStore, + }) + require.NoError(t, err) return nil }) require.NoError(t, err) defer s.Shutdown() require.Same(t, s.sqlStore.GetMasterX(), s.sqlStore.GetSearchReplicaX()) - require.Len(t, s.Config().SqlSettings.DataSourceSearchReplicas, 1) + require.Len(t, s.platform.Config().SqlSettings.DataSourceSearchReplicas, 1) }) t.Run("Search Replicas With License", func(t *testing.T) { s, err := NewServer(func(server *Server) error { configStore := config.NewTestMemoryStore() configStore.Set(&cfg) - server.configStore = &configWrapper{srv: server, Store: configStore} + var err error + server.platform, err = platform.New(platform.ServiceConfig{ + ConfigStore: configStore, + }) + require.NoError(t, err) server.licenseValue.Store(model.NewTestLicense()) return nil }) require.NoError(t, err) defer s.Shutdown() require.NotSame(t, s.sqlStore.GetMasterX(), s.sqlStore.GetSearchReplicaX()) - require.Len(t, s.Config().SqlSettings.DataSourceSearchReplicas, 1) + require.Len(t, s.platform.Config().SqlSettings.DataSourceSearchReplicas, 1) }) } @@ -143,7 +160,7 @@ func TestStartServerPortUnavailable(t *testing.T) { require.NoError(t, err) // Attempt to listen on the port used above. - s.UpdateConfig(func(cfg *model.Config) { + s.platform.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = listener.Addr().String() }) @@ -168,8 +185,12 @@ func TestStartServerNoS3Bucket(t *testing.T) { s, err := NewServer(func(server *Server) error { configStore, _ := config.NewFileStore("config.json", true) store, _ := config.NewStoreFromBacking(configStore, nil, false) - server.configStore = &configWrapper{srv: server, Store: store} - server.UpdateConfig(func(cfg *model.Config) { + var err error + server.platform, err = platform.New(platform.ServiceConfig{ + ConfigStore: store, + }) + require.NoError(t, err) + server.platform.UpdateConfig(func(cfg *model.Config) { cfg.FileSettings = model.FileSettings{ DriverName: model.NewString(model.ImageDriverS3), AmazonS3AccessKeyId: model.NewString(model.MinioAccessKey), @@ -393,7 +414,7 @@ func TestPanicLog(t *testing.T) { }) testDir, _ := fileutils.FindDir("tests") - s.UpdateConfig(func(cfg *model.Config) { + s.platform.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = ":0" *cfg.ServiceSettings.ConnectionSecurity = "TLS" *cfg.ServiceSettings.TLSKeyFile = path.Join(testDir, "tls_test_key.pem") diff --git a/app/slashcommands/command_expand_collapse.go b/app/slashcommands/command_expand_collapse.go index e9c6414d95..7c8ab6583f 100644 --- a/app/slashcommands/command_expand_collapse.go +++ b/app/slashcommands/command_expand_collapse.go @@ -77,9 +77,9 @@ func setCollapsePreference(a *app.App, args *model.CommandArgs, isCollapse bool) socketMessage := model.NewWebSocketEvent(model.WebsocketEventPreferenceChanged, "", "", args.UserId, nil) - prefJSON, jsonErr := json.Marshal(pref) - if jsonErr != nil { - return &model.CommandResponse{Text: args.T("api.marshal_error") + jsonErr.Error(), ResponseType: model.CommandResponseTypeEphemeral} + prefJSON, err := json.Marshal(pref) + if err != nil { + return &model.CommandResponse{Text: args.T("api.marshal_error") + err.Error(), ResponseType: model.CommandResponseTypeEphemeral} } socketMessage.Add("preference", string(prefJSON)) a.Publish(socketMessage) diff --git a/app/slashcommands/command_loadtest.go b/app/slashcommands/command_loadtest.go index d953ddd9fb..4ca6718446 100644 --- a/app/slashcommands/command_loadtest.go +++ b/app/slashcommands/command_loadtest.go @@ -570,7 +570,7 @@ func (*LoadTestProvider) JsonCommand(a *app.App, c request.CTX, args *model.Comm var post model.Post if jsonErr := json.NewDecoder(r.Body).Decode(&post); jsonErr != nil { - return &model.CommandResponse{Text: "Unable to decode post", ResponseType: model.CommandResponseTypeEphemeral}, errors.Errorf("could not decode post from json") + return &model.CommandResponse{Text: "Unable to decode post", ResponseType: model.CommandResponseTypeEphemeral}, errors.Wrapf(jsonErr, "could not decode post from json") } post.ChannelId = args.ChannelId post.UserId = args.UserId diff --git a/app/slashcommands/helper_test.go b/app/slashcommands/helper_test.go index c7fa8fcf3a..ff145921c7 100644 --- a/app/slashcommands/helper_test.go +++ b/app/slashcommands/helper_test.go @@ -6,7 +6,6 @@ package slashcommands import ( "bytes" "context" - "io/ioutil" "os" "path/filepath" "strings" @@ -42,7 +41,7 @@ type TestHelper struct { } func setupTestHelper(dbStore store.Store, enterprise bool, includeCacheLayer bool, tb testing.TB, configSet func(*model.Config)) *TestHelper { - tempWorkspace, err := ioutil.TempDir("", "apptest") + tempWorkspace, err := os.MkdirTemp("", "apptest") if err != nil { panic(err) } diff --git a/app/status.go b/app/status.go index 374e3477de..377261eeb9 100644 --- a/app/status.go +++ b/app/status.go @@ -22,9 +22,9 @@ func (a *App) AddStatusCache(status *model.Status) { a.AddStatusCacheSkipClusterSend(status) if a.Cluster() != nil { - statusJSON, jsonErr := json.Marshal(status) - if jsonErr != nil { - mlog.Warn("Failed to encode status to JSON") + statusJSON, err := json.Marshal(status) + if err != nil { + a.Log().Warn("Failed to encode status to JSON", mlog.Err(err)) } msg := &model.ClusterMessage{ Event: model.ClusterEventUpdateStatus, @@ -456,20 +456,20 @@ func (a *App) GetCustomStatus(userID string) (*model.CustomStatus, *model.AppErr func (a *App) addRecentCustomStatus(userID string, status *model.CustomStatus) *model.AppError { var newRCS model.RecentCustomStatuses - pref, err := a.GetPreferenceByCategoryAndNameForUser(userID, model.PreferenceCategoryCustomStatus, model.PreferenceNameRecentCustomStatuses) - if err != nil || pref.Value == "" { + pref, appErr := a.GetPreferenceByCategoryAndNameForUser(userID, model.PreferenceCategoryCustomStatus, model.PreferenceNameRecentCustomStatuses) + if appErr != nil || pref.Value == "" { newRCS = model.RecentCustomStatuses{*status} } else { var existingRCS model.RecentCustomStatuses - if jsonErr := json.Unmarshal([]byte(pref.Value), &existingRCS); jsonErr != nil { - return model.NewAppError("addRecentCustomStatus", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusBadRequest) + if err := json.Unmarshal([]byte(pref.Value), &existingRCS); err != nil { + return model.NewAppError("addRecentCustomStatus", "api.unmarshal_error", nil, "", http.StatusBadRequest).Wrap(err) } newRCS = existingRCS.Add(status) } - newRCSJSON, jsonErr := json.Marshal(newRCS) - if jsonErr != nil { - return model.NewAppError("addRecentCustomStatus", "api.marshal_error", nil, jsonErr.Error(), http.StatusBadRequest) + newRCSJSON, err := json.Marshal(newRCS) + if err != nil { + return model.NewAppError("addRecentCustomStatus", "api.marshal_error", nil, "", http.StatusBadRequest).Wrap(err) } pref = &model.Preference{ UserId: userID, @@ -477,17 +477,17 @@ func (a *App) addRecentCustomStatus(userID string, status *model.CustomStatus) * Name: model.PreferenceNameRecentCustomStatuses, Value: string(newRCSJSON), } - if err := a.UpdatePreferences(userID, model.Preferences{*pref}); err != nil { - return err + if appErr := a.UpdatePreferences(userID, model.Preferences{*pref}); appErr != nil { + return appErr } return nil } func (a *App) RemoveRecentCustomStatus(userID string, status *model.CustomStatus) *model.AppError { - pref, err := a.GetPreferenceByCategoryAndNameForUser(userID, model.PreferenceCategoryCustomStatus, model.PreferenceNameRecentCustomStatuses) - if err != nil { - return err + pref, appErr := a.GetPreferenceByCategoryAndNameForUser(userID, model.PreferenceCategoryCustomStatus, model.PreferenceNameRecentCustomStatuses) + if appErr != nil { + return appErr } if pref.Value == "" { @@ -495,26 +495,26 @@ func (a *App) RemoveRecentCustomStatus(userID string, status *model.CustomStatus } var existingRCS model.RecentCustomStatuses - if jsonErr := json.Unmarshal([]byte(pref.Value), &existingRCS); jsonErr != nil { - return model.NewAppError("RemoveRecentCustomStatus", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusBadRequest) + if err := json.Unmarshal([]byte(pref.Value), &existingRCS); err != nil { + return model.NewAppError("RemoveRecentCustomStatus", "api.unmarshal_error", nil, "", http.StatusBadRequest).Wrap(err) } if ok, err := existingRCS.Contains(status); !ok || err != nil { return model.NewAppError("RemoveRecentCustomStatus", "api.custom_status.recent_custom_statuses.delete.app_error", nil, "", http.StatusBadRequest) } - newRCS, removeErr := existingRCS.Remove(status) - if removeErr != nil { - return model.NewAppError("RemoveRecentCustomStatus", "api.custom_status.recent_custom_statuses.delete.app_error", nil, removeErr.Error(), http.StatusBadRequest) + newRCS, err := existingRCS.Remove(status) + if err != nil { + return model.NewAppError("RemoveRecentCustomStatus", "api.custom_status.recent_custom_statuses.delete.app_error", nil, "", http.StatusBadRequest).Wrap(err) } - newRCSJSON, jsonErr := json.Marshal(newRCS) - if jsonErr != nil { - return model.NewAppError("RemoveRecentCustomStatus", "api.marshal_error", nil, jsonErr.Error(), http.StatusBadRequest) + newRCSJSON, err := json.Marshal(newRCS) + if err != nil { + return model.NewAppError("RemoveRecentCustomStatus", "api.marshal_error", nil, "", http.StatusBadRequest).Wrap(err) } pref.Value = string(newRCSJSON) - if err := a.UpdatePreferences(userID, model.Preferences{*pref}); err != nil { - return err + if appErr := a.UpdatePreferences(userID, model.Preferences{*pref}); appErr != nil { + return appErr } return nil diff --git a/app/status_test.go b/app/status_test.go index e56ef60728..81ef4cebc4 100644 --- a/app/status_test.go +++ b/app/status_test.go @@ -104,7 +104,7 @@ func TestCustomStatusErrors(t *testing.T) { UserStore: &mockUserStore, SessionStore: &mockSessionStore, OAuthStore: &mockOAuthStore, - ConfigFn: th.App.ch.srv.Config, + ConfigFn: th.App.ch.srv.platform.Config, LicenseFn: th.App.ch.srv.License, }) require.NoError(t, err) diff --git a/app/support_packet.go b/app/support_packet.go index ea1a6b73ce..9b91471f02 100644 --- a/app/support_packet.go +++ b/app/support_packet.go @@ -6,7 +6,7 @@ package app import ( "encoding/json" "fmt" - "io/ioutil" + "os" "runtime" "strings" @@ -145,7 +145,7 @@ func (a *App) getNotificationsLog() (*model.FileData, string) { // notifications.log notificationsLog := config.GetNotificationsLogFileLocation(*a.Config().LogSettings.FileLocation) - notificationsLogFileData, notificationsLogFileDataErr := ioutil.ReadFile(notificationsLog) + notificationsLogFileData, notificationsLogFileDataErr := os.ReadFile(notificationsLog) if notificationsLogFileDataErr == nil { fileData := model.FileData{ @@ -155,7 +155,7 @@ func (a *App) getNotificationsLog() (*model.FileData, string) { return &fileData, "" } - warning = fmt.Sprintf("ioutil.ReadFile(notificationsLog) Error: %s", notificationsLogFileDataErr.Error()) + warning = fmt.Sprintf("os.ReadFile(notificationsLog) Error: %s", notificationsLogFileDataErr.Error()) } else { warning = "Unable to retrieve notifications.log because LogSettings: EnableFile is false in config.json" @@ -172,7 +172,7 @@ func (a *App) getMattermostLog() (*model.FileData, string) { // mattermost.log mattermostLog := config.GetLogFileLocation(*a.Config().LogSettings.FileLocation) - mattermostLogFileData, mattermostLogFileDataErr := ioutil.ReadFile(mattermostLog) + mattermostLogFileData, mattermostLogFileDataErr := os.ReadFile(mattermostLog) if mattermostLogFileDataErr == nil { fileData := model.FileData{ @@ -181,7 +181,7 @@ func (a *App) getMattermostLog() (*model.FileData, string) { } return &fileData, "" } - warning = fmt.Sprintf("ioutil.ReadFile(mattermostLog) Error: %s", mattermostLogFileDataErr.Error()) + warning = fmt.Sprintf("os.ReadFile(mattermostLog) Error: %s", mattermostLogFileDataErr.Error()) } else { warning = "Unable to retrieve mattermost.log because LogSettings: EnableFile is false in config.json" diff --git a/app/support_packet_test.go b/app/support_packet_test.go index 05e7d0418a..9ac966c0fa 100644 --- a/app/support_packet_test.go +++ b/app/support_packet_test.go @@ -4,7 +4,6 @@ package app import ( - "io/ioutil" "os" "testing" @@ -61,9 +60,9 @@ func TestGenerateSupportPacket(t *testing.T) { defer th.TearDown() d1 := []byte("hello\ngo\n") - err := ioutil.WriteFile("mattermost.log", d1, 0777) + err := os.WriteFile("mattermost.log", d1, 0777) require.NoError(t, err) - err = ioutil.WriteFile("notifications.log", d1, 0777) + err = os.WriteFile("notifications.log", d1, 0777) require.NoError(t, err) fileDatas := th.App.GenerateSupportPacket() @@ -111,11 +110,11 @@ func TestGetNotificationsLog(t *testing.T) { fileData, warning = th.App.getNotificationsLog() assert.Nil(t, fileData) - assert.Contains(t, warning, "ioutil.ReadFile(notificationsLog) Error:") + assert.Contains(t, warning, "os.ReadFile(notificationsLog) Error:") // Happy path where we have file and no warning d1 := []byte("hello\ngo\n") - err := ioutil.WriteFile("notifications.log", d1, 0777) + err := os.WriteFile("notifications.log", d1, 0777) defer os.Remove("notifications.log") require.NoError(t, err) @@ -149,11 +148,11 @@ func TestGetMattermostLog(t *testing.T) { fileData, warning = th.App.getMattermostLog() assert.Nil(t, fileData) - assert.Contains(t, warning, "ioutil.ReadFile(mattermostLog) Error:") + assert.Contains(t, warning, "os.ReadFile(mattermostLog) Error:") // Happy path where we get a log file and no warning d1 := []byte("hello\ngo\n") - err := ioutil.WriteFile("mattermost.log", d1, 0777) + err := os.WriteFile("mattermost.log", d1, 0777) defer os.Remove("mattermost.log") require.NoError(t, err) diff --git a/app/team_test.go b/app/team_test.go index bb69aa762c..3938aaacff 100644 --- a/app/team_test.go +++ b/app/team_test.go @@ -1044,7 +1044,7 @@ func TestLeaveTeamPanic(t *testing.T) { UserStore: &mockUserStore, SessionStore: &mocks.SessionStore{}, OAuthStore: &mocks.OAuthStore{}, - ConfigFn: th.App.ch.srv.Config, + ConfigFn: th.App.ch.srv.platform.Config, LicenseFn: th.App.ch.srv.License, }) require.NoError(t, err) @@ -1088,7 +1088,7 @@ func TestLeaveTeamPanic(t *testing.T) { GroupStore: &mocks.GroupStore{}, Users: th.App.ch.srv.userService, WebHub: th.App.ch.srv, - ConfigFn: th.App.ch.srv.Config, + ConfigFn: th.App.ch.srv.platform.Config, LicenseFn: th.App.ch.srv.License, }) require.NoError(t, err) diff --git a/app/teams/helper_test.go b/app/teams/helper_test.go index 4aa6987bce..176a63e9e2 100644 --- a/app/teams/helper_test.go +++ b/app/teams/helper_test.go @@ -5,7 +5,6 @@ package teams import ( "bytes" - "io/ioutil" "os" "path/filepath" "testing" @@ -43,7 +42,7 @@ func Setup(tb testing.TB) *TestHelper { } func setupTestHelper(s store.Store, includeCacheLayer bool, tb testing.TB) *TestHelper { - tempWorkspace, err := ioutil.TempDir("", "teamservicetest") + tempWorkspace, err := os.MkdirTemp("", "teamservicetest") if err != nil { panic(err) } diff --git a/app/upload_test.go b/app/upload_test.go index 447914fa25..128f157912 100644 --- a/app/upload_test.go +++ b/app/upload_test.go @@ -6,8 +6,8 @@ package app import ( "bytes" "io" - "io/ioutil" "math/rand" + "os" "path/filepath" "sync" "sync/atomic" @@ -213,7 +213,7 @@ func TestUploadData(t *testing.T) { t.Run("image processing", func(t *testing.T) { testDir, _ := fileutils.FindDir("tests") - data, err := ioutil.ReadFile(filepath.Join(testDir, "test.png")) + data, err := os.ReadFile(filepath.Join(testDir, "test.png")) require.NoError(t, err) require.NotEmpty(t, data) diff --git a/app/user.go b/app/user.go index 9d2a2eb3ac..ec4d24063d 100644 --- a/app/user.go +++ b/app/user.go @@ -1241,7 +1241,7 @@ func (a *App) updateUserNotifyProps(userID string, props map[string]string) *mod case errors.As(err, &appErr): return appErr default: - return model.NewAppError("UpdateUser", "app.user.update.finding.app_error", nil, err.Error(), http.StatusInternalServerError) + return model.NewAppError("UpdateUser", "app.user.update.finding.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } } @@ -1417,7 +1417,7 @@ func (a *App) CreatePasswordRecoveryToken(userID, email string) (*model.Token, * } jsonData, err := json.Marshal(tokenExtra) if err != nil { - return nil, model.NewAppError("CreatePasswordRecoveryToken", "api.user.create_password_token.error", nil, "", http.StatusInternalServerError) + return nil, model.NewAppError("CreatePasswordRecoveryToken", "api.user.create_password_token.error", nil, "", http.StatusInternalServerError).Wrap(err) } token := model.NewToken(TokenTypePasswordRecovery, string(jsonData)) @@ -2184,9 +2184,9 @@ func (a *App) PromoteGuestToUser(c *request.Context, user *model.User, requestor for _, member := range teamMembers { a.sendUpdatedMemberRoleEvent(user.Id, member) - channelMembers, err := a.GetChannelMembersForUser(c, member.TeamId, user.Id) - if err != nil { - c.Logger().Warn("Failed to get channel members for user on promote guest to user", mlog.Err(err)) + channelMembers, appErr := a.GetChannelMembersForUser(c, member.TeamId, user.Id) + if appErr != nil { + c.Logger().Warn("Failed to get channel members for user on promote guest to user", mlog.Err(appErr)) } for _, member := range channelMembers { @@ -2228,9 +2228,9 @@ func (a *App) DemoteUserToGuest(c request.CTX, user *model.User) *model.AppError for _, member := range teamMembers { a.sendUpdatedMemberRoleEvent(user.Id, member) - channelMembers, err := a.GetChannelMembersForUser(c, member.TeamId, user.Id) - if err != nil { - c.Logger().Warn("Failed to get channel members for users on demote user to guest", mlog.Err(err)) + channelMembers, appErr := a.GetChannelMembersForUser(c, member.TeamId, user.Id) + if appErr != nil { + c.Logger().Warn("Failed to get channel members for users on demote user to guest", mlog.Err(appErr)) continue } diff --git a/app/user_test.go b/app/user_test.go index 4d545f894f..75d5fa80f3 100644 --- a/app/user_test.go +++ b/app/user_test.go @@ -1712,7 +1712,7 @@ func TestUpdateThreadReadForUser(t *testing.T) { UserStore: &mockUserStore, SessionStore: &storemocks.SessionStore{}, OAuthStore: &storemocks.OAuthStore{}, - ConfigFn: th.App.ch.srv.Config, + ConfigFn: th.App.ch.srv.platform.Config, LicenseFn: th.App.ch.srv.License, }) require.NoError(t, err) @@ -1749,8 +1749,8 @@ func TestCreateUserWithInitialPreferences(t *testing.T) { }) t.Run("successfully create a user with insights feature flag disabled", func(t *testing.T) { - th.Server.configStore.SetReadOnlyFF(false) - defer th.Server.configStore.SetReadOnlyFF(true) + th.Server.platform.SetConfigReadOnlyFF(false) + defer th.Server.platform.SetConfigReadOnlyFF(true) th.App.UpdateConfig(func(cfg *model.Config) { cfg.FeatureFlags.InsightsEnabled = false }) defer th.App.UpdateConfig(func(cfg *model.Config) { cfg.FeatureFlags.InsightsEnabled = true }) testUser := th.CreateUser() @@ -1769,8 +1769,8 @@ func TestCreateUserWithInitialPreferences(t *testing.T) { }) t.Run("successfully create a guest user with initial tutorial, insights and recommended steps preferences", func(t *testing.T) { - th.Server.configStore.SetReadOnlyFF(false) - defer th.Server.configStore.SetReadOnlyFF(true) + th.Server.platform.SetConfigReadOnlyFF(false) + defer th.Server.platform.SetConfigReadOnlyFF(true) th.App.UpdateConfig(func(cfg *model.Config) { cfg.FeatureFlags.InsightsEnabled = true }) testUser := th.CreateGuest() defer th.App.PermanentDeleteUser(th.Context, testUser) diff --git a/app/users/helper_test.go b/app/users/helper_test.go index 8ddf4d97e5..44e55114b6 100644 --- a/app/users/helper_test.go +++ b/app/users/helper_test.go @@ -5,7 +5,6 @@ package users import ( "bytes" - "io/ioutil" "os" "path/filepath" "runtime" @@ -48,7 +47,7 @@ func Setup(tb testing.TB) *TestHelper { } func setupTestHelper(s store.Store, includeCacheLayer bool, tb testing.TB) *TestHelper { - tempWorkspace, err := ioutil.TempDir("", "userservicetest") + tempWorkspace, err := os.MkdirTemp("", "userservicetest") if err != nil { panic(err) } diff --git a/app/users/profile_picture.go b/app/users/profile_picture.go index c0260c5a5b..1858140e52 100644 --- a/app/users/profile_picture.go +++ b/app/users/profile_picture.go @@ -11,7 +11,7 @@ import ( "image/draw" "image/png" "io" - "io/ioutil" + "os" "path" "path/filepath" "strings" @@ -174,7 +174,7 @@ func getFont(initialFont string) (*truetype.Font, error) { } fontDir, _ := fileutils.FindDir("fonts") - fontBytes, err := ioutil.ReadFile(filepath.Join(fontDir, initialFont)) + fontBytes, err := os.ReadFile(filepath.Join(fontDir, initialFont)) if err != nil { return nil, err } diff --git a/app/web_hub_test.go b/app/web_hub_test.go index 10dd13c695..ee14d43fd2 100644 --- a/app/web_hub_test.go +++ b/app/web_hub_test.go @@ -167,7 +167,7 @@ func TestHubSessionRevokeRace(t *testing.T) { UserStore: &mockUserStore, SessionStore: &mockSessionStore, OAuthStore: &mockOAuthStore, - ConfigFn: th.App.ch.srv.Config, + ConfigFn: th.App.ch.srv.platform.Config, Metrics: th.App.Metrics(), Cluster: th.App.Cluster(), LicenseFn: th.App.ch.srv.License, diff --git a/app/webhook.go b/app/webhook.go index 37e68fd544..e8b201f056 100644 --- a/app/webhook.go +++ b/app/webhook.go @@ -98,9 +98,9 @@ func (a *App) TriggerWebhook(c request.CTX, payload *model.OutgoingWebhookPayloa var body io.Reader var contentType string if hook.ContentType == "application/json" { - js, jsonErr := json.Marshal(payload) - if jsonErr != nil { - mlog.Warn("Failed to encode to JSON", mlog.Err(jsonErr)) + js, err := json.Marshal(payload) + if err != nil { + c.Logger().Warn("Failed to encode to JSON", mlog.Err(err)) } body = bytes.NewReader(js) contentType = "application/json" @@ -116,7 +116,7 @@ func (a *App) TriggerWebhook(c request.CTX, payload *model.OutgoingWebhookPayloa a.Srv().Go(func() { webhookResp, err := a.doOutgoingWebhookRequest(url, body, contentType) if err != nil { - mlog.Error("Event POST failed.", mlog.Err(err)) + c.Logger().Error("Event POST failed.", mlog.Err(err)) return } @@ -147,7 +147,7 @@ func (a *App) TriggerWebhook(c request.CTX, payload *model.OutgoingWebhookPayloa webhookResp.IconURL = hook.IconURL } if _, err := a.CreateWebhookPost(c, hook.CreatorId, channel, text, webhookResp.Username, webhookResp.IconURL, "", webhookResp.Props, webhookResp.Type, postRootId); err != nil { - mlog.Error("Failed to create response post.", mlog.Err(err)) + c.Logger().Error("Failed to create response post.", mlog.Err(err)) } } }) @@ -175,7 +175,7 @@ func (a *App) doOutgoingWebhookRequest(url string, body io.Reader, contentType s if jsonErr == io.EOF { return nil, nil } - return nil, model.NewAppError("doOutgoingWebhookRequest", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + return nil, model.NewAppError("doOutgoingWebhookRequest", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr) } return &hookResp, nil diff --git a/app/webhub_fuzz.go b/app/webhub_fuzz.go index 5f39d8952d..a305b3cfc0 100644 --- a/app/webhub_fuzz.go +++ b/app/webhub_fuzz.go @@ -6,7 +6,6 @@ package app import ( - "io/ioutil" "math/rand" "net" "net/http" @@ -273,7 +272,7 @@ func generateInitialCorpus() error { if err != nil { return err } - err = ioutil.WriteFile("./workdir/corpus"+strconv.Itoa(i), data, 0644) + err = os.WriteFile("./workdir/corpus"+strconv.Itoa(i), data, 0644) if err != nil { return err } diff --git a/audit/audit_test.go b/audit/audit_test.go index cc3ce3d676..f6055c8166 100644 --- a/audit/audit_test.go +++ b/audit/audit_test.go @@ -6,7 +6,6 @@ package audit import ( "encoding/json" "fmt" - "io/ioutil" "os" "path/filepath" "regexp" @@ -72,7 +71,7 @@ func TestAudit_LogRecord(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.description, func(t *testing.T) { - tempDir, err := ioutil.TempDir(os.TempDir(), "TestAudit_LogRecord") + tempDir, err := os.MkdirTemp(os.TempDir(), "TestAudit_LogRecord") require.NoError(t, err) defer os.Remove(tempDir) @@ -92,7 +91,7 @@ func TestAudit_LogRecord(t *testing.T) { err = logger.Shutdown() require.NoError(t, err) - logs, err := ioutil.ReadFile(filePath) + logs, err := os.ReadFile(filePath) require.NoError(t, err) actual := strings.TrimSpace(string(logs)) diff --git a/cmd/mattermost/commands/cmdtestlib.go b/cmd/mattermost/commands/cmdtestlib.go index f79fdf9340..34a572d6b1 100644 --- a/cmd/mattermost/commands/cmdtestlib.go +++ b/cmd/mattermost/commands/cmdtestlib.go @@ -9,7 +9,6 @@ import ( "flag" "fmt" "io" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -127,7 +126,7 @@ func (h *testHelper) SetConfig(config *model.Config) { if err != nil { panic("failed to marshal config: " + err.Error()) } - if err := ioutil.WriteFile(h.configFilePath, buf, 0600); err != nil { + if err := os.WriteFile(h.configFilePath, buf, 0600); err != nil { panic("failed to write file " + h.configFilePath + ": " + err.Error()) } } diff --git a/cmd/mattermost/commands/init.go b/cmd/mattermost/commands/init.go index a4c58285fa..dfcb54b2ed 100644 --- a/cmd/mattermost/commands/init.go +++ b/cmd/mattermost/commands/init.go @@ -42,9 +42,10 @@ func initDBCommandContext(configDSN string, readOnlyConfigStore bool) (*app.App, model.AppErrorInit(i18n.T) s, err := app.NewServer( + // The option order is important as app.Config option reads app.StartMetrics option. + app.StartMetrics, app.Config(configDSN, readOnlyConfigStore, nil), app.StartSearchEngine, - app.StartMetrics, ) if err != nil { return nil, err diff --git a/cmd/mattermost/commands/server.go b/cmd/mattermost/commands/server.go index 3d0c430255..20309b31be 100644 --- a/cmd/mattermost/commands/server.go +++ b/cmd/mattermost/commands/server.go @@ -65,11 +65,12 @@ func runServer(configStore *config.Store, interruptChan chan os.Signal) error { debug.SetTraceback("crash") options := []app.Option{ + // The option order is important as app.Config option reads app.StartMetrics option. + app.StartMetrics, app.ConfigStore(configStore), app.RunEssentialJobs, app.JoinCluster, app.StartSearchEngine, - app.StartMetrics, } server, err := app.NewServer(options...) if err != nil { diff --git a/cmd/mattermost/commands/server_test.go b/cmd/mattermost/commands/server_test.go index 8d94a4de17..5a7d9aa8f3 100644 --- a/cmd/mattermost/commands/server_test.go +++ b/cmd/mattermost/commands/server_test.go @@ -4,7 +4,6 @@ package commands import ( - "io/ioutil" "net" "os" "syscall" @@ -77,7 +76,7 @@ func TestRunServerSystemdNotification(t *testing.T) { defer th.TearDownServerTest() // Get a random temporary filename for using as a mock systemd socket - socketFile, err := ioutil.TempFile("", "mattermost-systemd-mock-socket-") + socketFile, err := os.CreateTemp("", "mattermost-systemd-mock-socket-") if err != nil { panic(err) } diff --git a/config/file.go b/config/file.go index cbf53cf73e..1455a4d99e 100644 --- a/config/file.go +++ b/config/file.go @@ -5,7 +5,7 @@ package config import ( "fmt" - "io/ioutil" + "io" "os" "path/filepath" @@ -111,7 +111,7 @@ func (fs *FileStore) persist(cfg *model.Config) error { return errors.Wrap(err, "failed to serialize") } - err = ioutil.WriteFile(fs.path, b, 0600) + err = os.WriteFile(fs.path, b, 0600) if err != nil { return errors.Wrap(err, "failed to write file") } @@ -130,7 +130,7 @@ func (fs *FileStore) Load() ([]byte, error) { } defer f.Close() - fileBytes, err := ioutil.ReadAll(f) + fileBytes, err := io.ReadAll(f) if err != nil { return nil, err } @@ -142,7 +142,7 @@ func (fs *FileStore) Load() ([]byte, error) { func (fs *FileStore) GetFile(name string) ([]byte, error) { resolvedPath := fs.resolveFilePath(name) - data, err := ioutil.ReadFile(resolvedPath) + data, err := os.ReadFile(resolvedPath) if err != nil { return nil, errors.Wrapf(err, "failed to read file from %s", resolvedPath) } @@ -160,7 +160,7 @@ func (fs *FileStore) GetFilePath(name string) string { func (fs *FileStore) SetFile(name string, data []byte) error { resolvedPath := fs.resolveFilePath(name) - err := ioutil.WriteFile(resolvedPath, data, 0600) + err := os.WriteFile(resolvedPath, data, 0600) if err != nil { return errors.Wrapf(err, "failed to write file to %s", resolvedPath) } diff --git a/config/file_test.go b/config/file_test.go index 0ae493b499..35bf30f474 100644 --- a/config/file_test.go +++ b/config/file_test.go @@ -5,7 +5,6 @@ package config import ( "encoding/json" - "io/ioutil" "os" "path/filepath" "strings" @@ -24,7 +23,7 @@ func setupConfigFile(t *testing.T, cfg *model.Config) (string, func()) { os.Clearenv() t.Helper() - tempDir, err := ioutil.TempDir("", "setupConfigFile") + tempDir, err := os.MkdirTemp("", "setupConfigFile") require.NoError(t, err) err = os.Chdir(tempDir) @@ -32,13 +31,13 @@ func setupConfigFile(t *testing.T, cfg *model.Config) (string, func()) { var name string if cfg != nil { - f, err := ioutil.TempFile(tempDir, "setupConfigFile") + f, err := os.CreateTemp(tempDir, "setupConfigFile") require.NoError(t, err) cfgData, err := marshalConfig(cfg) require.NoError(t, err) - ioutil.WriteFile(f.Name(), cfgData, 0644) + os.WriteFile(f.Name(), cfgData, 0644) name = f.Name() } @@ -165,7 +164,7 @@ func TestFileStoreNew(t *testing.T) { _, tearDown := setupConfigFile(t, nil) defer tearDown() - tempDir, err := ioutil.TempDir("", "TestFileStoreNew") + tempDir, err := os.MkdirTemp("", "TestFileStoreNew") require.NoError(t, err) defer os.RemoveAll(tempDir) @@ -184,7 +183,7 @@ func TestFileStoreNew(t *testing.T) { _, tearDown := setupConfigFile(t, nil) defer tearDown() - tempDir, err := ioutil.TempDir("", "TestFileStoreNew") + tempDir, err := os.MkdirTemp("", "TestFileStoreNew") require.NoError(t, err) defer os.RemoveAll(tempDir) @@ -203,7 +202,7 @@ func TestFileStoreNew(t *testing.T) { _, tearDown := setupConfigFile(t, nil) defer tearDown() - tempDir, err := ioutil.TempDir("", "TestFileStoreNew") + tempDir, err := os.MkdirTemp("", "TestFileStoreNew") require.NoError(t, err) defer os.RemoveAll(tempDir) @@ -225,7 +224,7 @@ func TestFileStoreNew(t *testing.T) { cfgData, err := marshalConfig(testConfig) require.NoError(t, err) - ioutil.WriteFile(path, cfgData, 0644) + os.WriteFile(path, cfgData, 0644) fs, err := NewFileStore(path, false) require.NoError(t, err) @@ -815,7 +814,7 @@ func TestFileStoreLoad(t *testing.T) { cfgData, err := marshalConfig(invalidConfig) require.NoError(t, err) - ioutil.WriteFile(path, cfgData, 0644) + os.WriteFile(path, cfgData, 0644) err = fs.Load() if assert.Error(t, err) { @@ -876,7 +875,7 @@ func TestFileStoreLoad(t *testing.T) { cfgData, err := marshalConfig(minimalConfig) require.NoError(t, err) - err = ioutil.WriteFile(path, cfgData, 0644) + err = os.WriteFile(path, cfgData, 0644) require.NoError(t, err) err = fs.Load() @@ -971,11 +970,11 @@ func TestFileGetFile(t *testing.T) { err := os.MkdirAll("config", 0700) require.NoError(t, err) - f, err := ioutil.TempFile("config", "empty-file") + f, err := os.CreateTemp("config", "empty-file") require.NoError(t, err) defer os.Remove(f.Name()) - err = ioutil.WriteFile(f.Name(), nil, 0777) + err = os.WriteFile(f.Name(), nil, 0777) require.NoError(t, err) data, err := fs.GetFile(f.Name()) @@ -987,11 +986,11 @@ func TestFileGetFile(t *testing.T) { err := os.MkdirAll("config", 0700) require.NoError(t, err) - f, err := ioutil.TempFile("config", "test-file") + f, err := os.CreateTemp("config", "test-file") require.NoError(t, err) defer os.Remove(f.Name()) - err = ioutil.WriteFile(f.Name(), []byte("test"), 0777) + err = os.WriteFile(f.Name(), []byte("test"), 0777) require.NoError(t, err) data, err := fs.GetFile(f.Name()) @@ -1102,11 +1101,11 @@ func TestFileHasFile(t *testing.T) { err = os.MkdirAll("config", 0700) require.NoError(t, err) - f, err := ioutil.TempFile("config", "test-file") + f, err := os.CreateTemp("config", "test-file") require.NoError(t, err) defer os.Remove(f.Name()) - err = ioutil.WriteFile(f.Name(), []byte("test"), 0777) + err = os.WriteFile(f.Name(), []byte("test"), 0777) require.NoError(t, err) has, err := fs.HasFile(f.Name()) @@ -1191,11 +1190,11 @@ func TestFileRemoveFile(t *testing.T) { err = os.MkdirAll("config", 0700) require.NoError(t, err) - f, err := ioutil.TempFile("config", "test-file") + f, err := os.CreateTemp("config", "test-file") require.NoError(t, err) defer os.Remove(f.Name()) - err = ioutil.WriteFile(f.Name(), []byte("test"), 0777) + err = os.WriteFile(f.Name(), []byte("test"), 0777) require.NoError(t, err) err = fs.RemoveFile(f.Name()) @@ -1314,7 +1313,7 @@ func TestFileStoreSetReadOnlyFF(t *testing.T) { func TestResolveConfigPath(t *testing.T) { t.Run("should be able to resolve an absolute path", func(t *testing.T) { - cf, err := ioutil.TempFile("", "config-test.json") + cf, err := os.CreateTemp("", "config-test.json") require.NoError(t, err) info, err := cf.Stat() require.NoError(t, err) @@ -1329,7 +1328,7 @@ func TestResolveConfigPath(t *testing.T) { }) t.Run("should be able to resolve relative path", func(t *testing.T) { - tempDir, err := ioutil.TempDir("", "resolveconfig") + tempDir, err := os.MkdirTemp("", "resolveconfig") require.NoError(t, err) defer os.RemoveAll(tempDir) diff --git a/config/migrate_test.go b/config/migrate_test.go index 348f29bd5f..27a1b9ccda 100644 --- a/config/migrate_test.go +++ b/config/migrate_test.go @@ -4,7 +4,6 @@ package config import ( - "io/ioutil" "os" "path" "testing" @@ -39,7 +38,7 @@ func TestMigrate(t *testing.T) { os.Clearenv() t.Helper() - tempDir, err := ioutil.TempDir("", "TestMigrate") + tempDir, err := os.MkdirTemp("", "TestMigrate") require.NoError(t, err) t.Cleanup(func() { os.RemoveAll(tempDir) diff --git a/config/store_test.go b/config/store_test.go index dc13329522..35a999f75e 100644 --- a/config/store_test.go +++ b/config/store_test.go @@ -4,7 +4,6 @@ package config import ( - "io/ioutil" "os" "path/filepath" "testing" @@ -18,7 +17,7 @@ func TestNewStoreFromDSN(t *testing.T) { } sqlSettings := mainHelper.GetSQLSettings() - tempDir, err := ioutil.TempDir("", "TestNewStore") + tempDir, err := os.MkdirTemp("", "TestNewStore") require.NoError(t, err) err = os.Chdir(tempDir) @@ -46,7 +45,7 @@ func TestNewStoreReadOnly(t *testing.T) { } sqlSettings := mainHelper.GetSQLSettings() - tempDir, tErr := ioutil.TempDir("", "TestNewStore") + tempDir, tErr := os.MkdirTemp("", "TestNewStore") require.NoError(t, tErr) tErr = os.Chdir(tempDir) diff --git a/jobs/migrations/advanced_permissions_phase_2.go b/jobs/migrations/advanced_permissions_phase_2.go index 4dbf0b233b..e0c517f0ea 100644 --- a/jobs/migrations/advanced_permissions_phase_2.go +++ b/jobs/migrations/advanced_permissions_phase_2.go @@ -10,6 +10,7 @@ import ( "strings" "github.com/mattermost/mattermost-server/v6/model" + "github.com/mattermost/mattermost-server/v6/shared/mlog" ) type AdvancedPermissionsPhase2Progress struct { @@ -26,7 +27,10 @@ func (p *AdvancedPermissionsPhase2Progress) ToJSON() string { func AdvancedPermissionsPhase2ProgressFromJSON(data io.Reader) *AdvancedPermissionsPhase2Progress { var o *AdvancedPermissionsPhase2Progress - json.NewDecoder(data).Decode(&o) + err := json.NewDecoder(data).Decode(&o) + if err != nil { + mlog.Warn("Error decoding advanced permissions phase 2 progress", mlog.Err(err)) + } return o } @@ -57,13 +61,17 @@ func (worker *Worker) runAdvancedPermissionsPhase2Migration(lastDone string) (bo var progress *AdvancedPermissionsPhase2Progress if lastDone == "" { // Haven't started the migration yet. - progress = new(AdvancedPermissionsPhase2Progress) - progress.CurrentTable = "TeamMembers" - progress.LastChannelId = strings.Repeat("0", 26) - progress.LastTeamId = strings.Repeat("0", 26) - progress.LastUserId = strings.Repeat("0", 26) + progress = &AdvancedPermissionsPhase2Progress{ + CurrentTable: "TeamMembers", + LastChannelId: strings.Repeat("0", 26), + LastTeamId: strings.Repeat("0", 26), + LastUserId: strings.Repeat("0", 26), + } } else { - progress = AdvancedPermissionsPhase2ProgressFromJSON(strings.NewReader(lastDone)) + err := json.NewDecoder(strings.NewReader(lastDone)).Decode(&progress) + if err != nil { + return false, "", model.NewAppError("MigrationsWorker.runAdvancedPermissionsPhase2Migration", "migrations.worker.run_advanced_permissions_phase_2_migration.invalid_progress", map[string]any{"lastDone": lastDone}, "", http.StatusInternalServerError).Wrap(err) + } if !progress.IsValid() { return false, "", model.NewAppError("MigrationsWorker.runAdvancedPermissionsPhase2Migration", "migrations.worker.run_advanced_permissions_phase_2_migration.invalid_progress", map[string]any{"progress": progress.ToJSON()}, "", http.StatusInternalServerError) } diff --git a/model/bundle_info_test.go b/model/bundle_info_test.go index e91ec0efb4..eb771baea6 100644 --- a/model/bundle_info_test.go +++ b/model/bundle_info_test.go @@ -4,7 +4,6 @@ package model import ( - "io/ioutil" "os" "path/filepath" "testing" @@ -14,7 +13,7 @@ import ( ) func TestBundleInfoForPath(t *testing.T) { - dir, err := ioutil.TempDir("", "mm-plugin-test") + dir, err := os.MkdirTemp("", "mm-plugin-test") require.NoError(t, err) defer os.RemoveAll(dir) diff --git a/model/channel.go b/model/channel.go index cdf40140a5..e66c30faef 100644 --- a/model/channel.go +++ b/model/channel.go @@ -156,7 +156,6 @@ type ChannelModeratedRolesPatch struct { // Paginate whether to paginate the results. // Page page requested, if results are paginated. // PerPage number of results per page, if paginated. -// type ChannelSearchOpts struct { NotAssociatedToGroup string ExcludeDefaultChannels bool diff --git a/model/client4.go b/model/client4.go index 415be5d5b2..c935f72304 100644 --- a/model/client4.go +++ b/model/client4.go @@ -8,7 +8,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "mime/multipart" "net" "net/http" @@ -663,8 +662,8 @@ func (c *Client4) doUploadFile(url string, body io.Reader, contentType string, c } var res FileUploadResponse - if jsonErr := json.NewDecoder(rp.Body).Decode(&res); jsonErr != nil { - return nil, nil, NewAppError("doUploadFile", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(rp.Body).Decode(&res); err != nil { + return nil, nil, NewAppError("doUploadFile", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &res, BuildResponse(rp), nil } @@ -691,8 +690,8 @@ func (c *Client4) DoEmojiUploadFile(url string, data []byte, contentType string) } var e Emoji - if jsonErr := json.NewDecoder(rp.Body).Decode(&e); jsonErr != nil { - return nil, nil, NewAppError("DoEmojiUploadFile", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(rp.Body).Decode(&e); err != nil { + return nil, nil, NewAppError("DoEmojiUploadFile", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &e, BuildResponse(rp), nil } @@ -779,8 +778,8 @@ func (c *Client4) login(m map[string]string) (*User, *Response, error) { c.AuthType = HeaderBearer var user User - if jsonErr := json.NewDecoder(r.Body).Decode(&user); jsonErr != nil { - return nil, nil, NewAppError("login", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&user); err != nil { + return nil, nil, NewAppError("login", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &user, BuildResponse(r), nil } @@ -801,7 +800,7 @@ func (c *Client4) Logout() (*Response, error) { func (c *Client4) SwitchAccountType(switchRequest *SwitchRequest) (string, *Response, error) { buf, err := json.Marshal(switchRequest) if err != nil { - return "", BuildResponse(nil), NewAppError("SwitchAccountType", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) + return "", BuildResponse(nil), NewAppError("SwitchAccountType", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } r, err := c.DoAPIPostBytes(c.usersRoute()+"/login/switch", buf) if err != nil { @@ -815,9 +814,9 @@ func (c *Client4) SwitchAccountType(switchRequest *SwitchRequest) (string, *Resp // CreateUser creates a user in the system based on the provided user struct. func (c *Client4) CreateUser(user *User) (*User, *Response, error) { - userJSON, jsonErr := json.Marshal(user) - if jsonErr != nil { - return nil, nil, NewAppError("CreateUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + userJSON, err := json.Marshal(user) + if err != nil { + return nil, nil, NewAppError("CreateUser", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } r, err := c.DoAPIPost(c.usersRoute(), string(userJSON)) @@ -826,8 +825,8 @@ func (c *Client4) CreateUser(user *User) (*User, *Response, error) { } defer closeBody(r) var u User - if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { - return nil, nil, NewAppError("CreateUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&u); err != nil { + return nil, nil, NewAppError("CreateUser", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } return &u, BuildResponse(r), nil } @@ -838,10 +837,10 @@ func (c *Client4) CreateUserWithToken(user *User, tokenId string) (*User, *Respo return nil, nil, NewAppError("MissingHashOrData", "api.user.create_user.missing_token.app_error", nil, "", http.StatusBadRequest) } - query := fmt.Sprintf("?t=%v", tokenId) + query := "?t=" + tokenId buf, err := json.Marshal(user) if err != nil { - return nil, nil, NewAppError("CreateUserWithToken", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) + return nil, nil, NewAppError("CreateUserWithToken", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } r, err := c.DoAPIPostBytes(c.usersRoute()+query, buf) if err != nil { @@ -850,8 +849,8 @@ func (c *Client4) CreateUserWithToken(user *User, tokenId string) (*User, *Respo defer closeBody(r) var u User - if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { - return nil, nil, NewAppError("CreateUserWithToken", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&u); err != nil { + return nil, nil, NewAppError("CreateUserWithToken", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } return &u, BuildResponse(r), nil } @@ -862,10 +861,10 @@ func (c *Client4) CreateUserWithInviteId(user *User, inviteId string) (*User, *R return nil, nil, NewAppError("MissingInviteId", "api.user.create_user.missing_invite_id.app_error", nil, "", http.StatusBadRequest) } - query := fmt.Sprintf("?iid=%v", url.QueryEscape(inviteId)) + query := "?iid=" + url.QueryEscape(inviteId) buf, err := json.Marshal(user) if err != nil { - return nil, nil, NewAppError("CreateUserWithInviteId", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) + return nil, nil, NewAppError("CreateUserWithInviteId", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } r, err := c.DoAPIPostBytes(c.usersRoute()+query, buf) if err != nil { @@ -874,8 +873,8 @@ func (c *Client4) CreateUserWithInviteId(user *User, inviteId string) (*User, *R defer closeBody(r) var u User - if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { - return nil, nil, NewAppError("CreateUserWithInviteId", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&u); err != nil { + return nil, nil, NewAppError("CreateUserWithInviteId", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } return &u, BuildResponse(r), nil } @@ -891,8 +890,8 @@ func (c *Client4) GetMe(etag string) (*User, *Response, error) { if r.StatusCode == http.StatusNotModified { return &u, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { - return nil, nil, NewAppError("GetMe", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&u); err != nil { + return nil, nil, NewAppError("GetMe", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } return &u, BuildResponse(r), nil } @@ -908,8 +907,8 @@ func (c *Client4) GetUser(userId, etag string) (*User, *Response, error) { if r.StatusCode == http.StatusNotModified { return &u, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { - return nil, nil, NewAppError("GetUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&u); err != nil { + return nil, nil, NewAppError("GetUser", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } return &u, BuildResponse(r), nil } @@ -925,8 +924,8 @@ func (c *Client4) GetUserByUsername(userName, etag string) (*User, *Response, er if r.StatusCode == http.StatusNotModified { return &u, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { - return nil, nil, NewAppError("GetUserByUsername", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&u); err != nil { + return nil, nil, NewAppError("GetUserByUsername", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &u, BuildResponse(r), nil } @@ -942,8 +941,8 @@ func (c *Client4) GetUserByEmail(email, etag string) (*User, *Response, error) { if r.StatusCode == http.StatusNotModified { return &u, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { - return nil, nil, NewAppError("GetUserByEmail", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&u); err != nil { + return nil, nil, NewAppError("GetUserByEmail", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &u, BuildResponse(r), nil } @@ -960,8 +959,8 @@ func (c *Client4) AutocompleteUsersInTeam(teamId string, username string, limit if r.StatusCode == http.StatusNotModified { return &u, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { - return nil, nil, NewAppError("AutocompleteUsersInTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&u); err != nil { + return nil, nil, NewAppError("AutocompleteUsersInTeam", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &u, BuildResponse(r), nil } @@ -978,8 +977,8 @@ func (c *Client4) AutocompleteUsersInChannel(teamId string, channelId string, us if r.StatusCode == http.StatusNotModified { return &u, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { - return nil, nil, NewAppError("AutocompleteUsersInChannel", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&u); err != nil { + return nil, nil, NewAppError("AutocompleteUsersInChannel", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &u, BuildResponse(r), nil } @@ -996,8 +995,8 @@ func (c *Client4) AutocompleteUsers(username string, limit int, etag string) (*U if r.StatusCode == http.StatusNotModified { return &u, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { - return nil, nil, NewAppError("AutocompleteUsers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&u); err != nil { + return nil, nil, NewAppError("AutocompleteUsers", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &u, BuildResponse(r), nil } @@ -1010,7 +1009,7 @@ func (c *Client4) GetDefaultProfileImage(userId string) ([]byte, *Response, erro } defer closeBody(r) - data, err := ioutil.ReadAll(r.Body) + data, err := io.ReadAll(r.Body) if err != nil { return nil, BuildResponse(r), NewAppError("GetDefaultProfileImage", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode) } @@ -1026,7 +1025,7 @@ func (c *Client4) GetProfileImage(userId, etag string) ([]byte, *Response, error } defer closeBody(r) - data, err := ioutil.ReadAll(r.Body) + data, err := io.ReadAll(r.Body) if err != nil { return nil, BuildResponse(r), NewAppError("GetProfileImage", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode) } @@ -1045,8 +1044,8 @@ func (c *Client4) GetUsers(page int, perPage int, etag string) ([]*User, *Respon if r.StatusCode == http.StatusNotModified { return list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetUsers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetUsers", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -1063,8 +1062,8 @@ func (c *Client4) GetUsersInTeam(teamId string, page int, perPage int, etag stri if r.StatusCode == http.StatusNotModified { return list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetUsersInTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetUsersInTeam", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -1081,8 +1080,8 @@ func (c *Client4) GetNewUsersInTeam(teamId string, page int, perPage int, etag s if r.StatusCode == http.StatusNotModified { return list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetNewUsersInTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetNewUsersInTeam", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -1099,8 +1098,8 @@ func (c *Client4) GetRecentlyActiveUsersInTeam(teamId string, page int, perPage if r.StatusCode == http.StatusNotModified { return list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetRecentlyActiveUsersInTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetRecentlyActiveUsersInTeam", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -1117,8 +1116,8 @@ func (c *Client4) GetActiveUsersInTeam(teamId string, page int, perPage int, eta if r.StatusCode == http.StatusNotModified { return list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetActiveUsersInTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetActiveUsersInTeam", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -1135,8 +1134,8 @@ func (c *Client4) GetUsersNotInTeam(teamId string, page int, perPage int, etag s if r.StatusCode == http.StatusNotModified { return list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetUsersNotInTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetUsersNotInTeam", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -1153,8 +1152,8 @@ func (c *Client4) GetUsersInChannel(channelId string, page int, perPage int, eta if r.StatusCode == http.StatusNotModified { return list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetUsersInChannel", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetUsersInChannel", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -1171,8 +1170,8 @@ func (c *Client4) GetUsersInChannelByStatus(channelId string, page int, perPage if r.StatusCode == http.StatusNotModified { return list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetUsersInChannelByStatus", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetUsersInChannelByStatus", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -1189,8 +1188,8 @@ func (c *Client4) GetUsersNotInChannel(teamId, channelId string, page int, perPa if r.StatusCode == http.StatusNotModified { return list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetUsersNotInChannel", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetUsersNotInChannel", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -1207,8 +1206,8 @@ func (c *Client4) GetUsersWithoutTeam(page int, perPage int, etag string) ([]*Us if r.StatusCode == http.StatusNotModified { return list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetUsersWithoutTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetUsersWithoutTeam", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -1225,8 +1224,8 @@ func (c *Client4) GetUsersInGroup(groupID string, page int, perPage int, etag st if r.StatusCode == http.StatusNotModified { return list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetUsersInGroup", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetUsersInGroup", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -1239,8 +1238,8 @@ func (c *Client4) GetUsersByIds(userIds []string) ([]*User, *Response, error) { } defer closeBody(r) var list []*User - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetUsersByIds", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetUsersByIds", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -1263,8 +1262,8 @@ func (c *Client4) GetUsersByIdsWithOptions(userIds []string, options *UserGetByI } defer closeBody(r) var list []*User - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetUsersByIdsWithOptions", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetUsersByIdsWithOptions", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -1277,8 +1276,8 @@ func (c *Client4) GetUsersByUsernames(usernames []string) ([]*User, *Response, e } defer closeBody(r) var list []*User - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetUsersByUsernames", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetUsersByUsernames", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -1301,7 +1300,7 @@ func (c *Client4) GetUsersByGroupChannelIds(groupChannelIds []string) (map[strin func (c *Client4) SearchUsers(search *UserSearch) ([]*User, *Response, error) { buf, err := json.Marshal(search) if err != nil { - return nil, nil, NewAppError("SearchUsers", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) + return nil, nil, NewAppError("SearchUsers", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } r, err := c.DoAPIPostBytes(c.usersRoute()+"/search", buf) if err != nil { @@ -1309,8 +1308,8 @@ func (c *Client4) SearchUsers(search *UserSearch) ([]*User, *Response, error) { } defer closeBody(r) var list []*User - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("SearchUsers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("SearchUsers", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } return list, BuildResponse(r), nil } @@ -1319,7 +1318,7 @@ func (c *Client4) SearchUsers(search *UserSearch) ([]*User, *Response, error) { func (c *Client4) UpdateUser(user *User) (*User, *Response, error) { buf, err := json.Marshal(user) if err != nil { - return nil, nil, NewAppError("UpdateUser", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) + return nil, nil, NewAppError("UpdateUser", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } r, err := c.DoAPIPutBytes(c.userRoute(user.Id), buf) if err != nil { @@ -1327,8 +1326,8 @@ func (c *Client4) UpdateUser(user *User) (*User, *Response, error) { } defer closeBody(r) var u User - if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { - return nil, nil, NewAppError("UpdateUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&u); err != nil { + return nil, nil, NewAppError("UpdateUser", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } return &u, BuildResponse(r), nil } @@ -1337,7 +1336,7 @@ func (c *Client4) UpdateUser(user *User) (*User, *Response, error) { func (c *Client4) PatchUser(userId string, patch *UserPatch) (*User, *Response, error) { buf, err := json.Marshal(patch) if err != nil { - return nil, nil, NewAppError("PatchUser", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) + return nil, nil, NewAppError("PatchUser", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } r, err := c.DoAPIPutBytes(c.userRoute(userId)+"/patch", buf) if err != nil { @@ -1345,8 +1344,8 @@ func (c *Client4) PatchUser(userId string, patch *UserPatch) (*User, *Response, } defer closeBody(r) var u User - if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { - return nil, nil, NewAppError("PatchUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&u); err != nil { + return nil, nil, NewAppError("PatchUser", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } return &u, BuildResponse(r), nil } @@ -1355,7 +1354,7 @@ func (c *Client4) PatchUser(userId string, patch *UserPatch) (*User, *Response, func (c *Client4) UpdateUserAuth(userId string, userAuth *UserAuth) (*UserAuth, *Response, error) { buf, err := json.Marshal(userAuth) if err != nil { - return nil, nil, NewAppError("UpdateUserAuth", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) + return nil, nil, NewAppError("UpdateUserAuth", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } r, err := c.DoAPIPutBytes(c.userRoute(userId)+"/auth", buf) if err != nil { @@ -1363,8 +1362,8 @@ func (c *Client4) UpdateUserAuth(userId string, userAuth *UserAuth) (*UserAuth, } defer closeBody(r) var ua UserAuth - if jsonErr := json.NewDecoder(r.Body).Decode(&ua); jsonErr != nil { - return nil, nil, NewAppError("UpdateUserAuth", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&ua); err != nil { + return nil, nil, NewAppError("UpdateUserAuth", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } return &ua, BuildResponse(r), nil } @@ -1394,8 +1393,8 @@ func (c *Client4) GenerateMfaSecret(userId string) (*MfaSecret, *Response, error } defer closeBody(r) var secret MfaSecret - if jsonErr := json.NewDecoder(r.Body).Decode(&secret); jsonErr != nil { - return nil, nil, NewAppError("GenerateMfaSecret", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&secret); err != nil { + return nil, nil, NewAppError("GenerateMfaSecret", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } return &secret, BuildResponse(r), nil } @@ -1496,7 +1495,7 @@ func (c *Client4) ConvertUserToBot(userId string) (*Bot, *Response, error) { var bot *Bot err = json.NewDecoder(r.Body).Decode(&bot) if err != nil { - return nil, BuildResponse(r), NewAppError("ConvertUserToBot", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) + return nil, BuildResponse(r), NewAppError("ConvertUserToBot", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } return bot, BuildResponse(r), nil } @@ -1509,7 +1508,7 @@ func (c *Client4) ConvertBotToUser(userId string, userPatch *UserPatch, setSyste } buf, err := json.Marshal(userPatch) if err != nil { - return nil, nil, NewAppError("ConvertBotToUser", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) + return nil, nil, NewAppError("ConvertBotToUser", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } r, err := c.DoAPIPostBytes(c.botRoute(userId)+"/convert_to_user"+query, buf) if err != nil { @@ -1517,8 +1516,8 @@ func (c *Client4) ConvertBotToUser(userId string, userPatch *UserPatch, setSyste } defer closeBody(r) var u User - if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { - return nil, nil, NewAppError("ConvertBotToUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&u); err != nil { + return nil, nil, NewAppError("ConvertBotToUser", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } return &u, BuildResponse(r), nil } @@ -1564,8 +1563,8 @@ func (c *Client4) GetSessions(userId, etag string) ([]*Session, *Response, error } defer closeBody(r) var list []*Session - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetSessions", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetSessions", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } return list, BuildResponse(r), nil } @@ -1634,8 +1633,8 @@ func (c *Client4) GetTeamsUnreadForUser(userId, teamIdToExclude string, includeC defer closeBody(r) var list []*TeamUnread - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetTeamsUnreadForUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetTeamsUnreadForUser", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } return list, BuildResponse(r), nil } @@ -1652,7 +1651,7 @@ func (c *Client4) GetUserAudits(userId string, page int, perPage int, etag strin var audits Audits err = json.NewDecoder(r.Body).Decode(&audits) if err != nil { - return nil, BuildResponse(r), NewAppError("GetUserAudits", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) + return nil, BuildResponse(r), NewAppError("GetUserAudits", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } return audits, BuildResponse(r), nil } @@ -1676,8 +1675,8 @@ func (c *Client4) VerifyUserEmailWithoutToken(userId string) (*User, *Response, } defer closeBody(r) var u User - if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { - return nil, nil, NewAppError("VerifyUserEmailWithoutToken", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&u); err != nil { + return nil, nil, NewAppError("VerifyUserEmailWithoutToken", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } return &u, BuildResponse(r), nil } @@ -1711,15 +1710,15 @@ func (c *Client4) SetProfileImage(userId string, data []byte) (*Response, error) part, err := writer.CreateFormFile("image", "profile.png") if err != nil { - return nil, NewAppError("SetProfileImage", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest) + return nil, NewAppError("SetProfileImage", "model.client.set_profile_user.no_file.app_error", nil, "", http.StatusBadRequest).Wrap(err) } if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil { - return nil, NewAppError("SetProfileImage", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest) + return nil, NewAppError("SetProfileImage", "model.client.set_profile_user.no_file.app_error", nil, "", http.StatusBadRequest).Wrap(err) } if err = writer.Close(); err != nil { - return nil, NewAppError("SetProfileImage", "model.client.set_profile_user.writer.app_error", nil, err.Error(), http.StatusBadRequest) + return nil, NewAppError("SetProfileImage", "model.client.set_profile_user.writer.app_error", nil, "", http.StatusBadRequest).Wrap(err) } rq, err := http.NewRequest("POST", c.APIURL+c.userRoute(userId)+"/image", bytes.NewReader(body.Bytes())) @@ -1757,8 +1756,8 @@ func (c *Client4) CreateUserAccessToken(userId, description string) (*UserAccess } defer closeBody(r) var uat UserAccessToken - if jsonErr := json.NewDecoder(r.Body).Decode(&uat); jsonErr != nil { - return nil, nil, NewAppError("CreateUserAccessToken", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&uat); err != nil { + return nil, nil, NewAppError("CreateUserAccessToken", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } return &uat, BuildResponse(r), nil } @@ -1774,8 +1773,8 @@ func (c *Client4) GetUserAccessTokens(page int, perPage int) ([]*UserAccessToken } defer closeBody(r) var list []*UserAccessToken - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetUserAccessTokens", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetUserAccessTokens", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -1791,8 +1790,8 @@ func (c *Client4) GetUserAccessToken(tokenId string) (*UserAccessToken, *Respons } defer closeBody(r) var uat UserAccessToken - if jsonErr := json.NewDecoder(r.Body).Decode(&uat); jsonErr != nil { - return nil, nil, NewAppError("GetUserAccessToken", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&uat); err != nil { + return nil, nil, NewAppError("GetUserAccessToken", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &uat, BuildResponse(r), nil } @@ -1809,8 +1808,8 @@ func (c *Client4) GetUserAccessTokensForUser(userId string, page, perPage int) ( } defer closeBody(r) var list []*UserAccessToken - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetUserAccessTokensForUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetUserAccessTokensForUser", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -1840,8 +1839,8 @@ func (c *Client4) SearchUserAccessTokens(search *UserAccessTokenSearch) ([]*User } defer closeBody(r) var list []*UserAccessToken - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("SearchUserAccessTokens", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("SearchUserAccessTokens", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -2066,8 +2065,8 @@ func (c *Client4) CreateTeam(team *Team) (*Team, *Response, error) { } defer closeBody(r) var t Team - if jsonErr := json.NewDecoder(r.Body).Decode(&t); jsonErr != nil { - return nil, nil, NewAppError("CreateTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&t); err != nil { + return nil, nil, NewAppError("CreateTeam", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &t, BuildResponse(r), nil } @@ -2080,8 +2079,8 @@ func (c *Client4) GetTeam(teamId, etag string) (*Team, *Response, error) { } defer closeBody(r) var t Team - if jsonErr := json.NewDecoder(r.Body).Decode(&t); jsonErr != nil { - return nil, nil, NewAppError("GetTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&t); err != nil { + return nil, nil, NewAppError("GetTeam", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &t, BuildResponse(r), nil } @@ -2095,8 +2094,8 @@ func (c *Client4) GetAllTeams(etag string, page int, perPage int) ([]*Team, *Res } defer closeBody(r) var list []*Team - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetAllTeams", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetAllTeams", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -2110,8 +2109,8 @@ func (c *Client4) GetAllTeamsWithTotalCount(etag string, page int, perPage int) } defer closeBody(r) var listWithCount TeamsWithCount - if jsonErr := json.NewDecoder(r.Body).Decode(&listWithCount); jsonErr != nil { - return nil, 0, nil, NewAppError("GetAllTeamsWithTotalCount", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&listWithCount); err != nil { + return nil, 0, nil, NewAppError("GetAllTeamsWithTotalCount", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return listWithCount.Teams, listWithCount.TotalCount, BuildResponse(r), nil } @@ -2126,8 +2125,8 @@ func (c *Client4) GetAllTeamsExcludePolicyConstrained(etag string, page int, per } defer closeBody(r) var list []*Team - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetAllTeamsExcludePolicyConstrained", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetAllTeamsExcludePolicyConstrained", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -2140,8 +2139,8 @@ func (c *Client4) GetTeamByName(name, etag string) (*Team, *Response, error) { } defer closeBody(r) var t Team - if jsonErr := json.NewDecoder(r.Body).Decode(&t); jsonErr != nil { - return nil, nil, NewAppError("GetTeamByName", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&t); err != nil { + return nil, nil, NewAppError("GetTeamByName", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &t, BuildResponse(r), nil } @@ -2158,8 +2157,8 @@ func (c *Client4) SearchTeams(search *TeamSearch) ([]*Team, *Response, error) { } defer closeBody(r) var list []*Team - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("SearchTeams", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("SearchTeams", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -2182,8 +2181,8 @@ func (c *Client4) SearchTeamsPaged(search *TeamSearch) ([]*Team, int64, *Respons } defer closeBody(r) var listWithCount TeamsWithCount - if jsonErr := json.NewDecoder(r.Body).Decode(&listWithCount); jsonErr != nil { - return nil, 0, nil, NewAppError("GetAllTeamsWithTotalCount", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&listWithCount); err != nil { + return nil, 0, nil, NewAppError("GetAllTeamsWithTotalCount", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return listWithCount.Teams, listWithCount.TotalCount, BuildResponse(r), nil } @@ -2207,8 +2206,8 @@ func (c *Client4) GetTeamsForUser(userId, etag string) ([]*Team, *Response, erro } defer closeBody(r) var list []*Team - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetTeamsForUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetTeamsForUser", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -2224,8 +2223,8 @@ func (c *Client4) GetTeamMember(teamId, userId, etag string) (*TeamMember, *Resp if r.StatusCode == http.StatusNotModified { return &tm, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&tm); jsonErr != nil { - return nil, nil, NewAppError("GetTeamMember", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&tm); err != nil { + return nil, nil, NewAppError("GetTeamMember", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &tm, BuildResponse(r), nil } @@ -2267,8 +2266,8 @@ func (c *Client4) UpdateTeam(team *Team) (*Team, *Response, error) { } defer closeBody(r) var t Team - if jsonErr := json.NewDecoder(r.Body).Decode(&t); jsonErr != nil { - return nil, nil, NewAppError("UpdateTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&t); err != nil { + return nil, nil, NewAppError("UpdateTeam", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &t, BuildResponse(r), nil } @@ -2285,8 +2284,8 @@ func (c *Client4) PatchTeam(teamId string, patch *TeamPatch) (*Team, *Response, } defer closeBody(r) var t Team - if jsonErr := json.NewDecoder(r.Body).Decode(&t); jsonErr != nil { - return nil, nil, NewAppError("PatchTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&t); err != nil { + return nil, nil, NewAppError("PatchTeam", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &t, BuildResponse(r), nil } @@ -2299,8 +2298,8 @@ func (c *Client4) RestoreTeam(teamId string) (*Team, *Response, error) { } defer closeBody(r) var t Team - if jsonErr := json.NewDecoder(r.Body).Decode(&t); jsonErr != nil { - return nil, nil, NewAppError("RestoreTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&t); err != nil { + return nil, nil, NewAppError("RestoreTeam", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &t, BuildResponse(r), nil } @@ -2313,8 +2312,8 @@ func (c *Client4) RegenerateTeamInviteId(teamId string) (*Team, *Response, error } defer closeBody(r) var t Team - if jsonErr := json.NewDecoder(r.Body).Decode(&t); jsonErr != nil { - return nil, nil, NewAppError("RegenerateTeamInviteId", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&t); err != nil { + return nil, nil, NewAppError("RegenerateTeamInviteId", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &t, BuildResponse(r), nil } @@ -2350,8 +2349,8 @@ func (c *Client4) UpdateTeamPrivacy(teamId string, privacy string) (*Team, *Resp } defer closeBody(r) var t Team - if jsonErr := json.NewDecoder(r.Body).Decode(&t); jsonErr != nil { - return nil, nil, NewAppError("UpdateTeamPrivacy", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&t); err != nil { + return nil, nil, NewAppError("UpdateTeamPrivacy", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &t, BuildResponse(r), nil } @@ -2368,8 +2367,8 @@ func (c *Client4) GetTeamMembers(teamId string, page int, perPage int, etag stri if r.StatusCode == http.StatusNotModified { return tms, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&tms); jsonErr != nil { - return nil, nil, NewAppError("GetTeamMembers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&tms); err != nil { + return nil, nil, NewAppError("GetTeamMembers", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return tms, BuildResponse(r), nil } @@ -2387,8 +2386,8 @@ func (c *Client4) GetTeamMembersSortAndWithoutDeletedUsers(teamId string, page i if r.StatusCode == http.StatusNotModified { return tms, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&tms); jsonErr != nil { - return nil, nil, NewAppError("GetTeamMembersSortAndWithoutDeletedUsers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&tms); err != nil { + return nil, nil, NewAppError("GetTeamMembersSortAndWithoutDeletedUsers", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return tms, BuildResponse(r), nil } @@ -2404,8 +2403,8 @@ func (c *Client4) GetTeamMembersForUser(userId string, etag string) ([]*TeamMemb if r.StatusCode == http.StatusNotModified { return tms, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&tms); jsonErr != nil { - return nil, nil, NewAppError("GetTeamMembersForUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&tms); err != nil { + return nil, nil, NewAppError("GetTeamMembersForUser", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return tms, BuildResponse(r), nil } @@ -2419,8 +2418,8 @@ func (c *Client4) GetTeamMembersByIds(teamId string, userIds []string) ([]*TeamM } defer closeBody(r) var tms []*TeamMember - if jsonErr := json.NewDecoder(r.Body).Decode(&tms); jsonErr != nil { - return nil, nil, NewAppError("GetTeamMembersByIds", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&tms); err != nil { + return nil, nil, NewAppError("GetTeamMembersByIds", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return tms, BuildResponse(r), nil } @@ -2438,8 +2437,8 @@ func (c *Client4) AddTeamMember(teamId, userId string) (*TeamMember, *Response, } defer closeBody(r) var tm TeamMember - if jsonErr := json.NewDecoder(r.Body).Decode(&tm); jsonErr != nil { - return nil, nil, NewAppError("AddTeamMember", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&tm); err != nil { + return nil, nil, NewAppError("AddTeamMember", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &tm, BuildResponse(r), nil } @@ -2463,8 +2462,8 @@ func (c *Client4) AddTeamMemberFromInvite(token, inviteId string) (*TeamMember, } defer closeBody(r) var tm TeamMember - if jsonErr := json.NewDecoder(r.Body).Decode(&tm); jsonErr != nil { - return nil, nil, NewAppError("AddTeamMemberFromInvite", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&tm); err != nil { + return nil, nil, NewAppError("AddTeamMemberFromInvite", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &tm, BuildResponse(r), nil } @@ -2476,9 +2475,9 @@ func (c *Client4) AddTeamMembers(teamId string, userIds []string) ([]*TeamMember member := &TeamMember{TeamId: teamId, UserId: userId} members = append(members, member) } - js, jsonErr := json.Marshal(members) - if jsonErr != nil { - return nil, nil, NewAppError("AddTeamMembers", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(members) + if err != nil { + return nil, nil, NewAppError("AddTeamMembers", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPost(c.teamMembersRoute(teamId)+"/batch", string(js)) if err != nil { @@ -2486,8 +2485,8 @@ func (c *Client4) AddTeamMembers(teamId string, userIds []string) ([]*TeamMember } defer closeBody(r) var tms []*TeamMember - if jsonErr := json.NewDecoder(r.Body).Decode(&tms); jsonErr != nil { - return nil, nil, NewAppError("AddTeamMembers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&tms); err != nil { + return nil, nil, NewAppError("AddTeamMembers", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return tms, BuildResponse(r), nil } @@ -2499,9 +2498,9 @@ func (c *Client4) AddTeamMembersGracefully(teamId string, userIds []string) ([]* member := &TeamMember{TeamId: teamId, UserId: userId} members = append(members, member) } - js, jsonErr := json.Marshal(members) - if jsonErr != nil { - return nil, nil, NewAppError("AddTeamMembersGracefully", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(members) + if err != nil { + return nil, nil, NewAppError("AddTeamMembersGracefully", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPost(c.teamMembersRoute(teamId)+"/batch?graceful="+c.boolString(true), string(js)) @@ -2510,8 +2509,8 @@ func (c *Client4) AddTeamMembersGracefully(teamId string, userIds []string) ([]* } defer closeBody(r) var tms []*TeamMemberWithError - if jsonErr := json.NewDecoder(r.Body).Decode(&tms); jsonErr != nil { - return nil, nil, NewAppError("AddTeamMembersGracefully", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&tms); err != nil { + return nil, nil, NewAppError("AddTeamMembersGracefully", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return tms, BuildResponse(r), nil } @@ -2535,8 +2534,8 @@ func (c *Client4) GetTeamStats(teamId, etag string) (*TeamStats, *Response, erro } defer closeBody(r) var ts TeamStats - if jsonErr := json.NewDecoder(r.Body).Decode(&ts); jsonErr != nil { - return nil, nil, NewAppError("GetTeamStats", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&ts); err != nil { + return nil, nil, NewAppError("GetTeamStats", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &ts, BuildResponse(r), nil } @@ -2550,8 +2549,8 @@ func (c *Client4) GetTotalUsersStats(etag string) (*UsersStats, *Response, error } defer closeBody(r) var stats UsersStats - if jsonErr := json.NewDecoder(r.Body).Decode(&stats); jsonErr != nil { - return nil, nil, NewAppError("GetTotalUsersStats", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&stats); err != nil { + return nil, nil, NewAppError("GetTotalUsersStats", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &stats, BuildResponse(r), nil } @@ -2566,8 +2565,8 @@ func (c *Client4) GetTeamUnread(teamId, userId string) (*TeamUnread, *Response, } defer closeBody(r) var tu TeamUnread - if jsonErr := json.NewDecoder(r.Body).Decode(&tu); jsonErr != nil { - return nil, nil, NewAppError("GetTeamUnread", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&tu); err != nil { + return nil, nil, NewAppError("GetTeamUnread", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &tu, BuildResponse(r), nil } @@ -2649,8 +2648,8 @@ func (c *Client4) InviteUsersToTeamGracefully(teamId string, userEmails []string } defer closeBody(r) var list []*EmailInviteWithError - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("InviteUsersToTeamGracefully", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("InviteUsersToTeamGracefully", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -2672,8 +2671,8 @@ func (c *Client4) InviteUsersToTeamAndChannelsGracefully(teamId string, userEmai } defer closeBody(r) var list []*EmailInviteWithError - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("InviteUsersToTeamGracefully", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("InviteUsersToTeamGracefully", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -2695,8 +2694,8 @@ func (c *Client4) InviteGuestsToTeamGracefully(teamId string, userEmails []strin } defer closeBody(r) var list []*EmailInviteWithError - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("InviteGuestsToTeamGracefully", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("InviteGuestsToTeamGracefully", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -2719,8 +2718,8 @@ func (c *Client4) GetTeamInviteInfo(inviteId string) (*Team, *Response, error) { } defer closeBody(r) var t Team - if jsonErr := json.NewDecoder(r.Body).Decode(&t); jsonErr != nil { - return nil, nil, NewAppError("GetTeamInviteInfo", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&t); err != nil { + return nil, nil, NewAppError("GetTeamInviteInfo", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &t, BuildResponse(r), nil } @@ -2774,7 +2773,7 @@ func (c *Client4) GetTeamIcon(teamId, etag string) ([]byte, *Response, error) { } defer closeBody(r) - data, err := ioutil.ReadAll(r.Body) + data, err := io.ReadAll(r.Body) if err != nil { return nil, BuildResponse(r), NewAppError("GetTeamIcon", "model.client.get_team_icon.app_error", nil, err.Error(), r.StatusCode) } @@ -2845,9 +2844,9 @@ func (c *Client4) GetAllChannelsWithCount(page int, perPage int, etag string) (C // CreateChannel creates a channel based on the provided channel struct. func (c *Client4) CreateChannel(channel *Channel) (*Channel, *Response, error) { - channelJSON, jsonErr := json.Marshal(channel) - if jsonErr != nil { - return nil, nil, NewAppError("CreateChannel", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + channelJSON, err := json.Marshal(channel) + if err != nil { + return nil, nil, NewAppError("CreateChannel", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPost(c.channelsRoute(), string(channelJSON)) if err != nil { @@ -2865,9 +2864,9 @@ func (c *Client4) CreateChannel(channel *Channel) (*Channel, *Response, error) { // UpdateChannel updates a channel based on the provided channel struct. func (c *Client4) UpdateChannel(channel *Channel) (*Channel, *Response, error) { - channelJSON, jsonErr := json.Marshal(channel) - if jsonErr != nil { - return nil, nil, NewAppError("UpdateChannel", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + channelJSON, err := json.Marshal(channel) + if err != nil { + return nil, nil, NewAppError("UpdateChannel", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPut(c.channelRoute(channel.Id), string(channelJSON)) if err != nil { @@ -2994,8 +2993,8 @@ func (c *Client4) GetChannelStats(channelId string, etag string) (*ChannelStats, } defer closeBody(r) var stats ChannelStats - if jsonErr := json.NewDecoder(r.Body).Decode(&stats); jsonErr != nil { - return nil, nil, NewAppError("GetChannelStats", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&stats); err != nil { + return nil, nil, NewAppError("GetChannelStats", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &stats, BuildResponse(r), nil } @@ -3023,8 +3022,8 @@ func (c *Client4) GetPinnedPosts(channelId string, etag string) (*PostList, *Res return &list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetPinnedPosts", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetPinnedPosts", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &list, BuildResponse(r), nil } @@ -3150,9 +3149,9 @@ func (c *Client4) GetChannelsForUserWithLastDeleteAt(userID string, lastDeleteAt // SearchChannels returns the channels on a team matching the provided search term. func (c *Client4) SearchChannels(teamId string, search *ChannelSearch) ([]*Channel, *Response, error) { - searchJSON, jsonErr := json.Marshal(search) - if jsonErr != nil { - return nil, nil, NewAppError("SearchChannels", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + searchJSON, err := json.Marshal(search) + if err != nil { + return nil, nil, NewAppError("SearchChannels", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPost(c.channelsForTeamRoute(teamId)+"/search", string(searchJSON)) if err != nil { @@ -3170,9 +3169,9 @@ func (c *Client4) SearchChannels(teamId string, search *ChannelSearch) ([]*Chann // SearchArchivedChannels returns the archived channels on a team matching the provided search term. func (c *Client4) SearchArchivedChannels(teamId string, search *ChannelSearch) ([]*Channel, *Response, error) { - searchJSON, jsonErr := json.Marshal(search) - if jsonErr != nil { - return nil, nil, NewAppError("SearchArchivedChannels", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + searchJSON, err := json.Marshal(search) + if err != nil { + return nil, nil, NewAppError("SearchArchivedChannels", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPost(c.channelsForTeamRoute(teamId)+"/search_archived", string(searchJSON)) if err != nil { @@ -3190,9 +3189,9 @@ func (c *Client4) SearchArchivedChannels(teamId string, search *ChannelSearch) ( // SearchAllChannels search in all the channels. Must be a system administrator. func (c *Client4) SearchAllChannels(search *ChannelSearch) (ChannelListWithTeamData, *Response, error) { - searchJSON, jsonErr := json.Marshal(search) - if jsonErr != nil { - return nil, nil, NewAppError("SearchAllChannels", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + searchJSON, err := json.Marshal(search) + if err != nil { + return nil, nil, NewAppError("SearchAllChannels", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPost(c.channelsRoute()+"/search", string(searchJSON)) if err != nil { @@ -3213,9 +3212,9 @@ func (c *Client4) SearchAllChannelsForUser(term string) (ChannelListWithTeamData search := &ChannelSearch{ Term: term, } - searchJSON, jsonErr := json.Marshal(search) - if jsonErr != nil { - return nil, nil, NewAppError("SearchAllChannelsForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + searchJSON, err := json.Marshal(search) + if err != nil { + return nil, nil, NewAppError("SearchAllChannelsForUser", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPost(c.channelsRoute()+"/search?system_console=false", string(searchJSON)) if err != nil { @@ -3233,9 +3232,9 @@ func (c *Client4) SearchAllChannelsForUser(term string) (ChannelListWithTeamData // SearchAllChannelsPaged searches all the channels and returns the results paged with the total count. func (c *Client4) SearchAllChannelsPaged(search *ChannelSearch) (*ChannelsWithCount, *Response, error) { - searchJSON, jsonErr := json.Marshal(search) - if jsonErr != nil { - return nil, nil, NewAppError("SearchAllChannelsPaged", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + searchJSON, err := json.Marshal(search) + if err != nil { + return nil, nil, NewAppError("SearchAllChannelsPaged", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPost(c.channelsRoute()+"/search", string(searchJSON)) if err != nil { @@ -3253,9 +3252,9 @@ func (c *Client4) SearchAllChannelsPaged(search *ChannelSearch) (*ChannelsWithCo // SearchGroupChannels returns the group channels of the user whose members' usernames match the search term. func (c *Client4) SearchGroupChannels(search *ChannelSearch) ([]*Channel, *Response, error) { - searchJSON, jsonErr := json.Marshal(search) - if jsonErr != nil { - return nil, nil, NewAppError("SearchGroupChannels", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + searchJSON, err := json.Marshal(search) + if err != nil { + return nil, nil, NewAppError("SearchGroupChannels", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPost(c.channelsRoute()+"/group/search", string(searchJSON)) if err != nil { @@ -3617,8 +3616,8 @@ func (c *Client4) GetTopChannelsForTeamSince(teamId string, timeRange string, pa } defer closeBody(r) var topChannels *TopChannelList - if jsonErr := json.NewDecoder(r.Body).Decode(&topChannels); jsonErr != nil { - return nil, nil, NewAppError("GetTopChannelsForTeamSince", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&topChannels); err != nil { + return nil, nil, NewAppError("GetTopChannelsForTeamSince", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return topChannels, BuildResponse(r), nil } @@ -3637,8 +3636,8 @@ func (c *Client4) GetTopChannelsForUserSince(teamId string, timeRange string, pa } defer closeBody(r) var topChannels *TopChannelList - if jsonErr := json.NewDecoder(r.Body).Decode(&topChannels); jsonErr != nil { - return nil, nil, NewAppError("GetTopChannelsForUserSince", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&topChannels); err != nil { + return nil, nil, NewAppError("GetTopChannelsForUserSince", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return topChannels, BuildResponse(r), nil } @@ -3647,9 +3646,9 @@ func (c *Client4) GetTopChannelsForUserSince(teamId string, timeRange string, pa // CreatePost creates a post based on the provided post struct. func (c *Client4) CreatePost(post *Post) (*Post, *Response, error) { - postJSON, jsonErr := json.Marshal(post) - if jsonErr != nil { - return nil, nil, NewAppError("CreatePost", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + postJSON, err := json.Marshal(post) + if err != nil { + return nil, nil, NewAppError("CreatePost", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPost(c.postsRoute(), string(postJSON)) if err != nil { @@ -3660,17 +3659,17 @@ func (c *Client4) CreatePost(post *Post) (*Post, *Response, error) { if r.StatusCode == http.StatusNotModified { return &p, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil { - return nil, nil, NewAppError("CreatePost", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&p); err != nil { + return nil, nil, NewAppError("CreatePost", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &p, BuildResponse(r), nil } // CreatePostEphemeral creates a ephemeral post based on the provided post struct which is send to the given user id. func (c *Client4) CreatePostEphemeral(post *PostEphemeral) (*Post, *Response, error) { - postJSON, jsonErr := json.Marshal(post) - if jsonErr != nil { - return nil, nil, NewAppError("CreatePostEphemeral", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + postJSON, err := json.Marshal(post) + if err != nil { + return nil, nil, NewAppError("CreatePostEphemeral", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPost(c.postsEphemeralRoute(), string(postJSON)) if err != nil { @@ -3681,17 +3680,17 @@ func (c *Client4) CreatePostEphemeral(post *PostEphemeral) (*Post, *Response, er if r.StatusCode == http.StatusNotModified { return &p, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil { - return nil, nil, NewAppError("CreatePostEphemeral", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&p); err != nil { + return nil, nil, NewAppError("CreatePostEphemeral", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &p, BuildResponse(r), nil } // UpdatePost updates a post based on the provided post struct. func (c *Client4) UpdatePost(postId string, post *Post) (*Post, *Response, error) { - postJSON, jsonErr := json.Marshal(post) - if jsonErr != nil { - return nil, nil, NewAppError("UpdatePost", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + postJSON, err := json.Marshal(post) + if err != nil { + return nil, nil, NewAppError("UpdatePost", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPut(c.postRoute(postId), string(postJSON)) if err != nil { @@ -3702,8 +3701,8 @@ func (c *Client4) UpdatePost(postId string, post *Post) (*Post, *Response, error if r.StatusCode == http.StatusNotModified { return &p, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil { - return nil, nil, NewAppError("UpdatePost", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&p); err != nil { + return nil, nil, NewAppError("UpdatePost", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &p, BuildResponse(r), nil } @@ -3723,8 +3722,8 @@ func (c *Client4) PatchPost(postId string, patch *PostPatch) (*Post, *Response, if r.StatusCode == http.StatusNotModified { return &p, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil { - return nil, nil, NewAppError("PatchPost", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&p); err != nil { + return nil, nil, NewAppError("PatchPost", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &p, BuildResponse(r), nil } @@ -3792,8 +3791,8 @@ func (c *Client4) GetPost(postId string, etag string) (*Post, *Response, error) if r.StatusCode == http.StatusNotModified { return &post, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&post); jsonErr != nil { - return nil, nil, NewAppError("GetPost", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&post); err != nil { + return nil, nil, NewAppError("GetPost", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &post, BuildResponse(r), nil } @@ -3810,8 +3809,8 @@ func (c *Client4) GetPostIncludeDeleted(postId string, etag string) (*Post, *Res if r.StatusCode == http.StatusNotModified { return &post, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&post); jsonErr != nil { - return nil, nil, NewAppError("GetPostIncludeDeleted", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&post); err != nil { + return nil, nil, NewAppError("GetPostIncludeDeleted", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &post, BuildResponse(r), nil } @@ -3841,8 +3840,8 @@ func (c *Client4) GetPostThread(postId string, etag string, collapsedThreads boo if r.StatusCode == http.StatusNotModified { return &list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetPostThread", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetPostThread", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &list, BuildResponse(r), nil } @@ -3884,8 +3883,8 @@ func (c *Client4) GetPostThreadWithOpts(postID string, etag string, opts GetPost if r.StatusCode == http.StatusNotModified { return &list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetPostThread", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetPostThread", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &list, BuildResponse(r), nil } @@ -3905,17 +3904,17 @@ func (c *Client4) GetPostsForChannel(channelId string, page, perPage int, etag s if r.StatusCode == http.StatusNotModified { return &list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetPostsForChannel", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetPostsForChannel", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &list, BuildResponse(r), nil } // GetPostsByIds gets a list of posts by taking an array of post ids func (c *Client4) GetPostsByIds(postIds []string) ([]*Post, *Response, error) { - js, jsonErr := json.Marshal(postIds) - if jsonErr != nil { - return nil, nil, NewAppError("SearchFilesWithParams", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(postIds) + if err != nil { + return nil, nil, NewAppError("SearchFilesWithParams", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPost(c.postsRoute()+"/ids", string(js)) if err != nil { @@ -3926,8 +3925,8 @@ func (c *Client4) GetPostsByIds(postIds []string) ([]*Post, *Response, error) { if r.StatusCode == http.StatusNotModified { return list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetPostsByIds", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetPostsByIds", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -3944,8 +3943,8 @@ func (c *Client4) GetFlaggedPostsForUser(userId string, page int, perPage int) ( if r.StatusCode == http.StatusNotModified { return &list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetFlaggedPostsForUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetFlaggedPostsForUser", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &list, BuildResponse(r), nil } @@ -3966,8 +3965,8 @@ func (c *Client4) GetFlaggedPostsForUserInTeam(userId string, teamId string, pag if r.StatusCode == http.StatusNotModified { return &list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetFlaggedPostsForUserInTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetFlaggedPostsForUserInTeam", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &list, BuildResponse(r), nil } @@ -3988,8 +3987,8 @@ func (c *Client4) GetFlaggedPostsForUserInChannel(userId string, channelId strin if r.StatusCode == http.StatusNotModified { return &list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetFlaggedPostsForUserInChannel", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetFlaggedPostsForUserInChannel", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &list, BuildResponse(r), nil } @@ -4009,8 +4008,8 @@ func (c *Client4) GetPostsSince(channelId string, time int64, collapsedThreads b if r.StatusCode == http.StatusNotModified { return &list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetPostsSince", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetPostsSince", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &list, BuildResponse(r), nil } @@ -4030,8 +4029,8 @@ func (c *Client4) GetPostsAfter(channelId, postId string, page, perPage int, eta if r.StatusCode == http.StatusNotModified { return &list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetPostsAfter", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetPostsAfter", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &list, BuildResponse(r), nil } @@ -4051,8 +4050,8 @@ func (c *Client4) GetPostsBefore(channelId, postId string, page, perPage int, et if r.StatusCode == http.StatusNotModified { return &list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetPostsBefore", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetPostsBefore", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &list, BuildResponse(r), nil } @@ -4072,8 +4071,8 @@ func (c *Client4) GetPostsAroundLastUnread(userId, channelId string, limitBefore if r.StatusCode == http.StatusNotModified { return &list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetPostsAroundLastUnread", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetPostsAroundLastUnread", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &list, BuildResponse(r), nil } @@ -4089,9 +4088,9 @@ func (c *Client4) SearchFiles(teamId string, terms string, isOrSearch bool) (*Fi // SearchFilesWithParams returns any posts with matching terms string. func (c *Client4) SearchFilesWithParams(teamId string, params *SearchParameter) (*FileInfoList, *Response, error) { - js, jsonErr := json.Marshal(params) - if jsonErr != nil { - return nil, nil, NewAppError("SearchFilesWithParams", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(params) + if err != nil { + return nil, nil, NewAppError("SearchFilesWithParams", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPost(c.teamRoute(teamId)+"/files/search", string(js)) if err != nil { @@ -4100,8 +4099,8 @@ func (c *Client4) SearchFilesWithParams(teamId string, params *SearchParameter) defer closeBody(r) var list FileInfoList - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("SearchFilesWithParams", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("SearchFilesWithParams", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &list, BuildResponse(r), nil } @@ -4117,9 +4116,9 @@ func (c *Client4) SearchPosts(teamId string, terms string, isOrSearch bool) (*Po // SearchPostsWithParams returns any posts with matching terms string. func (c *Client4) SearchPostsWithParams(teamId string, params *SearchParameter) (*PostList, *Response, error) { - js, jsonErr := json.Marshal(params) - if jsonErr != nil { - return nil, nil, NewAppError("SearchFilesWithParams", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + js, err := json.Marshal(params) + if err != nil { + return nil, nil, NewAppError("SearchFilesWithParams", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } var route string if teamId == "" { @@ -4136,8 +4135,8 @@ func (c *Client4) SearchPostsWithParams(teamId string, params *SearchParameter) if r.StatusCode == http.StatusNotModified { return &list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("SearchFilesWithParams", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("SearchFilesWithParams", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &list, BuildResponse(r), nil } @@ -4157,8 +4156,8 @@ func (c *Client4) SearchPostsWithMatches(teamId string, terms string, isOrSearch } defer closeBody(r) var psr PostSearchResults - if jsonErr := json.NewDecoder(r.Body).Decode(&psr); jsonErr != nil { - return nil, nil, NewAppError("SearchPostsWithMatches", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&psr); err != nil { + return nil, nil, NewAppError("SearchPostsWithMatches", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &psr, BuildResponse(r), nil } @@ -4177,13 +4176,13 @@ func (c *Client4) DoPostAction(postId, actionId string) (*Response, error) { func (c *Client4) DoPostActionWithCookie(postId, actionId, selected, cookieStr string) (*Response, error) { var body []byte if selected != "" || cookieStr != "" { - var jsonErr error - body, jsonErr = json.Marshal(DoPostActionRequest{ + var err error + body, err = json.Marshal(DoPostActionRequest{ SelectedOption: selected, Cookie: cookieStr, }) - if jsonErr != nil { - return nil, NewAppError("DoPostActionWithCookie", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err != nil { + return nil, NewAppError("DoPostActionWithCookie", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } } r, err := c.DoAPIPost(c.postRoute(postId)+"/actions/"+actionId, string(body)) @@ -4203,8 +4202,8 @@ func (c *Client4) GetTopThreadsForTeamSince(teamId string, timeRange string, pag } defer closeBody(r) var topThreads *TopThreadList - if jsonErr := json.NewDecoder(r.Body).Decode(&topThreads); jsonErr != nil { - return nil, nil, NewAppError("GetTopThreadsForTeamSince", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&topThreads); err != nil { + return nil, nil, NewAppError("GetTopThreadsForTeamSince", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return topThreads, BuildResponse(r), nil } @@ -4223,8 +4222,8 @@ func (c *Client4) GetTopThreadsForUserSince(teamId string, timeRange string, pag } defer closeBody(r) var topThreads *TopThreadList - if jsonErr := json.NewDecoder(r.Body).Decode(&topThreads); jsonErr != nil { - return nil, nil, NewAppError("GetTopThreadsForUserSince", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&topThreads); err != nil { + return nil, nil, NewAppError("GetTopThreadsForUserSince", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return topThreads, BuildResponse(r), nil } @@ -4234,9 +4233,9 @@ func (c *Client4) GetTopThreadsForUserSince(teamId string, timeRange string, pag // provided data. Used with interactive message buttons, menus and // slash commands. func (c *Client4) OpenInteractiveDialog(request OpenDialogRequest) (*Response, error) { - b, jsonErr := json.Marshal(request) - if jsonErr != nil { - return nil, NewAppError("OpenInteractiveDialog", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + b, err := json.Marshal(request) + if err != nil { + return nil, NewAppError("OpenInteractiveDialog", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPost("/actions/dialogs/open", string(b)) if err != nil { @@ -4249,9 +4248,9 @@ func (c *Client4) OpenInteractiveDialog(request OpenDialogRequest) (*Response, e // SubmitInteractiveDialog will submit the provided dialog data to the integration // configured by the URL. Used with the interactive dialogs integration feature. func (c *Client4) SubmitInteractiveDialog(request SubmitDialogRequest) (*SubmitDialogResponse, *Response, error) { - b, jsonErr := json.Marshal(request) - if jsonErr != nil { - return nil, nil, NewAppError("SubmitInteractiveDialog", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + b, err := json.Marshal(request) + if err != nil { + return nil, nil, NewAppError("SubmitInteractiveDialog", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPost("/actions/dialogs/submit", string(b)) if err != nil { @@ -4311,7 +4310,7 @@ func (c *Client4) GetFile(fileId string) ([]byte, *Response, error) { } defer closeBody(r) - data, err := ioutil.ReadAll(r.Body) + data, err := io.ReadAll(r.Body) if err != nil { return nil, BuildResponse(r), NewAppError("GetFile", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode) } @@ -4326,7 +4325,7 @@ func (c *Client4) DownloadFile(fileId string, download bool) ([]byte, *Response, } defer closeBody(r) - data, err := ioutil.ReadAll(r.Body) + data, err := io.ReadAll(r.Body) if err != nil { return nil, BuildResponse(r), NewAppError("DownloadFile", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode) } @@ -4341,7 +4340,7 @@ func (c *Client4) GetFileThumbnail(fileId string) ([]byte, *Response, error) { } defer closeBody(r) - data, err := ioutil.ReadAll(r.Body) + data, err := io.ReadAll(r.Body) if err != nil { return nil, BuildResponse(r), NewAppError("GetFileThumbnail", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode) } @@ -4356,7 +4355,7 @@ func (c *Client4) DownloadFileThumbnail(fileId string, download bool) ([]byte, * } defer closeBody(r) - data, err := ioutil.ReadAll(r.Body) + data, err := io.ReadAll(r.Body) if err != nil { return nil, BuildResponse(r), NewAppError("DownloadFileThumbnail", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode) } @@ -4381,7 +4380,7 @@ func (c *Client4) GetFilePreview(fileId string) ([]byte, *Response, error) { } defer closeBody(r) - data, err := ioutil.ReadAll(r.Body) + data, err := io.ReadAll(r.Body) if err != nil { return nil, BuildResponse(r), NewAppError("GetFilePreview", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode) } @@ -4396,7 +4395,7 @@ func (c *Client4) DownloadFilePreview(fileId string, download bool) ([]byte, *Re } defer closeBody(r) - data, err := ioutil.ReadAll(r.Body) + data, err := io.ReadAll(r.Body) if err != nil { return nil, BuildResponse(r), NewAppError("DownloadFilePreview", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode) } @@ -4412,8 +4411,8 @@ func (c *Client4) GetFileInfo(fileId string) (*FileInfo, *Response, error) { defer closeBody(r) var fi FileInfo - if jsonErr := json.NewDecoder(r.Body).Decode(&fi); jsonErr != nil { - return nil, nil, NewAppError("GetFileInfo", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&fi); err != nil { + return nil, nil, NewAppError("GetFileInfo", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &fi, BuildResponse(r), nil } @@ -4430,8 +4429,8 @@ func (c *Client4) GetFileInfosForPost(postId string, etag string) ([]*FileInfo, if r.StatusCode == http.StatusNotModified { return list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetFileInfosForPost", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetFileInfosForPost", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -4448,8 +4447,8 @@ func (c *Client4) GetFileInfosForPostIncludeDeleted(postId string, etag string) if r.StatusCode == http.StatusNotModified { return list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetFileInfosForPostIncludeDeleted", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetFileInfosForPostIncludeDeleted", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -4464,7 +4463,7 @@ func (c *Client4) GenerateSupportPacket() ([]byte, *Response, error) { } defer closeBody(r) - data, err := ioutil.ReadAll(r.Body) + data, err := io.ReadAll(r.Body) if err != nil { return nil, BuildResponse(r), NewAppError("GetFile", "model.client.read_job_result_file.app_error", nil, err.Error(), r.StatusCode) } @@ -4562,7 +4561,10 @@ func (c *Client4) GetConfig() (*Config, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return ConfigFromJSON(r.Body), BuildResponse(r), nil + + var cfg *Config + d := json.NewDecoder(r.Body) + return cfg, BuildResponse(r), d.Decode(&cfg) } // ReloadConfig will reload the server configuration. @@ -4640,7 +4642,10 @@ func (c *Client4) UpdateConfig(config *Config) (*Config, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return ConfigFromJSON(r.Body), BuildResponse(r), nil + + var cfg *Config + d := json.NewDecoder(r.Body) + return cfg, BuildResponse(r), d.Decode(&cfg) } // MigrateConfig will migrate existing config to the new one. @@ -4746,8 +4751,8 @@ func (c *Client4) CreateIncomingWebhook(hook *IncomingWebhook) (*IncomingWebhook defer closeBody(r) var iw IncomingWebhook - if jsonErr := json.NewDecoder(r.Body).Decode(&iw); jsonErr != nil { - return nil, nil, NewAppError("CreateIncomingWebhook", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&iw); err != nil { + return nil, nil, NewAppError("CreateIncomingWebhook", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &iw, BuildResponse(r), nil } @@ -4765,8 +4770,8 @@ func (c *Client4) UpdateIncomingWebhook(hook *IncomingWebhook) (*IncomingWebhook defer closeBody(r) var iw IncomingWebhook - if jsonErr := json.NewDecoder(r.Body).Decode(&iw); jsonErr != nil { - return nil, nil, NewAppError("UpdateIncomingWebhook", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&iw); err != nil { + return nil, nil, NewAppError("UpdateIncomingWebhook", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &iw, BuildResponse(r), nil } @@ -4783,8 +4788,8 @@ func (c *Client4) GetIncomingWebhooks(page int, perPage int, etag string) ([]*In if r.StatusCode == http.StatusNotModified { return iwl, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&iwl); jsonErr != nil { - return nil, nil, NewAppError("GetIncomingWebhooks", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&iwl); err != nil { + return nil, nil, NewAppError("GetIncomingWebhooks", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return iwl, BuildResponse(r), nil } @@ -4801,8 +4806,8 @@ func (c *Client4) GetIncomingWebhooksForTeam(teamId string, page int, perPage in if r.StatusCode == http.StatusNotModified { return iwl, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&iwl); jsonErr != nil { - return nil, nil, NewAppError("GetIncomingWebhooksForTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&iwl); err != nil { + return nil, nil, NewAppError("GetIncomingWebhooksForTeam", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return iwl, BuildResponse(r), nil } @@ -4818,8 +4823,8 @@ func (c *Client4) GetIncomingWebhook(hookID string, etag string) (*IncomingWebho if r.StatusCode == http.StatusNotModified { return &iw, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&iw); jsonErr != nil { - return nil, nil, NewAppError("GetIncomingWebhook", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&iw); err != nil { + return nil, nil, NewAppError("GetIncomingWebhook", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &iw, BuildResponse(r), nil } @@ -4846,8 +4851,8 @@ func (c *Client4) CreateOutgoingWebhook(hook *OutgoingWebhook) (*OutgoingWebhook } defer closeBody(r) var ow OutgoingWebhook - if jsonErr := json.NewDecoder(r.Body).Decode(&ow); jsonErr != nil { - return nil, nil, NewAppError("CreateOutgoingWebhook", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&ow); err != nil { + return nil, nil, NewAppError("CreateOutgoingWebhook", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &ow, BuildResponse(r), nil } @@ -4864,8 +4869,8 @@ func (c *Client4) UpdateOutgoingWebhook(hook *OutgoingWebhook) (*OutgoingWebhook } defer closeBody(r) var ow OutgoingWebhook - if jsonErr := json.NewDecoder(r.Body).Decode(&ow); jsonErr != nil { - return nil, nil, NewAppError("UpdateOutgoingWebhook", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&ow); err != nil { + return nil, nil, NewAppError("UpdateOutgoingWebhook", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &ow, BuildResponse(r), nil } @@ -4882,8 +4887,8 @@ func (c *Client4) GetOutgoingWebhooks(page int, perPage int, etag string) ([]*Ou if r.StatusCode == http.StatusNotModified { return owl, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&owl); jsonErr != nil { - return nil, nil, NewAppError("GetOutgoingWebhooks", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&owl); err != nil { + return nil, nil, NewAppError("GetOutgoingWebhooks", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return owl, BuildResponse(r), nil } @@ -4896,8 +4901,8 @@ func (c *Client4) GetOutgoingWebhook(hookId string) (*OutgoingWebhook, *Response } defer closeBody(r) var ow OutgoingWebhook - if jsonErr := json.NewDecoder(r.Body).Decode(&ow); jsonErr != nil { - return nil, nil, NewAppError("GetOutgoingWebhook", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&ow); err != nil { + return nil, nil, NewAppError("GetOutgoingWebhook", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &ow, BuildResponse(r), nil } @@ -4914,8 +4919,8 @@ func (c *Client4) GetOutgoingWebhooksForChannel(channelId string, page int, perP if r.StatusCode == http.StatusNotModified { return owl, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&owl); jsonErr != nil { - return nil, nil, NewAppError("GetOutgoingWebhooksForChannel", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&owl); err != nil { + return nil, nil, NewAppError("GetOutgoingWebhooksForChannel", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return owl, BuildResponse(r), nil } @@ -4932,8 +4937,8 @@ func (c *Client4) GetOutgoingWebhooksForTeam(teamId string, page int, perPage in if r.StatusCode == http.StatusNotModified { return owl, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&owl); jsonErr != nil { - return nil, nil, NewAppError("GetOutgoingWebhooksForTeam", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&owl); err != nil { + return nil, nil, NewAppError("GetOutgoingWebhooksForTeam", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return owl, BuildResponse(r), nil } @@ -4946,8 +4951,8 @@ func (c *Client4) RegenOutgoingHookToken(hookId string) (*OutgoingWebhook, *Resp } defer closeBody(r) var ow OutgoingWebhook - if jsonErr := json.NewDecoder(r.Body).Decode(&ow); jsonErr != nil { - return nil, nil, NewAppError("RegenOutgoingHookToken", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&ow); err != nil { + return nil, nil, NewAppError("RegenOutgoingHookToken", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &ow, BuildResponse(r), nil } @@ -4973,8 +4978,8 @@ func (c *Client4) GetPreferences(userId string) (Preferences, *Response, error) defer closeBody(r) var prefs Preferences - if jsonErr := json.NewDecoder(r.Body).Decode(&prefs); jsonErr != nil { - return nil, nil, NewAppError("GetPreferences", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&prefs); err != nil { + return nil, nil, NewAppError("GetPreferences", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return prefs, BuildResponse(r), nil } @@ -5016,8 +5021,8 @@ func (c *Client4) GetPreferencesByCategory(userId string, category string) (Pref } defer closeBody(r) var prefs Preferences - if jsonErr := json.NewDecoder(r.Body).Decode(&prefs); jsonErr != nil { - return nil, nil, NewAppError("GetPreferencesByCategory", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&prefs); err != nil { + return nil, nil, NewAppError("GetPreferencesByCategory", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return prefs, BuildResponse(r), nil } @@ -5032,8 +5037,8 @@ func (c *Client4) GetPreferenceByCategoryAndName(userId string, category string, defer closeBody(r) var pref Preference - if jsonErr := json.NewDecoder(r.Body).Decode(&pref); jsonErr != nil { - return nil, nil, NewAppError("GetPreferenceByCategoryAndName", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&pref); err != nil { + return nil, nil, NewAppError("GetPreferenceByCategoryAndName", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &pref, BuildResponse(r), nil } @@ -5152,8 +5157,8 @@ func (c *Client4) GetSamlCertificateStatus() (*SamlCertificateStatus, *Response, defer closeBody(r) var status SamlCertificateStatus - if jsonErr := json.NewDecoder(r.Body).Decode(&status); jsonErr != nil { - return nil, nil, NewAppError("GetSamlCertificateStatus", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&status); err != nil { + return nil, nil, NewAppError("GetSamlCertificateStatus", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &status, BuildResponse(r), nil } @@ -5168,8 +5173,8 @@ func (c *Client4) GetSamlMetadataFromIdp(samlMetadataURL string) (*SamlMetadataR defer closeBody(r) var resp SamlMetadataResponse - if jsonErr := json.NewDecoder(r.Body).Decode(&resp); jsonErr != nil { - return nil, nil, NewAppError("GetSamlMetadataFromIdp", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&resp); err != nil { + return nil, nil, NewAppError("GetSamlMetadataFromIdp", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &resp, BuildResponse(r), nil } @@ -5181,9 +5186,9 @@ func (c *Client4) ResetSamlAuthDataToEmail(includeDeleted bool, dryRun bool, use "dry_run": dryRun, "user_ids": userIDs, } - b, jsonErr := json.Marshal(params) - if jsonErr != nil { - return 0, nil, NewAppError("ResetSamlAuthDataToEmail", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + b, err := json.Marshal(params) + if err != nil { + return 0, nil, NewAppError("ResetSamlAuthDataToEmail", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPostBytes(c.samlRoute()+"/reset_auth_data", b) if err != nil { @@ -5212,8 +5217,8 @@ func (c *Client4) CreateComplianceReport(report *Compliance) (*Compliance, *Resp } defer closeBody(r) var comp Compliance - if jsonErr := json.NewDecoder(r.Body).Decode(&comp); jsonErr != nil { - return nil, nil, NewAppError("CreateComplianceReport", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&comp); err != nil { + return nil, nil, NewAppError("CreateComplianceReport", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &comp, BuildResponse(r), nil } @@ -5227,8 +5232,8 @@ func (c *Client4) GetComplianceReports(page, perPage int) (Compliances, *Respons } defer closeBody(r) var comp Compliances - if jsonErr := json.NewDecoder(r.Body).Decode(&comp); jsonErr != nil { - return nil, nil, NewAppError("GetComplianceReports", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&comp); err != nil { + return nil, nil, NewAppError("GetComplianceReports", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return comp, BuildResponse(r), nil } @@ -5241,8 +5246,8 @@ func (c *Client4) GetComplianceReport(reportId string) (*Compliance, *Response, } defer closeBody(r) var comp Compliance - if jsonErr := json.NewDecoder(r.Body).Decode(&comp); jsonErr != nil { - return nil, nil, NewAppError("GetComplianceReport", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&comp); err != nil { + return nil, nil, NewAppError("GetComplianceReport", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &comp, BuildResponse(r), nil } @@ -5268,7 +5273,7 @@ func (c *Client4) DownloadComplianceReport(reportId string) ([]byte, *Response, return nil, BuildResponse(rp), AppErrorFromJSON(rp.Body) } - data, err := ioutil.ReadAll(rp.Body) + data, err := io.ReadAll(rp.Body) if err != nil { return nil, BuildResponse(rp), NewAppError("DownloadComplianceReport", "model.client.read_file.app_error", nil, err.Error(), rp.StatusCode) } @@ -5286,8 +5291,8 @@ func (c *Client4) GetClusterStatus() ([]*ClusterInfo, *Response, error) { } defer closeBody(r) var list []*ClusterInfo - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetClusterStatus", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetClusterStatus", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -5298,11 +5303,11 @@ func (c *Client4) GetClusterStatus() ([]*ClusterInfo, *Response, error) { // If includeRemovedMembers is true, then group members who left or were removed from a // synced team/channel will be re-joined; otherwise, they will be excluded. func (c *Client4) SyncLdap(includeRemovedMembers bool) (*Response, error) { - reqBody, jsonErr := json.Marshal(map[string]any{ + reqBody, err := json.Marshal(map[string]any{ "include_removed_members": includeRemovedMembers, }) - if jsonErr != nil { - return nil, NewAppError("SyncLdap", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err != nil { + return nil, NewAppError("SyncLdap", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPostBytes(c.ldapRoute()+"/sync", reqBody) if err != nil { @@ -5358,8 +5363,8 @@ func (c *Client4) LinkLdapGroup(dn string) (*Group, *Response, error) { defer closeBody(r) var g Group - if jsonErr := json.NewDecoder(r.Body).Decode(&g); jsonErr != nil { - return nil, nil, NewAppError("LinkLdapGroup", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&g); err != nil { + return nil, nil, NewAppError("LinkLdapGroup", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &g, BuildResponse(r), nil } @@ -5375,8 +5380,8 @@ func (c *Client4) UnlinkLdapGroup(dn string) (*Group, *Response, error) { defer closeBody(r) var g Group - if jsonErr := json.NewDecoder(r.Body).Decode(&g); jsonErr != nil { - return nil, nil, NewAppError("UnlinkLdapGroup", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&g); err != nil { + return nil, nil, NewAppError("UnlinkLdapGroup", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &g, BuildResponse(r), nil } @@ -5487,8 +5492,8 @@ func (c *Client4) GetGroups(opts GroupSearchOpts) ([]*Group, *Response, error) { defer closeBody(r) var list []*Group - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetGroups", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetGroups", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -5507,8 +5512,8 @@ func (c *Client4) GetGroupsByUserId(userId string) ([]*Group, *Response, error) } defer closeBody(r) var list []*Group - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetGroupsByUserId", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetGroupsByUserId", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -5614,7 +5619,7 @@ func (c *Client4) GetBrandImage() ([]byte, *Response, error) { return nil, BuildResponse(r), AppErrorFromJSON(r.Body) } - data, err := ioutil.ReadAll(r.Body) + data, err := io.ReadAll(r.Body) if err != nil { return nil, BuildResponse(r), NewAppError("GetBrandImage", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode) } @@ -5712,8 +5717,8 @@ func (c *Client4) CreateOAuthApp(app *OAuthApp) (*OAuthApp, *Response, error) { defer closeBody(r) var oapp OAuthApp - if jsonErr := json.NewDecoder(r.Body).Decode(&oapp); jsonErr != nil { - return nil, nil, NewAppError("CreateOAuthApp", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&oapp); err != nil { + return nil, nil, NewAppError("CreateOAuthApp", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &oapp, BuildResponse(r), nil } @@ -5730,8 +5735,8 @@ func (c *Client4) UpdateOAuthApp(app *OAuthApp) (*OAuthApp, *Response, error) { } defer closeBody(r) var oapp OAuthApp - if jsonErr := json.NewDecoder(r.Body).Decode(&oapp); jsonErr != nil { - return nil, nil, NewAppError("UpdateOAuthApp", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&oapp); err != nil { + return nil, nil, NewAppError("UpdateOAuthApp", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &oapp, BuildResponse(r), nil } @@ -5745,8 +5750,8 @@ func (c *Client4) GetOAuthApps(page, perPage int) ([]*OAuthApp, *Response, error } defer closeBody(r) var list []*OAuthApp - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetOAuthApps", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetOAuthApps", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -5759,8 +5764,8 @@ func (c *Client4) GetOAuthApp(appId string) (*OAuthApp, *Response, error) { } defer closeBody(r) var oapp OAuthApp - if jsonErr := json.NewDecoder(r.Body).Decode(&oapp); jsonErr != nil { - return nil, nil, NewAppError("GetOAuthApp", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&oapp); err != nil { + return nil, nil, NewAppError("GetOAuthApp", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &oapp, BuildResponse(r), nil } @@ -5773,8 +5778,8 @@ func (c *Client4) GetOAuthAppInfo(appId string) (*OAuthApp, *Response, error) { } defer closeBody(r) var oapp OAuthApp - if jsonErr := json.NewDecoder(r.Body).Decode(&oapp); jsonErr != nil { - return nil, nil, NewAppError("GetOAuthAppInfo", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&oapp); err != nil { + return nil, nil, NewAppError("GetOAuthAppInfo", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &oapp, BuildResponse(r), nil } @@ -5797,8 +5802,8 @@ func (c *Client4) RegenerateOAuthAppSecret(appId string) (*OAuthApp, *Response, } defer closeBody(r) var oapp OAuthApp - if jsonErr := json.NewDecoder(r.Body).Decode(&oapp); jsonErr != nil { - return nil, nil, NewAppError("RegenerateOAuthAppSecret", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&oapp); err != nil { + return nil, nil, NewAppError("RegenerateOAuthAppSecret", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &oapp, BuildResponse(r), nil } @@ -5812,8 +5817,8 @@ func (c *Client4) GetAuthorizedOAuthAppsForUser(userId string, page, perPage int } defer closeBody(r) var list []*OAuthApp - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetAuthorizedOAuthAppsForUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetAuthorizedOAuthAppsForUser", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -5920,8 +5925,8 @@ func (c *Client4) GetDataRetentionPolicy() (*GlobalRetentionPolicy, *Response, e } defer closeBody(r) var p GlobalRetentionPolicy - if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil { - return nil, nil, NewAppError("GetDataRetentionPolicy", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&p); err != nil { + return nil, nil, NewAppError("GetDataRetentionPolicy", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &p, BuildResponse(r), nil } @@ -5935,8 +5940,8 @@ func (c *Client4) GetDataRetentionPolicyByID(policyID string) (*RetentionPolicyW defer closeBody(r) var p RetentionPolicyWithTeamAndChannelCounts - if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil { - return nil, nil, NewAppError("GetDataRetentionPolicyByID", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&p); err != nil { + return nil, nil, NewAppError("GetDataRetentionPolicyByID", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &p, BuildResponse(r), nil } @@ -5968,8 +5973,8 @@ func (c *Client4) GetDataRetentionPolicies(page, perPage int) (*RetentionPolicyW defer closeBody(r) var p RetentionPolicyWithTeamAndChannelCountsList - if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil { - return nil, nil, NewAppError("GetDataRetentionPolicies", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&p); err != nil { + return nil, nil, NewAppError("GetDataRetentionPolicies", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &p, BuildResponse(r), nil } @@ -5977,9 +5982,9 @@ func (c *Client4) GetDataRetentionPolicies(page, perPage int) (*RetentionPolicyW // CreateDataRetentionPolicy will create a new granular data retention policy which will be applied to // the specified teams and channels. The Id field of `policy` must be empty. func (c *Client4) CreateDataRetentionPolicy(policy *RetentionPolicyWithTeamAndChannelIDs) (*RetentionPolicyWithTeamAndChannelCounts, *Response, error) { - policyJSON, jsonErr := json.Marshal(policy) - if jsonErr != nil { - return nil, nil, NewAppError("CreateDataRetentionPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + policyJSON, err := json.Marshal(policy) + if err != nil { + return nil, nil, NewAppError("CreateDataRetentionPolicy", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPostBytes(c.dataRetentionRoute()+"/policies", policyJSON) if err != nil { @@ -5987,8 +5992,8 @@ func (c *Client4) CreateDataRetentionPolicy(policy *RetentionPolicyWithTeamAndCh } defer closeBody(r) var p RetentionPolicyWithTeamAndChannelCounts - if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil { - return nil, nil, NewAppError("CreateDataRetentionPolicy", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&p); err != nil { + return nil, nil, NewAppError("CreateDataRetentionPolicy", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &p, BuildResponse(r), nil } @@ -6006,9 +6011,9 @@ func (c *Client4) DeleteDataRetentionPolicy(policyID string) (*Response, error) // PatchDataRetentionPolicy will patch the granular data retention policy with the specified ID. // The Id field of `patch` must be non-empty. func (c *Client4) PatchDataRetentionPolicy(patch *RetentionPolicyWithTeamAndChannelIDs) (*RetentionPolicyWithTeamAndChannelCounts, *Response, error) { - patchJSON, jsonErr := json.Marshal(patch) - if jsonErr != nil { - return nil, nil, NewAppError("PatchDataRetentionPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + patchJSON, err := json.Marshal(patch) + if err != nil { + return nil, nil, NewAppError("PatchDataRetentionPolicy", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPatchBytes(c.dataRetentionPolicyRoute(patch.ID), patchJSON) if err != nil { @@ -6016,8 +6021,8 @@ func (c *Client4) PatchDataRetentionPolicy(patch *RetentionPolicyWithTeamAndChan } defer closeBody(r) var p RetentionPolicyWithTeamAndChannelCounts - if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil { - return nil, nil, NewAppError("PatchDataRetentionPolicy", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&p); err != nil { + return nil, nil, NewAppError("PatchDataRetentionPolicy", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &p, BuildResponse(r), nil } @@ -6039,9 +6044,9 @@ func (c *Client4) GetTeamsForRetentionPolicy(policyID string, page, perPage int) // SearchTeamsForRetentionPolicy will search the teams to which the specified policy is currently applied. func (c *Client4) SearchTeamsForRetentionPolicy(policyID string, term string) ([]*Team, *Response, error) { - body, jsonErr := json.Marshal(map[string]any{"term": term}) - if jsonErr != nil { - return nil, nil, NewAppError("SearchTeamsForRetentionPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + body, err := json.Marshal(map[string]any{"term": term}) + if err != nil { + return nil, nil, NewAppError("SearchTeamsForRetentionPolicy", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPostBytes(c.dataRetentionPolicyRoute(policyID)+"/teams/search", body) if err != nil { @@ -6058,9 +6063,9 @@ func (c *Client4) SearchTeamsForRetentionPolicy(policyID string, term string) ([ // AddTeamsToRetentionPolicy will add the specified teams to the granular data retention policy // with the specified ID. func (c *Client4) AddTeamsToRetentionPolicy(policyID string, teamIDs []string) (*Response, error) { - body, jsonErr := json.Marshal(teamIDs) - if jsonErr != nil { - return nil, NewAppError("AddTeamsToRetentionPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + body, err := json.Marshal(teamIDs) + if err != nil { + return nil, NewAppError("AddTeamsToRetentionPolicy", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPostBytes(c.dataRetentionPolicyRoute(policyID)+"/teams", body) if err != nil { @@ -6073,9 +6078,9 @@ func (c *Client4) AddTeamsToRetentionPolicy(policyID string, teamIDs []string) ( // RemoveTeamsFromRetentionPolicy will remove the specified teams from the granular data retention policy // with the specified ID. func (c *Client4) RemoveTeamsFromRetentionPolicy(policyID string, teamIDs []string) (*Response, error) { - body, jsonErr := json.Marshal(teamIDs) - if jsonErr != nil { - return nil, NewAppError("RemoveTeamsFromRetentionPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + body, err := json.Marshal(teamIDs) + if err != nil { + return nil, NewAppError("RemoveTeamsFromRetentionPolicy", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIDeleteBytes(c.dataRetentionPolicyRoute(policyID)+"/teams", body) if err != nil { @@ -6102,9 +6107,9 @@ func (c *Client4) GetChannelsForRetentionPolicy(policyID string, page, perPage i // SearchChannelsForRetentionPolicy will search the channels to which the specified policy is currently applied. func (c *Client4) SearchChannelsForRetentionPolicy(policyID string, term string) (ChannelListWithTeamData, *Response, error) { - body, jsonErr := json.Marshal(map[string]any{"term": term}) - if jsonErr != nil { - return nil, nil, NewAppError("SearchChannelsForRetentionPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + body, err := json.Marshal(map[string]any{"term": term}) + if err != nil { + return nil, nil, NewAppError("SearchChannelsForRetentionPolicy", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPostBytes(c.dataRetentionPolicyRoute(policyID)+"/channels/search", body) if err != nil { @@ -6121,9 +6126,9 @@ func (c *Client4) SearchChannelsForRetentionPolicy(policyID string, term string) // AddChannelsToRetentionPolicy will add the specified channels to the granular data retention policy // with the specified ID. func (c *Client4) AddChannelsToRetentionPolicy(policyID string, channelIDs []string) (*Response, error) { - body, jsonErr := json.Marshal(channelIDs) - if jsonErr != nil { - return nil, NewAppError("AddChannelsToRetentionPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + body, err := json.Marshal(channelIDs) + if err != nil { + return nil, NewAppError("AddChannelsToRetentionPolicy", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPostBytes(c.dataRetentionPolicyRoute(policyID)+"/channels", body) if err != nil { @@ -6136,9 +6141,9 @@ func (c *Client4) AddChannelsToRetentionPolicy(policyID string, channelIDs []str // RemoveChannelsFromRetentionPolicy will remove the specified channels from the granular data retention policy // with the specified ID. func (c *Client4) RemoveChannelsFromRetentionPolicy(policyID string, channelIDs []string) (*Response, error) { - body, jsonErr := json.Marshal(channelIDs) - if jsonErr != nil { - return nil, NewAppError("RemoveChannelsFromRetentionPolicy", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + body, err := json.Marshal(channelIDs) + if err != nil { + return nil, NewAppError("RemoveChannelsFromRetentionPolicy", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIDeleteBytes(c.dataRetentionPolicyRoute(policyID)+"/channels", body) if err != nil { @@ -6191,8 +6196,8 @@ func (c *Client4) CreateCommand(cmd *Command) (*Command, *Response, error) { defer closeBody(r) var command Command - if jsonErr := json.NewDecoder(r.Body).Decode(&command); jsonErr != nil { - return nil, nil, NewAppError("CreateCommand", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&command); err != nil { + return nil, nil, NewAppError("CreateCommand", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &command, BuildResponse(r), nil } @@ -6209,8 +6214,8 @@ func (c *Client4) UpdateCommand(cmd *Command) (*Command, *Response, error) { } defer closeBody(r) var command Command - if jsonErr := json.NewDecoder(r.Body).Decode(&command); jsonErr != nil { - return nil, nil, NewAppError("UpdateCommand", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&command); err != nil { + return nil, nil, NewAppError("UpdateCommand", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &command, BuildResponse(r), nil } @@ -6250,8 +6255,8 @@ func (c *Client4) ListCommands(teamId string, customOnly bool) ([]*Command, *Res defer closeBody(r) var list []*Command - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("ListCommands", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("ListCommands", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -6265,8 +6270,8 @@ func (c *Client4) ListCommandAutocompleteSuggestions(userInput, teamId string) ( } defer closeBody(r) var list []AutocompleteSuggestion - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("ListCommandAutocompleteSuggestions", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("ListCommandAutocompleteSuggestions", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -6280,8 +6285,8 @@ func (c *Client4) GetCommandById(cmdId string) (*Command, *Response, error) { } defer closeBody(r) var command Command - if jsonErr := json.NewDecoder(r.Body).Decode(&command); jsonErr != nil { - return nil, nil, NewAppError("GetCommandById", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&command); err != nil { + return nil, nil, NewAppError("GetCommandById", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &command, BuildResponse(r), nil } @@ -6342,8 +6347,8 @@ func (c *Client4) ListAutocompleteCommands(teamId string) ([]*Command, *Response } defer closeBody(r) var list []*Command - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("ListAutocompleteCommands", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("ListAutocompleteCommands", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -6371,8 +6376,8 @@ func (c *Client4) GetUserStatus(userId, etag string) (*Status, *Response, error) if r.StatusCode == http.StatusNotModified { return &s, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&s); jsonErr != nil { - return nil, nil, NewAppError("GetUserStatus", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&s); err != nil { + return nil, nil, NewAppError("GetUserStatus", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &s, BuildResponse(r), nil } @@ -6385,8 +6390,8 @@ func (c *Client4) GetUsersStatusesByIds(userIds []string) ([]*Status, *Response, } defer closeBody(r) var list []*Status - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetUsersStatusesByIds", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetUsersStatusesByIds", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -6403,8 +6408,8 @@ func (c *Client4) UpdateUserStatus(userId string, userStatus *Status) (*Status, } defer closeBody(r) var s Status - if jsonErr := json.NewDecoder(r.Body).Decode(&s); jsonErr != nil { - return nil, nil, NewAppError("UpdateUserStatus", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&s); err != nil { + return nil, nil, NewAppError("UpdateUserStatus", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &s, BuildResponse(r), nil } @@ -6462,13 +6467,14 @@ func (c *Client4) CreateEmoji(emoji *Emoji, image []byte, filename string) (*Emo return nil, nil, err } - if _, err := io.Copy(part, bytes.NewBuffer(image)); err != nil { + _, err = io.Copy(part, bytes.NewBuffer(image)) + if err != nil { return nil, nil, err } - emojiJSON, jsonErr := json.Marshal(emoji) - if jsonErr != nil { - return nil, nil, NewAppError("CreateEmoji", "api.marshal_error", nil, jsonErr.Error(), 0) + emojiJSON, err := json.Marshal(emoji) + if err != nil { + return nil, nil, NewAppError("CreateEmoji", "api.marshal_error", nil, err.Error(), 0) } if err := writer.WriteField("emoji", string(emojiJSON)); err != nil { @@ -6492,8 +6498,8 @@ func (c *Client4) GetEmojiList(page, perPage int) ([]*Emoji, *Response, error) { defer closeBody(r) var list []*Emoji - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetEmojiList", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetEmojiList", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -6508,8 +6514,8 @@ func (c *Client4) GetSortedEmojiList(page, perPage int, sort string) ([]*Emoji, } defer closeBody(r) var list []*Emoji - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetSortedEmojiList", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetSortedEmojiList", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -6532,8 +6538,8 @@ func (c *Client4) GetEmoji(emojiId string) (*Emoji, *Response, error) { } defer closeBody(r) var e Emoji - if jsonErr := json.NewDecoder(r.Body).Decode(&e); jsonErr != nil { - return nil, nil, NewAppError("GetEmoji", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&e); err != nil { + return nil, nil, NewAppError("GetEmoji", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &e, BuildResponse(r), nil } @@ -6546,8 +6552,8 @@ func (c *Client4) GetEmojiByName(name string) (*Emoji, *Response, error) { } defer closeBody(r) var e Emoji - if jsonErr := json.NewDecoder(r.Body).Decode(&e); jsonErr != nil { - return nil, nil, NewAppError("GetEmojiByName", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&e); err != nil { + return nil, nil, NewAppError("GetEmojiByName", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &e, BuildResponse(r), nil } @@ -6560,7 +6566,7 @@ func (c *Client4) GetEmojiImage(emojiId string) ([]byte, *Response, error) { } defer closeBody(r) - data, err := ioutil.ReadAll(r.Body) + data, err := io.ReadAll(r.Body) if err != nil { return nil, BuildResponse(r), NewAppError("GetEmojiImage", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode) } @@ -6580,8 +6586,8 @@ func (c *Client4) SearchEmoji(search *EmojiSearch) ([]*Emoji, *Response, error) } defer closeBody(r) var list []*Emoji - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("SearchEmoji", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("SearchEmoji", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -6595,8 +6601,8 @@ func (c *Client4) AutocompleteEmoji(name string, etag string) ([]*Emoji, *Respon } defer closeBody(r) var list []*Emoji - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("AutocompleteEmoji", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("AutocompleteEmoji", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -6615,8 +6621,8 @@ func (c *Client4) SaveReaction(reaction *Reaction) (*Reaction, *Response, error) } defer closeBody(r) var re Reaction - if jsonErr := json.NewDecoder(r.Body).Decode(&re); jsonErr != nil { - return nil, nil, NewAppError("SaveReaction", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&re); err != nil { + return nil, nil, NewAppError("SaveReaction", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &re, BuildResponse(r), nil } @@ -6629,8 +6635,8 @@ func (c *Client4) GetReactions(postId string) ([]*Reaction, *Response, error) { } defer closeBody(r) var list []*Reaction - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetReactions", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetReactions", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -6653,8 +6659,8 @@ func (c *Client4) GetBulkReactions(postIds []string) (map[string][]*Reaction, *R } defer closeBody(r) reactions := map[string][]*Reaction{} - if jsonErr := json.NewDecoder(r.Body).Decode(&reactions); jsonErr != nil { - return nil, nil, NewAppError("GetBulkReactions", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&reactions); err != nil { + return nil, nil, NewAppError("GetBulkReactions", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return reactions, BuildResponse(r), nil } @@ -6667,8 +6673,8 @@ func (c *Client4) GetTopReactionsForTeamSince(teamId string, timeRange string, p } defer closeBody(r) var topReactions *TopReactionList - if jsonErr := json.NewDecoder(r.Body).Decode(&topReactions); jsonErr != nil { - return nil, nil, NewAppError("GetTopReactionsForTeamSince", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&topReactions); err != nil { + return nil, nil, NewAppError("GetTopReactionsForTeamSince", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return topReactions, BuildResponse(r), nil } @@ -6686,8 +6692,8 @@ func (c *Client4) GetTopReactionsForUserSince(teamId string, timeRange string, p } defer closeBody(r) var topReactions *TopReactionList - if jsonErr := json.NewDecoder(r.Body).Decode(&topReactions); jsonErr != nil { - return nil, nil, NewAppError("GetTopReactionsForUserSince", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&topReactions); err != nil { + return nil, nil, NewAppError("GetTopReactionsForUserSince", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return topReactions, BuildResponse(r), nil } @@ -6746,8 +6752,8 @@ func (c *Client4) GetJob(id string) (*Job, *Response, error) { } defer closeBody(r) var j Job - if jsonErr := json.NewDecoder(r.Body).Decode(&j); jsonErr != nil { - return nil, nil, NewAppError("GetJob", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&j); err != nil { + return nil, nil, NewAppError("GetJob", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &j, BuildResponse(r), nil } @@ -6760,8 +6766,8 @@ func (c *Client4) GetJobs(page int, perPage int) ([]*Job, *Response, error) { } defer closeBody(r) var list []*Job - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetJobs", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetJobs", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -6774,8 +6780,8 @@ func (c *Client4) GetJobsByType(jobType string, page int, perPage int) ([]*Job, } defer closeBody(r) var list []*Job - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetJobsByType", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetJobsByType", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -6792,8 +6798,8 @@ func (c *Client4) CreateJob(job *Job) (*Job, *Response, error) { } defer closeBody(r) var j Job - if jsonErr := json.NewDecoder(r.Body).Decode(&j); jsonErr != nil { - return nil, nil, NewAppError("CreateJob", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&j); err != nil { + return nil, nil, NewAppError("CreateJob", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &j, BuildResponse(r), nil } @@ -6816,7 +6822,7 @@ func (c *Client4) DownloadJob(jobId string) ([]byte, *Response, error) { } defer closeBody(r) - data, err := ioutil.ReadAll(r.Body) + data, err := io.ReadAll(r.Body) if err != nil { return nil, BuildResponse(r), NewAppError("GetFile", "model.client.read_job_result_file.app_error", nil, err.Error(), r.StatusCode) } @@ -6833,8 +6839,8 @@ func (c *Client4) GetAllRoles() ([]*Role, *Response, error) { } defer closeBody(r) var list []*Role - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetAllRoles", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetAllRoles", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -6847,8 +6853,8 @@ func (c *Client4) GetRole(id string) (*Role, *Response, error) { } defer closeBody(r) var role Role - if jsonErr := json.NewDecoder(r.Body).Decode(&role); jsonErr != nil { - return nil, nil, NewAppError("GetRole", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&role); err != nil { + return nil, nil, NewAppError("GetRole", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &role, BuildResponse(r), nil } @@ -6861,8 +6867,8 @@ func (c *Client4) GetRoleByName(name string) (*Role, *Response, error) { } defer closeBody(r) var role Role - if jsonErr := json.NewDecoder(r.Body).Decode(&role); jsonErr != nil { - return nil, nil, NewAppError("GetRoleByName", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&role); err != nil { + return nil, nil, NewAppError("GetRoleByName", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &role, BuildResponse(r), nil } @@ -6875,8 +6881,8 @@ func (c *Client4) GetRolesByNames(roleNames []string) ([]*Role, *Response, error } defer closeBody(r) var list []*Role - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetRolesByNames", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetRolesByNames", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -6893,8 +6899,8 @@ func (c *Client4) PatchRole(roleId string, patch *RolePatch) (*Role, *Response, } defer closeBody(r) var role Role - if jsonErr := json.NewDecoder(r.Body).Decode(&role); jsonErr != nil { - return nil, nil, NewAppError("PatchRole", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&role); err != nil { + return nil, nil, NewAppError("PatchRole", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &role, BuildResponse(r), nil } @@ -6913,8 +6919,8 @@ func (c *Client4) CreateScheme(scheme *Scheme) (*Scheme, *Response, error) { } defer closeBody(r) var s Scheme - if jsonErr := json.NewDecoder(r.Body).Decode(&s); jsonErr != nil { - return nil, nil, NewAppError("CreateScheme", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&s); err != nil { + return nil, nil, NewAppError("CreateScheme", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &s, BuildResponse(r), nil } @@ -6927,8 +6933,8 @@ func (c *Client4) GetScheme(id string) (*Scheme, *Response, error) { } defer closeBody(r) var s Scheme - if jsonErr := json.NewDecoder(r.Body).Decode(&s); jsonErr != nil { - return nil, nil, NewAppError("GetScheme", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&s); err != nil { + return nil, nil, NewAppError("GetScheme", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &s, BuildResponse(r), nil } @@ -6941,8 +6947,8 @@ func (c *Client4) GetSchemes(scope string, page int, perPage int) ([]*Scheme, *R } defer closeBody(r) var list []*Scheme - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetSchemes", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetSchemes", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -6969,8 +6975,8 @@ func (c *Client4) PatchScheme(id string, patch *SchemePatch) (*Scheme, *Response } defer closeBody(r) var s Scheme - if jsonErr := json.NewDecoder(r.Body).Decode(&s); jsonErr != nil { - return nil, nil, NewAppError("PatchScheme", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&s); err != nil { + return nil, nil, NewAppError("PatchScheme", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &s, BuildResponse(r), nil } @@ -6983,8 +6989,8 @@ func (c *Client4) GetTeamsForScheme(schemeId string, page int, perPage int) ([]* } defer closeBody(r) var list []*Team - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetTeamsForScheme", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetTeamsForScheme", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -7061,8 +7067,8 @@ func (c *Client4) uploadPlugin(file io.Reader, force bool) (*Manifest, *Response } var m Manifest - if jsonErr := json.NewDecoder(rp.Body).Decode(&m); jsonErr != nil { - return nil, nil, NewAppError("uploadPlugin", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(rp.Body).Decode(&m); err != nil { + return nil, nil, NewAppError("uploadPlugin", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &m, BuildResponse(rp), nil } @@ -7078,8 +7084,8 @@ func (c *Client4) InstallPluginFromURL(downloadURL string, force bool) (*Manifes defer closeBody(r) var m Manifest - if jsonErr := json.NewDecoder(r.Body).Decode(&m); jsonErr != nil { - return nil, nil, NewAppError("InstallPluginFromUrl", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&m); err != nil { + return nil, nil, NewAppError("InstallPluginFromUrl", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &m, BuildResponse(r), nil } @@ -7097,8 +7103,8 @@ func (c *Client4) InstallMarketplacePlugin(request *InstallMarketplacePluginRequ defer closeBody(r) var m Manifest - if jsonErr := json.NewDecoder(r.Body).Decode(&m); jsonErr != nil { - return nil, nil, NewAppError("InstallMarketplacePlugin", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&m); err != nil { + return nil, nil, NewAppError("InstallMarketplacePlugin", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &m, BuildResponse(r), nil } @@ -7112,8 +7118,8 @@ func (c *Client4) GetPlugins() (*PluginsResponse, *Response, error) { defer closeBody(r) var resp PluginsResponse - if jsonErr := json.NewDecoder(r.Body).Decode(&resp); jsonErr != nil { - return nil, nil, NewAppError("GetPlugins", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&resp); err != nil { + return nil, nil, NewAppError("GetPlugins", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &resp, BuildResponse(r), nil } @@ -7127,8 +7133,8 @@ func (c *Client4) GetPluginStatuses() (PluginStatuses, *Response, error) { } defer closeBody(r) var list PluginStatuses - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetPluginStatuses", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetPluginStatuses", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -7152,8 +7158,8 @@ func (c *Client4) GetWebappPlugins() ([]*Manifest, *Response, error) { defer closeBody(r) var list []*Manifest - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetWebappPlugins", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetWebappPlugins", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -7274,8 +7280,8 @@ func (c *Client4) GetServerBusy() (*ServerBusyState, *Response, error) { defer closeBody(r) var sbs ServerBusyState - if jsonErr := json.NewDecoder(r.Body).Decode(&sbs); jsonErr != nil { - return nil, nil, NewAppError("GetServerBusy", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&sbs); err != nil { + return nil, nil, NewAppError("GetServerBusy", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &sbs, BuildResponse(r), nil } @@ -7301,8 +7307,8 @@ func (c *Client4) GetTermsOfService(etag string) (*TermsOfService, *Response, er } defer closeBody(r) var tos TermsOfService - if jsonErr := json.NewDecoder(r.Body).Decode(&tos); jsonErr != nil { - return nil, nil, NewAppError("GetTermsOfService", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&tos); err != nil { + return nil, nil, NewAppError("GetTermsOfService", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &tos, BuildResponse(r), nil } @@ -7316,8 +7322,8 @@ func (c *Client4) GetUserTermsOfService(userId, etag string) (*UserTermsOfServic } defer closeBody(r) var u UserTermsOfService - if jsonErr := json.NewDecoder(r.Body).Decode(&u); jsonErr != nil { - return nil, nil, NewAppError("GetUserTermsOfService", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&u); err != nil { + return nil, nil, NewAppError("GetUserTermsOfService", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &u, BuildResponse(r), nil } @@ -7332,8 +7338,8 @@ func (c *Client4) CreateTermsOfService(text, userId string) (*TermsOfService, *R } defer closeBody(r) var tos TermsOfService - if jsonErr := json.NewDecoder(r.Body).Decode(&tos); jsonErr != nil { - return nil, nil, NewAppError("CreateTermsOfService", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&tos); err != nil { + return nil, nil, NewAppError("CreateTermsOfService", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &tos, BuildResponse(r), nil } @@ -7345,16 +7351,16 @@ func (c *Client4) GetGroup(groupID, etag string) (*Group, *Response, error) { } defer closeBody(r) var g Group - if jsonErr := json.NewDecoder(r.Body).Decode(&g); jsonErr != nil { - return nil, nil, NewAppError("GetGroup", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&g); err != nil { + return nil, nil, NewAppError("GetGroup", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &g, BuildResponse(r), nil } func (c *Client4) CreateGroup(group *Group) (*Group, *Response, error) { - groupJSON, jsonErr := json.Marshal(group) - if jsonErr != nil { - return nil, nil, NewAppError("CreateGroup", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + groupJSON, err := json.Marshal(group) + if err != nil { + return nil, nil, NewAppError("CreateGroup", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPostBytes("/groups", groupJSON) if err != nil { @@ -7362,8 +7368,8 @@ func (c *Client4) CreateGroup(group *Group) (*Group, *Response, error) { } defer closeBody(r) var p Group - if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil { - return nil, nil, NewAppError("CreateGroup", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&p); err != nil { + return nil, nil, NewAppError("CreateGroup", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &p, BuildResponse(r), nil } @@ -7375,16 +7381,16 @@ func (c *Client4) DeleteGroup(groupID string) (*Group, *Response, error) { } defer closeBody(r) var p Group - if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil { - return nil, nil, NewAppError("DeleteGroup", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&p); err != nil { + return nil, nil, NewAppError("DeleteGroup", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &p, BuildResponse(r), nil } func (c *Client4) PatchGroup(groupID string, patch *GroupPatch) (*Group, *Response, error) { - payload, jsonErr := json.Marshal(patch) - if jsonErr != nil { - return nil, nil, NewAppError("PatchGroup", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + payload, err := json.Marshal(patch) + if err != nil { + return nil, nil, NewAppError("PatchGroup", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPut(c.groupRoute(groupID)+"/patch", string(payload)) if err != nil { @@ -7392,16 +7398,16 @@ func (c *Client4) PatchGroup(groupID string, patch *GroupPatch) (*Group, *Respon } defer closeBody(r) var g Group - if jsonErr := json.NewDecoder(r.Body).Decode(&g); jsonErr != nil { - return nil, nil, NewAppError("PatchGroup", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&g); err != nil { + return nil, nil, NewAppError("PatchGroup", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &g, BuildResponse(r), nil } func (c *Client4) UpsertGroupMembers(groupID string, userIds *GroupModifyMembers) ([]*GroupMember, *Response, error) { - payload, jsonErr := json.Marshal(userIds) - if jsonErr != nil { - return nil, nil, NewAppError("UpsertGroupMembers", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + payload, err := json.Marshal(userIds) + if err != nil { + return nil, nil, NewAppError("UpsertGroupMembers", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPostBytes(c.groupRoute(groupID)+"/members", payload) if err != nil { @@ -7409,16 +7415,16 @@ func (c *Client4) UpsertGroupMembers(groupID string, userIds *GroupModifyMembers } defer closeBody(r) var g []*GroupMember - if jsonErr := json.NewDecoder(r.Body).Decode(&g); jsonErr != nil { - return nil, nil, NewAppError("UpsertGroupMembers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&g); err != nil { + return nil, nil, NewAppError("UpsertGroupMembers", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return g, BuildResponse(r), nil } func (c *Client4) DeleteGroupMembers(groupID string, userIds *GroupModifyMembers) ([]*GroupMember, *Response, error) { - payload, jsonErr := json.Marshal(userIds) - if jsonErr != nil { - return nil, nil, NewAppError("DeleteGroupMembers", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + payload, err := json.Marshal(userIds) + if err != nil { + return nil, nil, NewAppError("DeleteGroupMembers", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIDeleteBytes(c.groupRoute(groupID)+"/members", payload) if err != nil { @@ -7426,16 +7432,16 @@ func (c *Client4) DeleteGroupMembers(groupID string, userIds *GroupModifyMembers } defer closeBody(r) var g []*GroupMember - if jsonErr := json.NewDecoder(r.Body).Decode(&g); jsonErr != nil { - return nil, nil, NewAppError("DeleteGroupMembers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&g); err != nil { + return nil, nil, NewAppError("DeleteGroupMembers", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return g, BuildResponse(r), nil } func (c *Client4) LinkGroupSyncable(groupID, syncableID string, syncableType GroupSyncableType, patch *GroupSyncablePatch) (*GroupSyncable, *Response, error) { - payload, jsonErr := json.Marshal(patch) - if jsonErr != nil { - return nil, nil, NewAppError("LinkGroupSyncable", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + payload, err := json.Marshal(patch) + if err != nil { + return nil, nil, NewAppError("LinkGroupSyncable", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } url := fmt.Sprintf("%s/link", c.groupSyncableRoute(groupID, syncableID, syncableType)) r, err := c.DoAPIPost(url, string(payload)) @@ -7444,8 +7450,8 @@ func (c *Client4) LinkGroupSyncable(groupID, syncableID string, syncableType Gro } defer closeBody(r) var gs GroupSyncable - if jsonErr := json.NewDecoder(r.Body).Decode(&gs); jsonErr != nil { - return nil, nil, NewAppError("LinkGroupSyncable", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&gs); err != nil { + return nil, nil, NewAppError("LinkGroupSyncable", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &gs, BuildResponse(r), nil } @@ -7467,8 +7473,8 @@ func (c *Client4) GetGroupSyncable(groupID, syncableID string, syncableType Grou } defer closeBody(r) var gs GroupSyncable - if jsonErr := json.NewDecoder(r.Body).Decode(&gs); jsonErr != nil { - return nil, nil, NewAppError("GetGroupSyncable", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&gs); err != nil { + return nil, nil, NewAppError("GetGroupSyncable", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &gs, BuildResponse(r), nil } @@ -7480,16 +7486,16 @@ func (c *Client4) GetGroupSyncables(groupID string, syncableType GroupSyncableTy } defer closeBody(r) var list []*GroupSyncable - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetGroupSyncables", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetGroupSyncables", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } func (c *Client4) PatchGroupSyncable(groupID, syncableID string, syncableType GroupSyncableType, patch *GroupSyncablePatch) (*GroupSyncable, *Response, error) { - payload, jsonErr := json.Marshal(patch) - if jsonErr != nil { - return nil, nil, NewAppError("PatchGroupSyncable", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + payload, err := json.Marshal(patch) + if err != nil { + return nil, nil, NewAppError("PatchGroupSyncable", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPut(c.groupSyncableRoute(groupID, syncableID, syncableType)+"/patch", string(payload)) if err != nil { @@ -7497,8 +7503,8 @@ func (c *Client4) PatchGroupSyncable(groupID, syncableID string, syncableType Gr } defer closeBody(r) var gs GroupSyncable - if jsonErr := json.NewDecoder(r.Body).Decode(&gs); jsonErr != nil { - return nil, nil, NewAppError("PatchGroupSyncable", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&gs); err != nil { + return nil, nil, NewAppError("PatchGroupSyncable", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &gs, BuildResponse(r), nil } @@ -7513,8 +7519,8 @@ func (c *Client4) TeamMembersMinusGroupMembers(teamID string, groupIDs []string, defer closeBody(r) var ugc UsersWithGroupsAndCount - if jsonErr := json.NewDecoder(r.Body).Decode(&ugc); jsonErr != nil { - return nil, 0, nil, NewAppError("TeamMembersMinusGroupMembers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&ugc); err != nil { + return nil, 0, nil, NewAppError("TeamMembersMinusGroupMembers", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return ugc.Users, ugc.Count, BuildResponse(r), nil } @@ -7528,8 +7534,8 @@ func (c *Client4) ChannelMembersMinusGroupMembers(channelID string, groupIDs []s } defer closeBody(r) var ugc UsersWithGroupsAndCount - if jsonErr := json.NewDecoder(r.Body).Decode(&ugc); jsonErr != nil { - return nil, 0, nil, NewAppError("ChannelMembersMinusGroupMembers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&ugc); err != nil { + return nil, 0, nil, NewAppError("ChannelMembersMinusGroupMembers", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return ugc.Users, ugc.Count, BuildResponse(r), nil } @@ -7544,7 +7550,10 @@ func (c *Client4) PatchConfig(config *Config) (*Config, *Response, error) { return nil, BuildResponse(r), err } defer closeBody(r) - return ConfigFromJSON(r.Body), BuildResponse(r), nil + + var cfg *Config + d := json.NewDecoder(r.Body) + return cfg, BuildResponse(r), d.Decode(&cfg) } func (c *Client4) GetChannelModerations(channelID string, etag string) ([]*ChannelModeration, *Response, error) { @@ -7624,9 +7633,9 @@ func (c *Client4) GetChannelMemberCountsByGroup(channelID string, includeTimezon // RequestTrialLicense will request a trial license and install it in the server func (c *Client4) RequestTrialLicense(users int) (*Response, error) { - b, jsonErr := json.Marshal(map[string]any{"users": users, "terms_accepted": true}) - if jsonErr != nil { - return nil, NewAppError("RequestTrialLicense", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + b, err := json.Marshal(map[string]any{"users": users, "terms_accepted": true}) + if err != nil { + return nil, NewAppError("RequestTrialLicense", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPost("/trial-license", string(b)) if err != nil { @@ -7644,8 +7653,8 @@ func (c *Client4) GetGroupStats(groupID string) (*GroupStats, *Response, error) } defer closeBody(r) var gs GroupStats - if jsonErr := json.NewDecoder(r.Body).Decode(&gs); jsonErr != nil { - return nil, nil, NewAppError("GetGroupStats", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&gs); err != nil { + return nil, nil, NewAppError("GetGroupStats", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &gs, BuildResponse(r), nil } @@ -7666,9 +7675,9 @@ func (c *Client4) GetSidebarCategoriesForTeamForUser(userID, teamID, etag string } func (c *Client4) CreateSidebarCategoryForTeamForUser(userID, teamID string, category *SidebarCategoryWithChannels) (*SidebarCategoryWithChannels, *Response, error) { - payload, jsonErr := json.Marshal(category) - if jsonErr != nil { - return nil, nil, NewAppError("CreateSidebarCategoryForTeamForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + payload, err := json.Marshal(category) + if err != nil { + return nil, nil, NewAppError("CreateSidebarCategoryForTeamForUser", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } route := c.userCategoryRoute(userID, teamID) r, err := c.DoAPIPostBytes(route, payload) @@ -7685,9 +7694,9 @@ func (c *Client4) CreateSidebarCategoryForTeamForUser(userID, teamID string, cat } func (c *Client4) UpdateSidebarCategoriesForTeamForUser(userID, teamID string, categories []*SidebarCategoryWithChannels) ([]*SidebarCategoryWithChannels, *Response, error) { - payload, jsonErr := json.Marshal(categories) - if jsonErr != nil { - return nil, nil, NewAppError("UpdateSidebarCategoriesForTeamForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + payload, err := json.Marshal(categories) + if err != nil { + return nil, nil, NewAppError("UpdateSidebarCategoriesForTeamForUser", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } route := c.userCategoryRoute(userID, teamID) @@ -7717,9 +7726,9 @@ func (c *Client4) GetSidebarCategoryOrderForTeamForUser(userID, teamID, etag str } func (c *Client4) UpdateSidebarCategoryOrderForTeamForUser(userID, teamID string, order []string) ([]string, *Response, error) { - payload, jsonErr := json.Marshal(order) - if jsonErr != nil { - return nil, nil, NewAppError("UpdateSidebarCategoryOrderForTeamForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + payload, err := json.Marshal(order) + if err != nil { + return nil, nil, NewAppError("UpdateSidebarCategoryOrderForTeamForUser", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } route := c.userCategoryRoute(userID, teamID) + "/order" r, err := c.DoAPIPutBytes(route, payload) @@ -7747,9 +7756,9 @@ func (c *Client4) GetSidebarCategoryForTeamForUser(userID, teamID, categoryID, e } func (c *Client4) UpdateSidebarCategoryForTeamForUser(userID, teamID, categoryID string, category *SidebarCategoryWithChannels) (*SidebarCategoryWithChannels, *Response, error) { - payload, jsonErr := json.Marshal(category) - if jsonErr != nil { - return nil, nil, NewAppError("UpdateSidebarCategoryForTeamForUser", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + payload, err := json.Marshal(category) + if err != nil { + return nil, nil, NewAppError("UpdateSidebarCategoryForTeamForUser", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } route := c.userCategoryRoute(userID, teamID) + "/" + categoryID r, err := c.DoAPIPutBytes(route, payload) @@ -7830,8 +7839,8 @@ func (c *Client4) CreateUpload(us *UploadSession) (*UploadSession, *Response, er defer closeBody(r) var s UploadSession - if jsonErr := json.NewDecoder(r.Body).Decode(&s); jsonErr != nil { - return nil, nil, NewAppError("CreateUpload", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&s); err != nil { + return nil, nil, NewAppError("CreateUpload", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &s, BuildResponse(r), nil } @@ -7844,8 +7853,8 @@ func (c *Client4) GetUpload(uploadId string) (*UploadSession, *Response, error) } defer closeBody(r) var s UploadSession - if jsonErr := json.NewDecoder(r.Body).Decode(&s); jsonErr != nil { - return nil, nil, NewAppError("GetUpload", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&s); err != nil { + return nil, nil, NewAppError("GetUpload", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &s, BuildResponse(r), nil } @@ -7859,8 +7868,8 @@ func (c *Client4) GetUploadsForUser(userId string) ([]*UploadSession, *Response, } defer closeBody(r) var list []*UploadSession - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetUploadsForUser", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetUploadsForUser", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -7878,8 +7887,8 @@ func (c *Client4) UploadData(uploadId string, data io.Reader) (*FileInfo, *Respo if r.StatusCode == http.StatusNoContent { return nil, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&fi); jsonErr != nil { - return nil, nil, NewAppError("UploadData", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&fi); err != nil { + return nil, nil, NewAppError("UploadData", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return &fi, BuildResponse(r), nil } @@ -7936,9 +7945,9 @@ func (c *Client4) CreateCustomerPayment() (*StripeSetupIntent, *Response, error) } func (c *Client4) ConfirmCustomerPayment(confirmRequest *ConfirmPaymentMethodRequest) (*Response, error) { - json, jsonErr := json.Marshal(confirmRequest) - if jsonErr != nil { - return nil, NewAppError("ConfirmCustomerPayment", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + json, err := json.Marshal(confirmRequest) + if err != nil { + return nil, NewAppError("ConfirmCustomerPayment", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPostBytes(c.cloudRoute()+"/payment/confirm", json) if err != nil { @@ -7950,9 +7959,9 @@ func (c *Client4) ConfirmCustomerPayment(confirmRequest *ConfirmPaymentMethodReq } func (c *Client4) RequestCloudTrial(email *StartCloudTrialRequest) (*Subscription, *Response, error) { - payload, jsonErr := json.Marshal(email) - if jsonErr != nil { - return nil, nil, NewAppError("RequestCloudTrial", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + payload, err := json.Marshal(email) + if err != nil { + return nil, nil, NewAppError("RequestCloudTrial", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPutBytes(c.cloudRoute()+"/request-trial", payload) if err != nil { @@ -7977,8 +7986,8 @@ func (c *Client4) ValidateWorkspaceBusinessEmail() (*Response, error) { } func (c *Client4) NotifyAdmin(nr *NotifyAdminToUpgradeRequest) int { - nrJSON, jsonErr := json.Marshal(nr) - if jsonErr != nil { + nrJSON, err := json.Marshal(nr) + if err != nil { return 0 } @@ -8043,9 +8052,9 @@ func (c *Client4) GetInvoicesForSubscription() ([]*Invoice, *Response, error) { } func (c *Client4) UpdateCloudCustomer(customerInfo *CloudCustomerInfo) (*CloudCustomer, *Response, error) { - customerBytes, jsonErr := json.Marshal(customerInfo) - if jsonErr != nil { - return nil, nil, NewAppError("UpdateCloudCustomer", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + customerBytes, err := json.Marshal(customerInfo) + if err != nil { + return nil, nil, NewAppError("UpdateCloudCustomer", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPutBytes(c.cloudRoute()+"/customer", customerBytes) if err != nil { @@ -8060,9 +8069,9 @@ func (c *Client4) UpdateCloudCustomer(customerInfo *CloudCustomerInfo) (*CloudCu } func (c *Client4) UpdateCloudCustomerAddress(address *Address) (*CloudCustomer, *Response, error) { - addressBytes, jsonErr := json.Marshal(address) - if jsonErr != nil { - return nil, nil, NewAppError("UpdateCloudCustomerAddress", "api.marshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + addressBytes, err := json.Marshal(address) + if err != nil { + return nil, nil, NewAppError("UpdateCloudCustomerAddress", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) } r, err := c.DoAPIPutBytes(c.cloudRoute()+"/customer/address", addressBytes) if err != nil { @@ -8287,8 +8296,8 @@ func (c *Client4) GetUsersWithInvalidEmails(page, perPage int) ([]*User, *Respon if r.StatusCode == http.StatusNotModified { return list, BuildResponse(r), nil } - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetUsers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetUsers", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } @@ -8300,8 +8309,8 @@ func (c *Client4) GetAppliedSchemaMigrations() ([]AppliedMigration, *Response, e } defer closeBody(r) var list []AppliedMigration - if jsonErr := json.NewDecoder(r.Body).Decode(&list); jsonErr != nil { - return nil, nil, NewAppError("GetUsers", "api.unmarshal_error", nil, jsonErr.Error(), http.StatusInternalServerError) + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetUsers", "api.unmarshal_error", nil, err.Error(), http.StatusInternalServerError) } return list, BuildResponse(r), nil } diff --git a/model/command_response.go b/model/command_response.go index b2521f8e0f..381a0f0c3d 100644 --- a/model/command_response.go +++ b/model/command_response.go @@ -6,7 +6,6 @@ package model import ( "encoding/json" "io" - "io/ioutil" "strings" "github.com/mattermost/mattermost-server/v6/utils/jsonutils" @@ -36,7 +35,7 @@ func CommandResponseFromHTTPBody(contentType string, body io.Reader) (*CommandRe if strings.TrimSpace(strings.Split(contentType, ";")[0]) == "application/json" { return CommandResponseFromJSON(body) } - if b, err := ioutil.ReadAll(body); err == nil { + if b, err := io.ReadAll(body); err == nil { return CommandResponseFromPlainText(string(b)), nil } return nil, nil @@ -49,7 +48,7 @@ func CommandResponseFromPlainText(text string) *CommandResponse { } func CommandResponseFromJSON(data io.Reader) (*CommandResponse, error) { - b, err := ioutil.ReadAll(data) + b, err := io.ReadAll(data) if err != nil { return nil, err } diff --git a/model/file_info_test.go b/model/file_info_test.go index 9d060f34c1..e2552dd77c 100644 --- a/model/file_info_test.go +++ b/model/file_info_test.go @@ -8,7 +8,7 @@ import ( "encoding/base64" _ "image/gif" _ "image/png" - "io/ioutil" + "os" "strings" "testing" @@ -76,13 +76,13 @@ func TestFileInfoIsImage(t *testing.T) { func TestGetInfoForFile(t *testing.T) { fakeFile := make([]byte, 1000) - pngFile, err := ioutil.ReadFile("../tests/test.png") + pngFile, err := os.ReadFile("../tests/test.png") require.NoError(t, err, "Failed to load test.png") // base 64 encoded version of handtinywhite.gif from http://probablyprogramming.com/2009/03/15/the-tiniest-gif-ever gifFile, _ := base64.StdEncoding.DecodeString("R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=") - animatedGifFile, err := ioutil.ReadFile("../tests/testgif.gif") + animatedGifFile, err := os.ReadFile("../tests/testgif.gif") require.NoError(t, err, "Failed to load testgif.gif") var ttc = []struct { diff --git a/model/manifest.go b/model/manifest.go index 6b7ddbd84d..9b1551e921 100644 --- a/model/manifest.go +++ b/model/manifest.go @@ -6,7 +6,7 @@ package model import ( "encoding/json" "fmt" - "io/ioutil" + "io" "os" "path/filepath" "strings" @@ -108,42 +108,41 @@ type PluginSettingsSchema struct { // // Example plugin.json: // -// -// { -// "id": "com.mycompany.myplugin", -// "name": "My Plugin", -// "description": "This is my plugin", -// "homepage_url": "https://example.com", -// "support_url": "https://example.com/support", -// "release_notes_url": "https://example.com/releases/v0.0.1", -// "icon_path": "assets/logo.svg", -// "version": "0.1.0", -// "min_server_version": "5.6.0", -// "server": { -// "executables": { -// "linux-amd64": "server/dist/plugin-linux-amd64", -// "darwin-amd64": "server/dist/plugin-darwin-amd64", -// "windows-amd64": "server/dist/plugin-windows-amd64.exe" -// } -// }, -// "webapp": { -// "bundle_path": "webapp/dist/main.js" -// }, -// "settings_schema": { -// "header": "Some header text", -// "footer": "Some footer text", -// "settings": [{ -// "key": "someKey", -// "display_name": "Enable Extra Feature", -// "type": "bool", -// "help_text": "When true, an extra feature will be enabled!", -// "default": "false" -// }] -// }, -// "props": { -// "someKey": "someData" -// } -// } +// { +// "id": "com.mycompany.myplugin", +// "name": "My Plugin", +// "description": "This is my plugin", +// "homepage_url": "https://example.com", +// "support_url": "https://example.com/support", +// "release_notes_url": "https://example.com/releases/v0.0.1", +// "icon_path": "assets/logo.svg", +// "version": "0.1.0", +// "min_server_version": "5.6.0", +// "server": { +// "executables": { +// "linux-amd64": "server/dist/plugin-linux-amd64", +// "darwin-amd64": "server/dist/plugin-darwin-amd64", +// "windows-amd64": "server/dist/plugin-windows-amd64.exe" +// } +// }, +// "webapp": { +// "bundle_path": "webapp/dist/main.js" +// }, +// "settings_schema": { +// "header": "Some header text", +// "footer": "Some footer text", +// "settings": [{ +// "key": "someKey", +// "display_name": "Enable Extra Feature", +// "type": "bool", +// "help_text": "When true, an extra feature will be enabled!", +// "default": "false" +// }] +// }, +// "props": { +// "someKey": "someData" +// } +// } type Manifest struct { // The id is a globally unique identifier that represents your plugin. Ids must be at least // 3 characters, at most 190 characters and must match ^[a-zA-Z0-9-_\.]+$. @@ -426,7 +425,7 @@ func FindManifest(dir string) (manifest *Manifest, path string, err error) { } continue } - b, ioerr := ioutil.ReadAll(f) + b, ioerr := io.ReadAll(f) f.Close() if ioerr != nil { return nil, path, ioerr diff --git a/model/manifest_test.go b/model/manifest_test.go index ae816b340d..de93569b53 100644 --- a/model/manifest_test.go +++ b/model/manifest_test.go @@ -5,7 +5,6 @@ package model import ( "encoding/json" - "io/ioutil" "os" "path/filepath" "strings" @@ -244,7 +243,7 @@ func TestFindManifest(t *testing.T) { {"plugin.yml", `id: FOO`, false, false}, {"plugin.yml", "bar", true, false}, } { - dir, err := ioutil.TempDir("", "mm-plugin-test") + dir, err := os.MkdirTemp("", "mm-plugin-test") require.NoError(t, err) defer os.RemoveAll(dir) @@ -396,7 +395,7 @@ settings_schema: func TestFindManifest_FileErrors(t *testing.T) { for _, tc := range []string{"plugin.yaml", "plugin.json"} { - dir, err := ioutil.TempDir("", "mm-plugin-test") + dir, err := os.MkdirTemp("", "mm-plugin-test") require.NoError(t, err) defer os.RemoveAll(dir) @@ -417,7 +416,7 @@ func TestFindManifest_FolderPermission(t *testing.T) { } for _, tc := range []string{"plugin.yaml", "plugin.json"} { - dir, err := ioutil.TempDir("", "mm-plugin-test") + dir, err := os.MkdirTemp("", "mm-plugin-test") require.NoError(t, err) defer os.RemoveAll(dir) diff --git a/model/post_test.go b/model/post_test.go index f6935c7ca6..3cbb785100 100644 --- a/model/post_test.go +++ b/model/post_test.go @@ -5,7 +5,7 @@ package model import ( "encoding/json" - "io/ioutil" + "os" "strings" "sync" "testing" @@ -369,13 +369,13 @@ func TestPost_AttachmentsEqual(t *testing.T) { var markdownSample, markdownSampleWithRewrittenImageURLs string func init() { - bytes, err := ioutil.ReadFile("testdata/markdown-sample.md") + bytes, err := os.ReadFile("testdata/markdown-sample.md") if err != nil { panic(err) } markdownSample = string(bytes) - bytes, err = ioutil.ReadFile("testdata/markdown-sample-with-rewritten-image-urls.md") + bytes, err = os.ReadFile("testdata/markdown-sample-with-rewritten-image-urls.md") if err != nil { panic(err) } diff --git a/model/preference.go b/model/preference.go index 6ce93be67a..98e0a08c5a 100644 --- a/model/preference.go +++ b/model/preference.go @@ -91,23 +91,21 @@ func (o *Preference) IsValid() *AppError { if o.Category == PreferenceCategoryTheme { var unused map[string]string if err := json.NewDecoder(strings.NewReader(o.Value)).Decode(&unused); err != nil { - return NewAppError("Preference.IsValid", "model.preference.is_valid.theme.app_error", nil, "value="+o.Value, http.StatusBadRequest) + return NewAppError("Preference.IsValid", "model.preference.is_valid.theme.app_error", nil, "value="+o.Value, http.StatusBadRequest).Wrap(err) } } return nil } +var preUpdateColorPattern = regexp.MustCompile(`^#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?$`) + func (o *Preference) PreUpdate() { if o.Category == PreferenceCategoryTheme { // decode the value of theme (a map of strings to string) and eliminate any invalid values var props map[string]string - if err := json.NewDecoder(strings.NewReader(o.Value)).Decode(&props); err != nil { - // just continue, the invalid preference value should get caught by IsValid before saving - return - } - - colorPattern := regexp.MustCompile(`^#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?$`) + // just continue, the invalid preference value should get caught by IsValid before saving + json.NewDecoder(strings.NewReader(o.Value)).Decode(&props) // blank out any invalid theme values for name, value := range props { @@ -115,7 +113,7 @@ func (o *Preference) PreUpdate() { continue } - if !colorPattern.MatchString(value) { + if !preUpdateColorPattern.MatchString(value) { props[name] = "#ffffff" } } diff --git a/model/utils.go b/model/utils.go index 8d93015c57..86ec1536f2 100644 --- a/model/utils.go +++ b/model/utils.go @@ -293,7 +293,7 @@ func AppErrorFromJSON(data io.Reader) *AppError { var er AppError err := decoder.Decode(&er) if err != nil { - return NewAppError("AppErrorFromJSON", "model.utils.decode_json.app_error", nil, "body: "+str, http.StatusInternalServerError) + return NewAppError("AppErrorFromJSON", "model.utils.decode_json.app_error", nil, "body: "+str, http.StatusInternalServerError).Wrap(err) } return &er } @@ -401,23 +401,25 @@ func MapBoolToJSON(objmap map[string]bool) string { // MapFromJSON will decode the key/value pair map func MapFromJSON(data io.Reader) map[string]string { - decoder := json.NewDecoder(data) - var objmap map[string]string - if err := decoder.Decode(&objmap); err != nil { + + json.NewDecoder(data).Decode(&objmap) + if objmap == nil { return make(map[string]string) } + return objmap } // MapFromJSON will decode the key/value pair map func MapBoolFromJSON(data io.Reader) map[string]bool { - decoder := json.NewDecoder(data) - var objmap map[string]bool - if err := decoder.Decode(&objmap); err != nil { + + json.NewDecoder(data).Decode(&objmap) + if objmap == nil { return make(map[string]bool) } + return objmap } @@ -427,12 +429,13 @@ func ArrayToJSON(objmap []string) string { } func ArrayFromJSON(data io.Reader) []string { - decoder := json.NewDecoder(data) - var objmap []string - if err := decoder.Decode(&objmap); err != nil { + + json.NewDecoder(data).Decode(&objmap) + if objmap == nil { return make([]string, 0) } + return objmap } @@ -459,12 +462,13 @@ func StringInterfaceToJSON(objmap map[string]any) string { } func StringInterfaceFromJSON(data io.Reader) map[string]any { - decoder := json.NewDecoder(data) - var objmap map[string]any - if err := decoder.Decode(&objmap); err != nil { + + json.NewDecoder(data).Decode(&objmap) + if objmap == nil { return make(map[string]any) } + return objmap } diff --git a/plugin/client_rpc.go b/plugin/client_rpc.go index 12c54b61ba..feea87005a 100644 --- a/plugin/client_rpc.go +++ b/plugin/client_rpc.go @@ -13,7 +13,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "log" "net/http" "net/rpc" @@ -444,7 +443,7 @@ func (s *hooksRPCServer) ServeHTTP(args *Z_ServeHTTPArgs, returns *struct{}) err } r.Body = connectIOReader(connection) } else { - r.Body = ioutil.NopCloser(&bytes.Buffer{}) + r.Body = io.NopCloser(&bytes.Buffer{}) } defer r.Body.Close() @@ -487,7 +486,7 @@ func (g *apiRPCClient) PluginHTTP(request *http.Request) *http.Response { } if request.Body != nil { - requestBody, err := ioutil.ReadAll(request.Body) + requestBody, err := io.ReadAll(request.Body) if err != nil { log.Printf("RPC call to PluginHTTP API failed: %s", err.Error()) return nil @@ -504,20 +503,20 @@ func (g *apiRPCClient) PluginHTTP(request *http.Request) *http.Response { return nil } - _returns.Response.Body = ioutil.NopCloser(bytes.NewBuffer(_returns.ResponseBody)) + _returns.Response.Body = io.NopCloser(bytes.NewBuffer(_returns.ResponseBody)) return _returns.Response } func (s *apiRPCServer) PluginHTTP(args *Z_PluginHTTPArgs, returns *Z_PluginHTTPReturns) error { - args.Request.Body = ioutil.NopCloser(bytes.NewBuffer(args.RequestBody)) + args.Request.Body = io.NopCloser(bytes.NewBuffer(args.RequestBody)) if hook, ok := s.impl.(interface { PluginHTTP(request *http.Request) *http.Response }); ok { response := hook.PluginHTTP(args.Request) - responseBody, err := ioutil.ReadAll(response.Body) + responseBody, err := io.ReadAll(response.Body) if err != nil { return encodableError(fmt.Errorf("RPC call to PluginHTTP API failed: %s", err.Error())) } diff --git a/plugin/environment.go b/plugin/environment.go index 6469c9352b..9226a2e878 100644 --- a/plugin/environment.go +++ b/plugin/environment.go @@ -6,7 +6,6 @@ package plugin import ( "fmt" "hash/fnv" - "io/ioutil" "os" "path/filepath" "sync" @@ -86,7 +85,7 @@ func NewEnvironment(newAPIImpl apiImplCreatorFunc, // // Plugins are found non-recursively and paths beginning with a dot are always ignored. func scanSearchPath(path string) ([]*model.BundleInfo, error) { - files, err := ioutil.ReadDir(path) + files, err := os.ReadDir(path) if err != nil { return nil, err } @@ -468,7 +467,7 @@ func (env *Environment) UnpackWebappBundle(id string) (*model.Manifest, error) { sourceBundleFilepath := filepath.Join(destinationPath, filepath.Base(bundlePath)) - sourceBundleFileContents, err := ioutil.ReadFile(sourceBundleFilepath) + sourceBundleFileContents, err := os.ReadFile(sourceBundleFilepath) if err != nil { return nil, errors.Wrapf(err, "unable to read webapp bundle: %v", id) } diff --git a/plugin/environment_test.go b/plugin/environment_test.go index 827b822422..389021040c 100644 --- a/plugin/environment_test.go +++ b/plugin/environment_test.go @@ -5,7 +5,6 @@ package plugin import ( "encoding/json" - "io/ioutil" "os" "path/filepath" "testing" @@ -16,7 +15,7 @@ import ( ) func TestAvailablePlugins(t *testing.T) { - dir, err1 := ioutil.TempDir("", "mm-plugin-test") + dir, err1 := os.MkdirTemp("", "mm-plugin-test") require.NoError(t, err1) t.Cleanup(func() { os.RemoveAll(dir) @@ -40,7 +39,7 @@ func TestAvailablePlugins(t *testing.T) { path := filepath.Join(dir, "plugin1", "plugin.json") manifestJSON, jsonErr := json.Marshal(bundle1.Manifest) require.NoError(t, jsonErr) - err = ioutil.WriteFile(path, manifestJSON, 0644) + err = os.WriteFile(path, manifestJSON, 0644) require.NoError(t, err) bundles, err := env.Available() @@ -54,7 +53,7 @@ func TestAvailablePlugins(t *testing.T) { defer os.RemoveAll(filepath.Join(dir, "plugin2")) path := filepath.Join(dir, "plugin2", "manifest.json") - err = ioutil.WriteFile(path, []byte("{}"), 0644) + err = os.WriteFile(path, []byte("{}"), 0644) require.NoError(t, err) bundles, err := env.Available() diff --git a/plugin/health_check_test.go b/plugin/health_check_test.go index 1854af0a9e..f2dc44c766 100644 --- a/plugin/health_check_test.go +++ b/plugin/health_check_test.go @@ -4,7 +4,6 @@ package plugin import ( - "io/ioutil" "os" "path/filepath" "testing" @@ -27,7 +26,7 @@ func TestPluginHealthCheck(t *testing.T) { } func testPluginHealthCheckSuccess(t *testing.T) { - dir, err := ioutil.TempDir("", "") + dir, err := os.MkdirTemp("", "") require.NoError(t, err) defer os.RemoveAll(dir) @@ -48,7 +47,7 @@ func testPluginHealthCheckSuccess(t *testing.T) { } `, backend) - err = ioutil.WriteFile(filepath.Join(dir, "plugin.json"), []byte(`{"id": "foo", "server": {"executable": "backend.exe"}}`), 0600) + err = os.WriteFile(filepath.Join(dir, "plugin.json"), []byte(`{"id": "foo", "server": {"executable": "backend.exe"}}`), 0600) require.NoError(t, err) bundle := model.BundleInfoForPath(dir) @@ -65,7 +64,7 @@ func testPluginHealthCheckSuccess(t *testing.T) { } func testPluginHealthCheckPanic(t *testing.T) { - dir, err := ioutil.TempDir("", "") + dir, err := os.MkdirTemp("", "") require.NoError(t, err) defer os.RemoveAll(dir) @@ -91,7 +90,7 @@ func testPluginHealthCheckPanic(t *testing.T) { } `, backend) - err = ioutil.WriteFile(filepath.Join(dir, "plugin.json"), []byte(`{"id": "foo", "server": {"executable": "backend.exe"}}`), 0600) + err = os.WriteFile(filepath.Join(dir, "plugin.json"), []byte(`{"id": "foo", "server": {"executable": "backend.exe"}}`), 0600) require.NoError(t, err) bundle := model.BundleInfoForPath(dir) diff --git a/plugin/interface_generator/main.go b/plugin/interface_generator/main.go index 878b94501b..763868f52e 100644 --- a/plugin/interface_generator/main.go +++ b/plugin/interface_generator/main.go @@ -10,8 +10,8 @@ import ( "go/parser" "go/printer" "go/token" - "io/ioutil" "log" + "os" "os/exec" "path/filepath" "strings" @@ -580,7 +580,7 @@ func generateHooksGlue(info *PluginInterfaceInfo) { panic(err) } - if err := ioutil.WriteFile(filepath.Join(getPluginPackageDir(), "client_rpc_generated.go"), formatted, 0664); err != nil { + if err := os.WriteFile(filepath.Join(getPluginPackageDir(), "client_rpc_generated.go"), formatted, 0664); err != nil { panic(err) } } @@ -613,7 +613,7 @@ func generateProductHooksInterfaces(info *PluginInterfaceInfo) { panic(err) } - if err := ioutil.WriteFile(filepath.Join(getPluginPackageDir(), "product_hooks_generated.go"), formatted, 0664); err != nil { + if err := os.WriteFile(filepath.Join(getPluginPackageDir(), "product_hooks_generated.go"), formatted, 0664); err != nil { panic(err) } } @@ -667,7 +667,7 @@ func generatePluginTimerLayer(info *PluginInterfaceInfo) { panic(err) } - if err := ioutil.WriteFile(filepath.Join(getPluginPackageDir(), fileName), formatted, 0664); err != nil { + if err := os.WriteFile(filepath.Join(getPluginPackageDir(), fileName), formatted, 0664); err != nil { panic(err) } } diff --git a/plugin/plugintest/example_hello_user_test.go b/plugin/plugintest/example_hello_user_test.go index 36b57f65b2..2095b914d3 100644 --- a/plugin/plugintest/example_hello_user_test.go +++ b/plugin/plugintest/example_hello_user_test.go @@ -5,7 +5,7 @@ package plugintest_test import ( "fmt" - "io/ioutil" + io "io" "net/http" "net/http/httptest" "testing" @@ -52,7 +52,7 @@ func Example() { r := httptest.NewRequest("GET", "/", nil) r.Header.Add("Mattermost-User-Id", user.Id) p.ServeHTTP(&plugin.Context{}, w, r) - body, err := ioutil.ReadAll(w.Result().Body) + body, err := io.ReadAll(w.Result().Body) require.NoError(t, err) assert.Equal(t, "Welcome back, billybob!", string(body)) } diff --git a/plugin/supervisor_test.go b/plugin/supervisor_test.go index 81b8d6a912..f5aa7538c0 100644 --- a/plugin/supervisor_test.go +++ b/plugin/supervisor_test.go @@ -4,7 +4,6 @@ package plugin import ( - "io/ioutil" "os" "path/filepath" "testing" @@ -28,11 +27,11 @@ func TestSupervisor(t *testing.T) { } func testSupervisorInvalidExecutablePath(t *testing.T) { - dir, err := ioutil.TempDir("", "") + dir, err := os.MkdirTemp("", "") require.NoError(t, err) defer os.RemoveAll(dir) - ioutil.WriteFile(filepath.Join(dir, "plugin.json"), []byte(`{"id": "foo", "server": {"executable": "/foo/../../backend.exe"}}`), 0600) + os.WriteFile(filepath.Join(dir, "plugin.json"), []byte(`{"id": "foo", "server": {"executable": "/foo/../../backend.exe"}}`), 0600) bundle := model.BundleInfoForPath(dir) log := mlog.CreateConsoleTestLogger(true, mlog.LvlError) @@ -43,11 +42,11 @@ func testSupervisorInvalidExecutablePath(t *testing.T) { } func testSupervisorNonExistentExecutablePath(t *testing.T) { - dir, err := ioutil.TempDir("", "") + dir, err := os.MkdirTemp("", "") require.NoError(t, err) defer os.RemoveAll(dir) - ioutil.WriteFile(filepath.Join(dir, "plugin.json"), []byte(`{"id": "foo", "server": {"executable": "thisfileshouldnotexist"}}`), 0600) + os.WriteFile(filepath.Join(dir, "plugin.json"), []byte(`{"id": "foo", "server": {"executable": "thisfileshouldnotexist"}}`), 0600) bundle := model.BundleInfoForPath(dir) log := mlog.CreateConsoleTestLogger(true, mlog.LvlError) @@ -59,7 +58,7 @@ func testSupervisorNonExistentExecutablePath(t *testing.T) { // If plugin development goes really wrong, let's make sure plugin activation won't block forever. func testSupervisorStartTimeout(t *testing.T) { - dir, err := ioutil.TempDir("", "") + dir, err := os.MkdirTemp("", "") require.NoError(t, err) defer os.RemoveAll(dir) @@ -73,7 +72,7 @@ func testSupervisorStartTimeout(t *testing.T) { } `, backend) - ioutil.WriteFile(filepath.Join(dir, "plugin.json"), []byte(`{"id": "foo", "server": {"executable": "backend.exe"}}`), 0600) + os.WriteFile(filepath.Join(dir, "plugin.json"), []byte(`{"id": "foo", "server": {"executable": "backend.exe"}}`), 0600) bundle := model.BundleInfoForPath(dir) log := mlog.CreateConsoleTestLogger(true, mlog.LvlError) diff --git a/scripts/config_generator/main_test.go b/scripts/config_generator/main_test.go index e0afc34d04..8dba358c44 100644 --- a/scripts/config_generator/main_test.go +++ b/scripts/config_generator/main_test.go @@ -5,7 +5,6 @@ package main import ( "encoding/json" - "io/ioutil" "os" "testing" @@ -15,14 +14,14 @@ import ( ) func TestDefaultsGenerator(t *testing.T) { - tmpFile, err := ioutil.TempFile("", "tempconfig") + tmpFile, err := os.CreateTemp("", "tempconfig") defer os.Remove(tmpFile.Name()) require.NoError(t, err) require.NoError(t, generateDefaultConfig(tmpFile)) _ = tmpFile.Close() var config model.Config - b, err := ioutil.ReadFile(tmpFile.Name()) + b, err := os.ReadFile(tmpFile.Name()) require.NoError(t, err) require.NoError(t, json.Unmarshal(b, &config)) require.Equal(t, *config.SqlSettings.AtRestEncryptKey, "") diff --git a/services/docextractor/archive.go b/services/docextractor/archive.go index 96194252cb..1c0e228afb 100644 --- a/services/docextractor/archive.go +++ b/services/docextractor/archive.go @@ -7,7 +7,6 @@ import ( "bytes" "fmt" "io" - "io/ioutil" "os" "path/filepath" "strings" @@ -25,7 +24,7 @@ func (ae *archiveExtractor) Match(filename string) bool { } func (ae *archiveExtractor) Extract(name string, r io.ReadSeeker) (string, error) { - dir, err := ioutil.TempDir(os.TempDir(), "archiver") + dir, err := os.MkdirTemp(os.TempDir(), "archiver") if err != nil { return "", fmt.Errorf("error creating temporary file: %v", err) } @@ -49,7 +48,7 @@ func (ae *archiveExtractor) Extract(name string, r io.ReadSeeker) (string, error filename = strings.ReplaceAll(filename, "-", " ") filename = strings.ReplaceAll(filename, ".", " ") filename = strings.ReplaceAll(filename, ",", " ") - data, err2 := ioutil.ReadAll(file) + data, err2 := io.ReadAll(file) if err2 != nil { return err2 } diff --git a/services/docextractor/mmpreview.go b/services/docextractor/mmpreview.go index a46cc3f956..b38e16c5af 100644 --- a/services/docextractor/mmpreview.go +++ b/services/docextractor/mmpreview.go @@ -10,7 +10,6 @@ package docextractor import ( "bytes" "io" - "io/ioutil" "mime/multipart" "net/http" "path" @@ -63,7 +62,7 @@ func (mpe *mmPreviewExtractor) Extract(filename string, file io.ReadSeeker) (str if resp.StatusCode != 200 { return "", errors.New("Unable to generate file preview using mmpreview (The server has replied with an error)") } - data, err := ioutil.ReadAll(resp.Body) + data, err := io.ReadAll(resp.Body) if err != nil { return "", errors.Wrap(err, "unable to read the response from mmpreview") } diff --git a/services/docextractor/pdf.go b/services/docextractor/pdf.go index 43010d4d29..baa7d6685e 100644 --- a/services/docextractor/pdf.go +++ b/services/docextractor/pdf.go @@ -8,7 +8,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "os" "path" "strings" @@ -33,7 +32,7 @@ func (pe *pdfExtractor) Extract(filename string, r io.ReadSeeker) (out string, o outErr = errors.New("error extracting pdf text") } }() - f, err := ioutil.TempFile(os.TempDir(), "pdflib") + f, err := os.CreateTemp(os.TempDir(), "pdflib") if err != nil { return "", fmt.Errorf("error creating temporary file: %v", err) } diff --git a/services/docextractor/plain.go b/services/docextractor/plain.go index 4d3b084502..e97bb1d0b8 100644 --- a/services/docextractor/plain.go +++ b/services/docextractor/plain.go @@ -5,7 +5,6 @@ package docextractor import ( "io" - "io/ioutil" "unicode" "unicode/utf8" ) @@ -47,6 +46,6 @@ func (pe *plainExtractor) Extract(filename string, r io.ReadSeeker) (string, err } } - text, _ := ioutil.ReadAll(r) + text, _ := io.ReadAll(r) return string(runes[0:total]) + string(text), nil } diff --git a/services/httpservice/client_test.go b/services/httpservice/client_test.go index a57e5134ad..a274ebf5f3 100644 --- a/services/httpservice/client_test.go +++ b/services/httpservice/client_test.go @@ -6,7 +6,7 @@ package httpservice import ( "context" "fmt" - "io/ioutil" + "io" "net" "net/http" "net/http/httptest" @@ -108,7 +108,7 @@ func TestHTTPClientWithProxy(t *testing.T) { require.NoError(t, err) defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) require.NoError(t, err) require.Equal(t, "proxy", string(body)) } diff --git a/services/imageproxy/atmos_camo_test.go b/services/imageproxy/atmos_camo_test.go index 114071b4e6..087724e122 100644 --- a/services/imageproxy/atmos_camo_test.go +++ b/services/imageproxy/atmos_camo_test.go @@ -4,7 +4,7 @@ package imageproxy import ( - "io/ioutil" + "io" "net/http" "net/http/httptest" "net/url" @@ -85,7 +85,7 @@ func TestAtmosCamoBackend_GetImageDirect(t *testing.T) { assert.Equal(t, "image/png", contentType) require.NotNil(t, body) - respBody, _ := ioutil.ReadAll(body) + respBody, _ := io.ReadAll(body) assert.Equal(t, []byte("1111111111"), respBody) } diff --git a/services/imageproxy/local.go b/services/imageproxy/local.go index fc98f6eeb8..950582ebf1 100644 --- a/services/imageproxy/local.go +++ b/services/imageproxy/local.go @@ -8,7 +8,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "mime" "net" "net/http" @@ -134,7 +133,7 @@ func (backend *LocalBackend) GetImageDirect(imageURL string) (io.ReadCloser, str return nil, "", ErrLocalRequestFailed } - return ioutil.NopCloser(recorder.Body), recorder.Header().Get("Content-Type"), nil + return io.NopCloser(recorder.Body), recorder.Header().Get("Content-Type"), nil } func (backend *LocalBackend) ServeImage(w http.ResponseWriter, req *http.Request) { @@ -176,7 +175,7 @@ func (backend *LocalBackend) ServeImage(w http.ResponseWriter, req *http.Request if contentType == "" || contentType == "application/octet-stream" || contentType == "binary/octet-stream" { // try to detect content type b := bufio.NewReader(resp.Body) - resp.Body = ioutil.NopCloser(b) + resp.Body = io.NopCloser(b) contentType = peekContentType(b) } if resp.ContentLength != 0 && !contentTypeMatches(imageContentTypes, contentType) { diff --git a/services/imageproxy/local_test.go b/services/imageproxy/local_test.go index da32132546..fe724bca4b 100644 --- a/services/imageproxy/local_test.go +++ b/services/imageproxy/local_test.go @@ -4,7 +4,7 @@ package imageproxy import ( - "io/ioutil" + "io" "net/http" "net/http/httptest" "testing" @@ -60,7 +60,7 @@ func TestLocalBackend_GetImage(t *testing.T) { assert.Equal(t, "max-age=2592000, private", resp.Header.Get("Cache-Control")) assert.Equal(t, "10", resp.Header.Get("Content-Length")) - respBody, _ := ioutil.ReadAll(resp.Body) + respBody, _ := io.ReadAll(resp.Body) assert.Equal(t, []byte("1111111111"), respBody) }) @@ -190,7 +190,7 @@ func TestLocalBackend_GetImage(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, "attachment;filename=\"test.svg\"", resp.Header.Get("Content-Disposition")) - _, err = ioutil.ReadAll(resp.Body) + _, err = io.ReadAll(resp.Body) require.NoError(t, err) }) @@ -247,7 +247,7 @@ func TestLocalBackend_GetImageDirect(t *testing.T) { assert.NoError(t, err) assert.Equal(t, "image/png", contentType) - respBody, _ := ioutil.ReadAll(body) + respBody, _ := io.ReadAll(body) assert.Equal(t, []byte("1111111111"), respBody) }) diff --git a/services/remotecluster/sendfile.go b/services/remotecluster/sendfile.go index d94434e2bf..9bf224cbf6 100644 --- a/services/remotecluster/sendfile.go +++ b/services/remotecluster/sendfile.go @@ -7,7 +7,7 @@ import ( "context" "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "net/url" "path" @@ -117,7 +117,7 @@ func (rcs *Service) sendFileToRemote(timeout time.Duration, task sendFileTask) ( } defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { return nil, err } diff --git a/services/remotecluster/sendmsg.go b/services/remotecluster/sendmsg.go index 2b66cdcb6a..78350a3e4a 100644 --- a/services/remotecluster/sendmsg.go +++ b/services/remotecluster/sendmsg.go @@ -8,7 +8,7 @@ import ( "context" "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "net/url" "os" @@ -163,7 +163,7 @@ func (rcs *Service) sendFrameToRemote(timeout time.Duration, rc *model.RemoteClu return nil, err } defer resp.Body.Close() - body, err = ioutil.ReadAll(resp.Body) + body, err = io.ReadAll(resp.Body) if err != nil { return nil, err } diff --git a/services/remotecluster/sendprofileImage.go b/services/remotecluster/sendprofileImage.go index ff148a3472..e86adff2ba 100644 --- a/services/remotecluster/sendprofileImage.go +++ b/services/remotecluster/sendprofileImage.go @@ -8,7 +8,6 @@ import ( "context" "fmt" "io" - "io/ioutil" "mime/multipart" "net/http" "net/url" @@ -134,7 +133,7 @@ func (rcs *Service) sendProfileImageToRemote(timeout time.Duration, task sendPro } defer resp.Body.Close() - _, err = ioutil.ReadAll(resp.Body) + _, err = io.ReadAll(resp.Body) if err != nil { return err } diff --git a/services/searchengine/bleveengine/bleve_test.go b/services/searchengine/bleveengine/bleve_test.go index a0ed1e1736..62e30386eb 100644 --- a/services/searchengine/bleveengine/bleve_test.go +++ b/services/searchengine/bleveengine/bleve_test.go @@ -4,7 +4,6 @@ package bleveengine import ( - "io/ioutil" "os" "testing" @@ -37,7 +36,7 @@ func TestBleveEngineTestSuite(t *testing.T) { } func (s *BleveEngineTestSuite) setupIndexes() { - indexDir, err := ioutil.TempDir("", "mmbleve") + indexDir, err := os.MkdirTemp("", "mmbleve") if err != nil { s.Require().FailNow("Cannot setup bleveengine tests: %s", err.Error()) } diff --git a/services/searchengine/bleveengine/indexer/indexing_job_test.go b/services/searchengine/bleveengine/indexer/indexing_job_test.go index 16de60201e..ce6f169306 100644 --- a/services/searchengine/bleveengine/indexer/indexing_job_test.go +++ b/services/searchengine/bleveengine/indexer/indexing_job_test.go @@ -5,7 +5,6 @@ package indexer import ( "errors" - "io/ioutil" "os" "testing" @@ -33,7 +32,7 @@ func TestBleveIndexer(t *testing.T) { mockStore.JobStore.On("UpdateOptimistically", job, model.JobStatusInProgress).Return(true, nil) mockStore.PostStore.On("GetOldestEntityCreationTime").Return(int64(1), errors.New("")) // intentionally return error to return from function - tempDir, err := ioutil.TempDir("", "setupConfigFile") + tempDir, err := os.MkdirTemp("", "setupConfigFile") require.NoError(t, err) t.Cleanup(func() { diff --git a/services/slackimport/parsers.go b/services/slackimport/parsers.go index f3eab0ab1a..fcd50f3de9 100644 --- a/services/slackimport/parsers.go +++ b/services/slackimport/parsers.go @@ -16,7 +16,7 @@ func slackParseChannels(data io.Reader, channelType model.ChannelType) ([]slackC var channels []slackChannel if err := decoder.Decode(&channels); err != nil { - mlog.Warn("Slack Import: Error occurred when parsing some Slack channels. Import may work anyway.") + mlog.Warn("Slack Import: Error occurred when parsing some Slack channels. Import may work anyway.", mlog.Err(err)) return channels, err } @@ -43,7 +43,7 @@ func slackParsePosts(data io.Reader) ([]slackPost, error) { var posts []slackPost if err := decoder.Decode(&posts); err != nil { - mlog.Warn("Slack Import: Error occurred when parsing some Slack posts. Import may work anyway.") + mlog.Warn("Slack Import: Error occurred when parsing some Slack posts. Import may work anyway.", mlog.Err(err)) return posts, err } return posts, nil diff --git a/services/telemetry/telemetry_test.go b/services/telemetry/telemetry_test.go index cd5d0626aa..31ab7656ad 100644 --- a/services/telemetry/telemetry_test.go +++ b/services/telemetry/telemetry_test.go @@ -9,7 +9,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "net/http" "net/http/httptest" "os" @@ -108,7 +108,7 @@ func makeTelemetryServiceAndReceiver(t *testing.T, cloudLicense bool) (*Telemetr pchan := make(chan testTelemetryPayload, 100) receiver := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - body, err := ioutil.ReadAll(r.Body) + body, err := io.ReadAll(r.Body) require.NoError(t, err) var p testTelemetryPayload @@ -154,8 +154,8 @@ func initializeMocks(cfg *model.Config, cloudLicense bool) (*mocks.ServerIface, serverIfaceMock.On("Config").Return(cfg) serverIfaceMock.On("IsLeader").Return(true) - pluginDir, _ := ioutil.TempDir("", "") - webappPluginDir, _ := ioutil.TempDir("", "") + pluginDir, _ := os.MkdirTemp("", "") + webappPluginDir, _ := os.MkdirTemp("", "") cleanUp := func() { os.RemoveAll(pluginDir) os.RemoveAll(webappPluginDir) diff --git a/services/upgrader/upgrader_linux.go b/services/upgrader/upgrader_linux.go index fa45dd4951..b76c4d2d28 100644 --- a/services/upgrader/upgrader_linux.go +++ b/services/upgrader/upgrader_linux.go @@ -10,7 +10,6 @@ import ( _ "embed" "fmt" "io" - "io/ioutil" "net/http" "os" "os/user" @@ -257,7 +256,7 @@ func download(url string, limit int64) (string, error) { } defer resp.Body.Close() - out, err := ioutil.TempFile("", "*_mattermost.tar.gz") + out, err := os.CreateTemp("", "*_mattermost.tar.gz") if err != nil { return "", err } @@ -310,7 +309,7 @@ func extractBinary(executablePath string, filename string) error { if header.Typeflag == tar.TypeReg && header.Name == "mattermost/bin/mattermost" { permissions := getFilePermissionsOrDefault(executablePath, 0755) - tmpFile, err := ioutil.TempFile(path.Dir(executablePath), "*") + tmpFile, err := os.CreateTemp(path.Dir(executablePath), "*") if err != nil { return err } diff --git a/services/upgrader/upgrader_linux_test.go b/services/upgrader/upgrader_linux_test.go index 43583a243a..73853b3281 100644 --- a/services/upgrader/upgrader_linux_test.go +++ b/services/upgrader/upgrader_linux_test.go @@ -6,7 +6,7 @@ package upgrader import ( "archive/tar" "compress/gzip" - "io/ioutil" + "io" "os" "testing" @@ -75,12 +75,12 @@ func TestGetCurrentVersionTgzURL(t *testing.T) { func TestExtractBinary(t *testing.T) { t.Run("extract from empty file", func(t *testing.T) { - tmpMockTarGz, err := ioutil.TempFile("", "mock_tgz") + tmpMockTarGz, err := os.CreateTemp("", "mock_tgz") require.NoError(t, err) defer os.Remove(tmpMockTarGz.Name()) tmpMockTarGz.Close() - tmpMockExecutable, err := ioutil.TempFile("", "mock_exe") + tmpMockExecutable, err := os.CreateTemp("", "mock_exe") require.NoError(t, err) defer os.Remove(tmpMockExecutable.Name()) tmpMockExecutable.Close() @@ -89,7 +89,7 @@ func TestExtractBinary(t *testing.T) { }) t.Run("extract from empty tar.gz file", func(t *testing.T) { - tmpMockTarGz, err := ioutil.TempFile("", "mock_tgz") + tmpMockTarGz, err := os.CreateTemp("", "mock_tgz") require.NoError(t, err) defer os.Remove(tmpMockTarGz.Name()) gz := gzip.NewWriter(tmpMockTarGz) @@ -98,7 +98,7 @@ func TestExtractBinary(t *testing.T) { gz.Close() tmpMockTarGz.Close() - tmpMockExecutable, err := ioutil.TempFile("", "mock_exe") + tmpMockExecutable, err := os.CreateTemp("", "mock_exe") require.NoError(t, err) defer os.Remove(tmpMockExecutable.Name()) tmpMockExecutable.Close() @@ -107,7 +107,7 @@ func TestExtractBinary(t *testing.T) { }) t.Run("extract from tar.gz without mattermost/bin/mattermost file", func(t *testing.T) { - tmpMockTarGz, err := ioutil.TempFile("", "mock_tgz") + tmpMockTarGz, err := os.CreateTemp("", "mock_tgz") require.NoError(t, err) defer os.Remove(tmpMockTarGz.Name()) gz := gzip.NewWriter(tmpMockTarGz) @@ -123,7 +123,7 @@ func TestExtractBinary(t *testing.T) { gz.Close() tmpMockTarGz.Close() - tmpMockExecutable, err := ioutil.TempFile("", "mock_exe") + tmpMockExecutable, err := os.CreateTemp("", "mock_exe") require.NoError(t, err) defer os.Remove(tmpMockExecutable.Name()) tmpMockExecutable.Close() @@ -132,7 +132,7 @@ func TestExtractBinary(t *testing.T) { }) t.Run("extract from tar.gz with mattermost/bin/mattermost file", func(t *testing.T) { - tmpMockTarGz, err := ioutil.TempFile("", "mock_tgz") + tmpMockTarGz, err := os.CreateTemp("", "mock_tgz") require.NoError(t, err) defer os.Remove(tmpMockTarGz.Name()) gz := gzip.NewWriter(tmpMockTarGz) @@ -148,7 +148,7 @@ func TestExtractBinary(t *testing.T) { gz.Close() tmpMockTarGz.Close() - tmpMockExecutable, err := ioutil.TempFile("", "mock_exe") + tmpMockExecutable, err := os.CreateTemp("", "mock_exe") require.NoError(t, err) defer os.Remove(tmpMockExecutable.Name()) tmpMockExecutable.Close() @@ -157,7 +157,7 @@ func TestExtractBinary(t *testing.T) { tmpMockExecutableAfter, err := os.Open(tmpMockExecutable.Name()) require.NoError(t, err) defer tmpMockExecutableAfter.Close() - bytes, err := ioutil.ReadAll(tmpMockExecutableAfter) + bytes, err := io.ReadAll(tmpMockExecutableAfter) require.NoError(t, err) require.Equal(t, []byte("test"), bytes) }) diff --git a/shared/filestore/filesstore_test.go b/shared/filestore/filesstore_test.go index 662b2ef150..dae092e8a7 100644 --- a/shared/filestore/filesstore_test.go +++ b/shared/filestore/filesstore_test.go @@ -6,7 +6,6 @@ package filestore import ( "bytes" "fmt" - "io/ioutil" "math/rand" "os" "testing" @@ -38,7 +37,7 @@ func TestLocalFileBackendTestSuite(t *testing.T) { mlog.InitGlobalLogger(logger) - dir, err := ioutil.TempDir("", "") + dir, err := os.MkdirTemp("", "") require.NoError(t, err) defer os.RemoveAll(dir) @@ -501,15 +500,16 @@ func (s *FileBackendTestSuite) TestFileModTime() { func BenchmarkS3WriteFile(b *testing.B) { settings := FileBackendSettings{ - DriverName: driverS3, - AmazonS3AccessKeyId: "minioaccesskey", - AmazonS3SecretAccessKey: "miniosecretkey", - AmazonS3Bucket: "mattermost-test", - AmazonS3Region: "", - AmazonS3Endpoint: "localhost:9000", - AmazonS3PathPrefix: "", - AmazonS3SSL: false, - AmazonS3SSE: false, + DriverName: driverS3, + AmazonS3AccessKeyId: "minioaccesskey", + AmazonS3SecretAccessKey: "miniosecretkey", + AmazonS3Bucket: "mattermost-test", + AmazonS3Region: "", + AmazonS3Endpoint: "localhost:9000", + AmazonS3PathPrefix: "", + AmazonS3SSL: false, + AmazonS3SSE: false, + AmazonS3RequestTimeoutMilliseconds: 20000, } backend, err := NewFileBackend(settings) diff --git a/shared/filestore/localstore.go b/shared/filestore/localstore.go index e2d53e4942..1a21305bda 100644 --- a/shared/filestore/localstore.go +++ b/shared/filestore/localstore.go @@ -6,7 +6,6 @@ package filestore import ( "bytes" "io" - "io/ioutil" "os" "path/filepath" "time" @@ -88,7 +87,7 @@ func (b *LocalFileBackend) Reader(path string) (ReadCloseSeeker, error) { } func (b *LocalFileBackend) ReadFile(path string) ([]byte, error) { - f, err := ioutil.ReadFile(filepath.Join(b.directory, path)) + f, err := os.ReadFile(filepath.Join(b.directory, path)) if err != nil { return nil, errors.Wrapf(err, "unable to read file %s", path) } diff --git a/shared/filestore/s3store.go b/shared/filestore/s3store.go index c8738a7b5a..1cdaddd812 100644 --- a/shared/filestore/s3store.go +++ b/shared/filestore/s3store.go @@ -8,7 +8,6 @@ import ( "context" "crypto/tls" "io" - "io/ioutil" "net/http" "os" "path/filepath" @@ -241,7 +240,7 @@ func (b *S3FileBackend) ReadFile(path string) ([]byte, error) { } defer minioObject.Close() - f, err := ioutil.ReadAll(minioObject) + f, err := io.ReadAll(minioObject) if err != nil { return nil, errors.Wrapf(err, "unable to read file %s", path) } diff --git a/shared/i18n/i18n.go b/shared/i18n/i18n.go index 42108b38b4..5bf0f13bfe 100644 --- a/shared/i18n/i18n.go +++ b/shared/i18n/i18n.go @@ -6,8 +6,8 @@ package i18n import ( "fmt" "html/template" - "io/ioutil" "net/http" + "os" "path/filepath" "reflect" "strings" @@ -59,7 +59,7 @@ func InitTranslations(serverLocale, clientLocale string) error { } func initTranslationsWithDir(dir string) error { - files, _ := ioutil.ReadDir(dir) + files, _ := os.ReadDir(dir) for _, f := range files { if filepath.Ext(f.Name()) == ".json" { filename := f.Name() diff --git a/shared/mail/mail.go b/shared/mail/mail.go index b3c2ef10d0..03dbddc62a 100644 --- a/shared/mail/mail.go +++ b/shared/mail/mail.go @@ -58,7 +58,6 @@ type mailData struct { } // smtpClient is implemented by an smtp.Client. See https://golang.org/pkg/net/smtp/#Client. -// type smtpClient interface { Mail(string) error Rcpt(string) error diff --git a/shared/mail/mail_test.go b/shared/mail/mail_test.go index 207da90442..ff5c0cd71c 100644 --- a/shared/mail/mail_test.go +++ b/shared/mail/mail_test.go @@ -7,7 +7,6 @@ import ( "bytes" "context" "io" - "io/ioutil" "net" "net/mail" "net/smtp" @@ -195,12 +194,12 @@ func TestSendMailUsingConfigAdvanced(t *testing.T) { DeleteMailBox("test2@example.com") // create two files with the same name that will both be attached to the email - file1, err := ioutil.TempFile("", "*") + file1, err := os.CreateTemp("", "*") require.NoError(t, err) defer os.Remove(file1.Name()) file1.Write([]byte("hello world")) file1.Close() - file2, err := ioutil.TempFile("", "*") + file2, err := os.CreateTemp("", "*") require.NoError(t, err) defer os.Remove(file2.Name()) @@ -326,7 +325,7 @@ func (m *mockMailer) Write(p []byte) (int, error) { func (m *mockMailer) Close() error { return nil } func TestSendMail(t *testing.T) { - dir, err := ioutil.TempDir(".", "mail-test-") + dir, err := os.MkdirTemp(".", "mail-test-") require.NoError(t, err) defer os.RemoveAll(dir) mocm := &mockMailer{} diff --git a/shared/mlog/global_test.go b/shared/mlog/global_test.go index 3fae371f76..d97b3b15a3 100644 --- a/shared/mlog/global_test.go +++ b/shared/mlog/global_test.go @@ -6,7 +6,6 @@ package mlog_test import ( "encoding/json" "fmt" - "io/ioutil" "os" "path/filepath" "regexp" @@ -99,7 +98,7 @@ func TestLoggingAfterInitialized(t *testing.T) { t.Run(testCase.description, func(t *testing.T) { var filePath string if testCase.cfg.Type == "file" { - tempDir, err := ioutil.TempDir(os.TempDir(), "TestLoggingAfterInitialized") + tempDir, err := os.MkdirTemp(os.TempDir(), "TestLoggingAfterInitialized") require.NoError(t, err) defer os.Remove(tempDir) @@ -122,7 +121,7 @@ func TestLoggingAfterInitialized(t *testing.T) { logger.Shutdown() if testCase.cfg.Type == "file" { - logs, err := ioutil.ReadFile(filePath) + logs, err := os.ReadFile(filePath) require.NoError(t, err) actual := strings.TrimSpace(string(logs)) diff --git a/shared/mlog/mlog.go b/shared/mlog/mlog.go index 8618b28352..060f3cd302 100644 --- a/shared/mlog/mlog.go +++ b/shared/mlog/mlog.go @@ -10,7 +10,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "log" "os" "strings" @@ -181,12 +180,14 @@ func NewLogger(options ...Option) (*Logger, error) { // Configure provides a new configuration for this logger. // Zero or more sources of config can be provided: -// cfgFile - path to file containing JSON -// cfgEscaped - JSON string probably from ENV var +// +// cfgFile - path to file containing JSON +// cfgEscaped - JSON string probably from ENV var // // For each case JSON containing log targets is provided. Target name collisions are resolved // using the following precedence: -// cfgFile > cfgEscaped +// +// cfgFile > cfgEscaped // // An optional set of factories can be provided which will be called to create any target // types or formatters not built-in. @@ -199,7 +200,7 @@ func (l *Logger) Configure(cfgFile string, cfgEscaped string, factories *Factori // Add config from file if cfgFile != "" { - b, err := ioutil.ReadFile(cfgFile) + b, err := os.ReadFile(cfgFile) if err != nil { return fmt.Errorf("error reading logger config file %s: %w", cfgFile, err) } diff --git a/shared/templates/templates_test.go b/shared/templates/templates_test.go index f847790cfe..4a11207db9 100644 --- a/shared/templates/templates_test.go +++ b/shared/templates/templates_test.go @@ -6,7 +6,6 @@ package templates import ( "bytes" "html/template" - "io/ioutil" "os" "path/filepath" "testing" @@ -17,12 +16,12 @@ import ( ) func TestHTMLTemplateWatcher(t *testing.T) { - dir, err := ioutil.TempDir("", "") + dir, err := os.MkdirTemp("", "") require.NoError(t, err) defer os.RemoveAll(dir) require.NoError(t, os.Mkdir(filepath.Join(dir, "templates"), 0700)) - require.NoError(t, ioutil.WriteFile(filepath.Join(dir, "templates", "foo.html"), []byte(`{{ define "foo" }}foo{{ end }}`), 0600)) + require.NoError(t, os.WriteFile(filepath.Join(dir, "templates", "foo.html"), []byte(`{{ define "foo" }}foo{{ end }}`), 0600)) prevDir, err := os.Getwd() require.NoError(t, err) @@ -45,7 +44,7 @@ func TestHTMLTemplateWatcher(t *testing.T) { require.NoError(t, err) assert.Equal(t, "foo", text) - require.NoError(t, ioutil.WriteFile(filepath.Join(dir, "templates", "foo.html"), []byte(`{{ define "foo" }}bar{{ end }}`), 0600)) + require.NoError(t, os.WriteFile(filepath.Join(dir, "templates", "foo.html"), []byte(`{{ define "foo" }}bar{{ end }}`), 0600)) require.Eventually(t, func() bool { text, err := watcher.RenderToString("foo", Data{}) diff --git a/store/layer_generators/main.go b/store/layer_generators/main.go index 28b015ac0c..cfb95abdb8 100644 --- a/store/layer_generators/main.go +++ b/store/layer_generators/main.go @@ -10,7 +10,7 @@ import ( "go/format" "go/parser" "go/token" - "io/ioutil" + "io" "log" "os" "path" @@ -49,7 +49,7 @@ func buildRetryLayer() error { return err } - return ioutil.WriteFile(path.Join("retrylayer/retrylayer.go"), formatedCode, 0644) + return os.WriteFile(path.Join("retrylayer/retrylayer.go"), formatedCode, 0644) } func buildTimerLayer() error { @@ -62,7 +62,7 @@ func buildTimerLayer() error { return err } - return ioutil.WriteFile(path.Join("timerlayer", "timerlayer.go"), formatedCode, 0644) + return os.WriteFile(path.Join("timerlayer", "timerlayer.go"), formatedCode, 0644) } func buildOpenTracingLayer() error { @@ -75,7 +75,7 @@ func buildOpenTracingLayer() error { return err } - return ioutil.WriteFile(path.Join("opentracinglayer", "opentracinglayer.go"), formatedCode, 0644) + return os.WriteFile(path.Join("opentracinglayer", "opentracinglayer.go"), formatedCode, 0644) } type methodParam struct { @@ -155,7 +155,7 @@ func extractStoreMetadata() (*storeMetadata, error) { if err != nil { return nil, fmt.Errorf("unable to open store/store.go file: %w", err) } - src, err := ioutil.ReadAll(file) + src, err := io.ReadAll(file) if err != nil { return nil, err } diff --git a/store/sqlstore/reaction_store.go b/store/sqlstore/reaction_store.go index 7651257ff5..d1a56b6e08 100644 --- a/store/sqlstore/reaction_store.go +++ b/store/sqlstore/reaction_store.go @@ -316,8 +316,7 @@ func (s *SqlReactionStore) GetTopForUserSince(userID string, teamID string, sinc count(EmojiName) AS Count FROM Reactions - INNER JOIN Posts ON Reactions.PostId = Posts.Id - INNER JOIN Channels ON Posts.ChannelId = Channels.Id + INNER JOIN Channels ON Channels.Id = Reactions.ChannelId WHERE Reactions.DeleteAt = 0 AND Reactions.UserId = ? diff --git a/testlib/helper.go b/testlib/helper.go index c28d998bfd..e4b4021404 100644 --- a/testlib/helper.go +++ b/testlib/helper.go @@ -6,7 +6,6 @@ package testlib import ( "flag" "fmt" - "io/ioutil" "log" "os" "path/filepath" @@ -164,7 +163,7 @@ func (h *MainHelper) PreloadMigrations() { } else { finalPath = filepath.Join("mattermost-server", relPath, "postgres_migration_warmup.sql") } - buf, err = ioutil.ReadFile(finalPath) + buf, err = os.ReadFile(finalPath) if err != nil { panic(fmt.Errorf("cannot read file: %v", err)) } @@ -175,7 +174,7 @@ func (h *MainHelper) PreloadMigrations() { } else { finalPath = filepath.Join("mattermost-server", relPath, "mysql_migration_warmup.sql") } - buf, err = ioutil.ReadFile(finalPath) + buf, err = os.ReadFile(finalPath) if err != nil { panic(fmt.Errorf("cannot read file: %v", err)) } diff --git a/testlib/resources.go b/testlib/resources.go index 716692a447..15bc08bc5d 100644 --- a/testlib/resources.go +++ b/testlib/resources.go @@ -6,7 +6,6 @@ package testlib import ( "encoding/json" "fmt" - "io/ioutil" "os" "path" "path/filepath" @@ -116,7 +115,7 @@ func CopyFile(src, dst string) error { func SetupTestResources() (string, error) { testResourcesToSetup := getTestResourcesToSetup() - tempDir, err := ioutil.TempDir("", "testlib") + tempDir, err := os.MkdirTemp("", "testlib") if err != nil { return "", errors.Wrap(err, "failed to create temporary directory") } @@ -195,7 +194,7 @@ func setupConfig(configDir string) error { } configJSON := path.Join(configDir, "config.json") - err = ioutil.WriteFile(configJSON, buf, 0644) + err = os.WriteFile(configJSON, buf, 0644) if err != nil { return errors.Wrapf(err, "failed to write config to %s", configJSON) } diff --git a/utils/archive_test.go b/utils/archive_test.go index 37444311ab..576c4e91f9 100644 --- a/utils/archive_test.go +++ b/utils/archive_test.go @@ -6,7 +6,6 @@ package utils import ( "archive/zip" "errors" - "io/ioutil" "os" "path/filepath" "testing" @@ -90,7 +89,7 @@ func TestUnzipToPath(t *testing.T) { testDir, _ := fileutils.FindDir("tests") require.NotEmpty(t, testDir) - dir, err := ioutil.TempDir("", "unzip") + dir, err := os.MkdirTemp("", "unzip") require.NoError(t, err) defer os.RemoveAll(dir) diff --git a/utils/file.go b/utils/file.go index 175aa9ac21..4338f51508 100644 --- a/utils/file.go +++ b/utils/file.go @@ -7,7 +7,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "os" "path/filepath" ) @@ -85,7 +84,7 @@ func CopyDir(src string, dst string) (err error) { return } - items, err := ioutil.ReadDir(src) + items, err := os.ReadDir(src) if err != nil { return } @@ -100,7 +99,12 @@ func CopyDir(src string, dst string) (err error) { return } } else { - if item.Mode()&os.ModeSymlink != 0 { + info, ierr := item.Info() + if ierr != nil { + continue + } + + if info.Mode()&os.ModeSymlink != 0 { continue } diff --git a/utils/file_test.go b/utils/file_test.go index e74c273cb7..f41c092c42 100644 --- a/utils/file_test.go +++ b/utils/file_test.go @@ -7,7 +7,6 @@ import ( "bytes" "crypto/rand" "io" - "io/ioutil" "os" "path/filepath" "testing" @@ -17,18 +16,18 @@ import ( ) func TestCopyDir(t *testing.T) { - srcDir, err := ioutil.TempDir("", "src") + srcDir, err := os.MkdirTemp("", "src") require.NoError(t, err) defer os.RemoveAll(srcDir) - dstParentDir, err := ioutil.TempDir("", "dstparent") + dstParentDir, err := os.MkdirTemp("", "dstparent") require.NoError(t, err) defer os.RemoveAll(dstParentDir) dstDir := filepath.Join(dstParentDir, "dst") tempFile := "temp.txt" - err = ioutil.WriteFile(filepath.Join(srcDir, tempFile), []byte("test file"), 0655) + err = os.WriteFile(filepath.Join(srcDir, tempFile), []byte("test file"), 0655) require.NoError(t, err) childDir := "child" @@ -36,7 +35,7 @@ func TestCopyDir(t *testing.T) { require.NoError(t, err) childTempFile := "childtemp.txt" - err = ioutil.WriteFile(filepath.Join(srcDir, childDir, childTempFile), []byte("test file"), 0755) + err = os.WriteFile(filepath.Join(srcDir, childDir, childTempFile), []byte("test file"), 0755) require.NoError(t, err) err = CopyDir(srcDir, dstDir) @@ -46,7 +45,7 @@ func TestCopyDir(t *testing.T) { assert.NoError(t, err) assert.Equal(t, uint32(0655), uint32(stat.Mode())) assert.False(t, stat.IsDir()) - data, err := ioutil.ReadFile(filepath.Join(dstDir, tempFile)) + data, err := os.ReadFile(filepath.Join(dstDir, tempFile)) assert.NoError(t, err) assert.Equal(t, "test file", string(data)) @@ -58,7 +57,7 @@ func TestCopyDir(t *testing.T) { assert.NoError(t, err) assert.Equal(t, uint32(0755), uint32(stat.Mode())) assert.False(t, stat.IsDir()) - data, err = ioutil.ReadFile(filepath.Join(dstDir, childDir, childTempFile)) + data, err = os.ReadFile(filepath.Join(dstDir, childDir, childTempFile)) assert.NoError(t, err) assert.Equal(t, "test file", string(data)) diff --git a/utils/fileutils/fileutils_test.go b/utils/fileutils/fileutils_test.go index 93dcfffd10..c223586443 100644 --- a/utils/fileutils/fileutils_test.go +++ b/utils/fileutils/fileutils_test.go @@ -5,7 +5,6 @@ package fileutils import ( "fmt" - "io/ioutil" "os" "path/filepath" "testing" @@ -26,23 +25,23 @@ func TestFindFile(t *testing.T) { // tmpDir3/ // tmpDir4/ // tmpDir5/ - tmpDir1, err := ioutil.TempDir("", "") + tmpDir1, err := os.MkdirTemp("", "") require.NoError(t, err) defer os.RemoveAll(tmpDir1) - tmpDir2, err := ioutil.TempDir(tmpDir1, "") + tmpDir2, err := os.MkdirTemp(tmpDir1, "") require.NoError(t, err) err = os.Mkdir(filepath.Join(tmpDir2, "other.txt"), 0700) require.NoError(t, err) - tmpDir3, err := ioutil.TempDir(tmpDir2, "") + tmpDir3, err := os.MkdirTemp(tmpDir2, "") require.NoError(t, err) - tmpDir4, err := ioutil.TempDir(tmpDir3, "") + tmpDir4, err := os.MkdirTemp(tmpDir3, "") require.NoError(t, err) - tmpDir5, err := ioutil.TempDir(tmpDir4, "") + tmpDir5, err := os.MkdirTemp(tmpDir4, "") require.NoError(t, err) type testCase struct { @@ -56,7 +55,7 @@ func TestFindFile(t *testing.T) { for _, fileName := range []string{"file1.json", "file2.xml", "other.txt"} { filePath := filepath.Join(tmpDir1, fileName) - require.NoError(t, ioutil.WriteFile(filePath, []byte("{}"), 0600)) + require.NoError(t, os.WriteFile(filePath, []byte("{}"), 0600)) // Relative paths end up getting symlinks fully resolved, so use this below as necessary. filePathResolved, err := filepath.EvalSymlinks(filePath) diff --git a/utils/license.go b/utils/license.go index 96a228ba8e..c18b9fad7f 100644 --- a/utils/license.go +++ b/utils/license.go @@ -11,7 +11,7 @@ import ( "encoding/base64" "encoding/json" "encoding/pem" - "io/ioutil" + "io" "net/http" "os" "path/filepath" @@ -141,7 +141,7 @@ func GetLicenseFileFromDisk(fileName string) []byte { } defer file.Close() - licenseBytes, err := ioutil.ReadAll(file) + licenseBytes, err := io.ReadAll(file) if err != nil { mlog.Error("Failed to read license key from disk at", mlog.String("filename", fileName), mlog.Err(err)) return nil diff --git a/utils/license_test.go b/utils/license_test.go index c32faa044f..8c57685444 100644 --- a/utils/license_test.go +++ b/utils/license_test.go @@ -6,7 +6,6 @@ package utils import ( "bytes" "encoding/base64" - "io/ioutil" "os" "testing" @@ -80,10 +79,10 @@ func TestGetLicenseFileFromDisk(t *testing.T) { }) t.Run("not a license file", func(t *testing.T) { - f, err := ioutil.TempFile("", "TestGetLicenseFileFromDisk") + f, err := os.CreateTemp("", "TestGetLicenseFileFromDisk") require.NoError(t, err) defer os.Remove(f.Name()) - ioutil.WriteFile(f.Name(), []byte("not a license"), 0777) + os.WriteFile(f.Name(), []byte("not a license"), 0777) fileBytes := GetLicenseFileFromDisk(f.Name()) require.NotEmpty(t, fileBytes, "should have read the file") diff --git a/utils/subpath.go b/utils/subpath.go index 078527244c..f70b299472 100644 --- a/utils/subpath.go +++ b/utils/subpath.go @@ -7,7 +7,6 @@ import ( "crypto/sha256" "encoding/base64" "fmt" - "io/ioutil" "net/url" "os" "path" @@ -63,7 +62,7 @@ func UpdateAssetsSubpathInDir(subpath, directory string) error { } rootHTMLPath := filepath.Join(staticDir, "root.html") - oldRootHTML, err := ioutil.ReadFile(rootHTMLPath) + oldRootHTML, err := os.ReadFile(rootHTMLPath) if err != nil { return errors.Wrap(err, "failed to open root.html") } @@ -113,19 +112,19 @@ func UpdateAssetsSubpathInDir(subpath, directory string) error { } // Write out the updated root.html. - if err = ioutil.WriteFile(rootHTMLPath, []byte(newRootHTML), 0); err != nil { + if err = os.WriteFile(rootHTMLPath, []byte(newRootHTML), 0); err != nil { return errors.Wrapf(err, "failed to update root.html with subpath %s", subpath) } // Rewrite the manifest.json and *.css references to `/static/*` (or a previously rewritten subpath). err = filepath.Walk(staticDir, func(walkPath string, info os.FileInfo, err error) error { if filepath.Base(walkPath) == "manifest.json" || filepath.Ext(walkPath) == ".css" { - old, err := ioutil.ReadFile(walkPath) + old, err := os.ReadFile(walkPath) if err != nil { return errors.Wrapf(err, "failed to open %s", walkPath) } new := strings.Replace(string(old), pathToReplace, newPath, -1) - if err = ioutil.WriteFile(walkPath, []byte(new), 0); err != nil { + if err = os.WriteFile(walkPath, []byte(new), 0); err != nil { return errors.Wrapf(err, "failed to update %s with subpath %s", walkPath, subpath) } } diff --git a/utils/subpath_test.go b/utils/subpath_test.go index efc9c383e3..85724aabaa 100644 --- a/utils/subpath_test.go +++ b/utils/subpath_test.go @@ -5,7 +5,6 @@ package utils_test import ( "fmt" - "io/ioutil" "os" "path/filepath" "strings" @@ -41,7 +40,7 @@ func TestUpdateAssetsSubpathFromConfig(t *testing.T) { }) t.Run("no config", func(t *testing.T) { - tempDir, err := ioutil.TempDir("", "test_update_assets_subpath") + tempDir, err := os.MkdirTemp("", "test_update_assets_subpath") require.NoError(t, err) defer os.RemoveAll(tempDir) os.Chdir(tempDir) @@ -53,7 +52,7 @@ func TestUpdateAssetsSubpathFromConfig(t *testing.T) { func TestUpdateAssetsSubpath(t *testing.T) { t.Run("no client dir", func(t *testing.T) { - tempDir, err := ioutil.TempDir("", "test_update_assets_subpath") + tempDir, err := os.MkdirTemp("", "test_update_assets_subpath") require.NoError(t, err) defer os.RemoveAll(tempDir) os.Chdir(tempDir) @@ -63,7 +62,7 @@ func TestUpdateAssetsSubpath(t *testing.T) { }) t.Run("valid", func(t *testing.T) { - tempDir, err := ioutil.TempDir("", "test_update_assets_subpath") + tempDir, err := os.MkdirTemp("", "test_update_assets_subpath") require.NoError(t, err) defer os.RemoveAll(tempDir) os.Chdir(tempDir) @@ -163,9 +162,9 @@ func TestUpdateAssetsSubpath(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.Description, func(t *testing.T) { - ioutil.WriteFile(filepath.Join(tempDir, model.ClientDir, "root.html"), []byte(testCase.RootHTML), 0700) - ioutil.WriteFile(filepath.Join(tempDir, model.ClientDir, "main.css"), []byte(testCase.MainCSS), 0700) - ioutil.WriteFile(filepath.Join(tempDir, model.ClientDir, "manifest.json"), []byte(testCase.ManifestJSON), 0700) + os.WriteFile(filepath.Join(tempDir, model.ClientDir, "root.html"), []byte(testCase.RootHTML), 0700) + os.WriteFile(filepath.Join(tempDir, model.ClientDir, "main.css"), []byte(testCase.MainCSS), 0700) + os.WriteFile(filepath.Join(tempDir, model.ClientDir, "manifest.json"), []byte(testCase.ManifestJSON), 0700) err := utils.UpdateAssetsSubpath(testCase.Subpath) if testCase.ExpectedError != nil { require.Equal(t, testCase.ExpectedError, err) @@ -173,7 +172,7 @@ func TestUpdateAssetsSubpath(t *testing.T) { require.NoError(t, err) } - contents, err := ioutil.ReadFile(filepath.Join(tempDir, model.ClientDir, "root.html")) + contents, err := os.ReadFile(filepath.Join(tempDir, model.ClientDir, "root.html")) require.NoError(t, err) // Rewrite the expected and contents for simpler diffs when failed. @@ -181,11 +180,11 @@ func TestUpdateAssetsSubpath(t *testing.T) { contentsStr := strings.Replace(string(contents), ">", ">\n", -1) require.Equal(t, expectedRootHTML, contentsStr) - contents, err = ioutil.ReadFile(filepath.Join(tempDir, model.ClientDir, "main.css")) + contents, err = os.ReadFile(filepath.Join(tempDir, model.ClientDir, "main.css")) require.NoError(t, err) require.Equal(t, testCase.ExpectedMainCSS, string(contents)) - contents, err = ioutil.ReadFile(filepath.Join(tempDir, model.ClientDir, "manifest.json")) + contents, err = os.ReadFile(filepath.Join(tempDir, model.ClientDir, "manifest.json")) require.NoError(t, err) require.Equal(t, testCase.ExpectedManifestJSON, string(contents)) }) diff --git a/utils/test_files_compiler.go b/utils/test_files_compiler.go index 77ad84ce02..904cb4b6e9 100644 --- a/utils/test_files_compiler.go +++ b/utils/test_files_compiler.go @@ -5,7 +5,6 @@ package utils import ( "bytes" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -16,7 +15,7 @@ import ( ) func CompileGo(t *testing.T, sourceCode, outputPath string) { - dir, err := ioutil.TempDir(".", "") + dir, err := os.MkdirTemp(".", "") require.NoError(t, err) defer os.RemoveAll(dir) @@ -25,7 +24,7 @@ func CompileGo(t *testing.T, sourceCode, outputPath string) { // Write out main.go given the source code. main := filepath.Join(dir, "main.go") - err = ioutil.WriteFile(main, []byte(sourceCode), 0600) + err = os.WriteFile(main, []byte(sourceCode), 0600) require.NoError(t, err) _, sourceFile, _, ok := runtime.Caller(0) @@ -45,7 +44,7 @@ func CompileGo(t *testing.T, sourceCode, outputPath string) { } func CompileGoTest(t *testing.T, sourceCode, outputPath string) { - dir, err := ioutil.TempDir(".", "") + dir, err := os.MkdirTemp(".", "") require.NoError(t, err) defer os.RemoveAll(dir) @@ -54,7 +53,7 @@ func CompileGoTest(t *testing.T, sourceCode, outputPath string) { // Write out main.go given the source code. main := filepath.Join(dir, "main_test.go") - err = ioutil.WriteFile(main, []byte(sourceCode), 0600) + err = os.WriteFile(main, []byte(sourceCode), 0600) require.NoError(t, err) _, sourceFile, _, ok := runtime.Caller(0) diff --git a/utils/utils.go b/utils/utils.go index 9fad79e6d7..cf53e19f55 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -4,7 +4,7 @@ package utils import ( - "io/ioutil" + "io" "math" "net" "net/http" @@ -165,7 +165,7 @@ func GetURLWithCache(url string, cache *RequestCache, skip bool) ([]byte, error) return nil, errors.Errorf("Fetching notices failed with status code %d", resp.StatusCode) } - cache.Data, err = ioutil.ReadAll(resp.Body) + cache.Data, err = io.ReadAll(resp.Body) if err != nil { cache.Data = nil return nil, err diff --git a/web/context.go b/web/context.go index de02d18c03..fb9dd48169 100644 --- a/web/context.go +++ b/web/context.go @@ -241,8 +241,8 @@ func (c *Context) SetInvalidRemoteClusterTokenError() { c.Err = NewInvalidRemoteClusterTokenError() } -func (c *Context) SetJSONEncodingError() { - c.Err = NewJSONEncodingError() +func (c *Context) SetJSONEncodingError(err error) { + c.Err = NewJSONEncodingError(err) } func (c *Context) SetCommandNotFoundError() { @@ -294,9 +294,9 @@ func NewInvalidRemoteClusterTokenError() *model.AppError { return err } -func NewJSONEncodingError() *model.AppError { - err := model.NewAppError("Context", "api.context.json_encoding.app_error", nil, "", http.StatusInternalServerError) - return err +func NewJSONEncodingError(err error) *model.AppError { + appErr := model.NewAppError("Context", "api.context.json_encoding.app_error", nil, "", http.StatusInternalServerError).Wrap(err) + return appErr } func (c *Context) SetPermissionError(permissions ...*model.Permission) { diff --git a/web/oauth.go b/web/oauth.go index bee17266b0..2ed3a86f3c 100644 --- a/web/oauth.go +++ b/web/oauth.go @@ -48,7 +48,7 @@ func authorizeOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) { var authRequest *model.AuthorizeRequest err := json.NewDecoder(r.Body).Decode(&authRequest) if err != nil || authRequest == nil { - c.SetInvalidParam("authorize_request") + c.SetInvalidParamWithErr("authorize_request", err) return } @@ -241,7 +241,7 @@ func getAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { c.LogAudit("success") if err := json.NewEncoder(w).Encode(accessRsp); err != nil { - mlog.Warn("Error writing response", mlog.Err(err)) + c.Logger.Warn("Error writing response", mlog.Err(err)) } } diff --git a/web/oauth_test.go b/web/oauth_test.go index d8513d1579..1f8c610cc5 100644 --- a/web/oauth_test.go +++ b/web/oauth_test.go @@ -8,7 +8,6 @@ import ( "encoding/base64" "encoding/json" "io" - "io/ioutil" "net/http" "net/http/httptest" "net/url" @@ -636,7 +635,7 @@ func HTTPGet(url string, httpClient *http.Client, authToken string, followRedire func closeBody(r *http.Response) { if r != nil && r.Body != nil { - ioutil.ReadAll(r.Body) + io.ReadAll(r.Body) r.Body.Close() } } diff --git a/web/web_test.go b/web/web_test.go index 8c79c4cd33..d68abdf754 100644 --- a/web/web_test.go +++ b/web/web_test.go @@ -5,7 +5,6 @@ package web import ( "fmt" - "io/ioutil" "net/http" "net/http/httptest" "os" @@ -102,16 +101,17 @@ func setupTestHelper(tb testing.TB, includeCacheLayer bool) *TestHelper { } } + a := app.New(app.ServerConnector(s.Channels())) prevListenAddress := *s.Config().ServiceSettings.ListenAddress - s.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = ":0" }) + a.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = ":0" }) serverErr := s.Start() if serverErr != nil { panic(serverErr) } - s.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = prevListenAddress }) + a.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = prevListenAddress }) // Disable strict password requirements for test - s.UpdateConfig(func(cfg *model.Config) { + a.UpdateConfig(func(cfg *model.Config) { *cfg.PasswordSettings.MinimumLength = 5 *cfg.PasswordSettings.Lowercase = false *cfg.PasswordSettings.Uppercase = false @@ -119,15 +119,13 @@ func setupTestHelper(tb testing.TB, includeCacheLayer bool) *TestHelper { *cfg.PasswordSettings.Number = false }) - a := app.New(app.ServerConnector(s.Channels())) - web := New(s) URL = fmt.Sprintf("http://localhost:%v", s.ListenAddr.Port) apiClient = model.NewAPIv4Client(URL) s.Store.MarkSystemRanUnitTests() - s.UpdateConfig(func(cfg *model.Config) { + a.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableOpenServer = true }) @@ -219,12 +217,12 @@ func TestStaticFilesRequest(t *testing.T) { mainJS := `var x = alert();` mainJSPath := filepath.Join(pluginDir, "main.js") require.NoError(t, err) - err = ioutil.WriteFile(mainJSPath, []byte(mainJS), 0777) + err = os.WriteFile(mainJSPath, []byte(mainJS), 0777) require.NoError(t, err) // Write the plugin.json manifest pluginManifest := `{"id": "com.mattermost.sample", "server": {"executable": "backend.exe"}, "webapp": {"bundle_path":"main.js"}, "settings_schema": {"settings": []}}` - ioutil.WriteFile(filepath.Join(pluginDir, "plugin.json"), []byte(pluginManifest), 0600) + os.WriteFile(filepath.Join(pluginDir, "plugin.json"), []byte(pluginManifest), 0600) // Activate the plugin manifest, activated, reterr := th.App.GetPluginsEnvironment().Activate(pluginID) @@ -273,9 +271,9 @@ func TestPublicFilesRequest(t *testing.T) { th := Setup(t).InitPlugins() defer th.TearDown() - pluginDir, err := ioutil.TempDir("", "") + pluginDir, err := os.MkdirTemp("", "") require.NoError(t, err) - webappPluginDir, err := ioutil.TempDir("", "") + webappPluginDir, err := os.MkdirTemp("", "") require.NoError(t, err) defer os.RemoveAll(pluginDir) defer os.RemoveAll(webappPluginDir) @@ -307,7 +305,7 @@ func TestPublicFilesRequest(t *testing.T) { // Write the plugin.json manifest pluginManifest := `{"id": "com.mattermost.sample", "server": {"executable": "backend.exe"}, "settings_schema": {"settings": []}}` - ioutil.WriteFile(filepath.Join(pluginDir, pluginID, "plugin.json"), []byte(pluginManifest), 0600) + os.WriteFile(filepath.Join(pluginDir, pluginID, "plugin.json"), []byte(pluginManifest), 0600) // Write the test public file helloHTML := `Hello from the static files public folder for the com.mattermost.sample plugin!` @@ -315,11 +313,11 @@ func TestPublicFilesRequest(t *testing.T) { os.MkdirAll(htmlFolderPath, os.ModePerm) htmlFilePath := filepath.Join(htmlFolderPath, "hello.html") - htmlFileErr := ioutil.WriteFile(htmlFilePath, []byte(helloHTML), 0600) + htmlFileErr := os.WriteFile(htmlFilePath, []byte(helloHTML), 0600) assert.NoError(t, htmlFileErr) nefariousHTML := `You shouldn't be able to get here!` - htmlFileErr = ioutil.WriteFile(filepath.Join(pluginDir, pluginID, "nefarious-file-access.html"), []byte(nefariousHTML), 0600) + htmlFileErr = os.WriteFile(filepath.Join(pluginDir, pluginID, "nefarious-file-access.html"), []byte(nefariousHTML), 0600) assert.NoError(t, htmlFileErr) manifest, activated, reterr := env.Activate(pluginID) diff --git a/web/webhook.go b/web/webhook.go index 858a551b5d..a54e72e301 100644 --- a/web/webhook.go +++ b/web/webhook.go @@ -50,8 +50,15 @@ func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) { defer func() { if *c.App.Config().LogSettings.EnableWebhookDebugging { if c.Err != nil { - payload, _ := json.Marshal(incomingWebhookPayload) - mlog.Debug("Incoming webhook received", mlog.String("webhook_id", id), mlog.String("request_id", c.AppContext.RequestId()), mlog.String("payload", string(payload))) + fields := []mlog.Field{mlog.String("webhook_id", id), mlog.String("request_id", c.AppContext.RequestId())} + payload, err := json.Marshal(incomingWebhookPayload) + if err != nil { + fields = append(fields, mlog.NamedErr("encoding_err", err)) + } else { + fields = append(fields, mlog.String("payload", string(payload))) + } + + mlog.Debug("Incoming webhook received", fields...) } } }()