[MM-60689] Add Webhook ID in the logs (#28846)

* add webhook id to logs

* Move hook_id context to api level from app level.

* pass errCtx to other references of same app-error-id

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
Vishal
2024-11-21 13:53:10 +05:30
коммит произвёл GitHub
родитель c98f2e75fb
Коммит 746eb70e01
10 изменённых файлов: 88 добавлений и 69 удалений

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

@@ -1842,12 +1842,13 @@ func (a *App) GetChannel(c request.CTX, channelID string) (*model.Channel, *mode
func (s *Server) getChannel(c request.CTX, channelID string) (*model.Channel, *model.AppError) { func (s *Server) getChannel(c request.CTX, channelID string) (*model.Channel, *model.AppError) {
channel, err := s.Store().Channel().Get(channelID, true) channel, err := s.Store().Channel().Get(channelID, true)
if err != nil { if err != nil {
errCtx := map[string]any{"channel_id": channelID}
var nfErr *store.ErrNotFound var nfErr *store.ErrNotFound
switch { switch {
case errors.As(err, &nfErr): case errors.As(err, &nfErr):
return nil, model.NewAppError("GetChannel", "app.channel.get.existing.app_error", nil, "", http.StatusNotFound).Wrap(err) return nil, model.NewAppError("GetChannel", "app.channel.get.existing.app_error", errCtx, "", http.StatusNotFound).Wrap(err)
default: default:
return nil, model.NewAppError("GetChannel", "app.channel.get.find.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return nil, model.NewAppError("GetChannel", "app.channel.get.find.app_error", errCtx, "", http.StatusInternalServerError).Wrap(err)
} }
} }
return channel, nil return channel, nil
@@ -1856,12 +1857,13 @@ func (s *Server) getChannel(c request.CTX, channelID string) (*model.Channel, *m
func (a *App) GetChannels(c request.CTX, channelIDs []string) ([]*model.Channel, *model.AppError) { func (a *App) GetChannels(c request.CTX, channelIDs []string) ([]*model.Channel, *model.AppError) {
channels, err := a.Srv().Store().Channel().GetMany(channelIDs, true) channels, err := a.Srv().Store().Channel().GetMany(channelIDs, true)
if err != nil { if err != nil {
errCtx := map[string]any{"channel_id": channelIDs}
var nfErr *store.ErrNotFound var nfErr *store.ErrNotFound
switch { switch {
case errors.As(err, &nfErr): case errors.As(err, &nfErr):
return nil, model.NewAppError("GetChannel", "app.channel.get.existing.app_error", nil, "", http.StatusNotFound).Wrap(err) return nil, model.NewAppError("GetChannel", "app.channel.get.existing.app_error", errCtx, "", http.StatusNotFound).Wrap(err)
default: default:
return nil, model.NewAppError("GetChannel", "app.channel.get.find.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return nil, model.NewAppError("GetChannel", "app.channel.get.find.app_error", errCtx, "", http.StatusInternalServerError).Wrap(err)
} }
} }
return channels, nil return channels, nil
@@ -2370,12 +2372,13 @@ func (a *App) LeaveChannel(c request.CTX, channelID string, userID string) *mode
cresult := <-sc cresult := <-sc
if cresult.NErr != nil { if cresult.NErr != nil {
errCtx := map[string]any{"channel_id": channelID}
var nfErr *store.ErrNotFound var nfErr *store.ErrNotFound
switch { switch {
case errors.As(cresult.NErr, &nfErr): case errors.As(cresult.NErr, &nfErr):
return model.NewAppError("LeaveChannel", "app.channel.get.existing.app_error", nil, "", http.StatusNotFound).Wrap(cresult.NErr) return model.NewAppError("LeaveChannel", "app.channel.get.existing.app_error", errCtx, "", http.StatusNotFound).Wrap(cresult.NErr)
default: default:
return model.NewAppError("LeaveChannel", "app.channel.get.find.app_error", nil, "", http.StatusInternalServerError).Wrap(cresult.NErr) return model.NewAppError("LeaveChannel", "app.channel.get.find.app_error", errCtx, "", http.StatusInternalServerError).Wrap(cresult.NErr)
} }
} }
uresult := <-uc uresult := <-uc

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

@@ -421,12 +421,13 @@ func (a *App) tryExecuteCustomCommand(c request.CTX, args *model.CommandArgs, tr
cr := <-chanChan cr := <-chanChan
if cr.NErr != nil { if cr.NErr != nil {
errCtx := map[string]any{"channel_id": args.ChannelId}
var nfErr *store.ErrNotFound var nfErr *store.ErrNotFound
switch { switch {
case errors.As(cr.NErr, &nfErr): case errors.As(cr.NErr, &nfErr):
return nil, nil, model.NewAppError("tryExecuteCustomCommand", "app.channel.get.existing.app_error", nil, "", http.StatusNotFound).Wrap(cr.NErr) return nil, nil, model.NewAppError("tryExecuteCustomCommand", "app.channel.get.existing.app_error", errCtx, "", http.StatusNotFound).Wrap(cr.NErr)
default: default:
return nil, nil, model.NewAppError("tryExecuteCustomCommand", "app.channel.get.find.app_error", nil, "", http.StatusInternalServerError).Wrap(cr.NErr) return nil, nil, model.NewAppError("tryExecuteCustomCommand", "app.channel.get.find.app_error", errCtx, "", http.StatusInternalServerError).Wrap(cr.NErr)
} }
} }
channel := cr.Data channel := cr.Data

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

@@ -370,12 +370,13 @@ func (a *App) UpsertGroupSyncable(groupSyncable *model.GroupSyncable) (*model.Gr
if groupSyncable.Type == model.GroupSyncableTypeChannel { if groupSyncable.Type == model.GroupSyncableTypeChannel {
channel, nErr := a.Srv().Store().Channel().Get(groupSyncable.SyncableId, true) channel, nErr := a.Srv().Store().Channel().Get(groupSyncable.SyncableId, true)
if nErr != nil { if nErr != nil {
errCtx := map[string]any{"channel_id": groupSyncable.SyncableId}
var nfErr *store.ErrNotFound var nfErr *store.ErrNotFound
switch { switch {
case errors.As(nErr, &nfErr): case errors.As(nErr, &nfErr):
return nil, model.NewAppError("UpsertGroupSyncable", "app.channel.get.existing.app_error", nil, "", http.StatusNotFound).Wrap(nErr) return nil, model.NewAppError("UpsertGroupSyncable", "app.channel.get.existing.app_error", errCtx, "", http.StatusNotFound).Wrap(nErr)
default: default:
return nil, model.NewAppError("UpsertGroupSyncable", "app.channel.get.find.app_error", nil, "", http.StatusInternalServerError).Wrap(nErr) return nil, model.NewAppError("UpsertGroupSyncable", "app.channel.get.find.app_error", errCtx, "", http.StatusInternalServerError).Wrap(nErr)
} }
} }

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

@@ -107,12 +107,13 @@ func (a *App) DoPostActionWithCookie(c request.CTX, postID, actionId, userID, se
channel, err := a.Srv().Store().Channel().Get(cookie.ChannelId, true) channel, err := a.Srv().Store().Channel().Get(cookie.ChannelId, true)
if err != nil { if err != nil {
errCtx := map[string]any{"channel_id": cookie.ChannelId}
var nfErr *store.ErrNotFound var nfErr *store.ErrNotFound
switch { switch {
case errors.As(err, &nfErr): case errors.As(err, &nfErr):
return "", model.NewAppError("DoPostActionWithCookie", "app.channel.get.existing.app_error", nil, "", http.StatusNotFound).Wrap(err) return "", model.NewAppError("DoPostActionWithCookie", "app.channel.get.existing.app_error", errCtx, "", http.StatusNotFound).Wrap(err)
default: default:
return "", model.NewAppError("DoPostActionWithCookie", "app.channel.get.find.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return "", model.NewAppError("DoPostActionWithCookie", "app.channel.get.find.app_error", errCtx, "", http.StatusInternalServerError).Wrap(err)
} }
} }

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

@@ -118,12 +118,13 @@ func (a *App) CreatePostAsUser(c request.CTX, post *model.Post, currentSessionId
func (a *App) CreatePostMissingChannel(c request.CTX, post *model.Post, triggerWebhooks bool, setOnline bool) (*model.Post, *model.AppError) { func (a *App) CreatePostMissingChannel(c request.CTX, post *model.Post, triggerWebhooks bool, setOnline bool) (*model.Post, *model.AppError) {
channel, err := a.Srv().Store().Channel().Get(post.ChannelId, true) channel, err := a.Srv().Store().Channel().Get(post.ChannelId, true)
if err != nil { if err != nil {
errCtx := map[string]any{"channel_id": post.ChannelId}
var nfErr *store.ErrNotFound var nfErr *store.ErrNotFound
switch { switch {
case errors.As(err, &nfErr): case errors.As(err, &nfErr):
return nil, model.NewAppError("CreatePostMissingChannel", "app.channel.get.existing.app_error", nil, "", http.StatusNotFound).Wrap(err) return nil, model.NewAppError("CreatePostMissingChannel", "app.channel.get.existing.app_error", errCtx, "", http.StatusNotFound).Wrap(err)
default: default:
return nil, model.NewAppError("CreatePostMissingChannel", "app.channel.get.find.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return nil, model.NewAppError("CreatePostMissingChannel", "app.channel.get.find.app_error", errCtx, "", http.StatusInternalServerError).Wrap(err)
} }
} }
@@ -573,7 +574,7 @@ func (a *App) handlePostEvents(c request.CTX, post *model.Post, user *model.User
if triggerWebhooks { if triggerWebhooks {
a.Srv().Go(func() { a.Srv().Go(func() {
if err := a.handleWebhookEvents(c, post, team, channel, user); err != nil { if err := a.handleWebhookEvents(c, post, team, channel, user); err != nil {
c.Logger().Error("Failed to handle webhook event", mlog.Err(err)) c.Logger().Error("Failed to handle webhook event", mlog.String("user_id", user.Id), mlog.String("post_id", post.Id), mlog.Err(err))
} }
}) })
} }

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

@@ -95,15 +95,16 @@ func (a *App) handleWebhookEvents(c request.CTX, post *model.Post, team *model.T
} }
func (a *App) TriggerWebhook(c request.CTX, payload *model.OutgoingWebhookPayload, hook *model.OutgoingWebhook, post *model.Post, channel *model.Channel) { func (a *App) TriggerWebhook(c request.CTX, payload *model.OutgoingWebhookPayload, hook *model.OutgoingWebhook, post *model.Post, channel *model.Channel) {
logger := c.Logger().With(mlog.String("outgoing_webhook_id", hook.Id), mlog.String("post_id", post.Id), mlog.String("channel_id", channel.Id), mlog.String("content_type", hook.ContentType))
var jsonBytes []byte var jsonBytes []byte
var err error var err error
contentType := "application/x-www-form-urlencoded" contentType := "application/x-www-form-urlencoded"
if hook.ContentType == "application/json" { if hook.ContentType == "application/json" {
contentType = "application/json" contentType = "application/json"
jsonBytes, err = json.Marshal(payload) jsonBytes, err = json.Marshal(payload)
if err != nil { if err != nil {
c.Logger().Warn("Failed to encode to JSON", mlog.Err(err)) logger.Warn("Failed to encode to JSON", mlog.Err(err))
return return
} }
} }
@@ -131,14 +132,14 @@ func (a *App) TriggerWebhook(c request.CTX, payload *model.OutgoingWebhookPayloa
if a.Config().ServiceSettings.EnableOutgoingOAuthConnections != nil && *a.Config().ServiceSettings.EnableOutgoingOAuthConnections && a.OutgoingOAuthConnections() != nil { if a.Config().ServiceSettings.EnableOutgoingOAuthConnections != nil && *a.Config().ServiceSettings.EnableOutgoingOAuthConnections && a.OutgoingOAuthConnections() != nil {
connection, err := a.OutgoingOAuthConnections().GetConnectionForAudience(c, url) connection, err := a.OutgoingOAuthConnections().GetConnectionForAudience(c, url)
if err != nil { if err != nil {
c.Logger().Error("Failed to find an outgoing oauth connection for the webhook", mlog.Err(err)) logger.Error("Failed to find an outgoing oauth connection for the webhook", mlog.Err(err))
return return
} }
if connection != nil { if connection != nil {
accessToken, err = a.OutgoingOAuthConnections().RetrieveTokenForConnection(c, connection) accessToken, err = a.OutgoingOAuthConnections().RetrieveTokenForConnection(c, connection)
if err != nil { if err != nil {
c.Logger().Error("Failed to retrieve token for outgoing oauth connection", mlog.Err(err)) logger.Error("Failed to retrieve token for outgoing oauth connection", mlog.Err(err))
return return
} }
} }
@@ -147,9 +148,9 @@ func (a *App) TriggerWebhook(c request.CTX, payload *model.OutgoingWebhookPayloa
webhookResp, err := a.doOutgoingWebhookRequest(url, body, contentType, accessToken) webhookResp, err := a.doOutgoingWebhookRequest(url, body, contentType, accessToken)
if err != nil { if err != nil {
if errors.Is(err, context.DeadlineExceeded) { if errors.Is(err, context.DeadlineExceeded) {
c.Logger().Error("Outgoing Webhook POST timed out. Consider increasing ServiceSettings.OutgoingIntegrationRequestsTimeout.", mlog.Err(err)) logger.Error("Outgoing Webhook POST timed out. Consider increasing ServiceSettings.OutgoingIntegrationRequestsTimeout.", mlog.Err(err))
} else { } else {
c.Logger().Error("Outgoing Webhook POST failed", mlog.Err(err)) logger.Error("Outgoing Webhook POST failed", mlog.Err(err))
} }
return return
} }
@@ -181,7 +182,7 @@ func (a *App) TriggerWebhook(c request.CTX, payload *model.OutgoingWebhookPayloa
webhookResp.IconURL = hook.IconURL webhookResp.IconURL = hook.IconURL
} }
if _, err := a.CreateWebhookPost(c, hook.CreatorId, channel, text, webhookResp.Username, webhookResp.IconURL, "", webhookResp.Props, webhookResp.Type, postRootId, webhookResp.Priority); err != nil { if _, err := a.CreateWebhookPost(c, hook.CreatorId, channel, text, webhookResp.Username, webhookResp.IconURL, "", webhookResp.Props, webhookResp.Type, postRootId, webhookResp.Priority); err != nil {
c.Logger().Error("Failed to create response post.", mlog.Err(err)) logger.Error("Failed to create response post.", mlog.Err(err))
} }
} }
}() }()
@@ -528,12 +529,13 @@ func (a *App) CreateOutgoingWebhook(hook *model.OutgoingWebhook) (*model.Outgoin
if hook.ChannelId != "" { if hook.ChannelId != "" {
channel, errCh := a.Srv().Store().Channel().Get(hook.ChannelId, true) channel, errCh := a.Srv().Store().Channel().Get(hook.ChannelId, true)
if errCh != nil { if errCh != nil {
errCtx := map[string]any{"channel_id": hook.ChannelId}
var nfErr *store.ErrNotFound var nfErr *store.ErrNotFound
switch { switch {
case errors.As(errCh, &nfErr): case errors.As(errCh, &nfErr):
return nil, model.NewAppError("CreateOutgoingWebhook", "app.channel.get.existing.app_error", nil, "", http.StatusNotFound).Wrap(errCh) return nil, model.NewAppError("CreateOutgoingWebhook", "app.channel.get.existing.app_error", errCtx, "", http.StatusNotFound).Wrap(errCh)
default: default:
return nil, model.NewAppError("CreateOutgoingWebhook", "app.channel.get.find.app_error", nil, "", http.StatusInternalServerError).Wrap(errCh) return nil, model.NewAppError("CreateOutgoingWebhook", "app.channel.get.find.app_error", errCtx, "", http.StatusInternalServerError).Wrap(errCh)
} }
} }
@@ -780,7 +782,7 @@ func (a *App) HandleIncomingWebhook(c request.CTX, hookID string, req *model.Inc
if channelName[0] == '@' { if channelName[0] == '@' {
result, nErr := a.Srv().Store().User().GetByUsername(channelName[1:]) result, nErr := a.Srv().Store().User().GetByUsername(channelName[1:])
if nErr != nil { if nErr != nil {
return model.NewAppError("HandleIncomingWebhook", "web.incoming_webhook.user.app_error", nil, "", http.StatusBadRequest).Wrap(nErr) return model.NewAppError("HandleIncomingWebhook", "web.incoming_webhook.user.app_error", map[string]any{"user": channelName[1:]}, "", http.StatusBadRequest).Wrap(nErr)
} }
ch, err := a.GetOrCreateDirectChannel(c, hook.UserId, result.Id) ch, err := a.GetOrCreateDirectChannel(c, hook.UserId, result.Id)
if err != nil { if err != nil {
@@ -806,12 +808,13 @@ func (a *App) HandleIncomingWebhook(c request.CTX, hookID string, req *model.Inc
var err error var err error
channel, err = a.Srv().Store().Channel().Get(hook.ChannelId, true) channel, err = a.Srv().Store().Channel().Get(hook.ChannelId, true)
if err != nil { if err != nil {
errCtx := map[string]any{"channel_id": hook.ChannelId}
var nfErr *store.ErrNotFound var nfErr *store.ErrNotFound
switch { switch {
case errors.As(err, &nfErr): case errors.As(err, &nfErr):
return model.NewAppError("HandleIncomingWebhook", "app.channel.get.existing.app_error", nil, "", http.StatusNotFound).Wrap(err) return model.NewAppError("HandleIncomingWebhook", "app.channel.get.existing.app_error", errCtx, "", http.StatusNotFound).Wrap(err)
default: default:
return model.NewAppError("HandleIncomingWebhook", "app.channel.get.find.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return model.NewAppError("HandleIncomingWebhook", "app.channel.get.find.app_error", errCtx, "", http.StatusInternalServerError).Wrap(err)
} }
} }
} }
@@ -831,16 +834,16 @@ func (a *App) HandleIncomingWebhook(c request.CTX, hookID string, req *model.Inc
} }
if hook.ChannelLocked && hook.ChannelId != channel.Id { if hook.ChannelLocked && hook.ChannelId != channel.Id {
return model.NewAppError("HandleIncomingWebhook", "web.incoming_webhook.channel_locked.app_error", nil, "", http.StatusForbidden) return model.NewAppError("HandleIncomingWebhook", "web.incoming_webhook.channel_locked.app_error", map[string]any{"channel_id": channel.Id}, "", http.StatusForbidden)
} }
resultU := <-uchan resultU := <-uchan
if resultU.NErr != nil { if resultU.NErr != nil {
return model.NewAppError("HandleIncomingWebhook", "web.incoming_webhook.user.app_error", nil, "", http.StatusForbidden).Wrap(resultU.NErr) return model.NewAppError("HandleIncomingWebhook", "web.incoming_webhook.user.app_error", map[string]any{"user": hook.UserId}, "", http.StatusForbidden).Wrap(resultU.NErr)
} }
if channel.Type != model.ChannelTypeOpen && !a.HasPermissionToChannel(c, hook.UserId, channel.Id, model.PermissionReadChannelContent) { if channel.Type != model.ChannelTypeOpen && !a.HasPermissionToChannel(c, hook.UserId, channel.Id, model.PermissionReadChannelContent) {
return model.NewAppError("HandleIncomingWebhook", "web.incoming_webhook.permissions.app_error", nil, "", http.StatusForbidden) return model.NewAppError("HandleIncomingWebhook", "web.incoming_webhook.permissions.app_error", map[string]any{"user": hook.UserId, "channel": channel.Id}, "", http.StatusForbidden)
} }
overrideUsername := hook.Username overrideUsername := hook.Username
@@ -891,7 +894,7 @@ func (a *App) HandleCommandWebhook(c request.CTX, hookID string, response *model
var nfErr *store.ErrNotFound var nfErr *store.ErrNotFound
switch { switch {
case errors.As(nErr, &nfErr): case errors.As(nErr, &nfErr):
return model.NewAppError("HandleCommandWebhook", "app.command_webhook.get.missing", map[string]any{"hook_id": hookID}, "", http.StatusNotFound).Wrap(nErr) return model.NewAppError("HandleCommandWebhook", "app.command_webhook.get.missing", nil, "", http.StatusNotFound).Wrap(nErr)
default: default:
return model.NewAppError("HandleCommandWebhook", "app.command_webhook.get.internal_error", nil, "", http.StatusInternalServerError).Wrap(nErr) return model.NewAppError("HandleCommandWebhook", "app.command_webhook.get.internal_error", nil, "", http.StatusInternalServerError).Wrap(nErr)
} }
@@ -904,7 +907,7 @@ func (a *App) HandleCommandWebhook(c request.CTX, hookID string, response *model
case errors.As(cmdErr, &appErr): case errors.As(cmdErr, &appErr):
return appErr return appErr
default: default:
return model.NewAppError("HandleCommandWebhook", "web.command_webhook.command.app_error", nil, "", http.StatusBadRequest).Wrap(cmdErr) return model.NewAppError("HandleCommandWebhook", "web.command_webhook.command.app_error", map[string]any{"command_id": hook.CommandId}, "", http.StatusBadRequest).Wrap(cmdErr)
} }
} }

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

@@ -25,10 +25,11 @@ func (w *Web) InitWebhooks() {
func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) { func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
id := params["id"] id := params["id"]
errCtx := map[string]any{"hook_id": id}
r.ParseForm() r.ParseForm()
var err *model.AppError var appErr *model.AppError
var mediaType string var mediaType string
incomingWebhookPayload := &model.IncomingWebhookRequest{} incomingWebhookPayload := &model.IncomingWebhookRequest{}
contentType := r.Header.Get("Content-Type") contentType := r.Header.Get("Content-Type")
@@ -37,12 +38,7 @@ func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) {
var mimeErr error var mimeErr error
mediaType, _, mimeErr = mime.ParseMediaType(contentType) mediaType, _, mimeErr = mime.ParseMediaType(contentType)
if mimeErr != nil && mimeErr != mime.ErrInvalidMediaParameter { if mimeErr != nil && mimeErr != mime.ErrInvalidMediaParameter {
c.Err = model.NewAppError("incomingWebhook", c.Err = model.NewAppError("incomingWebhook", "web.incoming_webhook.media_type.app_error", errCtx, "", http.StatusBadRequest).Wrap(mimeErr)
"api.webhook.incoming.error",
nil,
"webhook_id="+id+", error: "+mimeErr.Error(),
http.StatusBadRequest,
)
return return
} }
} }
@@ -63,12 +59,13 @@ func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) {
} }
}() }()
errCtx["media_type"] = mediaType
if mediaType == "application/x-www-form-urlencoded" { if mediaType == "application/x-www-form-urlencoded" {
payload := strings.NewReader(r.FormValue("payload")) payload := strings.NewReader(r.FormValue("payload"))
incomingWebhookPayload, err = decodePayload(payload) incomingWebhookPayload, appErr = decodePayload(payload)
if err != nil { if appErr != nil {
c.Err = err c.Err = model.NewAppError("incomingWebhook", "web.incoming_webhook.decode.app_error", errCtx, "", http.StatusBadRequest).Wrap(appErr)
return return
} }
} else if mediaType == "multipart/form-data" { } else if mediaType == "multipart/form-data" {
@@ -78,25 +75,20 @@ func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) {
err := decoder.Decode(incomingWebhookPayload, r.PostForm) err := decoder.Decode(incomingWebhookPayload, r.PostForm)
if err != nil { if err != nil {
c.Err = model.NewAppError("incomingWebhook", c.Err = model.NewAppError("incomingWebhook", "web.incoming_webhook.decode.app_error", errCtx, "", http.StatusBadRequest).Wrap(err)
"api.webhook.incoming.error",
nil,
"webhook_id="+id+", error: "+err.Error(),
http.StatusBadRequest,
)
return return
} }
} else { } else {
incomingWebhookPayload, err = decodePayload(r.Body) incomingWebhookPayload, appErr = decodePayload(r.Body)
if err != nil { if appErr != nil {
c.Err = err c.Err = model.NewAppError("incomingWebhook", "web.incoming_webhook.decode.app_error", errCtx, "", appErr.StatusCode).Wrap(appErr)
return return
} }
} }
err = c.App.HandleIncomingWebhook(c.AppContext, id, incomingWebhookPayload) appErr = c.App.HandleIncomingWebhook(c.AppContext, id, incomingWebhookPayload)
if err != nil { if appErr != nil {
c.Err = err c.Err = model.NewAppError("incomingWebhook", "web.incoming_webhook.general.app_error", errCtx, "", appErr.StatusCode).Wrap(appErr)
return return
} }
@@ -107,16 +99,17 @@ func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) {
func commandWebhook(c *Context, w http.ResponseWriter, r *http.Request) { func commandWebhook(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
id := params["id"] id := params["id"]
errCtx := map[string]any{"hook_id": id}
response, err := model.CommandResponseFromHTTPBody(r.Header.Get("Content-Type"), r.Body) response, err := model.CommandResponseFromHTTPBody(r.Header.Get("Content-Type"), r.Body)
if err != nil { if err != nil {
c.Err = model.NewAppError("commandWebhook", "web.command_webhook.parse.app_error", nil, "", http.StatusBadRequest).Wrap(err) c.Err = model.NewAppError("commandWebhook", "web.command_webhook.parse.app_error", errCtx, "", http.StatusBadRequest).Wrap(err)
return return
} }
appErr := c.App.HandleCommandWebhook(c.AppContext, id, response) appErr := c.App.HandleCommandWebhook(c.AppContext, id, response)
if appErr != nil { if appErr != nil {
c.Err = appErr c.Err = model.NewAppError("commandWebhook", "web.command_webhook.general.app_error", errCtx, "", appErr.StatusCode).Wrap(appErr)
return return
} }

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

@@ -357,7 +357,7 @@ func (s *MmctlE2ETestSuite) TestDeleteChannelsCmd() {
_, err = s.th.App.GetChannel(s.th.Context, channel.Id) _, err = s.th.App.GetChannel(s.th.Context, channel.Id)
s.Require().NotNil(err) s.Require().NotNil(err)
s.Require().Equal(fmt.Sprintf("GetChannel: Unable to find the existing channel., resource \"Channel\" not found, id: %s", channel.Id), err.Error()) s.CheckErrorID(err, "app.channel.get.existing.app_error")
}) })
s.Run("Delete channel without permissions", func() { s.Run("Delete channel without permissions", func() {
@@ -401,7 +401,7 @@ func (s *MmctlE2ETestSuite) TestDeleteChannelsCmd() {
s.Require().Nil(channel) s.Require().Nil(channel)
s.Require().NotNil(err) s.Require().NotNil(err)
s.Require().Equal(fmt.Sprintf("GetChannel: Unable to find the existing channel., resource \"Channel\" not found, id: %s", notExistingChannelID), err.Error()) s.CheckErrorID(err, "app.channel.get.existing.app_error")
}) })
} }

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

@@ -96,3 +96,7 @@ func (s *MmctlE2ETestSuite) RunForAllClients(testName string, fn func(client.Cli
fn(s.th.LocalClient) fn(s.th.LocalClient)
}) })
} }
func (s *MmctlE2ETestSuite) CheckErrorID(err error, errorId string) {
api4.CheckErrorID(s.T(), err, errorId)
}

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

@@ -4382,10 +4382,6 @@
"id": "api.webhook.create_outgoing.triggers.app_error", "id": "api.webhook.create_outgoing.triggers.app_error",
"translation": "Either trigger_words or channel_id must be set." "translation": "Either trigger_words or channel_id must be set."
}, },
{
"id": "api.webhook.incoming.error",
"translation": "Could not decode the multipart payload of incoming webhook."
},
{ {
"id": "api.webhook.team_mismatch.app_error", "id": "api.webhook.team_mismatch.app_error",
"translation": "Unable to update webhook across teams." "translation": "Unable to update webhook across teams."
@@ -4580,11 +4576,11 @@
}, },
{ {
"id": "app.channel.get.existing.app_error", "id": "app.channel.get.existing.app_error",
"translation": "Unable to find the existing channel." "translation": "Unable to find the existing channel {{.channel_id}}."
}, },
{ {
"id": "app.channel.get.find.app_error", "id": "app.channel.get.find.app_error",
"translation": "We encountered an error finding the channel." "translation": "We encountered an error finding the channel {{.channel_id}}."
}, },
{ {
"id": "app.channel.get_all.app_error", "id": "app.channel.get_all.app_error",
@@ -10270,11 +10266,15 @@
}, },
{ {
"id": "web.command_webhook.command.app_error", "id": "web.command_webhook.command.app_error",
"translation": "Couldn't find the command." "translation": "Couldn't find the command {{.command_id}}."
},
{
"id": "web.command_webhook.general.app_error",
"translation": "Failed to handle command webhook {{.hook_id}}."
}, },
{ {
"id": "web.command_webhook.parse.app_error", "id": "web.command_webhook.parse.app_error",
"translation": "Unable to parse incoming data." "translation": "Unable to parse incoming data for webhook {{.hook_id}}."
}, },
{ {
"id": "web.error.unsupported_browser.browser_get_latest.chrome", "id": "web.error.unsupported_browser.browser_get_latest.chrome",
@@ -10382,23 +10382,35 @@
}, },
{ {
"id": "web.incoming_webhook.channel_locked.app_error", "id": "web.incoming_webhook.channel_locked.app_error",
"translation": "This webhook is not permitted to post to the requested channel." "translation": "This webhook is not permitted to post to the requested channel {{.channel_id}}"
},
{
"id": "web.incoming_webhook.decode.app_error",
"translation": "Failed to decode the payload of media type {{.media_type}} for incoming webhook {{.hook_id}}."
}, },
{ {
"id": "web.incoming_webhook.disabled.app_error", "id": "web.incoming_webhook.disabled.app_error",
"translation": "Incoming webhooks have been disabled by the system admin." "translation": "Incoming webhooks have been disabled by the system admin."
}, },
{
"id": "web.incoming_webhook.general.app_error",
"translation": "Failed to handle the payload of media type {{.media_type}} for incoming webhook {{.hook_id}}."
},
{ {
"id": "web.incoming_webhook.invalid.app_error", "id": "web.incoming_webhook.invalid.app_error",
"translation": "Invalid webhook." "translation": "Invalid webhook."
}, },
{
"id": "web.incoming_webhook.media_type.app_error",
"translation": "Failed to parse media incoming webhook {{.hook_id}}."
},
{ {
"id": "web.incoming_webhook.parse.app_error", "id": "web.incoming_webhook.parse.app_error",
"translation": "Unable to parse incoming data." "translation": "Unable to parse incoming data."
}, },
{ {
"id": "web.incoming_webhook.permissions.app_error", "id": "web.incoming_webhook.permissions.app_error",
"translation": "Inappropriate channel permissions." "translation": "User {{.user}} does not have appropriate permissions to channel {{.channel}}"
}, },
{ {
"id": "web.incoming_webhook.split_props_length.app_error", "id": "web.incoming_webhook.split_props_length.app_error",
@@ -10410,6 +10422,6 @@
}, },
{ {
"id": "web.incoming_webhook.user.app_error", "id": "web.incoming_webhook.user.app_error",
"translation": "Couldn't find the user." "translation": "Couldn't find the user {{.user}}"
} }
] ]