[MM-40935] Add OnInstall() plugin hook (#19499)

Этот коммит содержится в:
Ben Schumacher
2022-02-09 20:29:00 +01:00
коммит произвёл GitHub
родитель 2d986ef920
Коммит 6dab9eadf8
9 изменённых файлов: 102 добавлений и 11 удалений

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

@@ -897,7 +897,7 @@ func completeOnboarding(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec.AddMeta("install_plugin", onboardingRequest.InstallPlugins)
appErr := c.App.CompleteOnboarding(onboardingRequest)
appErr := c.App.CompleteOnboarding(c.AppContext, onboardingRequest)
if appErr != nil {
c.Err = appErr
return

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

@@ -438,7 +438,7 @@ type AppIface interface {
CompareAndDeletePluginKey(pluginID string, key string, oldValue []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)
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)
Compliance() einterfaces.ComplianceInterface
Config() *model.Config

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

@@ -7,18 +7,21 @@ import (
"net/http"
"sync"
"github.com/mattermost/mattermost-server/v6/app/request"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
)
func (a *App) CompleteOnboarding(request *model.CompleteOnboardingRequest) *model.AppError {
var wg sync.WaitGroup
if !*a.Config().PluginSettings.Enable {
return model.NewAppError("completeOnboarding", "app.plugin.disabled.app_error", nil, "", http.StatusNotImplemented)
func (a *App) CompleteOnboarding(c *request.Context, request *model.CompleteOnboardingRequest) *model.AppError {
pluginsEnvironment := a.Channels().GetPluginsEnvironment()
if pluginsEnvironment == nil {
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)
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))
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()

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

@@ -1671,7 +1671,7 @@ func (a *OpenTracingAppLayer) CompleteOAuth(c *request.Context, service string,
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
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CompleteOnboarding")
@@ -1683,7 +1683,7 @@ func (a *OpenTracingAppLayer) CompleteOnboarding(request *model.CompleteOnboardi
}()
defer span.Finish()
resultVar0 := a.app.CompleteOnboarding(request)
resultVar0 := a.app.CompleteOnboarding(c, request)
if resultVar0 != nil {
span.LogFields(spanlog.Error(resultVar0))

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
}
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 {
A *model.Command
}

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

@@ -40,6 +40,7 @@ const (
OnWebSocketDisconnectID = 22
WebSocketMessageHasBeenPostedID = 23
RunDataRetentionID = 24
OnInstallID = 25
TotalHooksID = iota
)
@@ -249,4 +250,12 @@ type Hooks interface {
//
// Minimum server version: 6.4
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)
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
}
// 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
func (_m *Hooks) OnPluginClusterEvent(c *plugin.Context, ev model.PluginClusterEvent) {
_m.Called(c, ev)