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
```
Этот коммит содержится в:
Agniva De Sarker
2022-08-05 08:49:01 +05:30
коммит произвёл GitHub
родитель 151f295d82
Коммит 14246abdef
16 изменённых файлов: 166 добавлений и 104 удалений

Просмотреть файл

@@ -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

Просмотреть файл

@@ -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) {

Просмотреть файл

@@ -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))

Просмотреть файл

@@ -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) {

Просмотреть файл

@@ -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)

Просмотреть файл

@@ -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
}

Просмотреть файл

@@ -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")

Просмотреть файл

@@ -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)

Просмотреть файл

@@ -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)

Просмотреть файл

@@ -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 {

Просмотреть файл

@@ -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)

Просмотреть файл

@@ -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))
}
}
}

Просмотреть файл

@@ -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
}

Просмотреть файл

@@ -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) {

Просмотреть файл

@@ -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))

Просмотреть файл

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