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 ```
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
151f295d82
Коммит
14246abdef
88
app/team.go
88
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
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user