MM-12855 Plugin Context (#9922)
* Basic plugin context. * Adding more useful fields to plugin context. * Fix spelling Co-Authored-By: crspeller <crspeller@gmail.com> * Fixing location of context creation.
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
de5440d979
Коммит
aba194188f
@@ -28,6 +28,8 @@ type App struct {
|
|||||||
RequestId string
|
RequestId string
|
||||||
IpAddress string
|
IpAddress string
|
||||||
Path string
|
Path string
|
||||||
|
UserAgent string
|
||||||
|
AcceptLanguage string
|
||||||
|
|
||||||
AccountMigration einterfaces.AccountMigrationInterface
|
AccountMigration einterfaces.AccountMigrationInterface
|
||||||
Cluster einterfaces.ClusterInterface
|
Cluster einterfaces.ClusterInterface
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ func (a *App) CreateChannel(channel *model.Channel, addMember bool) (*model.Chan
|
|||||||
|
|
||||||
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
a.Srv.Go(func() {
|
a.Srv.Go(func() {
|
||||||
pluginContext := &plugin.Context{}
|
pluginContext := a.PluginContext()
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.ChannelHasBeenCreated(pluginContext, sc)
|
hooks.ChannelHasBeenCreated(pluginContext, sc)
|
||||||
return true
|
return true
|
||||||
@@ -243,7 +243,7 @@ func (a *App) GetOrCreateDirectChannel(userId, otherUserId string) (*model.Chann
|
|||||||
|
|
||||||
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
a.Srv.Go(func() {
|
a.Srv.Go(func() {
|
||||||
pluginContext := &plugin.Context{}
|
pluginContext := a.PluginContext()
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.ChannelHasBeenCreated(pluginContext, channel)
|
hooks.ChannelHasBeenCreated(pluginContext, channel)
|
||||||
return true
|
return true
|
||||||
@@ -866,7 +866,7 @@ func (a *App) AddChannelMember(userId string, channel *model.Channel, userReques
|
|||||||
|
|
||||||
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
a.Srv.Go(func() {
|
a.Srv.Go(func() {
|
||||||
pluginContext := &plugin.Context{}
|
pluginContext := a.PluginContext()
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.UserHasJoinedChannel(pluginContext, cm, userRequestor)
|
hooks.UserHasJoinedChannel(pluginContext, cm, userRequestor)
|
||||||
return true
|
return true
|
||||||
@@ -1256,7 +1256,7 @@ func (a *App) JoinChannel(channel *model.Channel, userId string) *model.AppError
|
|||||||
|
|
||||||
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
a.Srv.Go(func() {
|
a.Srv.Go(func() {
|
||||||
pluginContext := &plugin.Context{}
|
pluginContext := a.PluginContext()
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.UserHasJoinedChannel(pluginContext, cm, nil)
|
hooks.UserHasJoinedChannel(pluginContext, cm, nil)
|
||||||
return true
|
return true
|
||||||
@@ -1462,7 +1462,7 @@ func (a *App) removeUserFromChannel(userIdToRemove string, removerUserId string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
a.Srv.Go(func() {
|
a.Srv.Go(func() {
|
||||||
pluginContext := &plugin.Context{}
|
pluginContext := a.PluginContext()
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.UserHasLeftChannel(pluginContext, cm, actorUser)
|
hooks.UserHasLeftChannel(pluginContext, cm, actorUser)
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -462,7 +462,7 @@ func (a *App) DoUploadFileExpectModification(now time.Time, rawTeamId string, ra
|
|||||||
|
|
||||||
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
var rejectionError *model.AppError
|
var rejectionError *model.AppError
|
||||||
pluginContext := &plugin.Context{}
|
pluginContext := a.PluginContext()
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
||||||
var newBytes bytes.Buffer
|
var newBytes bytes.Buffer
|
||||||
replacementInfo, rejectionReason := hooks.FileWillBeUploaded(pluginContext, info, bytes.NewReader(data), &newBytes)
|
replacementInfo, rejectionReason := hooks.FileWillBeUploaded(pluginContext, info, bytes.NewReader(data), &newBytes)
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ func (a *App) AuthenticateUserForLogin(id, loginId, password, mfaToken string, l
|
|||||||
|
|
||||||
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
var rejectionReason string
|
var rejectionReason string
|
||||||
pluginContext := &plugin.Context{}
|
pluginContext := a.PluginContext()
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
||||||
rejectionReason = hooks.UserWillLogIn(pluginContext, user)
|
rejectionReason = hooks.UserWillLogIn(pluginContext, user)
|
||||||
return rejectionReason == ""
|
return rejectionReason == ""
|
||||||
@@ -79,7 +79,7 @@ func (a *App) AuthenticateUserForLogin(id, loginId, password, mfaToken string, l
|
|||||||
}
|
}
|
||||||
|
|
||||||
a.Srv.Go(func() {
|
a.Srv.Go(func() {
|
||||||
pluginContext := &plugin.Context{}
|
pluginContext := a.PluginContext()
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.UserHasLoggedIn(pluginContext, user)
|
hooks.UserHasLoggedIn(pluginContext, user)
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/mattermost/mattermost-server/model"
|
"github.com/mattermost/mattermost-server/model"
|
||||||
"github.com/mattermost/mattermost-server/plugin"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type PluginCommand struct {
|
type PluginCommand struct {
|
||||||
@@ -106,7 +105,7 @@ func (a *App) ExecutePluginCommand(args *model.CommandArgs) (*model.Command, *mo
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return pc.Command, nil, model.NewAppError("ExecutePluginCommand", "model.plugin_command.error.app_error", nil, "err="+err.Error(), http.StatusInternalServerError)
|
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
|
return pc.Command, response, appErr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
17
app/plugin_context.go
Обычный файл
17
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
|
||||||
|
}
|
||||||
@@ -887,3 +887,62 @@ func TestErrorString(t *testing.T) {
|
|||||||
require.Equal(t, expectedErr, cause)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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)) {
|
func (a *App) servePluginRequest(w http.ResponseWriter, r *http.Request, handler func(*plugin.Context, http.ResponseWriter, *http.Request)) {
|
||||||
token := ""
|
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
|
cookieAuth := false
|
||||||
|
|
||||||
authHeader := r.Header.Get(model.HEADER_AUTH)
|
authHeader := r.Header.Get(model.HEADER_AUTH)
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ func (a *App) CreatePost(post *model.Post, channel *model.Channel, triggerWebhoo
|
|||||||
|
|
||||||
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
var rejectionError *model.AppError
|
var rejectionError *model.AppError
|
||||||
pluginContext := &plugin.Context{}
|
pluginContext := a.PluginContext()
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
||||||
replacementPost, rejectionReason := hooks.MessageWillBePosted(pluginContext, post)
|
replacementPost, rejectionReason := hooks.MessageWillBePosted(pluginContext, post)
|
||||||
if rejectionReason != "" {
|
if rejectionReason != "" {
|
||||||
@@ -181,7 +181,7 @@ func (a *App) CreatePost(post *model.Post, channel *model.Channel, triggerWebhoo
|
|||||||
|
|
||||||
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
a.Srv.Go(func() {
|
a.Srv.Go(func() {
|
||||||
pluginContext := &plugin.Context{}
|
pluginContext := a.PluginContext()
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.MessageHasBeenPosted(pluginContext, rpost)
|
hooks.MessageHasBeenPosted(pluginContext, rpost)
|
||||||
return true
|
return true
|
||||||
@@ -371,7 +371,7 @@ func (a *App) UpdatePost(post *model.Post, safeUpdate bool) (*model.Post, *model
|
|||||||
|
|
||||||
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
var rejectionReason string
|
var rejectionReason string
|
||||||
pluginContext := &plugin.Context{}
|
pluginContext := a.PluginContext()
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
||||||
newPost, rejectionReason = hooks.MessageWillBeUpdated(pluginContext, newPost, oldPost)
|
newPost, rejectionReason = hooks.MessageWillBeUpdated(pluginContext, newPost, oldPost)
|
||||||
return post != nil
|
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 {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
a.Srv.Go(func() {
|
a.Srv.Go(func() {
|
||||||
pluginContext := &plugin.Context{}
|
pluginContext := a.PluginContext()
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.MessageHasBeenUpdated(pluginContext, newPost, oldPost)
|
hooks.MessageHasBeenUpdated(pluginContext, newPost, oldPost)
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -468,7 +468,7 @@ func (a *App) JoinUserToTeam(team *model.Team, user *model.User, userRequestorId
|
|||||||
}
|
}
|
||||||
|
|
||||||
a.Srv.Go(func() {
|
a.Srv.Go(func() {
|
||||||
pluginContext := &plugin.Context{}
|
pluginContext := a.PluginContext()
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.UserHasJoinedTeam(pluginContext, tm, actor)
|
hooks.UserHasJoinedTeam(pluginContext, tm, actor)
|
||||||
return true
|
return true
|
||||||
@@ -791,7 +791,7 @@ func (a *App) LeaveTeam(team *model.Team, user *model.User, requestorId string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
a.Srv.Go(func() {
|
a.Srv.Go(func() {
|
||||||
pluginContext := &plugin.Context{}
|
pluginContext := a.PluginContext()
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.UserHasLeftTeam(pluginContext, teamMember, actor)
|
hooks.UserHasLeftTeam(pluginContext, teamMember, actor)
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -4,8 +4,12 @@
|
|||||||
package plugin
|
package plugin
|
||||||
|
|
||||||
// Context passes through metadata about the request or hook event.
|
// Context passes through metadata about the request or hook event.
|
||||||
//
|
// For requests this is built in app/plugin_requests.go
|
||||||
// It is currently a placeholder while the implementation details are sorted out.
|
// For hooks, app.PluginContext() is called.
|
||||||
type Context struct {
|
type Context struct {
|
||||||
SessionId string
|
SessionId string
|
||||||
|
RequestId string
|
||||||
|
IpAddress string
|
||||||
|
AcceptLanguage string
|
||||||
|
UserAgent string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import (
|
|||||||
"github.com/mattermost/mattermost-server/app"
|
"github.com/mattermost/mattermost-server/app"
|
||||||
"github.com/mattermost/mattermost-server/mlog"
|
"github.com/mattermost/mattermost-server/mlog"
|
||||||
"github.com/mattermost/mattermost-server/model"
|
"github.com/mattermost/mattermost-server/model"
|
||||||
"github.com/mattermost/mattermost-server/plugin"
|
|
||||||
"github.com/mattermost/mattermost-server/utils"
|
"github.com/mattermost/mattermost-server/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -520,11 +519,3 @@ func (c *Context) RequireRoleName() *Context {
|
|||||||
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) ToPluginContext() *plugin.Context {
|
|
||||||
return &plugin.Context{
|
|
||||||
//sessionId: c.Session.Id,
|
|
||||||
//requestId: c.RequestId,
|
|
||||||
//userIp: c.IpAddress,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
c.App.T, _ = utils.GetTranslationsAndLocale(w, r)
|
c.App.T, _ = utils.GetTranslationsAndLocale(w, r)
|
||||||
c.App.RequestId = model.NewId()
|
c.App.RequestId = model.NewId()
|
||||||
c.App.IpAddress = utils.GetIpAddress(r)
|
c.App.IpAddress = utils.GetIpAddress(r)
|
||||||
|
c.App.UserAgent = r.UserAgent()
|
||||||
|
c.App.AcceptLanguage = r.Header.Get("Accept-Language")
|
||||||
c.Params = ParamsFromRequest(r)
|
c.Params = ParamsFromRequest(r)
|
||||||
c.App.Path = r.URL.Path
|
c.App.Path = r.URL.Path
|
||||||
c.Log = c.App.Log
|
c.Log = c.App.Log
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user