From 14246abdef4ae7a5ea18cb2362361b2537c8b01e Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Fri, 5 Aug 2022 08:49:01 +0530 Subject: [PATCH] MM-45993: Return errors during sending websocket messages (#20760) During attaching an object to a websocket message, we would marshal it to json and attach the string output. But if the marshalling failed, we would just log a warning and move on. This would add an empty string to the message. But the client assumes that the object is correctly attached and would fail silently if it cannot find it. So we become more strict and return the error so that it reaches the caller. https://mattermost.atlassian.net/browse/MM-45993 ```release-note NONE ``` --- app/app_iface.go | 14 ++-- app/channel.go | 23 ++--- app/channel_category.go | 2 +- app/channel_test.go | 2 +- app/emoji.go | 2 +- app/group.go | 30 ++++--- app/opentracing/opentracing_layer.go | 32 +++++-- app/post.go | 2 +- app/preference.go | 5 +- app/role.go | 20 +++-- app/slashcommands/command_expand_collapse.go | 5 +- app/syncables.go | 32 +++---- app/team.go | 88 +++++++++++++------- app/team_test.go | 2 +- app/user.go | 7 +- i18n/en.json | 4 + 16 files changed, 166 insertions(+), 104 deletions(-) diff --git a/app/app_iface.go b/app/app_iface.go index 384f3f95a3..f2466ad4c2 100644 --- a/app/app_iface.go +++ b/app/app_iface.go @@ -328,7 +328,7 @@ type AppIface interface { SyncPlugins() *model.AppError // SyncRolesAndMembership updates the SchemeAdmin status and membership of all of the members of the given // syncable. - SyncRolesAndMembership(c *request.Context, syncableID string, syncableType model.GroupSyncableType, includeRemovedMembers bool) + SyncRolesAndMembership(c request.CTX, syncableID string, syncableType model.GroupSyncableType, includeRemovedMembers bool) // SyncSyncableRoles updates the SchemeAdmin field value of the given syncable's members based on the configuration of // the member's group memberships and the configuration of those groups to the syncable. This method should only // be invoked on group-synced (aka group-constrained) syncables. @@ -402,12 +402,12 @@ type AppIface interface { AddSessionToCache(session *model.Session) AddStatusCache(status *model.Status) AddStatusCacheSkipClusterSend(status *model.Status) - AddTeamMember(c *request.Context, teamID, userID string) (*model.TeamMember, *model.AppError) + AddTeamMember(c request.CTX, teamID, userID string) (*model.TeamMember, *model.AppError) AddTeamMemberByInviteId(c *request.Context, inviteId, userID string) (*model.TeamMember, *model.AppError) AddTeamMemberByToken(c *request.Context, userID, tokenID string) (*model.TeamMember, *model.AppError) AddTeamMembers(c *request.Context, teamID string, userIDs []string, userRequestorId string, graceful bool) ([]*model.TeamMemberWithError, *model.AppError) AddTeamsToRetentionPolicy(policyID string, teamIDs []string) *model.AppError - AddUserToTeam(c *request.Context, teamID string, userID string, userRequestorId string) (*model.Team, *model.TeamMember, *model.AppError) + AddUserToTeam(c request.CTX, teamID string, userID string, userRequestorId string) (*model.Team, *model.TeamMember, *model.AppError) AddUserToTeamByInviteId(c *request.Context, inviteId string, userID string) (*model.Team, *model.TeamMember, *model.AppError) AddUserToTeamByTeamId(c *request.Context, teamID string, user *model.User) *model.AppError AddUserToTeamByToken(c *request.Context, userID string, tokenID string) (*model.Team, *model.TeamMember, *model.AppError) @@ -449,13 +449,13 @@ type AppIface interface { CheckUserPostflightAuthenticationCriteria(user *model.User) *model.AppError CheckUserPreflightAuthenticationCriteria(user *model.User, mfaToken string) *model.AppError CheckWebConn(userID, connectionID string) *CheckConnResult - ClearChannelMembersCache(c request.CTX, channelID string) + ClearChannelMembersCache(c request.CTX, channelID string) error ClearLatestVersionCache() ClearSessionCacheForAllUsers() ClearSessionCacheForAllUsersSkipClusterSend() ClearSessionCacheForUser(userID string) ClearSessionCacheForUserSkipClusterSend(userID string) - ClearTeamMembersCache(teamID string) + ClearTeamMembersCache(teamID string) error ClientConfig() map[string]string ClientConfigHash() string Cloud() einterfaces.CloudInterface @@ -873,7 +873,7 @@ type AppIface interface { JoinUserToTeam(c request.CTX, team *model.Team, user *model.User, userRequestorId string) (*model.TeamMember, *model.AppError) Ldap() einterfaces.LdapInterface LeaveChannel(c request.CTX, channelID string, userID string) *model.AppError - LeaveTeam(c *request.Context, team *model.Team, user *model.User, requestorId string) *model.AppError + LeaveTeam(c request.CTX, team *model.Team, user *model.User, requestorId string) *model.AppError License() *model.License LimitedClientConfig() map[string]string ListAllCommands(teamID string, T i18n.TranslateFunc) ([]*model.Command, *model.AppError) @@ -954,7 +954,7 @@ type AppIface interface { RemoveTeamIcon(teamID string) *model.AppError RemoveTeamsFromRetentionPolicy(policyID string, teamIDs []string) *model.AppError RemoveUserFromChannel(c request.CTX, userIDToRemove string, removerUserId string, channel *model.Channel) *model.AppError - RemoveUserFromTeam(c *request.Context, teamID string, userID string, requestorId string) *model.AppError + RemoveUserFromTeam(c request.CTX, teamID string, userID string, requestorId string) *model.AppError RemoveUsersFromChannelNotMemberOfTeam(c request.CTX, remover *model.User, channel *model.Channel, team *model.Team) *model.AppError RequestLicenseAndAckWarnMetric(c *request.Context, warnMetricId string, isBot bool) *model.AppError ResetPasswordFromToken(c request.CTX, userSuppliedTokenString, newPassword string) *model.AppError diff --git a/app/channel.go b/app/channel.go index 860b44f125..e5f0c7aefc 100644 --- a/app/channel.go +++ b/app/channel.go @@ -654,7 +654,7 @@ func (a *App) UpdateChannel(c request.CTX, channel *model.Channel) (*model.Chann messageWs := model.NewWebSocketEvent(model.WebsocketEventChannelUpdated, "", channel.Id, "", nil) channelJSON, jsonErr := json.Marshal(channel) if jsonErr != nil { - c.Logger().Warn("Failed to encode channel to JSON", mlog.Err(jsonErr)) + return nil, model.NewAppError("UpdateChannel", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr) } messageWs.Add("channel", string(channelJSON)) a.Publish(messageWs) @@ -1012,7 +1012,9 @@ func (a *App) PatchChannelModerationsForChannel(c request.CTX, channel *model.Ch if err != nil { return nil, err } - a.sendUpdatedRoleEvent(adminRole) + if appErr := a.sendUpdatedRoleEvent(adminRole); appErr != nil { + return nil, appErr + } message := model.NewWebSocketEvent(model.WebsocketEventChannelSchemeUpdated, "", channel.Id, "", nil) a.Publish(message) @@ -1278,7 +1280,7 @@ func (a *App) UpdateChannelMemberNotifyProps(c request.CTX, data map[string]stri evt := model.NewWebSocketEvent(model.WebsocketEventChannelMemberUpdated, "", "", member.UserId, nil) memberJSON, jsonErr := json.Marshal(member) if jsonErr != nil { - c.Logger().Warn("Failed to encode channel member to JSON", mlog.Err(jsonErr)) + return nil, model.NewAppError("UpdateChannelMemberNotifyProps", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr) } evt.Add("channelMember", string(memberJSON)) a.Publish(evt) @@ -1307,7 +1309,7 @@ func (a *App) updateChannelMember(c request.CTX, member *model.ChannelMember) (* evt := model.NewWebSocketEvent(model.WebsocketEventChannelMemberUpdated, "", "", member.UserId, nil) memberJSON, jsonErr := json.Marshal(member) if jsonErr != nil { - c.Logger().Warn("Failed to encode channel member to JSON", mlog.Err(jsonErr)) + return nil, model.NewAppError("updateChannelMember", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr) } evt.Add("channelMember", string(memberJSON)) a.Publish(evt) @@ -1580,7 +1582,7 @@ func (a *App) AddChannelMember(c request.CTX, userID string, channel *model.Chan if opts.UserRequestorID == "" || userID == opts.UserRequestorID { if err := a.postJoinChannelMessage(c, user, channel); err != nil { - mlog.Error("Failed to post join channel message", mlog.Err(err)) + return nil, err } } else { a.Srv().Go(func() { @@ -2692,7 +2694,7 @@ func (a *App) markChannelAsUnreadFromPostCRTUnsupported(c request.CTX, postID st if a.IsCRTEnabledForUser(c, userID) { payload, jsonErr := json.Marshal(thread) if jsonErr != nil { - c.Logger().Warn("Failed to encode thread to JSON") + return nil, model.NewAppError("MarkChannelAsUnreadFromPost", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr) } message := model.NewWebSocketEvent(model.WebsocketEventThreadUpdated, channel.TeamId, "", userID, nil) message.Add("thread", string(payload)) @@ -3259,7 +3261,7 @@ func (a *App) setChannelsMuted(c request.CTX, channelIDs []string, userID string memberJSON, jsonErr := json.Marshal(member) if jsonErr != nil { - c.Logger().Warn("Failed to encode channel member to JSON", mlog.Err(jsonErr)) + return nil, model.NewAppError("setChannelsMuted", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr) } evt.Add("channelMember", string(memberJSON)) @@ -3360,21 +3362,22 @@ func (a *App) forEachChannelMember(c request.CTX, channelID string, f func(model return nil } -func (a *App) ClearChannelMembersCache(c request.CTX, channelID string) { +func (a *App) ClearChannelMembersCache(c request.CTX, channelID string) error { clearSessionCache := func(channelMember model.ChannelMember) error { a.ClearSessionCacheForUser(channelMember.UserId) message := model.NewWebSocketEvent(model.WebsocketEventChannelMemberUpdated, "", "", channelMember.UserId, nil) memberJSON, jsonErr := json.Marshal(channelMember) if jsonErr != nil { - c.Logger().Warn("Failed to encode channel member to JSON", mlog.Err(jsonErr)) + return jsonErr } message.Add("channelMember", string(memberJSON)) a.Publish(message) return nil } if err := a.forEachChannelMember(c, channelID, clearSessionCache); err != nil { - c.Logger().Warn("error clearing cache for channel members", mlog.String("channel_id", channelID)) + return fmt.Errorf("error clearing cache for channel members: channel_id: %s, error: %v", channelID, err) } + return nil } func (a *App) GetMemberCountsByGroup(ctx context.Context, channelID string, includeTimezones bool) ([]*model.ChannelMemberCountByGroup, *model.AppError) { diff --git a/app/channel_category.go b/app/channel_category.go index 4cba5b9b17..ff7ef067d8 100644 --- a/app/channel_category.go +++ b/app/channel_category.go @@ -151,7 +151,7 @@ func (a *App) UpdateSidebarCategories(c request.CTX, userID, teamID string, cate updatedCategoriesJSON, jsonErr := json.Marshal(updatedCategories) if jsonErr != nil { - c.Logger().Warn("Failed to encode original categories to JSON", mlog.Err(jsonErr)) + return nil, model.NewAppError("UpdateSidebarCategories", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr) } message.Add("updatedCategories", string(updatedCategoriesJSON)) diff --git a/app/channel_test.go b/app/channel_test.go index 2d5a9b559d..459423ab29 100644 --- a/app/channel_test.go +++ b/app/channel_test.go @@ -2092,7 +2092,7 @@ func TestClearChannelMembersCache(t *testing.T) { mockStore.On("Channel").Return(&mockChannelStore) mockStore.On("GetDBSchemaVersion").Return(1, nil) - th.App.ClearChannelMembersCache(th.Context, "channelID") + require.NoError(t, th.App.ClearChannelMembersCache(th.Context, "channelID")) } func TestGetMemberCountsByGroup(t *testing.T) { diff --git a/app/emoji.go b/app/emoji.go index 14f58d9128..496868dff3 100644 --- a/app/emoji.go +++ b/app/emoji.go @@ -82,7 +82,7 @@ func (a *App) CreateEmoji(sessionUserId string, emoji *model.Emoji, multiPartIma message := model.NewWebSocketEvent(model.WebsocketEventEmojiAdded, "", "", "", nil) emojiJSON, jsonErr := json.Marshal(emoji) if jsonErr != nil { - mlog.Warn("Failed to encode emoji to JSON", mlog.Err(jsonErr)) + return nil, model.NewAppError("CreateEmoji", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr) } message.Add("emoji", string(emojiJSON)) a.Publish(message) diff --git a/app/group.go b/app/group.go index b00a017fa3..686c2d6c0c 100644 --- a/app/group.go +++ b/app/group.go @@ -9,7 +9,6 @@ import ( "net/http" "github.com/mattermost/mattermost-server/v6/model" - "github.com/mattermost/mattermost-server/v6/shared/mlog" "github.com/mattermost/mattermost-server/v6/store" ) @@ -139,7 +138,7 @@ func (a *App) CreateGroupWithUserIds(group *model.GroupWithUserIds) (*model.Grou case errors.As(err, &invErr): return nil, model.NewAppError("CreateGroupWithUserIds", "app.group.id.app_error", nil, invErr.Error(), http.StatusBadRequest) case errors.As(err, &dupKey): - return nil, model.NewAppError("CreateGroup", "app.custom_group.unique_name", nil, dupKey.Error(), http.StatusBadRequest) + return nil, model.NewAppError("CreateGroupWithUserIds", "app.custom_group.unique_name", nil, dupKey.Error(), http.StatusBadRequest) default: return nil, model.NewAppError("CreateGroupWithUserIds", "app.insert_error", nil, err.Error(), http.StatusInternalServerError) } @@ -153,7 +152,7 @@ func (a *App) CreateGroupWithUserIds(group *model.GroupWithUserIds) (*model.Grou group.MemberCount = model.NewInt(int(count)) groupJSON, jsonErr := json.Marshal(newGroup) if jsonErr != nil { - mlog.Warn("Failed to encode group to JSON", mlog.Err(jsonErr)) + return nil, model.NewAppError("CreateGroupWithUserIds", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr) } messageWs.Add("group", string(groupJSON)) a.Publish(messageWs) @@ -172,13 +171,13 @@ func (a *App) UpdateGroup(group *model.Group) (*model.Group, *model.AppError) { if err == nil { count, countErr := a.Srv().Store.Group().GetMemberCount(updatedGroup.Id) if countErr != nil { - return nil, model.NewAppError("CreateGroupWithUserIds", "app.group.id.app_error", nil, countErr.Error(), http.StatusBadRequest) + 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 { - mlog.Warn("Failed to encode group to JSON", mlog.Err(jsonErr)) + return nil, model.NewAppError("UpdateGroup", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr) } messageWs.Add("group", string(groupJSON)) a.Publish(messageWs) @@ -272,7 +271,9 @@ func (a *App) UpsertGroupMember(groupID string, userID string) (*model.GroupMemb } } - a.publishGroupMemberEvent(model.WebsocketEventGroupMemberAdd, groupMember) + if appErr := a.publishGroupMemberEvent(model.WebsocketEventGroupMemberAdd, groupMember); appErr != nil { + return nil, appErr + } return groupMember, nil } @@ -289,7 +290,9 @@ func (a *App) DeleteGroupMember(groupID string, userID string) (*model.GroupMemb } } - a.publishGroupMemberEvent(model.WebsocketEventGroupMemberDelete, groupMember) + if appErr := a.publishGroupMemberEvent(model.WebsocketEventGroupMemberDelete, groupMember); appErr != nil { + return nil, appErr + } return groupMember, nil } @@ -743,7 +746,9 @@ func (a *App) UpsertGroupMembers(groupID string, userIDs []string) ([]*model.Gro } for _, groupMember := range members { - a.publishGroupMemberEvent(model.WebsocketEventGroupMemberAdd, groupMember) + if appErr := a.publishGroupMemberEvent(model.WebsocketEventGroupMemberAdd, groupMember); appErr != nil { + return nil, appErr + } } return members, nil @@ -765,18 +770,21 @@ func (a *App) DeleteGroupMembers(groupID string, userIDs []string) ([]*model.Gro } for _, groupMember := range members { - a.publishGroupMemberEvent(model.WebsocketEventGroupMemberDelete, groupMember) + if appErr := a.publishGroupMemberEvent(model.WebsocketEventGroupMemberDelete, groupMember); appErr != nil { + return nil, appErr + } } return members, nil } -func (a *App) publishGroupMemberEvent(eventName string, groupMember *model.GroupMember) { +func (a *App) publishGroupMemberEvent(eventName string, groupMember *model.GroupMember) *model.AppError { messageWs := model.NewWebSocketEvent(eventName, "", "", groupMember.UserId, nil) groupMemberJSON, jsonErr := json.Marshal(groupMember) if jsonErr != nil { - mlog.Warn("failed to encode group member to JSON", mlog.Err(jsonErr)) + return model.NewAppError("publishGroupMemberEvent", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr) } messageWs.Add("group_member", string(groupMemberJSON)) a.Publish(messageWs) + return nil } diff --git a/app/opentracing/opentracing_layer.go b/app/opentracing/opentracing_layer.go index 71ae068d0c..9b071c3ccc 100644 --- a/app/opentracing/opentracing_layer.go +++ b/app/opentracing/opentracing_layer.go @@ -383,7 +383,7 @@ func (a *OpenTracingAppLayer) AddStatusCacheSkipClusterSend(status *model.Status a.app.AddStatusCacheSkipClusterSend(status) } -func (a *OpenTracingAppLayer) AddTeamMember(c *request.Context, teamID string, userID string) (*model.TeamMember, *model.AppError) { +func (a *OpenTracingAppLayer) AddTeamMember(c request.CTX, teamID string, userID string) (*model.TeamMember, *model.AppError) { origCtx := a.ctx span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.AddTeamMember") @@ -515,7 +515,7 @@ func (a *OpenTracingAppLayer) AddUserToChannel(c request.CTX, user *model.User, return resultVar0, resultVar1 } -func (a *OpenTracingAppLayer) AddUserToTeam(c *request.Context, teamID string, userID string, userRequestorId string) (*model.Team, *model.TeamMember, *model.AppError) { +func (a *OpenTracingAppLayer) AddUserToTeam(c request.CTX, teamID string, userID string, userRequestorId string) (*model.Team, *model.TeamMember, *model.AppError) { origCtx := a.ctx span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.AddUserToTeam") @@ -1469,7 +1469,7 @@ func (a *OpenTracingAppLayer) CheckWebConn(userID string, connectionID string) * return resultVar0 } -func (a *OpenTracingAppLayer) ClearChannelMembersCache(c request.CTX, channelID string) { +func (a *OpenTracingAppLayer) ClearChannelMembersCache(c request.CTX, channelID string) error { origCtx := a.ctx span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.ClearChannelMembersCache") @@ -1481,7 +1481,14 @@ func (a *OpenTracingAppLayer) ClearChannelMembersCache(c request.CTX, channelID }() defer span.Finish() - a.app.ClearChannelMembersCache(c, channelID) + resultVar0 := a.app.ClearChannelMembersCache(c, channelID) + + if resultVar0 != nil { + span.LogFields(spanlog.Error(resultVar0)) + ext.Error.Set(span, true) + } + + return resultVar0 } func (a *OpenTracingAppLayer) ClearLatestVersionCache() { @@ -1559,7 +1566,7 @@ func (a *OpenTracingAppLayer) ClearSessionCacheForUserSkipClusterSend(userID str a.app.ClearSessionCacheForUserSkipClusterSend(userID) } -func (a *OpenTracingAppLayer) ClearTeamMembersCache(teamID string) { +func (a *OpenTracingAppLayer) ClearTeamMembersCache(teamID string) error { origCtx := a.ctx span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.ClearTeamMembersCache") @@ -1571,7 +1578,14 @@ func (a *OpenTracingAppLayer) ClearTeamMembersCache(teamID string) { }() defer span.Finish() - a.app.ClearTeamMembersCache(teamID) + resultVar0 := a.app.ClearTeamMembersCache(teamID) + + if resultVar0 != nil { + span.LogFields(spanlog.Error(resultVar0)) + ext.Error.Set(span, true) + } + + return resultVar0 } func (a *OpenTracingAppLayer) ClientConfig() map[string]string { @@ -11731,7 +11745,7 @@ func (a *OpenTracingAppLayer) LeaveChannel(c request.CTX, channelID string, user return resultVar0 } -func (a *OpenTracingAppLayer) LeaveTeam(c *request.Context, team *model.Team, user *model.User, requestorId string) *model.AppError { +func (a *OpenTracingAppLayer) LeaveTeam(c request.CTX, team *model.Team, user *model.User, requestorId string) *model.AppError { origCtx := a.ctx span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.LeaveTeam") @@ -13686,7 +13700,7 @@ func (a *OpenTracingAppLayer) RemoveUserFromChannel(c request.CTX, userIDToRemov return resultVar0 } -func (a *OpenTracingAppLayer) RemoveUserFromTeam(c *request.Context, teamID string, userID string, requestorId string) *model.AppError { +func (a *OpenTracingAppLayer) RemoveUserFromTeam(c request.CTX, teamID string, userID string, requestorId string) *model.AppError { origCtx := a.ctx span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.RemoveUserFromTeam") @@ -16153,7 +16167,7 @@ func (a *OpenTracingAppLayer) SyncPlugins() *model.AppError { return resultVar0 } -func (a *OpenTracingAppLayer) SyncRolesAndMembership(c *request.Context, syncableID string, syncableType model.GroupSyncableType, includeRemovedMembers bool) { +func (a *OpenTracingAppLayer) SyncRolesAndMembership(c request.CTX, syncableID string, syncableType model.GroupSyncableType, includeRemovedMembers bool) { origCtx := a.ctx span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SyncRolesAndMembership") diff --git a/app/post.go b/app/post.go index 716b821984..b537e43417 100644 --- a/app/post.go +++ b/app/post.go @@ -1251,7 +1251,7 @@ func (a *App) DeletePost(c request.CTX, postID, deleteByID string) (*model.Post, postJSON, jsonErr := json.Marshal(post) if jsonErr != nil { - mlog.Warn("Failed to encode post to JSON") + return nil, model.NewAppError("DeletePost", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr) } userMessage := model.NewWebSocketEvent(model.WebsocketEventPostDeleted, "", post.ChannelId, "", nil) diff --git a/app/preference.go b/app/preference.go index 23df83426c..843976d122 100644 --- a/app/preference.go +++ b/app/preference.go @@ -9,7 +9,6 @@ import ( "net/http" "github.com/mattermost/mattermost-server/v6/model" - "github.com/mattermost/mattermost-server/v6/shared/mlog" ) func (a *App) GetPreferencesForUser(userID string) (model.Preferences, *model.AppError) { @@ -69,7 +68,7 @@ func (a *App) UpdatePreferences(userID string, preferences model.Preferences) *m message = model.NewWebSocketEvent(model.WebsocketEventPreferencesChanged, "", "", userID, nil) prefsJSON, jsonErr := json.Marshal(preferences) if jsonErr != nil { - mlog.Warn("Failed to encode to JSON", mlog.Err(jsonErr)) + return model.NewAppError("UpdatePreferences", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr) } message.Add("preferences", string(prefsJSON)) a.Publish(message) @@ -103,7 +102,7 @@ func (a *App) DeletePreferences(userID string, preferences model.Preferences) *m message = model.NewWebSocketEvent(model.WebsocketEventPreferencesDeleted, "", "", userID, nil) prefsJSON, jsonErr := json.Marshal(preferences) if jsonErr != nil { - mlog.Warn("Failed to encode to JSON", mlog.Err(jsonErr)) + return model.NewAppError("DeletePreferences", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr) } message.Add("preferences", string(prefsJSON)) a.Publish(message) diff --git a/app/role.go b/app/role.go index 846d9d83f7..d0b946acf7 100644 --- a/app/role.go +++ b/app/role.go @@ -12,7 +12,6 @@ import ( "strings" "github.com/mattermost/mattermost-server/v6/model" - "github.com/mattermost/mattermost-server/v6/shared/mlog" "github.com/mattermost/mattermost-server/v6/store" "github.com/mattermost/mattermost-server/v6/utils" ) @@ -138,7 +137,9 @@ func (a *App) PatchRole(role *model.Role, patch *model.RolePatch) (*model.Role, return nil, err } - a.sendUpdatedRoleEvent(role) + if appErr := a.sendUpdatedRoleEvent(role); appErr != nil { + return nil, appErr + } return role, err } @@ -225,7 +226,10 @@ func (a *App) UpdateRole(role *model.Role) (*model.Role, *model.AppError) { for _, ir := range impactedRoles { if ir.Name != role.Name { - a.sendUpdatedRoleEvent(ir) + appErr = a.sendUpdatedRoleEvent(ir) + if appErr != nil { + return nil, appErr + } } } @@ -254,17 +258,15 @@ func (a *App) CheckRolesExist(roleNames []string) *model.AppError { return nil } -func (a *App) sendUpdatedRoleEvent(role *model.Role) { +func (a *App) sendUpdatedRoleEvent(role *model.Role) *model.AppError { message := model.NewWebSocketEvent(model.WebsocketEventRoleUpdated, "", "", "", nil) roleJSON, jsonErr := json.Marshal(role) if jsonErr != nil { - mlog.Warn("Failed to encode role to JSON", mlog.Err(jsonErr)) + return model.NewAppError("sendUpdatedRoleEvent", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr) } message.Add("role", string(roleJSON)) - - a.Srv().Go(func() { - a.Publish(message) - }) + a.Publish(message) + return nil } func RemoveRoles(rolesToRemove []string, roles string) string { diff --git a/app/slashcommands/command_expand_collapse.go b/app/slashcommands/command_expand_collapse.go index ecfc832251..e9c6414d95 100644 --- a/app/slashcommands/command_expand_collapse.go +++ b/app/slashcommands/command_expand_collapse.go @@ -11,7 +11,6 @@ import ( "github.com/mattermost/mattermost-server/v6/app/request" "github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/mattermost-server/v6/shared/i18n" - "github.com/mattermost/mattermost-server/v6/shared/mlog" ) type ExpandProvider struct { @@ -73,14 +72,14 @@ func setCollapsePreference(a *app.App, args *model.CommandArgs, isCollapse bool) } if err := a.Srv().Store.Preference().Save(model.Preferences{pref}); err != nil { - return &model.CommandResponse{Text: args.T("api.command_expand_collapse.fail.app_error"), ResponseType: model.CommandResponseTypeEphemeral} + return &model.CommandResponse{Text: args.T("api.command_expand_collapse.fail.app_error") + err.Error(), ResponseType: model.CommandResponseTypeEphemeral} } socketMessage := model.NewWebSocketEvent(model.WebsocketEventPreferenceChanged, "", "", args.UserId, nil) prefJSON, jsonErr := json.Marshal(pref) if jsonErr != nil { - mlog.Warn("Failed to encode to JSON", mlog.Err(jsonErr)) + return &model.CommandResponse{Text: args.T("api.marshal_error") + jsonErr.Error(), ResponseType: model.CommandResponseTypeEphemeral} } socketMessage.Add("preference", string(prefJSON)) a.Publish(socketMessage) diff --git a/app/syncables.go b/app/syncables.go index 4362991713..8b0b4cdc43 100644 --- a/app/syncables.go +++ b/app/syncables.go @@ -18,7 +18,7 @@ import ( // only that channel's members are created. If channelID is nil all channel memberships are created. // If includeRemovedMembers is true, then channel members who left or were removed from the channel will // be re-added; otherwise, they will not be re-added. -func (a *App) createDefaultChannelMemberships(c *request.Context, since int64, channelID *string, includeRemovedMembers bool) error { +func (a *App) createDefaultChannelMemberships(c request.CTX, since int64, channelID *string, includeRemovedMembers bool) error { channelMembers, appErr := a.ChannelMembersToAdd(since, channelID, includeRemovedMembers) if appErr != nil { return appErr @@ -40,7 +40,7 @@ func (a *App) createDefaultChannelMemberships(c *request.Context, since int64, c _, err = a.AddTeamMember(c, channel.TeamId, userChannel.UserID) if err != nil { if err.Id == "api.team.join_user_to_team.allowed_domains.app_error" { - a.Log().Info("User not added to channel - the domain associated with the user is not in the list of allowed team domains", + c.Logger().Info("User not added to channel - the domain associated with the user is not in the list of allowed team domains", mlog.String("user_id", userChannel.UserID), mlog.String("channel_id", userChannel.ChannelID), mlog.String("team_id", channel.TeamId), @@ -49,7 +49,7 @@ func (a *App) createDefaultChannelMemberships(c *request.Context, since int64, c } return err } - a.Log().Info("added teammember", + c.Logger().Info("added teammember", mlog.String("user_id", userChannel.UserID), mlog.String("team_id", channel.TeamId), ) @@ -60,7 +60,7 @@ func (a *App) createDefaultChannelMemberships(c *request.Context, since int64, c }) if err != nil { if err.Id == "api.channel.add_user.to.channel.failed.deleted.app_error" { - a.Log().Info("Not adding user to channel because they have already left the team", + c.Logger().Info("Not adding user to channel because they have already left the team", mlog.String("user_id", userChannel.UserID), mlog.String("channel_id", userChannel.ChannelID), ) @@ -69,7 +69,7 @@ func (a *App) createDefaultChannelMemberships(c *request.Context, since int64, c } } - a.Log().Info("added channelmember", + c.Logger().Info("added channelmember", mlog.String("user_id", userChannel.UserID), mlog.String("channel_id", userChannel.ChannelID), ) @@ -83,7 +83,7 @@ func (a *App) createDefaultChannelMemberships(c *request.Context, since int64, c // only that team's members are created. If teamID is nil all team memberships are created. // If includeRemovedMembers is true, then team members who left or were removed from the team will // be re-added; otherwise, they will not be re-added. -func (a *App) createDefaultTeamMemberships(c *request.Context, since int64, teamID *string, includeRemovedMembers bool) error { +func (a *App) createDefaultTeamMemberships(c request.CTX, since int64, teamID *string, includeRemovedMembers bool) error { teamMembers, appErr := a.TeamMembersToAdd(since, teamID, includeRemovedMembers) if appErr != nil { return appErr @@ -93,7 +93,7 @@ func (a *App) createDefaultTeamMemberships(c *request.Context, since int64, team _, err := a.AddTeamMember(c, userTeam.TeamID, userTeam.UserID) if err != nil { if err.Id == "api.team.join_user_to_team.allowed_domains.app_error" { - a.Log().Info("User not added to team - the domain associated with the user is not in the list of allowed team domains", + c.Logger().Info("User not added to team - the domain associated with the user is not in the list of allowed team domains", mlog.String("user_id", userTeam.UserID), mlog.String("team_id", userTeam.TeamID), ) @@ -102,7 +102,7 @@ func (a *App) createDefaultTeamMemberships(c *request.Context, since int64, team return err } - a.Log().Info("added teammember", + c.Logger().Info("added teammember", mlog.String("user_id", userTeam.UserID), mlog.String("team_id", userTeam.TeamID), ) @@ -148,7 +148,7 @@ func (a *App) DeleteGroupConstrainedMemberships(c *request.Context) error { // deleteGroupConstrainedTeamMemberships deletes team memberships of users who aren't members of the allowed // groups of the given group-constrained team. If a teamID is given then the procedure is scoped to the given team, // if teamID is nil then the procedure affects all teams. -func (a *App) deleteGroupConstrainedTeamMemberships(c *request.Context, teamID *string) error { +func (a *App) deleteGroupConstrainedTeamMemberships(c request.CTX, teamID *string) error { teamMembers, appErr := a.TeamMembersToRemove(teamID) if appErr != nil { return appErr @@ -160,7 +160,7 @@ func (a *App) deleteGroupConstrainedTeamMemberships(c *request.Context, teamID * return err } - a.Log().Info("removed teammember", + c.Logger().Info("removed teammember", mlog.String("user_id", userTeam.UserId), mlog.String("team_id", userTeam.TeamId), ) @@ -172,7 +172,7 @@ func (a *App) deleteGroupConstrainedTeamMemberships(c *request.Context, teamID * // deleteGroupConstrainedChannelMemberships deletes channel memberships of users who aren't members of the allowed // groups of the given group-constrained channel. If a channelID is given then the procedure is scoped to the given team, // if channelID is nil then the procedure affects all teams. -func (a *App) deleteGroupConstrainedChannelMemberships(c *request.Context, channelID *string) error { +func (a *App) deleteGroupConstrainedChannelMemberships(c request.CTX, channelID *string) error { channelMembers, appErr := a.ChannelMembersToRemove(channelID) if appErr != nil { return appErr @@ -233,7 +233,7 @@ func (a *App) SyncSyncableRoles(syncableID string, syncableType model.GroupSynca // SyncRolesAndMembership updates the SchemeAdmin status and membership of all of the members of the given // syncable. -func (a *App) SyncRolesAndMembership(c *request.Context, syncableID string, syncableType model.GroupSyncableType, includeRemovedMembers bool) { +func (a *App) SyncRolesAndMembership(c request.CTX, syncableID string, syncableType model.GroupSyncableType, includeRemovedMembers bool) { a.SyncSyncableRoles(syncableID, syncableType) lastJob, _ := a.Srv().Store.Job().GetNewestJobByStatusAndType(model.JobStatusSuccess, model.JobTypeLdapSync) @@ -246,10 +246,14 @@ func (a *App) SyncRolesAndMembership(c *request.Context, syncableID string, sync case model.GroupSyncableTypeTeam: a.createDefaultTeamMemberships(c, since, &syncableID, includeRemovedMembers) a.deleteGroupConstrainedTeamMemberships(c, &syncableID) - a.ClearTeamMembersCache(syncableID) + if err := a.ClearTeamMembersCache(syncableID); err != nil { + c.Logger().Warn("Error clearing team members cache", mlog.Err(err)) + } case model.GroupSyncableTypeChannel: a.createDefaultChannelMemberships(c, since, &syncableID, includeRemovedMembers) a.deleteGroupConstrainedChannelMemberships(c, &syncableID) - a.ClearChannelMembersCache(c, syncableID) + if err := a.ClearChannelMembersCache(c, syncableID); err != nil { + c.Logger().Warn("Error clearing channel members cache", mlog.Err(err)) + } } } diff --git a/app/team.go b/app/team.go index 6240f4b932..bf9425c145 100644 --- a/app/team.go +++ b/app/team.go @@ -231,7 +231,9 @@ func (a *App) UpdateTeam(team *model.Team) (*model.Team, *model.AppError) { } } - a.sendTeamEvent(oldTeam, model.WebsocketEventUpdateTeam) + if appErr := a.sendTeamEvent(oldTeam, model.WebsocketEventUpdateTeam); appErr != nil { + return nil, appErr + } return oldTeam, nil } @@ -301,9 +303,14 @@ func (a *App) UpdateTeamScheme(team *model.Team) (*model.Team, *model.AppError) } } - a.ClearTeamMembersCache(team.Id) + nErr = a.ClearTeamMembersCache(team.Id) + if nErr != nil { + return nil, model.NewAppError("UpdateTeamScheme", "app.team.clear_cache.app_error", nil, "", http.StatusInternalServerError).Wrap(nErr) + } - a.sendTeamEvent(oldTeam, model.WebsocketEventUpdateTeamScheme) + if appErr := a.sendTeamEvent(oldTeam, model.WebsocketEventUpdateTeamScheme); appErr != nil { + return nil, appErr + } return oldTeam, nil } @@ -336,7 +343,9 @@ func (a *App) UpdateTeamPrivacy(teamID string, teamType string, allowOpenInvite } } - a.sendTeamEvent(oldTeam, model.WebsocketEventUpdateTeam) + if appErr := a.sendTeamEvent(oldTeam, model.WebsocketEventUpdateTeam); appErr != nil { + return appErr + } return nil } @@ -362,7 +371,9 @@ func (a *App) PatchTeam(teamID string, patch *model.TeamPatch) (*model.Team, *mo } } - a.sendTeamEvent(team, model.WebsocketEventUpdateTeam) + if appErr := a.sendTeamEvent(team, model.WebsocketEventUpdateTeam); appErr != nil { + return nil, appErr + } return team, nil } @@ -389,12 +400,14 @@ func (a *App) RegenerateTeamInviteId(teamID string) (*model.Team, *model.AppErro } } - a.sendTeamEvent(updatedTeam, model.WebsocketEventUpdateTeam) + if appErr := a.sendTeamEvent(updatedTeam, model.WebsocketEventUpdateTeam); appErr != nil { + return nil, appErr + } return updatedTeam, nil } -func (a *App) sendTeamEvent(team *model.Team, event string) { +func (a *App) sendTeamEvent(team *model.Team, event string) *model.AppError { sanitizedTeam := &model.Team{} *sanitizedTeam = *team sanitizedTeam.Sanitize() @@ -407,10 +420,11 @@ func (a *App) sendTeamEvent(team *model.Team, event string) { message := model.NewWebSocketEvent(event, teamID, "", "", nil) teamJSON, jsonErr := json.Marshal(team) if jsonErr != nil { - mlog.Warn("Failed to encode team to JSON", mlog.Err(jsonErr)) + return model.NewAppError("sendTeamEvent", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr) } message.Add("team", string(teamJSON)) a.Publish(message) + return nil } func (a *App) GetSchemeRolesForTeam(teamID string) (string, string, string, *model.AppError) { @@ -507,7 +521,9 @@ func (a *App) UpdateTeamMemberRoles(teamID string, userID string, newRoles strin a.ClearSessionCacheForUser(userID) - a.sendUpdatedMemberRoleEvent(userID, member) + if appErr := a.sendUpdatedMemberRoleEvent(userID, member); appErr != nil { + return nil, appErr + } return member, nil } @@ -544,22 +560,25 @@ func (a *App) UpdateTeamMemberSchemeRoles(teamID string, userID string, isScheme a.ClearSessionCacheForUser(userID) - a.sendUpdatedMemberRoleEvent(userID, member) + if appErr := a.sendUpdatedMemberRoleEvent(userID, member); appErr != nil { + return nil, appErr + } return member, nil } -func (a *App) sendUpdatedMemberRoleEvent(userID string, member *model.TeamMember) { +func (a *App) sendUpdatedMemberRoleEvent(userID string, member *model.TeamMember) *model.AppError { message := model.NewWebSocketEvent(model.WebsocketEventMemberroleUpdated, "", "", userID, nil) tmJSON, jsonErr := json.Marshal(member) if jsonErr != nil { - mlog.Warn("Failed to encode team member to JSON", mlog.Err(jsonErr)) + return model.NewAppError("sendUpdatedMemberRoleEvent", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr) } message.Add("member", string(tmJSON)) a.Publish(message) + return nil } -func (a *App) AddUserToTeam(c *request.Context, teamID string, userID string, userRequestorId string) (*model.Team, *model.TeamMember, *model.AppError) { +func (a *App) AddUserToTeam(c request.CTX, teamID string, userID string, userRequestorId string) (*model.Team, *model.TeamMember, *model.AppError) { tchan := make(chan store.StoreResult, 1) go func() { team, err := a.Srv().Store.Team().Get(teamID) @@ -1059,7 +1078,7 @@ func (a *App) GetCommonTeamIDsForTwoUsers(userID, otherUserID string) ([]string, return teamIDs, nil } -func (a *App) AddTeamMember(c *request.Context, teamID, userID string) (*model.TeamMember, *model.AppError) { +func (a *App) AddTeamMember(c request.CTX, teamID, userID string) (*model.TeamMember, *model.AppError) { _, teamMember, err := a.AddUserToTeam(c, teamID, userID, "") if err != nil { return nil, err @@ -1152,7 +1171,7 @@ func (a *App) GetTeamUnread(teamID, userID string) (*model.TeamUnread, *model.Ap return teamUnread, nil } -func (a *App) RemoveUserFromTeam(c *request.Context, teamID string, userID string, requestorId string) *model.AppError { +func (a *App) RemoveUserFromTeam(c request.CTX, teamID string, userID string, requestorId string) *model.AppError { tchan := make(chan store.StoreResult, 1) go func() { team, err := a.Srv().Store.Team().Get(teamID) @@ -1245,7 +1264,7 @@ func (a *App) postProcessTeamMemberLeave(c request.CTX, teamMember *model.TeamMe return nil } -func (a *App) LeaveTeam(c *request.Context, team *model.Team, user *model.User, requestorId string) *model.AppError { +func (a *App) LeaveTeam(c request.CTX, team *model.Team, user *model.User, requestorId string) *model.AppError { teamMember, err := a.GetTeamMember(team.Id, user.Id) if err != nil { return model.NewAppError("LeaveTeam", "api.team.remove_user_from_team.missing.app_error", nil, err.Error(), http.StatusBadRequest) @@ -1288,11 +1307,11 @@ func (a *App) LeaveTeam(c *request.Context, team *model.Team, user *model.User, if requestorId == user.Id { if err = a.postLeaveTeamMessage(c, user, channel); err != nil { - mlog.Warn("Failed to post join/leave message", mlog.Err(err)) + c.Logger().Warn("Failed to post join/leave message", mlog.Err(err)) } } else { if err = a.postRemoveFromTeamMessage(c, user, channel); err != nil { - mlog.Warn("Failed to post join/leave message", mlog.Err(err)) + c.Logger().Warn("Failed to post join/leave message", mlog.Err(err)) } } } @@ -1308,7 +1327,7 @@ func (a *App) LeaveTeam(c *request.Context, team *model.Team, user *model.User, return nil } -func (a *App) postLeaveTeamMessage(c *request.Context, user *model.User, channel *model.Channel) *model.AppError { +func (a *App) postLeaveTeamMessage(c request.CTX, user *model.User, channel *model.Channel) *model.AppError { post := &model.Post{ ChannelId: channel.Id, Message: fmt.Sprintf(i18n.T("api.team.leave.left"), user.Username), @@ -1326,7 +1345,7 @@ func (a *App) postLeaveTeamMessage(c *request.Context, user *model.User, channel return nil } -func (a *App) postRemoveFromTeamMessage(c *request.Context, user *model.User, channel *model.Channel) *model.AppError { +func (a *App) postRemoveFromTeamMessage(c request.CTX, user *model.User, channel *model.Channel) *model.AppError { post := &model.Post{ ChannelId: channel.Id, Message: fmt.Sprintf(i18n.T("api.team.remove_user_from_team.removed"), user.Username), @@ -1797,7 +1816,9 @@ func (a *App) PermanentDeleteTeam(c request.CTX, team *model.Team) *model.AppErr return model.NewAppError("PermanentDeleteTeam", "app.team.permanent_delete.app_error", nil, err.Error(), http.StatusInternalServerError) } - a.sendTeamEvent(team, model.WebsocketEventDeleteTeam) + if appErr := a.sendTeamEvent(team, model.WebsocketEventDeleteTeam); appErr != nil { + return appErr + } return nil } @@ -1823,7 +1844,9 @@ func (a *App) SoftDeleteTeam(teamID string) *model.AppError { } } - a.sendTeamEvent(team, model.WebsocketEventDeleteTeam) + if appErr := a.sendTeamEvent(team, model.WebsocketEventDeleteTeam); appErr != nil { + return appErr + } return nil } @@ -1849,7 +1872,10 @@ func (a *App) RestoreTeam(teamID string) *model.AppError { } } - a.sendTeamEvent(team, model.WebsocketEventRestoreTeam) + if appErr := a.sendTeamEvent(team, model.WebsocketEventRestoreTeam); appErr != nil { + return appErr + } + return nil } @@ -2022,7 +2048,9 @@ func (a *App) SetTeamIconFromFile(team *model.Team, file io.Reader) *model.AppEr // manually set time to avoid possible cluster inconsistencies team.LastTeamIconUpdate = curTime - a.sendTeamEvent(team, model.WebsocketEventUpdateTeam) + if appErr := a.sendTeamEvent(team, model.WebsocketEventUpdateTeam); appErr != nil { + return appErr + } return nil } @@ -2039,7 +2067,9 @@ func (a *App) RemoveTeamIcon(teamID string) *model.AppError { team.LastTeamIconUpdate = 0 - a.sendTeamEvent(team, model.WebsocketEventUpdateTeam) + if appErr := a.sendTeamEvent(team, model.WebsocketEventUpdateTeam); appErr != nil { + return appErr + } return nil } @@ -2072,15 +2102,14 @@ func (a *App) InvalidateAllResendInviteEmailJobs() *model.AppError { return nil } -func (a *App) ClearTeamMembersCache(teamID string) { +func (a *App) ClearTeamMembersCache(teamID string) error { perPage := 100 page := 0 for { teamMembers, err := a.Srv().Store.Team().GetMembers(teamID, page*perPage, perPage, nil) if err != nil { - a.Log().Warn("error clearing cache for team members", mlog.String("team_id", teamID), mlog.String("err", err.Error())) - break + return fmt.Errorf("failed to get team members: %v", err) } for _, teamMember := range teamMembers { @@ -2089,7 +2118,7 @@ func (a *App) ClearTeamMembersCache(teamID string) { message := model.NewWebSocketEvent(model.WebsocketEventMemberroleUpdated, "", "", teamMember.UserId, nil) tmJSON, jsonErr := json.Marshal(teamMember) if jsonErr != nil { - mlog.Warn("Failed to encode team member to JSON", mlog.Err(jsonErr)) + return jsonErr } message.Add("member", string(tmJSON)) a.Publish(message) @@ -2102,4 +2131,5 @@ func (a *App) ClearTeamMembersCache(teamID string) { page++ } + return nil } diff --git a/app/team_test.go b/app/team_test.go index 9423927cec..bb69aa762c 100644 --- a/app/team_test.go +++ b/app/team_test.go @@ -1433,7 +1433,7 @@ func TestClearTeamMembersCache(t *testing.T) { mockStore.On("Team").Return(&mockTeamStore) mockStore.On("GetDBSchemaVersion").Return(1, nil) - th.App.ClearTeamMembersCache("teamID") + require.NoError(t, th.App.ClearTeamMembersCache("teamID")) } func TestInviteNewUsersToTeamGracefully(t *testing.T) { diff --git a/app/user.go b/app/user.go index 1dfa276012..9d2a2eb3ac 100644 --- a/app/user.go +++ b/app/user.go @@ -1416,7 +1416,6 @@ func (a *App) CreatePasswordRecoveryToken(userID, email string) (*model.Token, * email, } jsonData, err := json.Marshal(tokenExtra) - if err != nil { return nil, model.NewAppError("CreatePasswordRecoveryToken", "api.user.create_password_token.error", nil, "", http.StatusInternalServerError) } @@ -2196,7 +2195,7 @@ func (a *App) PromoteGuestToUser(c *request.Context, user *model.User, requestor evt := model.NewWebSocketEvent(model.WebsocketEventChannelMemberUpdated, "", "", user.Id, nil) memberJSON, jsonErr := json.Marshal(member) if jsonErr != nil { - c.Logger().Warn("Failed to encode channel member to JSON", mlog.Err(jsonErr)) + return model.NewAppError("PromoteGuestToUser", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr) } evt.Add("channelMember", string(memberJSON)) a.Publish(evt) @@ -2241,7 +2240,7 @@ func (a *App) DemoteUserToGuest(c request.CTX, user *model.User) *model.AppError evt := model.NewWebSocketEvent(model.WebsocketEventChannelMemberUpdated, "", "", user.Id, nil) memberJSON, jsonErr := json.Marshal(member) if jsonErr != nil { - c.Logger().Warn("Failed to encode channel member to JSON", mlog.Err(jsonErr)) + return model.NewAppError("DemoteUserToGuest", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr) } evt.Add("channelMember", string(memberJSON)) a.Publish(evt) @@ -2518,7 +2517,7 @@ func (a *App) UpdateThreadFollowForUserFromChannelAdd(c request.CTX, userID, tea payload, jsonErr := json.Marshal(userThread) if jsonErr != nil { - c.Logger().Warn("Failed to encode thread to JSON") + return model.NewAppError("UpdateThreadFollowForUserFromChannelAdd", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr) } message.Add("thread", string(payload)) message.Add("previous_unread_replies", int64(0)) diff --git a/i18n/en.json b/i18n/en.json index d5918e62f3..980c0ffe45 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -6151,6 +6151,10 @@ "id": "app.team.clear_all_custom_role_assignments.select.app_error", "translation": "Failed to retrieve the team members." }, + { + "id": "app.team.clear_cache.app_error", + "translation": "Error clearing team member cache" + }, { "id": "app.team.get.find.app_error", "translation": "Unable to find the existing team."