[MM-61140] Allow plugins to add Support Packet data without UI elements (#28833)

Co-authored-by: Ibrahim Serdar Acikgoz <serdaracikgoz86@gmail.com>
Этот коммит содержится в:
Ben Schumacher
2024-11-13 11:20:39 +01:00
коммит произвёл GitHub
родитель 9fed818200
Коммит 053d0b5f0a
21 изменённых файлов: 70 добавлений и 58 удалений

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

@@ -294,7 +294,7 @@ func (a *App) CreateChannel(c request.CTX, channel *model.Channel, addMember boo
a.Srv().Go(func() { a.Srv().Go(func() {
pluginContext := pluginContext(c) pluginContext := pluginContext(c)
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.ChannelHasBeenCreated(pluginContext, sc) hooks.ChannelHasBeenCreated(pluginContext, sc)
return true return true
}, plugin.ChannelHasBeenCreatedID) }, plugin.ChannelHasBeenCreatedID)
@@ -378,7 +378,7 @@ func (a *App) handleCreationEvent(c request.CTX, userID, otherUserID string, cha
a.Srv().Go(func() { a.Srv().Go(func() {
pluginContext := pluginContext(c) pluginContext := pluginContext(c)
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.ChannelHasBeenCreated(pluginContext, channel) hooks.ChannelHasBeenCreated(pluginContext, channel)
return true return true
}, plugin.ChannelHasBeenCreatedID) }, plugin.ChannelHasBeenCreatedID)
@@ -600,7 +600,7 @@ func (a *App) createGroupChannel(c request.CTX, userIDs []string) (*model.Channe
a.Srv().Go(func() { a.Srv().Go(func() {
pluginContext := pluginContext(c) pluginContext := pluginContext(c)
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.ChannelHasBeenCreated(pluginContext, channel) hooks.ChannelHasBeenCreated(pluginContext, channel)
return true return true
}, plugin.ChannelHasBeenCreatedID) }, plugin.ChannelHasBeenCreatedID)
@@ -1679,7 +1679,7 @@ func (a *App) AddChannelMember(c request.CTX, userID string, channel *model.Chan
a.Srv().Go(func() { a.Srv().Go(func() {
pluginContext := pluginContext(c) pluginContext := pluginContext(c)
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.UserHasJoinedChannel(pluginContext, cm, userRequestor) hooks.UserHasJoinedChannel(pluginContext, cm, userRequestor)
return true return true
}, plugin.UserHasJoinedChannelID) }, plugin.UserHasJoinedChannelID)
@@ -2284,7 +2284,7 @@ func (a *App) JoinChannel(c request.CTX, channel *model.Channel, userID string)
a.Srv().Go(func() { a.Srv().Go(func() {
pluginContext := pluginContext(c) pluginContext := pluginContext(c)
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.UserHasJoinedChannel(pluginContext, cm, nil) hooks.UserHasJoinedChannel(pluginContext, cm, nil)
return true return true
}, plugin.UserHasJoinedChannelID) }, plugin.UserHasJoinedChannelID)
@@ -2598,7 +2598,7 @@ func (a *App) removeUserFromChannel(c request.CTX, userIDToRemove string, remove
a.Srv().Go(func() { a.Srv().Go(func() {
pluginContext := pluginContext(c) pluginContext := pluginContext(c)
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.UserHasLeftChannel(pluginContext, cm, actorUser) hooks.UserHasLeftChannel(pluginContext, cm, actorUser)
return true return true
}, plugin.UserHasLeftChannelID) }, plugin.UserHasLeftChannelID)

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

@@ -219,7 +219,7 @@ func (ch *Channels) RemoveConfigListener(id string) {
ch.cfgSvc.RemoveConfigListener(id) ch.cfgSvc.RemoveConfigListener(id)
} }
func (ch *Channels) RunMultiHook(hookRunnerFunc func(hooks plugin.Hooks) bool, hookId int) { func (ch *Channels) RunMultiHook(hookRunnerFunc func(hooks plugin.Hooks, manifest *model.Manifest) bool, hookId int) {
if env := ch.GetPluginsEnvironment(); env != nil { if env := ch.GetPluginsEnvironment(); env != nil {
env.RunMultiPluginHook(hookRunnerFunc, hookId) env.RunMultiPluginHook(hookRunnerFunc, hookId)
} }

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

@@ -1039,7 +1039,7 @@ func (a *App) DoUploadFileExpectModification(c request.CTX, now time.Time, rawTe
var rejectionError *model.AppError var rejectionError *model.AppError
pluginContext := pluginContext(c) pluginContext := pluginContext(c)
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) 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)
if rejectionReason != "" { if rejectionReason != "" {

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

@@ -159,7 +159,7 @@ func (a *App) GetUserForLogin(c request.CTX, id, loginId string) (*model.User, *
func (a *App) DoLogin(c request.CTX, w http.ResponseWriter, r *http.Request, user *model.User, deviceID string, isMobile, isOAuthUser, isSaml bool) (*model.Session, *model.AppError) { func (a *App) DoLogin(c request.CTX, w http.ResponseWriter, r *http.Request, user *model.User, deviceID string, isMobile, isOAuthUser, isSaml bool) (*model.Session, *model.AppError) {
var rejectionReason string var rejectionReason string
pluginContext := pluginContext(c) pluginContext := pluginContext(c)
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
rejectionReason = hooks.UserWillLogIn(pluginContext, user) rejectionReason = hooks.UserWillLogIn(pluginContext, user)
return rejectionReason == "" return rejectionReason == ""
}, plugin.UserWillLogInID) }, plugin.UserWillLogInID)
@@ -230,7 +230,7 @@ func (a *App) DoLogin(c request.CTX, w http.ResponseWriter, r *http.Request, use
} }
a.Srv().Go(func() { a.Srv().Go(func() {
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.UserHasLoggedIn(pluginContext, user) hooks.UserHasLoggedIn(pluginContext, user)
return true return true
}, plugin.UserHasLoggedInID) }, plugin.UserHasLoggedInID)

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

@@ -91,7 +91,7 @@ func (a *App) sendPushNotificationSync(c request.CTX, post *model.Post, user *mo
func (a *App) sendPushNotificationToAllSessions(rctx request.CTX, msg *model.PushNotification, userID string, skipSessionId string) *model.AppError { func (a *App) sendPushNotificationToAllSessions(rctx request.CTX, msg *model.PushNotification, userID string, skipSessionId string) *model.AppError {
rejectionReason := "" rejectionReason := ""
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
var replacementNotification *model.PushNotification var replacementNotification *model.PushNotification
replacementNotification, rejectionReason = hooks.NotificationWillBePushed(msg, userID) replacementNotification, rejectionReason = hooks.NotificationWillBePushed(msg, userID)
if rejectionReason != "" { if rejectionReason != "" {

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

@@ -73,7 +73,7 @@ func (ps *PlatformService) IsConfigReadOnly() bool {
func (ps *PlatformService) SaveConfig(newCfg *model.Config, sendConfigChangeClusterMessage bool) (*model.Config, *model.Config, *model.AppError) { func (ps *PlatformService) SaveConfig(newCfg *model.Config, sendConfigChangeClusterMessage bool) (*model.Config, *model.Config, *model.AppError) {
if ps.pluginEnv != nil { if ps.pluginEnv != nil {
var hookErr error var hookErr error
ps.pluginEnv.RunMultiHook(func(hooks plugin.Hooks) bool { ps.pluginEnv.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
var cfg *model.Config var cfg *model.Config
cfg, hookErr = hooks.ConfigurationWillBeSaved(newCfg) cfg, hookErr = hooks.ConfigurationWillBeSaved(newCfg)
if hookErr == nil && cfg != nil { if hookErr == nil && cfg != nil {

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

@@ -106,7 +106,7 @@ type PlatformService struct {
} }
type HookRunner interface { type HookRunner interface {
RunMultiHook(hookRunnerFunc func(hooks plugin.Hooks) bool, hookId int) RunMultiHook(hookRunnerFunc func(hooks plugin.Hooks, _ *model.Manifest) bool, hookId int)
GetPluginsEnvironment() *plugin.Environment GetPluginsEnvironment() *plugin.Environment
} }

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

@@ -265,7 +265,7 @@ func (ps *PlatformService) NewWebConn(cfg *WebConnConfig, suite SuiteIFace, runn
wc.SetActiveThreadViewThreadChannelID(UnsetPresenceIndicator) wc.SetActiveThreadViewThreadChannelID(UnsetPresenceIndicator)
ps.Go(func() { ps.Go(func() {
runner.RunMultiHook(func(hooks plugin.Hooks) bool { runner.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.OnWebSocketConnect(wc.GetConnectionID(), userID) hooks.OnWebSocketConnect(wc.GetConnectionID(), userID)
return true return true
}, plugin.OnWebSocketConnectID) }, plugin.OnWebSocketConnectID)
@@ -278,7 +278,7 @@ func (wc *WebConn) pluginPostedConsumer(wg *sync.WaitGroup) {
defer wg.Done() defer wg.Done()
for msg := range wc.pluginPosted { for msg := range wc.pluginPosted {
wc.HookRunner.RunMultiHook(func(hooks plugin.Hooks) bool { wc.HookRunner.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.WebSocketMessageHasBeenPosted(msg.connectionID, msg.userID, msg.req) hooks.WebSocketMessageHasBeenPosted(msg.connectionID, msg.userID, msg.req)
return true return true
}, plugin.WebSocketMessageHasBeenPostedID) }, plugin.WebSocketMessageHasBeenPostedID)
@@ -417,7 +417,7 @@ func (wc *WebConn) Pump() {
userID := wc.UserId userID := wc.UserId
wc.Platform.Go(func() { wc.Platform.Go(func() {
wc.HookRunner.RunMultiHook(func(hooks plugin.Hooks) bool { wc.HookRunner.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.OnWebSocketDisconnect(wc.GetConnectionID(), userID) hooks.OnWebSocketDisconnect(wc.GetConnectionID(), userID)
return true return true
}, plugin.OnWebSocketDisconnectID) }, plugin.OnWebSocketDisconnectID)

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

@@ -22,7 +22,7 @@ import (
type hookRunner struct { type hookRunner struct {
} }
func (h *hookRunner) RunMultiHook(hookRunnerFunc func(hooks plugin.Hooks) bool, hookId int) { func (h *hookRunner) RunMultiHook(hookRunnerFunc func(hooks plugin.Hooks, _ *model.Manifest) bool, hookId int) {
} }
func (h *hookRunner) HooksForPlugin(id string) (plugin.Hooks, error) { func (h *hookRunner) HooksForPlugin(id string) (plugin.Hooks, error) {

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

@@ -244,7 +244,7 @@ func (ch *Channels) initPlugins(c request.CTX, pluginDir, webappPluginDir string
ch.syncPluginsActiveState() ch.syncPluginsActiveState()
} }
ch.RunMultiHook(func(hooks plugin.Hooks) bool { ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
if err := hooks.OnConfigurationChange(); err != nil { if err := hooks.OnConfigurationChange(); err != nil {
ch.srv.Log().Error("Plugin OnConfigurationChange hook failed", mlog.Err(err)) ch.srv.Log().Error("Plugin OnConfigurationChange hook failed", mlog.Err(err))
} }

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

@@ -1335,7 +1335,7 @@ func TestHookRunDataRetention(t *testing.T) {
require.True(t, th.App.GetPluginsEnvironment().IsActive(pluginID)) require.True(t, th.App.GetPluginsEnvironment().IsActive(pluginID))
hookCalled := false hookCalled := false
th.App.Channels().RunMultiHook(func(hooks plugin.Hooks) bool { th.App.Channels().RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
n, _ := hooks.RunDataRetention(0, 0) n, _ := hooks.RunDataRetention(0, 0)
// Ensure return it correct // Ensure return it correct
assert.Equal(t, int64(100), n) assert.Equal(t, int64(100), n)
@@ -1379,7 +1379,7 @@ func TestHookOnSendDailyTelemetry(t *testing.T) {
require.True(t, th.App.GetPluginsEnvironment().IsActive(pluginID)) require.True(t, th.App.GetPluginsEnvironment().IsActive(pluginID))
hookCalled := false hookCalled := false
th.App.Channels().RunMultiHook(func(hooks plugin.Hooks) bool { th.App.Channels().RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.OnSendDailyTelemetry() hooks.OnSendDailyTelemetry()
hookCalled = true hookCalled = true
@@ -1423,7 +1423,7 @@ func TestHookOnCloudLimitsUpdated(t *testing.T) {
require.True(t, th.App.GetPluginsEnvironment().IsActive(pluginID)) require.True(t, th.App.GetPluginsEnvironment().IsActive(pluginID))
hookCalled := false hookCalled := false
th.App.Channels().RunMultiHook(func(hooks plugin.Hooks) bool { th.App.Channels().RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.OnCloudLimitsUpdated(nil) hooks.OnCloudLimitsUpdated(nil)
hookCalled = true hookCalled = true

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

@@ -308,7 +308,7 @@ func (a *App) CreatePost(c request.CTX, post *model.Post, channel *model.Channel
} }
var rejectionError *model.AppError var rejectionError *model.AppError
pluginContext := pluginContext(c) pluginContext := pluginContext(c)
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
replacementPost, rejectionReason := hooks.MessageWillBePosted(pluginContext, post.ForPlugin()) replacementPost, rejectionReason := hooks.MessageWillBePosted(pluginContext, post.ForPlugin())
if rejectionReason != "" { if rejectionReason != "" {
id := "Post rejected by plugin. " + rejectionReason id := "Post rejected by plugin. " + rejectionReason
@@ -381,7 +381,7 @@ func (a *App) CreatePost(c request.CTX, post *model.Post, channel *model.Channel
// and to remove the non-GOB-encodable Metadata from it. // and to remove the non-GOB-encodable Metadata from it.
pluginPost := rpost.ForPlugin() pluginPost := rpost.ForPlugin()
a.Srv().Go(func() { a.Srv().Go(func() {
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.MessageHasBeenPosted(pluginContext, pluginPost) hooks.MessageHasBeenPosted(pluginContext, pluginPost)
return true return true
}, plugin.MessageHasBeenPostedID) }, plugin.MessageHasBeenPostedID)
@@ -738,7 +738,7 @@ func (a *App) UpdatePost(c request.CTX, receivedUpdatedPost *model.Post, safeUpd
var rejectionReason string var rejectionReason string
pluginContext := pluginContext(c) pluginContext := pluginContext(c)
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
newPost, rejectionReason = hooks.MessageWillBeUpdated(pluginContext, newPost.ForPlugin(), oldPost.ForPlugin()) newPost, rejectionReason = hooks.MessageWillBeUpdated(pluginContext, newPost.ForPlugin(), oldPost.ForPlugin())
return newPost != nil return newPost != nil
}, plugin.MessageWillBeUpdatedID) }, plugin.MessageWillBeUpdatedID)
@@ -762,7 +762,7 @@ func (a *App) UpdatePost(c request.CTX, receivedUpdatedPost *model.Post, safeUpd
pluginOldPost := oldPost.ForPlugin() pluginOldPost := oldPost.ForPlugin()
pluginNewPost := newPost.ForPlugin() pluginNewPost := newPost.ForPlugin()
a.Srv().Go(func() { a.Srv().Go(func() {
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.MessageHasBeenUpdated(pluginContext, pluginNewPost, pluginOldPost) hooks.MessageHasBeenUpdated(pluginContext, pluginNewPost, pluginOldPost)
return true return true
}, plugin.MessageHasBeenUpdatedID) }, plugin.MessageHasBeenUpdatedID)
@@ -2368,7 +2368,7 @@ func (a *App) applyPostsWillBeConsumedHook(posts map[string]*model.Post) {
for _, post := range posts { for _, post := range posts {
postsSlice = append(postsSlice, post.ForPlugin()) postsSlice = append(postsSlice, post.ForPlugin())
} }
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
postReplacements := hooks.MessagesWillBeConsumed(postsSlice) postReplacements := hooks.MessagesWillBeConsumed(postsSlice)
for _, postReplacement := range postReplacements { for _, postReplacement := range postReplacements {
posts[postReplacement.Id] = postReplacement posts[postReplacement.Id] = postReplacement
@@ -2383,7 +2383,7 @@ func (a *App) applyPostWillBeConsumedHook(post **model.Post) {
} }
ps := []*model.Post{*post} ps := []*model.Post{*post}
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
rp := hooks.MessagesWillBeConsumed(ps) rp := hooks.MessagesWillBeConsumed(ps)
if len(rp) > 0 { if len(rp) > 0 {
(*post) = rp[0] (*post) = rp[0]
@@ -2705,7 +2705,7 @@ func (a *App) CleanUpAfterPostDeletion(c request.CTX, post *model.Post, deleteBy
pluginPost := post.ForPlugin() pluginPost := post.ForPlugin()
pluginContext := pluginContext(c) pluginContext := pluginContext(c)
a.Srv().Go(func() { a.Srv().Go(func() {
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.MessageHasBeenDeleted(pluginContext, pluginPost) hooks.MessageHasBeenDeleted(pluginContext, pluginPost)
return true return true
}, plugin.MessageHasBeenDeletedID) }, plugin.MessageHasBeenDeletedID)

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

@@ -77,7 +77,7 @@ func (a *App) UpdatePreferences(c request.CTX, userID string, preferences model.
pluginContext := pluginContext(c) pluginContext := pluginContext(c)
a.Srv().Go(func() { a.Srv().Go(func() {
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.PreferencesHaveChanged(pluginContext, preferences) hooks.PreferencesHaveChanged(pluginContext, preferences)
return true return true
}, plugin.PreferencesHaveChangedID) }, plugin.PreferencesHaveChangedID)

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

@@ -84,7 +84,7 @@ func (a *App) SaveReactionForPost(c request.CTX, reaction *model.Reaction) (*mod
pluginContext := pluginContext(c) pluginContext := pluginContext(c)
a.Srv().Go(func() { a.Srv().Go(func() {
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.ReactionHasBeenAdded(pluginContext, reaction) hooks.ReactionHasBeenAdded(pluginContext, reaction)
return true return true
}, plugin.ReactionHasBeenAddedID) }, plugin.ReactionHasBeenAddedID)
@@ -155,7 +155,7 @@ func (a *App) DeleteReactionForPost(c request.CTX, reaction *model.Reaction) *mo
pluginContext := pluginContext(c) pluginContext := pluginContext(c)
a.Srv().Go(func() { a.Srv().Go(func() {
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.ReactionHasBeenRemoved(pluginContext, reaction) hooks.ReactionHasBeenRemoved(pluginContext, reaction)
return true return true
}, plugin.ReactionHasBeenRemovedID) }, plugin.ReactionHasBeenRemovedID)

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

@@ -6,6 +6,7 @@ package app
import ( import (
"encoding/json" "encoding/json"
"runtime" "runtime"
"slices"
"sync" "sync"
"github.com/hashicorp/go-multierror" "github.com/hashicorp/go-multierror"
@@ -13,6 +14,7 @@ import (
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
"github.com/mattermost/mattermost/server/public/model" "github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/plugin"
"github.com/mattermost/mattermost/server/public/shared/mlog" "github.com/mattermost/mattermost/server/public/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/request" "github.com/mattermost/mattermost/server/public/shared/request"
) )
@@ -82,26 +84,30 @@ func (a *App) GenerateSupportPacket(c request.CTX, options *model.SupportPacketO
wg.Wait() wg.Wait()
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
pluginContext := pluginContext(c) pluginContext := pluginContext(c)
for _, id := range options.PluginPackets { a.ch.RunMultiHook(func(hooks plugin.Hooks, manifest *model.Manifest) bool {
hooks, err := pluginsEnvironment.HooksForPlugin(id) // If the plugin defined the support_packet prop it means there is a UI element to include it in the support packet.
if err != nil { // Check if the plugin is in the list of plugins to include in the Support Packet.
c.Logger().Error("Failed to call hooks for plugin", mlog.Err(err), mlog.String("plugin", id)) if _, ok := manifest.Props["support_packet"]; ok {
warnings = multierror.Append(warnings, err) if !slices.Contains(options.PluginPackets, manifest.Id) {
continue return true
} }
}
// Otherwise, just call the hook as the plugin decided to always include it in the Support Packet.
pluginData, err := hooks.GenerateSupportData(pluginContext) pluginData, err := hooks.GenerateSupportData(pluginContext)
if err != nil { if err != nil {
c.Logger().Warn("Failed to generate plugin file for Support Packet", mlog.Err(err), mlog.String("plugin", id)) c.Logger().Warn("Failed to generate plugin file for Support Packet", mlog.String("plugin", manifest.Id), mlog.Err(err))
warnings = multierror.Append(warnings, err) warnings = multierror.Append(warnings, err)
continue return true
} }
for _, data := range pluginData { for _, data := range pluginData {
fileDatas = append(fileDatas, *data) fileDatas = append(fileDatas, *data)
} }
}
} return true
}, plugin.GenerateSupportDataID)
// Adding a warning.txt file to the fileDatas if any warning // Adding a warning.txt file to the fileDatas if any warning
if warnings != nil { if warnings != nil {

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

@@ -803,7 +803,7 @@ func (a *App) JoinUserToTeam(c request.CTX, team *model.Team, user *model.User,
a.Srv().Go(func() { a.Srv().Go(func() {
pluginContext := pluginContext(c) pluginContext := pluginContext(c)
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.UserHasJoinedTeam(pluginContext, teamMember, actor) hooks.UserHasJoinedTeam(pluginContext, teamMember, actor)
return true return true
}, plugin.UserHasJoinedTeamID) }, plugin.UserHasJoinedTeamID)
@@ -1175,7 +1175,7 @@ func (a *App) postProcessTeamMemberLeave(c request.CTX, teamMember *model.TeamMe
a.Srv().Go(func() { a.Srv().Go(func() {
pluginContext := pluginContext(c) pluginContext := pluginContext(c)
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.UserHasLeftTeam(pluginContext, teamMember, actor) hooks.UserHasLeftTeam(pluginContext, teamMember, actor)
return true return true
}, plugin.UserHasLeftTeamID) }, plugin.UserHasLeftTeamID)

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

@@ -62,7 +62,7 @@ func (a *App) runPluginsHook(c request.CTX, info *model.FileInfo, file io.Reader
var rejErr *model.AppError var rejErr *model.AppError
var once sync.Once var once sync.Once
pluginContext := pluginContext(c) pluginContext := pluginContext(c)
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
once.Do(func() { once.Do(func() {
hookHasRunCh <- struct{}{} hookHasRunCh <- struct{}{}
}) })

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

@@ -313,7 +313,7 @@ func (a *App) createUserOrGuest(c request.CTX, user *model.User, guest bool) (*m
pluginContext := pluginContext(c) pluginContext := pluginContext(c)
a.Srv().Go(func() { a.Srv().Go(func() {
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.UserHasBeenCreated(pluginContext, ruser) hooks.UserHasBeenCreated(pluginContext, ruser)
return true return true
}, plugin.UserHasBeenCreatedID) }, plugin.UserHasBeenCreatedID)
@@ -1045,10 +1045,10 @@ func (a *App) UpdateActive(c request.CTX, user *model.User, active bool) (*model
a.sendUpdatedUserEvent(ruser) a.sendUpdatedUserEvent(ruser)
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil && !active && user.DeleteAt != 0 { if !active && user.DeleteAt != 0 {
a.Srv().Go(func() { a.Srv().Go(func() {
pluginContext := pluginContext(c) pluginContext := pluginContext(c)
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { a.ch.RunMultiHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.UserHasBeenDeactivated(pluginContext, user) hooks.UserHasBeenDeactivated(pluginContext, user)
return true return true
}, plugin.UserHasBeenDeactivatedID) }, plugin.UserHasBeenDeactivatedID)

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

@@ -1065,7 +1065,7 @@ func (ts *TelemetryService) trackPlugins() {
"plugins_with_broken_manifests": brokenManifestCount, "plugins_with_broken_manifests": brokenManifestCount,
}) })
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks, _ *model.Manifest) bool {
hooks.OnSendDailyTelemetry() hooks.OnSendDailyTelemetry()
return true return true
}, plugin.OnSendDailyTelemetryID) }, plugin.OnSendDailyTelemetryID)

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

@@ -599,7 +599,7 @@ func (env *Environment) HooksForPlugin(id string) (Hooks, error) {
// //
// If hookRunnerFunc returns false, iteration will not continue. The iteration order among active // If hookRunnerFunc returns false, iteration will not continue. The iteration order among active
// plugins is not specified. // plugins is not specified.
func (env *Environment) RunMultiPluginHook(hookRunnerFunc func(hooks Hooks) bool, hookId int) { func (env *Environment) RunMultiPluginHook(hookRunnerFunc func(hooks Hooks, manifest *model.Manifest) bool, hookId int) {
startTime := time.Now() startTime := time.Now()
env.registeredPlugins.Range(func(key, value any) bool { env.registeredPlugins.Range(func(key, value any) bool {
@@ -610,7 +610,7 @@ func (env *Environment) RunMultiPluginHook(hookRunnerFunc func(hooks Hooks) bool
} }
hookStartTime := time.Now() hookStartTime := time.Now()
result := hookRunnerFunc(rp.supervisor.Hooks()) result := hookRunnerFunc(rp.supervisor.Hooks(), rp.BundleInfo.Manifest)
if env.metrics != nil { if env.metrics != nil {
elapsedTime := float64(time.Since(hookStartTime)) / float64(time.Second) elapsedTime := float64(time.Since(hookStartTime)) / float64(time.Second)

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

@@ -387,6 +387,12 @@ type Hooks interface {
// GenerateSupportData is invoked when a Support Packet gets generated. // GenerateSupportData is invoked when a Support Packet gets generated.
// It allows plugins to include their own content in the Support Packet. // It allows plugins to include their own content in the Support Packet.
// //
// Plugins may specififes a "support_packet" field in the manifest props with a custom text.
// By doing so, the plugin will be included in the Support Packet UI and the user will be able to select it.
// This hook will only be called, if the user selects the plugin in the Support Packet UI.
//
// If no "support_packet" is specified, this hook will always be called.
//
// Minimum server version: 9.8 // Minimum server version: 9.8
GenerateSupportData(c *Context) ([]*model.FileData, error) GenerateSupportData(c *Context) ([]*model.FileData, error)
} }