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."