[MM-40935] Add OnInstall() plugin hook (#19499)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
2d986ef920
Коммит
6dab9eadf8
@@ -897,7 +897,7 @@ func completeOnboarding(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
auditRec.AddMeta("install_plugin", onboardingRequest.InstallPlugins)
|
auditRec.AddMeta("install_plugin", onboardingRequest.InstallPlugins)
|
||||||
|
|
||||||
appErr := c.App.CompleteOnboarding(onboardingRequest)
|
appErr := c.App.CompleteOnboarding(c.AppContext, onboardingRequest)
|
||||||
if appErr != nil {
|
if appErr != nil {
|
||||||
c.Err = appErr
|
c.Err = appErr
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -438,7 +438,7 @@ type AppIface interface {
|
|||||||
CompareAndDeletePluginKey(pluginID string, key string, oldValue []byte) (bool, *model.AppError)
|
CompareAndDeletePluginKey(pluginID string, key string, oldValue []byte) (bool, *model.AppError)
|
||||||
CompareAndSetPluginKey(pluginID string, key string, oldValue, newValue []byte) (bool, *model.AppError)
|
CompareAndSetPluginKey(pluginID string, key string, oldValue, newValue []byte) (bool, *model.AppError)
|
||||||
CompleteOAuth(c *request.Context, service string, body io.ReadCloser, teamID string, props map[string]string, tokenUser *model.User) (*model.User, *model.AppError)
|
CompleteOAuth(c *request.Context, service string, body io.ReadCloser, teamID string, props map[string]string, tokenUser *model.User) (*model.User, *model.AppError)
|
||||||
CompleteOnboarding(request *model.CompleteOnboardingRequest) *model.AppError
|
CompleteOnboarding(c *request.Context, request *model.CompleteOnboardingRequest) *model.AppError
|
||||||
CompleteSwitchWithOAuth(service string, userData io.Reader, email string, tokenUser *model.User) (*model.User, *model.AppError)
|
CompleteSwitchWithOAuth(service string, userData io.Reader, email string, tokenUser *model.User) (*model.User, *model.AppError)
|
||||||
Compliance() einterfaces.ComplianceInterface
|
Compliance() einterfaces.ComplianceInterface
|
||||||
Config() *model.Config
|
Config() *model.Config
|
||||||
|
|||||||
@@ -7,18 +7,21 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/mattermost/mattermost-server/v6/app/request"
|
||||||
"github.com/mattermost/mattermost-server/v6/model"
|
"github.com/mattermost/mattermost-server/v6/model"
|
||||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *App) CompleteOnboarding(request *model.CompleteOnboardingRequest) *model.AppError {
|
func (a *App) CompleteOnboarding(c *request.Context, request *model.CompleteOnboardingRequest) *model.AppError {
|
||||||
var wg sync.WaitGroup
|
pluginsEnvironment := a.Channels().GetPluginsEnvironment()
|
||||||
|
if pluginsEnvironment == nil {
|
||||||
if !*a.Config().PluginSettings.Enable {
|
return model.NewAppError("CompleteOnboarding", "app.plugin.disabled.app_error", nil, "", http.StatusNotImplemented)
|
||||||
return model.NewAppError("completeOnboarding", "app.plugin.disabled.app_error", nil, "", http.StatusNotImplemented)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, id := range request.InstallPlugins {
|
pluginContext := pluginContext(c)
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for _, pluginID := range request.InstallPlugins {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
|
|
||||||
go func(id string) {
|
go func(id string) {
|
||||||
@@ -37,7 +40,20 @@ func (a *App) CompleteOnboarding(request *model.CompleteOnboardingRequest) *mode
|
|||||||
mlog.Error("Failed to enable plugin for onboarding", mlog.String("id", id), mlog.Err(appErr))
|
mlog.Error("Failed to enable plugin for onboarding", mlog.String("id", id), mlog.Err(appErr))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}(id)
|
|
||||||
|
hooks, err := pluginsEnvironment.HooksForPlugin(id)
|
||||||
|
if err != nil {
|
||||||
|
mlog.Warn("Getting hooks for plugin failed", mlog.String("plugin_id", id), mlog.Err(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
event := model.OnInstallEvent{
|
||||||
|
UserId: c.Session().UserId,
|
||||||
|
}
|
||||||
|
if err = hooks.OnInstall(pluginContext, event); err != nil {
|
||||||
|
mlog.Error("Plugin OnInstall hook failed", mlog.String("plugin_id", id), mlog.Err(err))
|
||||||
|
}
|
||||||
|
}(pluginID)
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|||||||
@@ -1671,7 +1671,7 @@ func (a *OpenTracingAppLayer) CompleteOAuth(c *request.Context, service string,
|
|||||||
return resultVar0, resultVar1
|
return resultVar0, resultVar1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) CompleteOnboarding(request *model.CompleteOnboardingRequest) *model.AppError {
|
func (a *OpenTracingAppLayer) CompleteOnboarding(c *request.Context, request *model.CompleteOnboardingRequest) *model.AppError {
|
||||||
origCtx := a.ctx
|
origCtx := a.ctx
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CompleteOnboarding")
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CompleteOnboarding")
|
||||||
|
|
||||||
@@ -1683,7 +1683,7 @@ func (a *OpenTracingAppLayer) CompleteOnboarding(request *model.CompleteOnboardi
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
resultVar0 := a.app.CompleteOnboarding(request)
|
resultVar0 := a.app.CompleteOnboarding(c, request)
|
||||||
|
|
||||||
if resultVar0 != nil {
|
if resultVar0 != nil {
|
||||||
span.LogFields(spanlog.Error(resultVar0))
|
span.LogFields(spanlog.Error(resultVar0))
|
||||||
|
|||||||
9
model/plugin_on_install_event.go
Обычный файл
9
model/plugin_on_install_event.go
Обычный файл
@@ -0,0 +1,9 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
package model
|
||||||
|
|
||||||
|
// OnInstallEvent is sent to the plugin when it gets installed.
|
||||||
|
type OnInstallEvent struct {
|
||||||
|
UserId string // The user who installed the plugin
|
||||||
|
}
|
||||||
@@ -706,6 +706,42 @@ func (s *hooksRPCServer) RunDataRetention(args *Z_RunDataRetentionArgs, returns
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
hookNameToId["OnInstall"] = OnInstallID
|
||||||
|
}
|
||||||
|
|
||||||
|
type Z_OnInstallArgs struct {
|
||||||
|
A *Context
|
||||||
|
B model.OnInstallEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
type Z_OnInstallReturns struct {
|
||||||
|
A error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *hooksRPCClient) OnInstall(c *Context, event model.OnInstallEvent) error {
|
||||||
|
_args := &Z_OnInstallArgs{c, event}
|
||||||
|
_returns := &Z_OnInstallReturns{}
|
||||||
|
if g.implemented[OnInstallID] {
|
||||||
|
if err := g.client.Call("Plugin.OnInstall", _args, _returns); err != nil {
|
||||||
|
g.log.Error("RPC call OnInstall to plugin failed.", mlog.Err(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _returns.A
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hooksRPCServer) OnInstall(args *Z_OnInstallArgs, returns *Z_OnInstallReturns) error {
|
||||||
|
if hook, ok := s.impl.(interface {
|
||||||
|
OnInstall(c *Context, event model.OnInstallEvent) error
|
||||||
|
}); ok {
|
||||||
|
returns.A = hook.OnInstall(args.A, args.B)
|
||||||
|
returns.A = encodableError(returns.A)
|
||||||
|
} else {
|
||||||
|
return encodableError(fmt.Errorf("Hook OnInstall called but not implemented."))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type Z_RegisterCommandArgs struct {
|
type Z_RegisterCommandArgs struct {
|
||||||
A *model.Command
|
A *model.Command
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ const (
|
|||||||
OnWebSocketDisconnectID = 22
|
OnWebSocketDisconnectID = 22
|
||||||
WebSocketMessageHasBeenPostedID = 23
|
WebSocketMessageHasBeenPostedID = 23
|
||||||
RunDataRetentionID = 24
|
RunDataRetentionID = 24
|
||||||
|
OnInstallID = 25
|
||||||
TotalHooksID = iota
|
TotalHooksID = iota
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -249,4 +250,12 @@ type Hooks interface {
|
|||||||
//
|
//
|
||||||
// Minimum server version: 6.4
|
// Minimum server version: 6.4
|
||||||
RunDataRetention(nowTime, batchSize int64) (int64, error)
|
RunDataRetention(nowTime, batchSize int64) (int64, error)
|
||||||
|
|
||||||
|
// OnInstall is invoked after the installation of a plugin as part of the onboarding.
|
||||||
|
// It's called on every installation, not only once.
|
||||||
|
//
|
||||||
|
// In the future, other plugin installation methods will trigger this hook, e.g. an installation via the Marketplace.
|
||||||
|
//
|
||||||
|
// Minimum server version: 6.5
|
||||||
|
OnInstall(c *Context, event model.OnInstallEvent) error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -193,3 +193,10 @@ func (hooks *hooksTimerLayer) RunDataRetention(nowTime, batchSize int64) (int64,
|
|||||||
hooks.recordTime(startTime, "RunDataRetention", _returnsB == nil)
|
hooks.recordTime(startTime, "RunDataRetention", _returnsB == nil)
|
||||||
return _returnsA, _returnsB
|
return _returnsA, _returnsB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (hooks *hooksTimerLayer) OnInstall(c *Context, event model.OnInstallEvent) error {
|
||||||
|
startTime := timePkg.Now()
|
||||||
|
_returnsA := hooks.hooksImpl.OnInstall(c, event)
|
||||||
|
hooks.recordTime(startTime, "OnInstall", _returnsA == nil)
|
||||||
|
return _returnsA
|
||||||
|
}
|
||||||
|
|||||||
@@ -194,6 +194,20 @@ func (_m *Hooks) OnDeactivate() error {
|
|||||||
return r0
|
return r0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OnInstall provides a mock function with given fields: c, event
|
||||||
|
func (_m *Hooks) OnInstall(c *plugin.Context, event model.OnInstallEvent) error {
|
||||||
|
ret := _m.Called(c, event)
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(*plugin.Context, model.OnInstallEvent) error); ok {
|
||||||
|
r0 = rf(c, event)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
// OnPluginClusterEvent provides a mock function with given fields: c, ev
|
// OnPluginClusterEvent provides a mock function with given fields: c, ev
|
||||||
func (_m *Hooks) OnPluginClusterEvent(c *plugin.Context, ev model.PluginClusterEvent) {
|
func (_m *Hooks) OnPluginClusterEvent(c *plugin.Context, ev model.PluginClusterEvent) {
|
||||||
_m.Called(c, ev)
|
_m.Called(c, ev)
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user