Files
mattermost/server/channels/api4/webhook.go
ab31663fce MM-69010: Validate incoming webhook user membership (#36811)
* MM-69010: Validate incoming webhook user membership

Incoming webhook creation/update did not verify that the assigned
user_id had legitimate access to the target team or channel, allowing a
team admin to attribute persisted posts to an arbitrary user.

Validate that the assigned user can read the target channel and does not
hold privileges the requester lacks at creation, re-check channel access
when a hook is moved, and require a shared team before a webhook creates
a direct message via an @username payload.

Co-authored-by: Cursor <cursoragent@cursor.com>

* MM-69010: Add regression test for owner+channel update

Verify that changing both the channel and the supplied user_id in a
single update still validates against the retained owner, since the
owner is immutable on update.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
2026-06-02 20:26:42 -04:00

707 lines
22 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package api4
import (
"encoding/json"
"net/http"
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
func (api *API) InitWebhook() {
api.BaseRoutes.IncomingHooks.Handle("", api.APISessionRequired(createIncomingHook)).Methods(http.MethodPost)
api.BaseRoutes.IncomingHooks.Handle("", api.APISessionRequired(getIncomingHooks)).Methods(http.MethodGet)
api.BaseRoutes.IncomingHook.Handle("", api.APISessionRequired(getIncomingHook)).Methods(http.MethodGet)
api.BaseRoutes.IncomingHook.Handle("", api.APISessionRequired(updateIncomingHook)).Methods(http.MethodPut)
api.BaseRoutes.IncomingHook.Handle("", api.APISessionRequired(deleteIncomingHook)).Methods(http.MethodDelete)
api.BaseRoutes.OutgoingHooks.Handle("", api.APISessionRequired(createOutgoingHook)).Methods(http.MethodPost)
api.BaseRoutes.OutgoingHooks.Handle("", api.APISessionRequired(getOutgoingHooks)).Methods(http.MethodGet)
api.BaseRoutes.OutgoingHook.Handle("", api.APISessionRequired(getOutgoingHook)).Methods(http.MethodGet)
api.BaseRoutes.OutgoingHook.Handle("", api.APISessionRequired(updateOutgoingHook)).Methods(http.MethodPut)
api.BaseRoutes.OutgoingHook.Handle("", api.APISessionRequired(deleteOutgoingHook)).Methods(http.MethodDelete)
api.BaseRoutes.OutgoingHook.Handle("/regen_token", api.APISessionRequired(regenOutgoingHookToken)).Methods(http.MethodPost)
}
func createIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
var hook model.IncomingWebhook
if jsonErr := json.NewDecoder(r.Body).Decode(&hook); jsonErr != nil {
c.SetInvalidParamWithErr("incoming_webhook", jsonErr)
return
}
channel, err := c.App.GetChannel(c.AppContext, hook.ChannelId)
if err != nil {
c.Err = err
return
}
auditRec := c.MakeAuditRecord(model.AuditEventCreateIncomingHook, model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
model.AddEventParameterAuditableToAuditRec(auditRec, "incoming_webhook", &hook)
model.AddEventParameterAuditableToAuditRec(auditRec, "channel", channel)
c.LogAudit("attempt")
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), channel.TeamId, model.PermissionManageOwnIncomingWebhooks) {
c.SetPermissionError(model.PermissionManageOwnIncomingWebhooks)
return
}
if ok, _ := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel); !ok {
c.LogAudit("fail - bad channel permissions")
c.SetPermissionError(model.PermissionReadChannelContent)
return
}
userId := c.AppContext.Session().UserId
if hook.UserId != "" && hook.UserId != userId {
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), channel.TeamId, model.PermissionManageOthersIncomingWebhooks) {
c.LogAudit("fail - inappropriate permissions")
c.SetPermissionError(model.PermissionManageOthersIncomingWebhooks)
return
}
var hookUser *model.User
if hookUser, err = c.App.GetUser(hook.UserId); err != nil {
c.Err = err
return
}
if appErr := c.App.ValidateIncomingWebhookUser(c.AppContext, *c.AppContext.Session(), hookUser, channel); appErr != nil {
c.LogAudit("fail - invalid webhook user")
c.Err = appErr
return
}
userId = hook.UserId
}
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), channel.TeamId, model.PermissionBypassIncomingWebhookChannelLock) {
hook.ChannelLocked = true
hook.ChannelId = channel.Id
}
incomingHook, err := c.App.CreateIncomingWebhookForChannel(userId, channel, &hook)
if err != nil {
c.Err = err
return
}
auditRec.Success()
auditRec.AddEventResultState(incomingHook)
auditRec.AddEventObjectType("hook")
c.LogAudit("success")
w.WriteHeader(http.StatusCreated)
if err := json.NewEncoder(w).Encode(incomingHook); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
}
func updateIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireHookId()
if c.Err != nil {
return
}
var updatedHook model.IncomingWebhook
if jsonErr := json.NewDecoder(r.Body).Decode(&updatedHook); jsonErr != nil {
c.SetInvalidParamWithErr("incoming_webhook", jsonErr)
return
}
// The hook being updated in the payload must be the same one as indicated in the URL.
if updatedHook.Id != c.Params.HookId {
c.SetInvalidParam("hook_id")
return
}
auditRec := c.MakeAuditRecord(model.AuditEventUpdateIncomingHook, model.AuditStatusFail)
model.AddEventParameterToAuditRec(auditRec, "hook_id", c.Params.HookId)
model.AddEventParameterAuditableToAuditRec(auditRec, "updated_hook", &updatedHook)
defer c.LogAuditRec(auditRec)
c.LogAudit("attempt")
oldHook, err := c.App.GetIncomingWebhook(c.Params.HookId)
if err != nil {
c.Err = err
return
}
auditRec.AddEventPriorState(oldHook)
auditRec.AddEventObjectType("incoming_webhook")
if updatedHook.TeamId == "" {
updatedHook.TeamId = oldHook.TeamId
}
if updatedHook.TeamId != oldHook.TeamId {
c.Err = model.NewAppError("updateIncomingHook", "api.webhook.team_mismatch.app_error", nil, "user_id="+c.AppContext.Session().UserId, http.StatusBadRequest)
return
}
channel, err := c.App.GetChannel(c.AppContext, updatedHook.ChannelId)
if err != nil {
c.Err = err
return
}
auditRec.AddMeta("channel_id", channel.Id)
auditRec.AddMeta("channel_name", channel.Name)
if channel.TeamId != updatedHook.TeamId {
c.SetInvalidParam("channel_id")
return
}
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), channel.TeamId, model.PermissionManageOwnIncomingWebhooks) {
c.SetPermissionError(model.PermissionManageOwnIncomingWebhooks)
return
}
if c.AppContext.Session().UserId != oldHook.UserId && !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), channel.TeamId, model.PermissionManageOthersIncomingWebhooks) {
c.LogAudit("fail - inappropriate permissions")
c.SetPermissionError(model.PermissionManageOthersIncomingWebhooks)
return
}
if channel.Type != model.ChannelTypeOpen {
if ok, _ := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel); !ok {
c.LogAudit("fail - bad channel permissions")
c.SetPermissionError(model.PermissionReadChannelContent)
return
}
}
// Moving the hook must not attribute its owner's posts to a channel they cannot access.
if updatedHook.ChannelId != oldHook.ChannelId {
if appErr := c.App.ValidateIncomingWebhookUserChannelAccess(c.AppContext, oldHook.UserId, channel); appErr != nil {
c.LogAudit("fail - invalid webhook user")
c.Err = appErr
return
}
}
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), channel.TeamId, model.PermissionBypassIncomingWebhookChannelLock) {
updatedHook.ChannelLocked = true
updatedHook.ChannelId = channel.Id
}
incomingHook, err := c.App.UpdateIncomingWebhook(oldHook, &updatedHook)
if err != nil {
c.Err = err
return
}
auditRec.AddEventResultState(incomingHook)
auditRec.Success()
c.LogAudit("success")
w.WriteHeader(http.StatusCreated)
if err := json.NewEncoder(w).Encode(incomingHook); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
}
func getIncomingHooks(c *Context, w http.ResponseWriter, r *http.Request) {
var (
teamID = r.URL.Query().Get("team_id")
userID = c.AppContext.Session().UserId
hooks []*model.IncomingWebhook
appErr *model.AppError
js []byte
err error
)
if teamID != "" {
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), teamID, model.PermissionManageOwnIncomingWebhooks) {
c.SetPermissionError(model.PermissionManageOwnIncomingWebhooks)
return
}
// Remove userId as a filter if they have permission to manage others.
if c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), teamID, model.PermissionManageOthersIncomingWebhooks) {
userID = ""
}
hooks, appErr = c.App.GetIncomingWebhooksForTeamPageByUser(teamID, userID, c.Params.Page, c.Params.PerPage)
} else {
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageOwnIncomingWebhooks) {
c.SetPermissionError(model.PermissionManageOwnIncomingWebhooks)
return
}
// Remove userId as a filter if they have permission to manage others.
if c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageOthersIncomingWebhooks) {
userID = ""
}
hooks, appErr = c.App.GetIncomingWebhooksPageByUser(userID, c.Params.Page, c.Params.PerPage)
}
if appErr != nil {
c.Err = appErr
return
}
if c.Params.IncludeTotalCount {
totalCount, appErr := c.App.GetIncomingWebhooksCount(teamID, userID)
if appErr != nil {
c.Err = appErr
return
}
hooksWithCount := model.IncomingWebhooksWithCount{Webhooks: hooks, TotalCount: totalCount}
js, err = json.Marshal(hooksWithCount)
} else {
js, err = json.Marshal(hooks)
}
if err != nil {
c.Err = model.NewAppError("getIncomingHooks", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err)
return
}
if _, err := w.Write(js); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
}
func getIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireHookId()
if c.Err != nil {
return
}
hookId := c.Params.HookId
var err *model.AppError
var hook *model.IncomingWebhook
var channel *model.Channel
hook, err = c.App.GetIncomingWebhook(hookId)
if err != nil {
c.Err = err
return
}
auditRec := c.MakeAuditRecord(model.AuditEventGetIncomingHook, model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
model.AddEventParameterToAuditRec(auditRec, "hook_id", c.Params.HookId)
auditRec.AddMeta("hook_id", hook.Id)
auditRec.AddMeta("hook_display", hook.DisplayName)
auditRec.AddMeta("channel_id", hook.ChannelId)
auditRec.AddMeta("team_id", hook.TeamId)
c.LogAudit("attempt")
channel, err = c.App.GetChannel(c.AppContext, hook.ChannelId)
if err != nil {
c.Err = err
return
}
isPrivate := channel.Type != model.ChannelTypeOpen
restrictedChannel := false
if isPrivate {
hasChannelPermission, _ := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel)
restrictedChannel = !hasChannelPermission
}
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), hook.TeamId, model.PermissionManageOwnIncomingWebhooks) || restrictedChannel {
c.LogAudit("fail - bad permissions")
c.SetPermissionError(model.PermissionManageOwnIncomingWebhooks)
return
}
if c.AppContext.Session().UserId != hook.UserId && !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), hook.TeamId, model.PermissionManageOthersIncomingWebhooks) {
c.LogAudit("fail - inappropriate permissions")
c.SetPermissionError(model.PermissionManageOthersIncomingWebhooks)
return
}
auditRec.Success()
c.LogAudit("success")
if err := json.NewEncoder(w).Encode(hook); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
}
func deleteIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireHookId()
if c.Err != nil {
return
}
hookId := c.Params.HookId
var err *model.AppError
var hook *model.IncomingWebhook
var channel *model.Channel
hook, err = c.App.GetIncomingWebhook(hookId)
if err != nil {
c.Err = err
return
}
channel, err = c.App.GetChannel(c.AppContext, hook.ChannelId)
if err != nil {
c.Err = err
return
}
auditRec := c.MakeAuditRecord(model.AuditEventDeleteIncomingHook, model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
model.AddEventParameterToAuditRec(auditRec, "hook_id", c.Params.HookId)
auditRec.AddMeta("hook_id", hook.Id)
auditRec.AddMeta("hook_display", hook.DisplayName)
auditRec.AddMeta("channel_id", channel.Id)
auditRec.AddMeta("channel_name", channel.Name)
auditRec.AddMeta("team_id", hook.TeamId)
isPrivate := channel.Type != model.ChannelTypeOpen
restrictedChannel := false
if isPrivate {
hasChannelPermission, _ := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel)
restrictedChannel = !hasChannelPermission
}
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), hook.TeamId, model.PermissionManageOwnIncomingWebhooks) || restrictedChannel {
c.LogAudit("fail - bad permissions")
c.SetPermissionError(model.PermissionManageOwnIncomingWebhooks)
return
}
if c.AppContext.Session().UserId != hook.UserId && !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), hook.TeamId, model.PermissionManageOthersIncomingWebhooks) {
c.LogAudit("fail - inappropriate permissions")
c.SetPermissionError(model.PermissionManageOthersIncomingWebhooks)
return
}
if err = c.App.DeleteIncomingWebhook(hookId); err != nil {
c.Err = err
return
}
auditRec.AddEventPriorState(hook)
auditRec.AddEventObjectType("incoming_webhook")
auditRec.Success()
ReturnStatusOK(w)
}
func updateOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireHookId()
if c.Err != nil {
return
}
var updatedHook model.OutgoingWebhook
if jsonErr := json.NewDecoder(r.Body).Decode(&updatedHook); jsonErr != nil {
c.SetInvalidParamWithErr("outgoing_webhook", jsonErr)
return
}
// The hook being updated in the payload must be the same one as indicated in the URL.
if updatedHook.Id != c.Params.HookId {
c.SetInvalidParam("hook_id")
return
}
auditRec := c.MakeAuditRecord(model.AuditEventUpdateOutgoingHook, model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
model.AddEventParameterAuditableToAuditRec(auditRec, "updated_hook", &updatedHook)
c.LogAudit("attempt")
oldHook, err := c.App.GetOutgoingWebhook(c.Params.HookId)
if err != nil {
c.Err = err
return
}
if updatedHook.TeamId == "" {
updatedHook.TeamId = oldHook.TeamId
}
if updatedHook.TeamId != oldHook.TeamId {
c.Err = model.NewAppError("updateOutgoingHook", "api.webhook.team_mismatch.app_error", nil, "user_id="+c.AppContext.Session().UserId, http.StatusBadRequest)
return
}
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), updatedHook.TeamId, model.PermissionManageOwnOutgoingWebhooks) {
c.SetPermissionError(model.PermissionManageOwnOutgoingWebhooks)
return
}
if c.AppContext.Session().UserId != oldHook.CreatorId && !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), updatedHook.TeamId, model.PermissionManageOthersOutgoingWebhooks) {
c.LogAudit("fail - inappropriate permissions")
c.SetPermissionError(model.PermissionManageOthersOutgoingWebhooks)
return
}
updatedHook.CreatorId = c.AppContext.Session().UserId
rhook, err := c.App.UpdateOutgoingWebhook(c.AppContext, oldHook, &updatedHook)
if err != nil {
c.Err = err
return
}
auditRec.Success()
c.LogAudit("success")
if err := json.NewEncoder(w).Encode(rhook); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
}
func createOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
var hook model.OutgoingWebhook
if jsonErr := json.NewDecoder(r.Body).Decode(&hook); jsonErr != nil {
c.SetInvalidParamWithErr("outgoing_webhook", jsonErr)
return
}
auditRec := c.MakeAuditRecord(model.AuditEventCreateOutgoingHook, model.AuditStatusFail)
model.AddEventParameterAuditableToAuditRec(auditRec, "hook", &hook)
defer c.LogAuditRec(auditRec)
c.LogAudit("attempt")
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), hook.TeamId, model.PermissionManageOwnOutgoingWebhooks) {
c.SetPermissionError(model.PermissionManageOwnOutgoingWebhooks)
return
}
if hook.CreatorId == "" {
hook.CreatorId = c.AppContext.Session().UserId
} else {
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), hook.TeamId, model.PermissionManageOthersOutgoingWebhooks) {
c.LogAudit("fail - inappropriate permissions")
c.SetPermissionError(model.PermissionManageOthersOutgoingWebhooks)
return
}
_, err := c.App.GetUser(hook.CreatorId)
if err != nil {
c.Err = err
return
}
}
rhook, err := c.App.CreateOutgoingWebhook(&hook)
if err != nil {
c.LogAudit("fail")
c.Err = err
return
}
auditRec.Success()
auditRec.AddEventResultState(rhook)
auditRec.AddEventObjectType("outgoing_webhook")
c.LogAudit("success")
w.WriteHeader(http.StatusCreated)
if err := json.NewEncoder(w).Encode(rhook); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
}
func getOutgoingHooks(c *Context, w http.ResponseWriter, r *http.Request) {
var (
query = r.URL.Query()
channelID = query.Get("channel_id")
teamID = query.Get("team_id")
userID = c.AppContext.Session().UserId
hooks []*model.OutgoingWebhook
appErr *model.AppError
)
if channelID != "" {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channelID, model.PermissionManageOwnOutgoingWebhooks); !ok {
c.SetPermissionError(model.PermissionManageOwnOutgoingWebhooks)
return
}
// Remove userId as a filter if they have permission to manage others.
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channelID, model.PermissionManageOthersOutgoingWebhooks); ok {
userID = ""
}
hooks, appErr = c.App.GetOutgoingWebhooksForChannelPageByUser(channelID, userID, c.Params.Page, c.Params.PerPage)
} else if teamID != "" {
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), teamID, model.PermissionManageOwnOutgoingWebhooks) {
c.SetPermissionError(model.PermissionManageOwnOutgoingWebhooks)
return
}
// Remove userId as a filter if they have permission to manage others.
if c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), teamID, model.PermissionManageOthersOutgoingWebhooks) {
userID = ""
}
hooks, appErr = c.App.GetOutgoingWebhooksForTeamPageByUser(teamID, userID, c.Params.Page, c.Params.PerPage)
} else {
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageOwnOutgoingWebhooks) {
c.SetPermissionError(model.PermissionManageOwnOutgoingWebhooks)
return
}
// Remove userId as a filter if they have permission to manage others.
if c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageOthersOutgoingWebhooks) {
userID = ""
}
hooks, appErr = c.App.GetOutgoingWebhooksPageByUser(userID, c.Params.Page, c.Params.PerPage)
}
if appErr != nil {
c.Err = appErr
return
}
js, err := json.Marshal(hooks)
if err != nil {
c.Err = model.NewAppError("getOutgoingHooks", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err)
return
}
if _, err := w.Write(js); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
}
func getOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireHookId()
if c.Err != nil {
return
}
hook, err := c.App.GetOutgoingWebhook(c.Params.HookId)
if err != nil {
c.Err = err
return
}
auditRec := c.MakeAuditRecord(model.AuditEventGetOutgoingHook, model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
model.AddEventParameterToAuditRec(auditRec, "hook_id", c.Params.HookId)
auditRec.AddMeta("hook_id", hook.Id)
auditRec.AddMeta("hook_display", hook.DisplayName)
auditRec.AddMeta("channel_id", hook.ChannelId)
auditRec.AddMeta("team_id", hook.TeamId)
c.LogAudit("attempt")
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), hook.TeamId, model.PermissionManageOwnOutgoingWebhooks) {
c.SetPermissionError(model.PermissionManageOwnOutgoingWebhooks)
return
}
if c.AppContext.Session().UserId != hook.CreatorId && !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), hook.TeamId, model.PermissionManageOthersOutgoingWebhooks) {
c.LogAudit("fail - inappropriate permissions")
c.SetPermissionError(model.PermissionManageOthersOutgoingWebhooks)
return
}
auditRec.Success()
c.LogAudit("success")
if err := json.NewEncoder(w).Encode(hook); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
}
func regenOutgoingHookToken(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireHookId()
if c.Err != nil {
return
}
hook, err := c.App.GetOutgoingWebhook(c.Params.HookId)
if err != nil {
c.Err = err
return
}
auditRec := c.MakeAuditRecord(model.AuditEventRegenOutgoingHookToken, model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("hook_id", hook.Id)
auditRec.AddMeta("hook_display", hook.DisplayName)
auditRec.AddMeta("channel_id", hook.ChannelId)
auditRec.AddMeta("team_id", hook.TeamId)
c.LogAudit("attempt")
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), hook.TeamId, model.PermissionManageOwnOutgoingWebhooks) {
c.SetPermissionError(model.PermissionManageOwnOutgoingWebhooks)
return
}
if c.AppContext.Session().UserId != hook.CreatorId && !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), hook.TeamId, model.PermissionManageOthersOutgoingWebhooks) {
c.LogAudit("fail - inappropriate permissions")
c.SetPermissionError(model.PermissionManageOthersOutgoingWebhooks)
return
}
rhook, err := c.App.RegenOutgoingWebhookToken(hook)
if err != nil {
c.Err = err
return
}
auditRec.AddEventResultState(rhook)
auditRec.AddEventObjectType("outgoing_webhook")
auditRec.Success()
c.LogAudit("success")
if err := json.NewEncoder(w).Encode(rhook); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
}
func deleteOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireHookId()
if c.Err != nil {
return
}
hook, err := c.App.GetOutgoingWebhook(c.Params.HookId)
if err != nil {
c.Err = err
return
}
auditRec := c.MakeAuditRecord(model.AuditEventDeleteOutgoingHook, model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
model.AddEventParameterToAuditRec(auditRec, "hook_id", c.Params.HookId)
auditRec.AddMeta("hook_id", hook.Id)
auditRec.AddMeta("hook_display", hook.DisplayName)
auditRec.AddMeta("channel_id", hook.ChannelId)
auditRec.AddMeta("team_id", hook.TeamId)
c.LogAudit("attempt")
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), hook.TeamId, model.PermissionManageOwnOutgoingWebhooks) {
c.SetPermissionError(model.PermissionManageOwnOutgoingWebhooks)
return
}
if c.AppContext.Session().UserId != hook.CreatorId && !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), hook.TeamId, model.PermissionManageOthersOutgoingWebhooks) {
c.LogAudit("fail - inappropriate permissions")
c.SetPermissionError(model.PermissionManageOthersOutgoingWebhooks)
return
}
if err := c.App.DeleteOutgoingWebhook(hook.Id); err != nil {
c.LogAudit("fail")
c.Err = err
return
}
auditRec.Success()
c.LogAudit("success")
ReturnStatusOK(w)
}