diff --git a/app/app.go b/app/app.go index f31fd76a48..e96f98e031 100644 --- a/app/app.go +++ b/app/app.go @@ -23,11 +23,13 @@ type App struct { Log *mlog.Logger - T goi18n.TranslateFunc - Session model.Session - RequestId string - IpAddress string - Path string + T goi18n.TranslateFunc + Session model.Session + RequestId string + IpAddress string + Path string + UserAgent string + AcceptLanguage string AccountMigration einterfaces.AccountMigrationInterface Cluster einterfaces.ClusterInterface diff --git a/app/channel.go b/app/channel.go index dca273636e..faf0fbf6eb 100644 --- a/app/channel.go +++ b/app/channel.go @@ -213,7 +213,7 @@ func (a *App) CreateChannel(channel *model.Channel, addMember bool) (*model.Chan if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil { a.Srv.Go(func() { - pluginContext := &plugin.Context{} + pluginContext := a.PluginContext() pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { hooks.ChannelHasBeenCreated(pluginContext, sc) return true @@ -243,7 +243,7 @@ func (a *App) GetOrCreateDirectChannel(userId, otherUserId string) (*model.Chann if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil { a.Srv.Go(func() { - pluginContext := &plugin.Context{} + pluginContext := a.PluginContext() pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { hooks.ChannelHasBeenCreated(pluginContext, channel) return true @@ -866,7 +866,7 @@ func (a *App) AddChannelMember(userId string, channel *model.Channel, userReques if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil { a.Srv.Go(func() { - pluginContext := &plugin.Context{} + pluginContext := a.PluginContext() pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { hooks.UserHasJoinedChannel(pluginContext, cm, userRequestor) return true @@ -1256,7 +1256,7 @@ func (a *App) JoinChannel(channel *model.Channel, userId string) *model.AppError if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil { a.Srv.Go(func() { - pluginContext := &plugin.Context{} + pluginContext := a.PluginContext() pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { hooks.UserHasJoinedChannel(pluginContext, cm, nil) return true @@ -1462,7 +1462,7 @@ func (a *App) removeUserFromChannel(userIdToRemove string, removerUserId string, } a.Srv.Go(func() { - pluginContext := &plugin.Context{} + pluginContext := a.PluginContext() pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { hooks.UserHasLeftChannel(pluginContext, cm, actorUser) return true diff --git a/app/file.go b/app/file.go index dccc177932..089f69630c 100644 --- a/app/file.go +++ b/app/file.go @@ -462,7 +462,7 @@ func (a *App) DoUploadFileExpectModification(now time.Time, rawTeamId string, ra if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil { var rejectionError *model.AppError - pluginContext := &plugin.Context{} + pluginContext := a.PluginContext() pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { var newBytes bytes.Buffer replacementInfo, rejectionReason := hooks.FileWillBeUploaded(pluginContext, info, bytes.NewReader(data), &newBytes) diff --git a/app/login.go b/app/login.go index 5e97f7f586..a12437190a 100644 --- a/app/login.go +++ b/app/login.go @@ -68,7 +68,7 @@ func (a *App) AuthenticateUserForLogin(id, loginId, password, mfaToken string, l if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil { var rejectionReason string - pluginContext := &plugin.Context{} + pluginContext := a.PluginContext() pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { rejectionReason = hooks.UserWillLogIn(pluginContext, user) return rejectionReason == "" @@ -79,7 +79,7 @@ func (a *App) AuthenticateUserForLogin(id, loginId, password, mfaToken string, l } a.Srv.Go(func() { - pluginContext := &plugin.Context{} + pluginContext := a.PluginContext() pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { hooks.UserHasLoggedIn(pluginContext, user) return true diff --git a/app/plugin_commands.go b/app/plugin_commands.go index 911f54cec1..5c8e6e12f4 100644 --- a/app/plugin_commands.go +++ b/app/plugin_commands.go @@ -9,7 +9,6 @@ import ( "strings" "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/plugin" ) type PluginCommand struct { @@ -106,7 +105,7 @@ func (a *App) ExecutePluginCommand(args *model.CommandArgs) (*model.Command, *mo if err != nil { return pc.Command, nil, model.NewAppError("ExecutePluginCommand", "model.plugin_command.error.app_error", nil, "err="+err.Error(), http.StatusInternalServerError) } - response, appErr := pluginHooks.ExecuteCommand(&plugin.Context{}, args) + response, appErr := pluginHooks.ExecuteCommand(a.PluginContext(), args) return pc.Command, response, appErr } } diff --git a/app/plugin_context.go b/app/plugin_context.go new file mode 100644 index 0000000000..2df1ae8b19 --- /dev/null +++ b/app/plugin_context.go @@ -0,0 +1,17 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package app + +import "github.com/mattermost/mattermost-server/plugin" + +func (a *App) PluginContext() *plugin.Context { + context := &plugin.Context{ + RequestId: a.RequestId, + SessionId: a.Session.Id, + IpAddress: a.IpAddress, + AcceptLanguage: a.AcceptLanguage, + UserAgent: a.UserAgent, + } + return context +} diff --git a/app/plugin_hooks_test.go b/app/plugin_hooks_test.go index ca3ff46cec..77391a2c4e 100644 --- a/app/plugin_hooks_test.go +++ b/app/plugin_hooks_test.go @@ -887,3 +887,62 @@ func TestErrorString(t *testing.T) { require.Equal(t, expectedErr, cause) }) } + +func TestHookContext(t *testing.T) { + th := Setup().InitBasic() + defer th.TearDown() + + // We don't actually have a session, we are faking it so just set something arbitrarily + th.App.Session.Id = model.NewId() + th.App.RequestId = model.NewId() + th.App.IpAddress = model.NewId() + th.App.AcceptLanguage = model.NewId() + th.App.UserAgent = model.NewId() + + var mockAPI plugintest.API + mockAPI.On("LoadPluginConfiguration", mock.Anything).Return(nil) + mockAPI.On("LogDebug", th.App.Session.Id).Return(nil) + mockAPI.On("LogInfo", th.App.RequestId).Return(nil) + mockAPI.On("LogError", th.App.IpAddress).Return(nil) + mockAPI.On("LogWarn", th.App.AcceptLanguage).Return(nil) + mockAPI.On("DeleteTeam", th.App.UserAgent).Return(nil) + + tearDown, _, _ := SetAppEnvironmentWithPlugins(t, + []string{ + ` + package main + + import ( + "github.com/mattermost/mattermost-server/plugin" + "github.com/mattermost/mattermost-server/model" + ) + + type MyPlugin struct { + plugin.MattermostPlugin + } + + func (p *MyPlugin) MessageHasBeenPosted(c *plugin.Context, post *model.Post) { + p.API.LogDebug(c.SessionId) + p.API.LogInfo(c.RequestId) + p.API.LogError(c.IpAddress) + p.API.LogWarn(c.AcceptLanguage) + p.API.DeleteTeam(c.UserAgent) + } + + func main() { + plugin.ClientMain(&MyPlugin{}) + } + `}, th.App, func(*model.Manifest) plugin.API { return &mockAPI }) + defer tearDown() + + post := &model.Post{ + UserId: th.BasicUser.Id, + ChannelId: th.BasicChannel.Id, + Message: "not this", + CreateAt: model.GetMillis() - 10000, + } + _, err := th.App.CreatePost(post, th.BasicChannel, false) + if err != nil { + t.Fatal(err) + } +} diff --git a/app/plugin_requests.go b/app/plugin_requests.go index e3ebc60421..18c72c4d62 100644 --- a/app/plugin_requests.go +++ b/app/plugin_requests.go @@ -42,7 +42,12 @@ func (a *App) ServePluginRequest(w http.ResponseWriter, r *http.Request) { func (a *App) servePluginRequest(w http.ResponseWriter, r *http.Request, handler func(*plugin.Context, http.ResponseWriter, *http.Request)) { token := "" - context := &plugin.Context{} + context := &plugin.Context{ + RequestId: model.NewId(), + IpAddress: utils.GetIpAddress(r), + AcceptLanguage: r.Header.Get("Accept-Language"), + UserAgent: r.UserAgent(), + } cookieAuth := false authHeader := r.Header.Get(model.HEADER_AUTH) diff --git a/app/post.go b/app/post.go index 74096d5a1b..778b733ccd 100644 --- a/app/post.go +++ b/app/post.go @@ -155,7 +155,7 @@ func (a *App) CreatePost(post *model.Post, channel *model.Channel, triggerWebhoo if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil { var rejectionError *model.AppError - pluginContext := &plugin.Context{} + pluginContext := a.PluginContext() pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { replacementPost, rejectionReason := hooks.MessageWillBePosted(pluginContext, post) if rejectionReason != "" { @@ -181,7 +181,7 @@ func (a *App) CreatePost(post *model.Post, channel *model.Channel, triggerWebhoo if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil { a.Srv.Go(func() { - pluginContext := &plugin.Context{} + pluginContext := a.PluginContext() pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { hooks.MessageHasBeenPosted(pluginContext, rpost) return true @@ -371,7 +371,7 @@ func (a *App) UpdatePost(post *model.Post, safeUpdate bool) (*model.Post, *model if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil { var rejectionReason string - pluginContext := &plugin.Context{} + pluginContext := a.PluginContext() pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { newPost, rejectionReason = hooks.MessageWillBeUpdated(pluginContext, newPost, oldPost) return post != nil @@ -389,7 +389,7 @@ func (a *App) UpdatePost(post *model.Post, safeUpdate bool) (*model.Post, *model if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil { a.Srv.Go(func() { - pluginContext := &plugin.Context{} + pluginContext := a.PluginContext() pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { hooks.MessageHasBeenUpdated(pluginContext, newPost, oldPost) return true diff --git a/app/team.go b/app/team.go index 457f839ca7..066d1ccae8 100644 --- a/app/team.go +++ b/app/team.go @@ -468,7 +468,7 @@ func (a *App) JoinUserToTeam(team *model.Team, user *model.User, userRequestorId } a.Srv.Go(func() { - pluginContext := &plugin.Context{} + pluginContext := a.PluginContext() pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { hooks.UserHasJoinedTeam(pluginContext, tm, actor) return true @@ -791,7 +791,7 @@ func (a *App) LeaveTeam(team *model.Team, user *model.User, requestorId string) } a.Srv.Go(func() { - pluginContext := &plugin.Context{} + pluginContext := a.PluginContext() pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { hooks.UserHasLeftTeam(pluginContext, teamMember, actor) return true diff --git a/plugin/context.go b/plugin/context.go index ec3f8b65ec..288739e7c3 100644 --- a/plugin/context.go +++ b/plugin/context.go @@ -4,8 +4,12 @@ package plugin // Context passes through metadata about the request or hook event. -// -// It is currently a placeholder while the implementation details are sorted out. +// For requests this is built in app/plugin_requests.go +// For hooks, app.PluginContext() is called. type Context struct { - SessionId string + SessionId string + RequestId string + IpAddress string + AcceptLanguage string + UserAgent string } diff --git a/web/context.go b/web/context.go index 40f9b8433f..1744ae3905 100644 --- a/web/context.go +++ b/web/context.go @@ -12,7 +12,6 @@ import ( "github.com/mattermost/mattermost-server/app" "github.com/mattermost/mattermost-server/mlog" "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/plugin" "github.com/mattermost/mattermost-server/utils" ) @@ -520,11 +519,3 @@ func (c *Context) RequireRoleName() *Context { return c } - -func (c *Context) ToPluginContext() *plugin.Context { - return &plugin.Context{ - //sessionId: c.Session.Id, - //requestId: c.RequestId, - //userIp: c.IpAddress, - } -} diff --git a/web/handlers.go b/web/handlers.go index ab862270c0..93669ccf24 100644 --- a/web/handlers.go +++ b/web/handlers.go @@ -56,6 +56,8 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { c.App.T, _ = utils.GetTranslationsAndLocale(w, r) c.App.RequestId = model.NewId() c.App.IpAddress = utils.GetIpAddress(r) + c.App.UserAgent = r.UserAgent() + c.App.AcceptLanguage = r.Header.Get("Accept-Language") c.Params = ParamsFromRequest(r) c.App.Path = r.URL.Path c.Log = c.App.Log