Move pluginCommands into Channels (#18974)

* Move pluginCommands into Channels

We move pluginCommands, pluginCommandsLock
into Channels.

We also move the plugin related route handlers
under Channels and move the init code under
NewChannels. To achieve this, the router initialization
is bumped up.

Along with it, we clean up some App methods
which were just wrappers over Channel methods.
Instead, we call the Channel method directly
to make things more readable and easy to understand.

```release-note
NONE
```

* fix tests

```release-note
NONE
```
Этот коммит содержится в:
Agniva De Sarker
2021-11-12 10:35:14 +05:30
коммит произвёл GitHub
родитель 27559c1c7b
Коммит a850704afe
21 изменённых файлов: 120 добавлений и 285 удалений

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

@@ -151,7 +151,7 @@ func installMarketplacePlugin(c *Context, w http.ResponseWriter, r *http.Request
} }
auditRec.AddMeta("plugin_id", pluginRequest.Id) auditRec.AddMeta("plugin_id", pluginRequest.Id)
manifest, appErr := c.App.InstallMarketplacePlugin(pluginRequest) manifest, appErr := c.App.Channels().InstallMarketplacePlugin(pluginRequest)
if appErr != nil { if appErr != nil {
c.Err = appErr c.Err = appErr
return return
@@ -231,7 +231,7 @@ func removePlugin(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
err := c.App.RemovePlugin(c.Params.PluginId) err := c.App.Channels().RemovePlugin(c.Params.PluginId)
if err != nil { if err != nil {
c.Err = err c.Err = err
return return

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

@@ -94,7 +94,7 @@ func TestPlugin(t *testing.T) {
assert.Equal(t, "testplugin", manifest.Id) assert.Equal(t, "testplugin", manifest.Id)
}) })
th.App.RemovePlugin(manifest.Id) th.App.Channels().RemovePlugin(manifest.Id)
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PluginSettings.Enable = false }) th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PluginSettings.Enable = false })

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

@@ -81,6 +81,9 @@ func (s *Server) getFirstServerRunTimestamp() (int64, *model.AppError) {
return value, nil return value, nil
} }
func (a *App) Channels() *Channels {
return a.ch
}
func (a *App) Srv() *Server { func (a *App) Srv() *Server {
return a.ch.srv return a.ch.srv
} }

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

@@ -212,13 +212,8 @@ type AppIface interface {
HubRegister(webConn *WebConn) HubRegister(webConn *WebConn)
// HubUnregister unregisters a connection from a hub. // HubUnregister unregisters a connection from a hub.
HubUnregister(webConn *WebConn) HubUnregister(webConn *WebConn)
// InstallMarketplacePlugin installs a plugin listed in the marketplace server. It will get the plugin bundle
// from the prepackaged folder, if available, or remotely if EnableRemoteMarketplace is true.
InstallMarketplacePlugin(request *model.InstallMarketplacePluginRequest) (*model.Manifest, *model.AppError)
// InstallPlugin unpacks and installs a plugin but does not enable or activate it. // InstallPlugin unpacks and installs a plugin but does not enable or activate it.
InstallPlugin(pluginFile io.ReadSeeker, replace bool) (*model.Manifest, *model.AppError) InstallPlugin(pluginFile io.ReadSeeker, replace bool) (*model.Manifest, *model.AppError)
// InstallPluginWithSignature verifies and installs plugin.
InstallPluginWithSignature(pluginFile, signature io.ReadSeeker) (*model.Manifest, *model.AppError)
// LimitedClientConfigWithComputed gets the configuration in a format suitable for sending to the client. // LimitedClientConfigWithComputed gets the configuration in a format suitable for sending to the client.
LimitedClientConfigWithComputed() map[string]string LimitedClientConfigWithComputed() map[string]string
// LogAuditRec logs an audit record using default LvlAuditCLI. // LogAuditRec logs an audit record using default LvlAuditCLI.
@@ -414,6 +409,7 @@ type AppIface interface {
BulkImportWithPath(c *request.Context, jsonlReader io.Reader, attachmentsReader *zip.Reader, dryRun bool, workers int, importPath string) (*model.AppError, int) BulkImportWithPath(c *request.Context, jsonlReader io.Reader, attachmentsReader *zip.Reader, dryRun bool, workers int, importPath string) (*model.AppError, int)
CancelJob(jobId string) *model.AppError CancelJob(jobId string) *model.AppError
ChannelMembersToRemove(teamID *string) ([]*model.ChannelMember, *model.AppError) ChannelMembersToRemove(teamID *string) ([]*model.ChannelMember, *model.AppError)
Channels() *Channels
CheckAndSendUserLimitWarningEmails(c *request.Context) *model.AppError CheckAndSendUserLimitWarningEmails(c *request.Context) *model.AppError
CheckCanInviteToSharedChannel(channelId string) error CheckCanInviteToSharedChannel(channelId string) error
CheckCloudAccountAtLimit() (bool, *model.AppError) CheckCloudAccountAtLimit() (bool, *model.AppError)
@@ -809,7 +805,6 @@ type AppIface interface {
ImageProxyRemover() (f func(string) string) ImageProxyRemover() (f func(string) string)
ImportPermissions(jsonl io.Reader) error ImportPermissions(jsonl io.Reader) error
InitPlugins(c *request.Context, pluginDir, webappPluginDir string) InitPlugins(c *request.Context, pluginDir, webappPluginDir string)
InstallPluginFromData(data model.PluginEventData)
InvalidateAllEmailInvites() *model.AppError InvalidateAllEmailInvites() *model.AppError
InvalidateCacheForUser(userID string) InvalidateCacheForUser(userID string)
InviteGuestsToChannels(teamID string, guestsInvite *model.GuestsInvite, senderId string) *model.AppError InviteGuestsToChannels(teamID string, guestsInvite *model.GuestsInvite, senderId string) *model.AppError
@@ -899,8 +894,6 @@ type AppIface interface {
RemoveFile(path string) *model.AppError RemoveFile(path string) *model.AppError
RemoveLdapPrivateCertificate() *model.AppError RemoveLdapPrivateCertificate() *model.AppError
RemoveLdapPublicCertificate() *model.AppError RemoveLdapPublicCertificate() *model.AppError
RemovePlugin(id string) *model.AppError
RemovePluginFromData(data model.PluginEventData)
RemoveRecentCustomStatus(userID string, status *model.CustomStatus) *model.AppError RemoveRecentCustomStatus(userID string, status *model.CustomStatus) *model.AppError
RemoveSamlIdpCertificate() *model.AppError RemoveSamlIdpCertificate() *model.AppError
RemoveSamlPrivateCertificate() *model.AppError RemoveSamlPrivateCertificate() *model.AppError
@@ -990,7 +983,6 @@ type AppIface interface {
SetPluginKey(pluginID string, key string, value []byte) *model.AppError SetPluginKey(pluginID string, key string, value []byte) *model.AppError
SetPluginKeyWithExpiry(pluginID string, key string, value []byte, expireInSeconds int64) *model.AppError SetPluginKeyWithExpiry(pluginID string, key string, value []byte, expireInSeconds int64) *model.AppError
SetPluginKeyWithOptions(pluginID string, key string, value []byte, options model.PluginKVSetOptions) (bool, *model.AppError) SetPluginKeyWithOptions(pluginID string, key string, value []byte, options model.PluginKVSetOptions) (bool, *model.AppError)
SetPluginsEnvironment(pluginsEnvironment *plugin.Environment)
SetProfileImage(userID string, imageData *multipart.FileHeader) *model.AppError SetProfileImage(userID string, imageData *multipart.FileHeader) *model.AppError
SetProfileImageFromFile(userID string, file io.Reader) *model.AppError SetProfileImageFromFile(userID string, file io.Reader) *model.AppError
SetProfileImageFromMultiPartFile(userID string, file multipart.File) *model.AppError SetProfileImageFromMultiPartFile(userID string, file multipart.File) *model.AppError
@@ -1014,7 +1006,6 @@ type AppIface interface {
SwitchEmailToOAuth(w http.ResponseWriter, r *http.Request, email, password, code, service string) (string, *model.AppError) SwitchEmailToOAuth(w http.ResponseWriter, r *http.Request, email, password, code, service string) (string, *model.AppError)
SwitchLdapToEmail(ldapPassword, code, email, newPassword string) (string, *model.AppError) SwitchLdapToEmail(ldapPassword, code, email, newPassword string) (string, *model.AppError)
SwitchOAuthToEmail(email, password, requesterId string) (string, *model.AppError) SwitchOAuthToEmail(email, password, requesterId string) (string, *model.AppError)
SyncPluginsActiveState()
TeamMembersToRemove(teamID *string) ([]*model.TeamMember, *model.AppError) TeamMembersToRemove(teamID *string) ([]*model.TeamMember, *model.AppError)
TelemetryId() string TelemetryId() string
TestElasticsearch(cfg *model.Config) *model.AppError TestElasticsearch(cfg *model.Config) *model.AppError
@@ -1028,7 +1019,6 @@ type AppIface interface {
TotalWebsocketConnections() int TotalWebsocketConnections() int
TriggerWebhook(c *request.Context, payload *model.OutgoingWebhookPayload, hook *model.OutgoingWebhook, post *model.Post, channel *model.Channel) TriggerWebhook(c *request.Context, payload *model.OutgoingWebhookPayload, hook *model.OutgoingWebhook, post *model.Post, channel *model.Channel)
UnregisterPluginCommand(pluginID, teamID, trigger string) UnregisterPluginCommand(pluginID, teamID, trigger string)
UnregisterPluginCommands(pluginID string)
UpdateActive(c *request.Context, user *model.User, active bool) (*model.User, *model.AppError) UpdateActive(c *request.Context, user *model.User, active bool) (*model.User, *model.AppError)
UpdateChannelLastViewedAt(channelIDs []string, userID string) *model.AppError UpdateChannelLastViewedAt(channelIDs []string, userID string) *model.AppError
UpdateChannelMemberNotifyProps(data map[string]string, channelID string, userID string) (*model.ChannelMember, *model.AppError) UpdateChannelMemberNotifyProps(data map[string]string, channelID string, userID string) (*model.ChannelMember, *model.AppError)

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

@@ -18,9 +18,11 @@ import (
type Channels struct { type Channels struct {
srv *Server srv *Server
pluginCommandsLock sync.RWMutex
pluginCommands []*PluginCommand
pluginsLock sync.RWMutex
pluginsEnvironment *plugin.Environment pluginsEnvironment *plugin.Environment
pluginConfigListenerID string pluginConfigListenerID string
pluginsLock sync.RWMutex
imageProxy *imageproxy.ImageProxy imageProxy *imageproxy.ImageProxy
@@ -44,10 +46,17 @@ func init() {
} }
func NewChannels(s *Server) (*Channels, error) { func NewChannels(s *Server) (*Channels, error) {
return &Channels{ ch := &Channels{
srv: s, srv: s,
imageProxy: imageproxy.MakeImageProxy(s, s.httpService, s.Log), imageProxy: imageproxy.MakeImageProxy(s, s.httpService, s.Log),
}, nil }
// Setup routes.
pluginsRoute := ch.srv.Router.PathPrefix("/plugins/{plugin_id:[A-Za-z0-9\\_\\-\\.]+}").Subrouter()
pluginsRoute.HandleFunc("", ch.ServePluginRequest)
pluginsRoute.HandleFunc("/public/{public_file:.*}", ch.ServePluginPublicRequest)
pluginsRoute.HandleFunc("/{anything:.*}", ch.ServePluginRequest)
return ch, nil
} }
func (ch *Channels) Start() error { func (ch *Channels) Start() error {

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

@@ -423,7 +423,7 @@ func (a *App) doPluginRequest(c *request.Context, method, rawURL string, values
params["plugin_id"] = pluginID params["plugin_id"] = pluginID
r = mux.SetURLVars(r, params) r = mux.SetURLVars(r, params)
a.ch.srv.ServePluginRequest(w, r) a.ch.ServePluginRequest(w, r)
resp := &http.Response{ resp := &http.Response{
StatusCode: w.status, StatusCode: w.status,

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

@@ -12,6 +12,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/gorilla/mux"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@@ -1381,6 +1382,7 @@ func TestPushNotificationRace(t *testing.T) {
configStore: memoryStore, configStore: memoryStore,
Store: mockStore, Store: mockStore,
products: make(map[string]Product), products: make(map[string]Product),
Router: mux.NewRouter(),
} }
ch, err := NewChannels(s) ch, err := NewChannels(s)
require.NoError(t, err) require.NoError(t, err)

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

@@ -1112,6 +1112,23 @@ func (a *OpenTracingAppLayer) ChannelMembersToRemove(teamID *string) ([]*model.C
return resultVar0, resultVar1 return resultVar0, resultVar1
} }
func (a *OpenTracingAppLayer) Channels() *app.Channels {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.Channels")
a.ctx = newCtx
a.app.Srv().Store.SetContext(newCtx)
defer func() {
a.app.Srv().Store.SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
resultVar0 := a.app.Channels()
return resultVar0
}
func (a *OpenTracingAppLayer) CheckAndSendUserLimitWarningEmails(c *request.Context) *model.AppError { func (a *OpenTracingAppLayer) CheckAndSendUserLimitWarningEmails(c *request.Context) *model.AppError {
origCtx := a.ctx origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CheckAndSendUserLimitWarningEmails") span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CheckAndSendUserLimitWarningEmails")
@@ -10623,28 +10640,6 @@ func (a *OpenTracingAppLayer) InitPlugins(c *request.Context, pluginDir string,
a.app.InitPlugins(c, pluginDir, webappPluginDir) a.app.InitPlugins(c, pluginDir, webappPluginDir)
} }
func (a *OpenTracingAppLayer) InstallMarketplacePlugin(request *model.InstallMarketplacePluginRequest) (*model.Manifest, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.InstallMarketplacePlugin")
a.ctx = newCtx
a.app.Srv().Store.SetContext(newCtx)
defer func() {
a.app.Srv().Store.SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
resultVar0, resultVar1 := a.app.InstallMarketplacePlugin(request)
if resultVar1 != nil {
span.LogFields(spanlog.Error(resultVar1))
ext.Error.Set(span, true)
}
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) InstallPlugin(pluginFile io.ReadSeeker, replace bool) (*model.Manifest, *model.AppError) { func (a *OpenTracingAppLayer) InstallPlugin(pluginFile io.ReadSeeker, replace bool) (*model.Manifest, *model.AppError) {
origCtx := a.ctx origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.InstallPlugin") span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.InstallPlugin")
@@ -10667,43 +10662,6 @@ func (a *OpenTracingAppLayer) InstallPlugin(pluginFile io.ReadSeeker, replace bo
return resultVar0, resultVar1 return resultVar0, resultVar1
} }
func (a *OpenTracingAppLayer) InstallPluginFromData(data model.PluginEventData) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.InstallPluginFromData")
a.ctx = newCtx
a.app.Srv().Store.SetContext(newCtx)
defer func() {
a.app.Srv().Store.SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
a.app.InstallPluginFromData(data)
}
func (a *OpenTracingAppLayer) InstallPluginWithSignature(pluginFile io.ReadSeeker, signature io.ReadSeeker) (*model.Manifest, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.InstallPluginWithSignature")
a.ctx = newCtx
a.app.Srv().Store.SetContext(newCtx)
defer func() {
a.app.Srv().Store.SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
resultVar0, resultVar1 := a.app.InstallPluginWithSignature(pluginFile, signature)
if resultVar1 != nil {
span.LogFields(spanlog.Error(resultVar1))
ext.Error.Set(span, true)
}
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) InvalidateAllEmailInvites() *model.AppError { func (a *OpenTracingAppLayer) InvalidateAllEmailInvites() *model.AppError {
origCtx := a.ctx origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.InvalidateAllEmailInvites") span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.InvalidateAllEmailInvites")
@@ -12769,43 +12727,6 @@ func (a *OpenTracingAppLayer) RemoveLdapPublicCertificate() *model.AppError {
return resultVar0 return resultVar0
} }
func (a *OpenTracingAppLayer) RemovePlugin(id string) *model.AppError {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.RemovePlugin")
a.ctx = newCtx
a.app.Srv().Store.SetContext(newCtx)
defer func() {
a.app.Srv().Store.SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
resultVar0 := a.app.RemovePlugin(id)
if resultVar0 != nil {
span.LogFields(spanlog.Error(resultVar0))
ext.Error.Set(span, true)
}
return resultVar0
}
func (a *OpenTracingAppLayer) RemovePluginFromData(data model.PluginEventData) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.RemovePluginFromData")
a.ctx = newCtx
a.app.Srv().Store.SetContext(newCtx)
defer func() {
a.app.Srv().Store.SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
a.app.RemovePluginFromData(data)
}
func (a *OpenTracingAppLayer) RemoveRecentCustomStatus(userID string, status *model.CustomStatus) *model.AppError { func (a *OpenTracingAppLayer) RemoveRecentCustomStatus(userID string, status *model.CustomStatus) *model.AppError {
origCtx := a.ctx origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.RemoveRecentCustomStatus") span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.RemoveRecentCustomStatus")
@@ -14835,21 +14756,6 @@ func (a *OpenTracingAppLayer) SetPluginKeyWithOptions(pluginID string, key strin
return resultVar0, resultVar1 return resultVar0, resultVar1
} }
func (a *OpenTracingAppLayer) SetPluginsEnvironment(pluginsEnvironment *plugin.Environment) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SetPluginsEnvironment")
a.ctx = newCtx
a.app.Srv().Store.SetContext(newCtx)
defer func() {
a.app.Srv().Store.SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
a.app.SetPluginsEnvironment(pluginsEnvironment)
}
func (a *OpenTracingAppLayer) SetProfileImage(userID string, imageData *multipart.FileHeader) *model.AppError { func (a *OpenTracingAppLayer) SetProfileImage(userID string, imageData *multipart.FileHeader) *model.AppError {
origCtx := a.ctx origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SetProfileImage") span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SetProfileImage")
@@ -15352,21 +15258,6 @@ func (a *OpenTracingAppLayer) SyncPlugins() *model.AppError {
return resultVar0 return resultVar0
} }
func (a *OpenTracingAppLayer) SyncPluginsActiveState() {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SyncPluginsActiveState")
a.ctx = newCtx
a.app.Srv().Store.SetContext(newCtx)
defer func() {
a.app.Srv().Store.SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
a.app.SyncPluginsActiveState()
}
func (a *OpenTracingAppLayer) SyncRolesAndMembership(c *request.Context, syncableID string, syncableType model.GroupSyncableType, includeRemovedMembers bool) { func (a *OpenTracingAppLayer) SyncRolesAndMembership(c *request.Context, syncableID string, syncableType model.GroupSyncableType, includeRemovedMembers bool) {
origCtx := a.ctx origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SyncRolesAndMembership") span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SyncRolesAndMembership")
@@ -15688,21 +15579,6 @@ func (a *OpenTracingAppLayer) UnregisterPluginCommand(pluginID string, teamID st
a.app.UnregisterPluginCommand(pluginID, teamID, trigger) a.app.UnregisterPluginCommand(pluginID, teamID, trigger)
} }
func (a *OpenTracingAppLayer) UnregisterPluginCommands(pluginID string) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UnregisterPluginCommands")
a.ctx = newCtx
a.app.Srv().Store.SetContext(newCtx)
defer func() {
a.app.Srv().Store.SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
a.app.UnregisterPluginCommands(pluginID)
}
func (a *OpenTracingAppLayer) UpdateActive(c *request.Context, user *model.User, active bool) (*model.User, *model.AppError) { func (a *OpenTracingAppLayer) UpdateActive(c *request.Context, user *model.User, active bool) (*model.User, *model.AppError) {
origCtx := a.ctx origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UpdateActive") span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UpdateActive")

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

@@ -62,15 +62,11 @@ func (a *App) GetPluginsEnvironment() *plugin.Environment {
return a.ch.GetPluginsEnvironment() return a.ch.GetPluginsEnvironment()
} }
func (a *App) SetPluginsEnvironment(pluginsEnvironment *plugin.Environment) { func (ch *Channels) SetPluginsEnvironment(pluginsEnvironment *plugin.Environment) {
a.ch.pluginsLock.Lock() ch.pluginsLock.Lock()
defer a.ch.pluginsLock.Unlock() defer ch.pluginsLock.Unlock()
a.ch.pluginsEnvironment = pluginsEnvironment ch.pluginsEnvironment = pluginsEnvironment
}
func (a *App) SyncPluginsActiveState() {
a.ch.syncPluginsActiveState()
} }
func (ch *Channels) syncPluginsActiveState() { func (ch *Channels) syncPluginsActiveState() {
@@ -452,7 +448,7 @@ func (ch *Channels) disablePlugin(id string) *model.AppError {
ch.srv.UpdateConfig(func(cfg *model.Config) { ch.srv.UpdateConfig(func(cfg *model.Config) {
cfg.PluginSettings.PluginStates[id] = &model.PluginState{Enable: false} cfg.PluginSettings.PluginStates[id] = &model.PluginState{Enable: false}
}) })
ch.srv.unregisterPluginCommands(id) ch.unregisterPluginCommands(id)
// This call will implicitly invoke SyncPluginsActiveState which will deactivate disabled plugins. // This call will implicitly invoke SyncPluginsActiveState which will deactivate disabled plugins.
if _, _, err := ch.srv.SaveConfig(ch.srv.Config(), true); err != nil { if _, _, err := ch.srv.SaveConfig(ch.srv.Config(), true); err != nil {
@@ -994,7 +990,7 @@ func (ch *Channels) installFeatureFlagPlugins() {
} }
} }
_, err := ch.installMarketplacePlugin(&model.InstallMarketplacePluginRequest{ _, err := ch.InstallMarketplacePlugin(&model.InstallMarketplacePluginRequest{
Id: pluginID, Id: pluginID,
Version: version, Version: version,
}) })

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

@@ -832,7 +832,7 @@ func (api *PluginAPI) DisablePlugin(id string) *model.AppError {
} }
func (api *PluginAPI) RemovePlugin(id string) *model.AppError { func (api *PluginAPI) RemovePlugin(id string) *model.AppError {
return api.app.RemovePlugin(id) return api.app.Channels().RemovePlugin(id)
} }
func (api *PluginAPI) GetPluginStatus(id string) (*model.PluginStatus, *model.AppError) { func (api *PluginAPI) GetPluginStatus(id string) (*model.PluginStatus, *model.AppError) {

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

@@ -119,7 +119,7 @@ func setupMultiPluginAPITest(t *testing.T, pluginCodes []string, pluginManifests
}) })
} }
app.SetPluginsEnvironment(env) app.ch.SetPluginsEnvironment(env)
return pluginDir return pluginDir
} }
@@ -854,7 +854,7 @@ func TestPluginAPIGetPlugins(t *testing.T) {
require.True(t, activated) require.True(t, activated)
pluginManifests = append(pluginManifests, manifest) pluginManifests = append(pluginManifests, manifest)
} }
th.App.SetPluginsEnvironment(env) th.App.ch.SetPluginsEnvironment(env)
// Deactivate the last one for testing // Deactivate the last one for testing
success := env.Deactivate(pluginIDs[len(pluginIDs)-1]) success := env.Deactivate(pluginIDs[len(pluginIDs)-1])
@@ -928,7 +928,7 @@ func TestInstallPlugin(t *testing.T) {
env, err := plugin.NewEnvironment(newPluginAPI, NewDriverImpl(app.Srv()), pluginDir, webappPluginDir, app.Log(), nil) env, err := plugin.NewEnvironment(newPluginAPI, NewDriverImpl(app.Srv()), pluginDir, webappPluginDir, app.Log(), nil)
require.NoError(t, err) require.NoError(t, err)
app.SetPluginsEnvironment(env) app.ch.SetPluginsEnvironment(env)
backend := filepath.Join(pluginDir, pluginID, "backend.exe") backend := filepath.Join(pluginDir, pluginID, "backend.exe")
utils.CompileGo(t, pluginCode, backend) utils.CompileGo(t, pluginCode, backend)
@@ -1604,7 +1604,7 @@ func TestAPIMetrics(t *testing.T) {
env, err := plugin.NewEnvironment(th.NewPluginAPI, NewDriverImpl(th.Server), pluginDir, webappPluginDir, th.App.Log(), metricsMock) env, err := plugin.NewEnvironment(th.NewPluginAPI, NewDriverImpl(th.Server), pluginDir, webappPluginDir, th.App.Log(), metricsMock)
require.NoError(t, err) require.NoError(t, err)
th.App.SetPluginsEnvironment(env) th.App.ch.SetPluginsEnvironment(env)
pluginID := model.NewId() pluginID := model.NewId()
backend := filepath.Join(pluginDir, pluginID, "backend.exe") backend := filepath.Join(pluginDir, pluginID, "backend.exe")

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

@@ -54,10 +54,10 @@ func (a *App) RegisterPluginCommand(pluginID string, command *model.Command) err
AutocompleteIconData: command.AutocompleteIconData, AutocompleteIconData: command.AutocompleteIconData,
} }
a.Srv().pluginCommandsLock.Lock() a.ch.pluginCommandsLock.Lock()
defer a.Srv().pluginCommandsLock.Unlock() defer a.ch.pluginCommandsLock.Unlock()
for _, pc := range a.Srv().pluginCommands { for _, pc := range a.ch.pluginCommands {
if pc.Command.Trigger == command.Trigger && pc.Command.TeamId == command.TeamId { if pc.Command.Trigger == command.Trigger && pc.Command.TeamId == command.TeamId {
if pc.PluginId == pluginID { if pc.PluginId == pluginID {
pc.Command = command pc.Command = command
@@ -66,7 +66,7 @@ func (a *App) RegisterPluginCommand(pluginID string, command *model.Command) err
} }
} }
a.Srv().pluginCommands = append(a.Srv().pluginCommands, &PluginCommand{ a.ch.pluginCommands = append(a.ch.pluginCommands, &PluginCommand{
Command: command, Command: command,
PluginId: pluginID, PluginId: pluginID,
}) })
@@ -76,41 +76,37 @@ func (a *App) RegisterPluginCommand(pluginID string, command *model.Command) err
func (a *App) UnregisterPluginCommand(pluginID, teamID, trigger string) { func (a *App) UnregisterPluginCommand(pluginID, teamID, trigger string) {
trigger = strings.ToLower(trigger) trigger = strings.ToLower(trigger)
a.Srv().pluginCommandsLock.Lock() a.ch.pluginCommandsLock.Lock()
defer a.Srv().pluginCommandsLock.Unlock() defer a.ch.pluginCommandsLock.Unlock()
var remaining []*PluginCommand var remaining []*PluginCommand
for _, pc := range a.Srv().pluginCommands { for _, pc := range a.ch.pluginCommands {
if pc.Command.TeamId != teamID || pc.Command.Trigger != trigger { if pc.Command.TeamId != teamID || pc.Command.Trigger != trigger {
remaining = append(remaining, pc) remaining = append(remaining, pc)
} }
} }
a.Srv().pluginCommands = remaining a.ch.pluginCommands = remaining
} }
func (a *App) UnregisterPluginCommands(pluginID string) { func (ch *Channels) unregisterPluginCommands(pluginID string) {
a.Srv().unregisterPluginCommands(pluginID) ch.pluginCommandsLock.Lock()
} defer ch.pluginCommandsLock.Unlock()
func (s *Server) unregisterPluginCommands(pluginID string) {
s.pluginCommandsLock.Lock()
defer s.pluginCommandsLock.Unlock()
var remaining []*PluginCommand var remaining []*PluginCommand
for _, pc := range s.pluginCommands { for _, pc := range ch.pluginCommands {
if pc.PluginId != pluginID { if pc.PluginId != pluginID {
remaining = append(remaining, pc) remaining = append(remaining, pc)
} }
} }
s.pluginCommands = remaining ch.pluginCommands = remaining
} }
func (a *App) PluginCommandsForTeam(teamID string) []*model.Command { func (a *App) PluginCommandsForTeam(teamID string) []*model.Command {
a.Srv().pluginCommandsLock.RLock() a.ch.pluginCommandsLock.RLock()
defer a.Srv().pluginCommandsLock.RUnlock() defer a.ch.pluginCommandsLock.RUnlock()
var commands []*model.Command var commands []*model.Command
for _, pc := range a.Srv().pluginCommands { for _, pc := range a.ch.pluginCommands {
if pc.Command.TeamId == "" || pc.Command.TeamId == teamID { if pc.Command.TeamId == "" || pc.Command.TeamId == teamID {
commands = append(commands, pc.Command) commands = append(commands, pc.Command)
} }
@@ -126,14 +122,14 @@ func (a *App) tryExecutePluginCommand(c *request.Context, args *model.CommandArg
trigger = strings.ToLower(trigger) trigger = strings.ToLower(trigger)
var matched *PluginCommand var matched *PluginCommand
a.Srv().pluginCommandsLock.RLock() a.ch.pluginCommandsLock.RLock()
for _, pc := range a.Srv().pluginCommands { for _, pc := range a.ch.pluginCommands {
if (pc.Command.TeamId == "" || pc.Command.TeamId == args.TeamId) && pc.Command.Trigger == trigger { if (pc.Command.TeamId == "" || pc.Command.TeamId == args.TeamId) && pc.Command.Trigger == trigger {
matched = pc matched = pc
break break
} }
} }
a.Srv().pluginCommandsLock.RUnlock() a.ch.pluginCommandsLock.RUnlock()
if matched == nil { if matched == nil {
return nil, nil, nil return nil, nil, nil
} }

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

@@ -106,7 +106,7 @@ func TestPluginCommand(t *testing.T) {
require.NotEqual(t, "plugin", commands.Trigger) require.NotEqual(t, "plugin", commands.Trigger)
} }
th.App.RemovePlugin(pluginIDs[0]) th.App.ch.RemovePlugin(pluginIDs[0])
}) })
t.Run("re-entrant command registration on config change", func(t *testing.T) { t.Run("re-entrant command registration on config change", func(t *testing.T) {
@@ -207,7 +207,7 @@ func TestPluginCommand(t *testing.T) {
killed = true killed = true
} }
th.App.RemovePlugin(pluginIDs[0]) th.App.ch.RemovePlugin(pluginIDs[0])
require.False(t, killed, "execute command appears to have deadlocked") require.False(t, killed, "execute command appears to have deadlocked")
}) })
@@ -285,7 +285,7 @@ func TestPluginCommand(t *testing.T) {
require.Equal(t, model.CommandResponseTypeEphemeral, resp.ResponseType) require.Equal(t, model.CommandResponseTypeEphemeral, resp.ResponseType)
require.Equal(t, "text", resp.Text) require.Equal(t, "text", resp.Text)
th.App.RemovePlugin(pluginIDs[0]) th.App.ch.RemovePlugin(pluginIDs[0])
}) })
t.Run("plugin has crashed before execution of command", func(t *testing.T) { t.Run("plugin has crashed before execution of command", func(t *testing.T) {
tearDown, pluginIDs, activationErrors := SetAppEnvironmentWithPlugins(t, []string{` tearDown, pluginIDs, activationErrors := SetAppEnvironmentWithPlugins(t, []string{`
@@ -329,7 +329,7 @@ func TestPluginCommand(t *testing.T) {
require.Nil(t, resp) require.Nil(t, resp)
require.NotNil(t, err) require.NotNil(t, err)
require.Equal(t, err.Id, "model.plugin_command_error.error.app_error") require.Equal(t, err.Id, "model.plugin_command_error.error.app_error")
th.App.RemovePlugin(pluginIDs[0]) th.App.ch.RemovePlugin(pluginIDs[0])
}) })
t.Run("plugin has crashed due to the execution of the command", func(t *testing.T) { t.Run("plugin has crashed due to the execution of the command", func(t *testing.T) {
@@ -374,7 +374,7 @@ func TestPluginCommand(t *testing.T) {
require.Nil(t, resp) require.Nil(t, resp)
require.NotNil(t, err) require.NotNil(t, err)
require.Equal(t, err.Id, "model.plugin_command_crash.error.app_error") require.Equal(t, err.Id, "model.plugin_command_crash.error.app_error")
th.App.RemovePlugin(pluginIDs[0]) th.App.ch.RemovePlugin(pluginIDs[0])
}) })
} }

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

@@ -37,7 +37,7 @@ func SetAppEnvironmentWithPlugins(t *testing.T, pluginCode []string, app *App, a
env, err := plugin.NewEnvironment(apiFunc, NewDriverImpl(app.Srv()), pluginDir, webappPluginDir, app.Log(), nil) env, err := plugin.NewEnvironment(apiFunc, NewDriverImpl(app.Srv()), pluginDir, webappPluginDir, app.Log(), nil)
require.NoError(t, err) require.NoError(t, err)
app.SetPluginsEnvironment(env) app.ch.SetPluginsEnvironment(env)
pluginIDs := []string{} pluginIDs := []string{}
activationErrors := []error{} activationErrors := []error{}
for _, code := range pluginCode { for _, code := range pluginCode {
@@ -1048,7 +1048,7 @@ func TestHookMetrics(t *testing.T) {
env, err := plugin.NewEnvironment(th.NewPluginAPI, NewDriverImpl(th.Server), pluginDir, webappPluginDir, th.App.Log(), metricsMock) env, err := plugin.NewEnvironment(th.NewPluginAPI, NewDriverImpl(th.Server), pluginDir, webappPluginDir, th.App.Log(), metricsMock)
require.NoError(t, err) require.NoError(t, err)
th.App.SetPluginsEnvironment(env) th.App.ch.SetPluginsEnvironment(env)
pluginID := model.NewId() pluginID := model.NewId()
backend := filepath.Join(pluginDir, pluginID, "backend.exe") backend := filepath.Join(pluginDir, pluginID, "backend.exe")

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

@@ -61,10 +61,6 @@ const managedPluginFileName = ".filestore"
// fileStorePluginFolder is the folder name in the file store of the plugin bundles installed. // fileStorePluginFolder is the folder name in the file store of the plugin bundles installed.
const fileStorePluginFolder = "plugins" const fileStorePluginFolder = "plugins"
func (a *App) InstallPluginFromData(data model.PluginEventData) {
a.ch.installPluginFromData(data)
}
func (ch *Channels) installPluginFromData(data model.PluginEventData) { func (ch *Channels) installPluginFromData(data model.PluginEventData) {
mlog.Debug("Installing plugin as per cluster message", mlog.String("plugin_id", data.Id)) mlog.Debug("Installing plugin as per cluster message", mlog.String("plugin_id", data.Id))
@@ -111,10 +107,6 @@ func (ch *Channels) installPluginFromData(data model.PluginEventData) {
} }
} }
func (a *App) RemovePluginFromData(data model.PluginEventData) {
a.ch.removePluginFromData(data)
}
func (ch *Channels) removePluginFromData(data model.PluginEventData) { func (ch *Channels) removePluginFromData(data model.PluginEventData) {
mlog.Debug("Removing plugin as per cluster message", mlog.String("plugin_id", data.Id)) mlog.Debug("Removing plugin as per cluster message", mlog.String("plugin_id", data.Id))
@@ -128,10 +120,6 @@ func (ch *Channels) removePluginFromData(data model.PluginEventData) {
} }
// InstallPluginWithSignature verifies and installs plugin. // InstallPluginWithSignature verifies and installs plugin.
func (a *App) InstallPluginWithSignature(pluginFile, signature io.ReadSeeker) (*model.Manifest, *model.AppError) {
return a.ch.installPluginWithSignature(pluginFile, signature)
}
func (ch *Channels) installPluginWithSignature(pluginFile, signature io.ReadSeeker) (*model.Manifest, *model.AppError) { func (ch *Channels) installPluginWithSignature(pluginFile, signature io.ReadSeeker) (*model.Manifest, *model.AppError) {
return ch.installPlugin(pluginFile, signature, installPluginLocallyAlways) return ch.installPlugin(pluginFile, signature, installPluginLocallyAlways)
} }
@@ -189,11 +177,7 @@ func (ch *Channels) installPlugin(pluginFile, signature io.ReadSeeker, installat
// InstallMarketplacePlugin installs a plugin listed in the marketplace server. It will get the plugin bundle // InstallMarketplacePlugin installs a plugin listed in the marketplace server. It will get the plugin bundle
// from the prepackaged folder, if available, or remotely if EnableRemoteMarketplace is true. // from the prepackaged folder, if available, or remotely if EnableRemoteMarketplace is true.
func (a *App) InstallMarketplacePlugin(request *model.InstallMarketplacePluginRequest) (*model.Manifest, *model.AppError) { func (ch *Channels) InstallMarketplacePlugin(request *model.InstallMarketplacePluginRequest) (*model.Manifest, *model.AppError) {
return a.ch.installMarketplacePlugin(request)
}
func (ch *Channels) installMarketplacePlugin(request *model.InstallMarketplacePluginRequest) (*model.Manifest, *model.AppError) {
var pluginFile, signatureFile io.ReadSeeker var pluginFile, signatureFile io.ReadSeeker
prepackagedPlugin, appErr := ch.getPrepackagedPlugin(request.Id, request.Version) prepackagedPlugin, appErr := ch.getPrepackagedPlugin(request.Id, request.Version)
@@ -257,10 +241,6 @@ const (
installPluginLocallyAlways installPluginLocallyAlways
) )
func (a *App) installPluginLocally(pluginFile, signature io.ReadSeeker, installationStrategy pluginInstallationStrategy) (*model.Manifest, *model.AppError) {
return a.ch.installPluginLocally(pluginFile, signature, installationStrategy)
}
func (ch *Channels) installPluginLocally(pluginFile, signature io.ReadSeeker, installationStrategy pluginInstallationStrategy) (*model.Manifest, *model.AppError) { func (ch *Channels) installPluginLocally(pluginFile, signature io.ReadSeeker, installationStrategy pluginInstallationStrategy) (*model.Manifest, *model.AppError) {
pluginsEnvironment := ch.GetPluginsEnvironment() pluginsEnvironment := ch.GetPluginsEnvironment()
if pluginsEnvironment == nil { if pluginsEnvironment == nil {
@@ -412,11 +392,7 @@ func (ch *Channels) installExtractedPlugin(manifest *model.Manifest, fromPluginD
return manifest, nil return manifest, nil
} }
func (a *App) RemovePlugin(id string) *model.AppError { func (ch *Channels) RemovePlugin(id string) *model.AppError {
return a.ch.removePlugin(id)
}
func (ch *Channels) removePlugin(id string) *model.AppError {
// Disable plugin before removal to make sure this // Disable plugin before removal to make sure this
// plugin remains disabled on re-install. // plugin remains disabled on re-install.
if err := ch.disablePlugin(id); err != nil { if err := ch.disablePlugin(id); err != nil {
@@ -457,10 +433,6 @@ func (ch *Channels) removePlugin(id string) *model.AppError {
return nil return nil
} }
func (a *App) removePluginLocally(id string) *model.AppError {
return a.ch.removePluginLocally(id)
}
func (ch *Channels) removePluginLocally(id string) *model.AppError { func (ch *Channels) removePluginLocally(id string) *model.AppError {
pluginsEnvironment := ch.GetPluginsEnvironment() pluginsEnvironment := ch.GetPluginsEnvironment()
if pluginsEnvironment == nil { if pluginsEnvironment == nil {
@@ -488,7 +460,7 @@ func (ch *Channels) removePluginLocally(id string) *model.AppError {
pluginsEnvironment.Deactivate(id) pluginsEnvironment.Deactivate(id)
pluginsEnvironment.RemovePlugin(id) pluginsEnvironment.RemovePlugin(id)
ch.srv.unregisterPluginCommands(id) ch.unregisterPluginCommands(id)
if err := os.RemoveAll(pluginPath); err != nil { if err := os.RemoveAll(pluginPath); err != nil {
return model.NewAppError("removePlugin", "app.plugin.remove.app_error", nil, err.Error(), http.StatusInternalServerError) return model.NewAppError("removePlugin", "app.plugin.remove.app_error", nil, err.Error(), http.StatusInternalServerError)

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

@@ -73,7 +73,7 @@ func TestInstallPluginLocally(t *testing.T) {
th := Setup(t) th := Setup(t)
defer th.TearDown() defer th.TearDown()
actualManifest, appErr := th.App.installPluginLocally(&nilReadSeeker{}, nil, installPluginLocallyOnlyIfNew) actualManifest, appErr := th.App.ch.installPluginLocally(&nilReadSeeker{}, nil, installPluginLocallyOnlyIfNew)
require.NotNil(t, appErr) require.NotNil(t, appErr)
assert.Equal(t, "app.plugin.extract.app_error", appErr.Id, appErr.Error()) assert.Equal(t, "app.plugin.extract.app_error", appErr.Id, appErr.Error())
require.Nil(t, actualManifest) require.Nil(t, actualManifest)
@@ -87,7 +87,7 @@ func TestInstallPluginLocally(t *testing.T) {
{"test", "test file"}, {"test", "test file"},
}) })
actualManifest, appErr := th.App.installPluginLocally(reader, nil, installPluginLocallyOnlyIfNew) actualManifest, appErr := th.App.ch.installPluginLocally(reader, nil, installPluginLocallyOnlyIfNew)
require.NotNil(t, appErr) require.NotNil(t, appErr)
assert.Equal(t, "app.plugin.manifest.app_error", appErr.Id, appErr.Error()) assert.Equal(t, "app.plugin.manifest.app_error", appErr.Id, appErr.Error())
require.Nil(t, actualManifest) require.Nil(t, actualManifest)
@@ -106,7 +106,7 @@ func TestInstallPluginLocally(t *testing.T) {
{"plugin.json", string(manifestJSON)}, {"plugin.json", string(manifestJSON)},
}) })
actualManifest, appError := th.App.installPluginLocally(reader, nil, installationStrategy) actualManifest, appError := th.App.ch.installPluginLocally(reader, nil, installationStrategy)
if actualManifest != nil { if actualManifest != nil {
require.Equal(t, manifest, actualManifest) require.Equal(t, manifest, actualManifest)
} }
@@ -134,7 +134,7 @@ func TestInstallPluginLocally(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
for _, bundleInfo := range bundleInfos { for _, bundleInfo := range bundleInfos {
err := th.App.removePluginLocally(bundleInfo.Manifest.Id) err := th.App.ch.removePluginLocally(bundleInfo.Manifest.Id)
require.Nilf(t, err, "failed to remove existing plugin %s", bundleInfo.Manifest.Id) require.Nilf(t, err, "failed to remove existing plugin %s", bundleInfo.Manifest.Id)
} }
} }

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

@@ -20,11 +20,11 @@ import (
"github.com/mattermost/mattermost-server/v6/utils" "github.com/mattermost/mattermost-server/v6/utils"
) )
func (s *Server) ServePluginRequest(w http.ResponseWriter, r *http.Request) { func (ch *Channels) ServePluginRequest(w http.ResponseWriter, r *http.Request) {
pluginsEnvironment := s.Channels().GetPluginsEnvironment() pluginsEnvironment := ch.GetPluginsEnvironment()
if pluginsEnvironment == nil { if pluginsEnvironment == nil {
err := model.NewAppError("ServePluginRequest", "app.plugin.disabled.app_error", nil, "Enable plugins to serve plugin requests", http.StatusNotImplemented) err := model.NewAppError("ServePluginRequest", "app.plugin.disabled.app_error", nil, "Enable plugins to serve plugin requests", http.StatusNotImplemented)
s.Log.Error(err.Error()) mlog.Error(err.Error())
w.WriteHeader(err.StatusCode) w.WriteHeader(err.StatusCode)
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
w.Write([]byte(err.ToJSON())) w.Write([]byte(err.ToJSON()))
@@ -34,7 +34,7 @@ func (s *Server) ServePluginRequest(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
hooks, err := pluginsEnvironment.HooksForPlugin(params["plugin_id"]) hooks, err := pluginsEnvironment.HooksForPlugin(params["plugin_id"])
if err != nil { if err != nil {
s.Log.Error("Access to route for non-existent plugin", mlog.Error("Access to route for non-existent plugin",
mlog.String("missing_plugin_id", params["plugin_id"]), mlog.String("missing_plugin_id", params["plugin_id"]),
mlog.String("url", r.URL.String()), mlog.String("url", r.URL.String()),
mlog.Err(err)) mlog.Err(err))
@@ -42,7 +42,7 @@ func (s *Server) ServePluginRequest(w http.ResponseWriter, r *http.Request) {
return return
} }
s.servePluginRequest(w, r, hooks.ServeHTTP) ch.servePluginRequest(w, r, hooks.ServeHTTP)
} }
func (a *App) ServeInterPluginRequest(w http.ResponseWriter, r *http.Request, sourcePluginId, destinationPluginId string) { func (a *App) ServeInterPluginRequest(w http.ResponseWriter, r *http.Request, sourcePluginId, destinationPluginId string) {
@@ -80,7 +80,7 @@ func (a *App) ServeInterPluginRequest(w http.ResponseWriter, r *http.Request, so
// ServePluginPublicRequest serves public plugin files // ServePluginPublicRequest serves public plugin files
// at the URL http(s)://$SITE_URL/plugins/$PLUGIN_ID/public/{anything} // at the URL http(s)://$SITE_URL/plugins/$PLUGIN_ID/public/{anything}
func (s *Server) ServePluginPublicRequest(w http.ResponseWriter, r *http.Request) { func (ch *Channels) ServePluginPublicRequest(w http.ResponseWriter, r *http.Request) {
if strings.HasSuffix(r.URL.Path, "/") { if strings.HasSuffix(r.URL.Path, "/") {
http.NotFound(w, r) http.NotFound(w, r)
return return
@@ -90,7 +90,7 @@ func (s *Server) ServePluginPublicRequest(w http.ResponseWriter, r *http.Request
vars := mux.Vars(r) vars := mux.Vars(r)
pluginID := vars["plugin_id"] pluginID := vars["plugin_id"]
pluginsEnv := s.Channels().GetPluginsEnvironment() pluginsEnv := ch.GetPluginsEnvironment()
// Check if someone has nullified the pluginsEnv in the meantime // Check if someone has nullified the pluginsEnv in the meantime
if pluginsEnv == nil { if pluginsEnv == nil {
@@ -114,11 +114,11 @@ func (s *Server) ServePluginPublicRequest(w http.ResponseWriter, r *http.Request
http.ServeFile(w, r, publicFile) http.ServeFile(w, r, publicFile)
} }
func (s *Server) servePluginRequest(w http.ResponseWriter, r *http.Request, handler func(*plugin.Context, http.ResponseWriter, *http.Request)) { func (ch *Channels) 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(), RequestId: model.NewId(),
IPAddress: utils.GetIPAddress(r, s.Config().ServiceSettings.TrustedProxyIPHeader), IPAddress: utils.GetIPAddress(r, ch.srv.Config().ServiceSettings.TrustedProxyIPHeader),
AcceptLanguage: r.Header.Get("Accept-Language"), AcceptLanguage: r.Header.Get("Accept-Language"),
UserAgent: r.UserAgent(), UserAgent: r.UserAgent(),
} }
@@ -141,8 +141,8 @@ func (s *Server) servePluginRequest(w http.ResponseWriter, r *http.Request, hand
r.Header.Del("Mattermost-User-Id") r.Header.Del("Mattermost-User-Id")
if token != "" { if token != "" {
session, err := New(ServerConnector(s.Channels())).GetSession(token) session, err := New(ServerConnector(ch)).GetSession(token)
defer s.userService.ReturnSessionToPool(session) defer ch.srv.userService.ReturnSessionToPool(session)
csrfCheckPassed := false csrfCheckPassed := false
@@ -183,10 +183,10 @@ func (s *Server) servePluginRequest(w http.ResponseWriter, r *http.Request, hand
mlog.String("user_id", userID), mlog.String("user_id", userID),
} }
if *s.Config().ServiceSettings.ExperimentalStrictCSRFEnforcement { if *ch.srv.Config().ServiceSettings.ExperimentalStrictCSRFEnforcement {
s.Log.Warn(csrfErrorMessage, fields...) mlog.Warn(csrfErrorMessage, fields...)
} else { } else {
s.Log.Debug(csrfErrorMessage, fields...) mlog.Debug(csrfErrorMessage, fields...)
csrfCheckPassed = true csrfCheckPassed = true
} }
} }
@@ -212,7 +212,7 @@ func (s *Server) servePluginRequest(w http.ResponseWriter, r *http.Request, hand
params := mux.Vars(r) params := mux.Vars(r)
subpath, _ := utils.GetSubpathFromConfig(s.Config()) subpath, _ := utils.GetSubpathFromConfig(ch.srv.Config())
newQuery := r.URL.Query() newQuery := r.URL.Query()
newQuery.Del("access_token") newQuery.Del("access_token")

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

@@ -24,7 +24,7 @@ func TestServePluginPublicRequest(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
rr := httptest.NewRecorder() rr := httptest.NewRecorder()
handler := http.HandlerFunc(th.App.Srv().ServePluginPublicRequest) handler := http.HandlerFunc(th.App.ch.ServePluginPublicRequest)
handler.ServeHTTP(rr, req) handler.ServeHTTP(rr, req)
assert.Equal(t, http.StatusNotFound, rr.Code) assert.Equal(t, http.StatusNotFound, rr.Code)

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

@@ -342,7 +342,7 @@ func TestServePluginRequest(t *testing.T) {
w := httptest.NewRecorder() w := httptest.NewRecorder()
r := httptest.NewRequest("GET", "/plugins/foo/bar", nil) r := httptest.NewRequest("GET", "/plugins/foo/bar", nil)
th.App.ch.srv.ServePluginRequest(w, r) th.App.ch.ServePluginRequest(w, r)
assert.Equal(t, http.StatusNotImplemented, w.Result().StatusCode) assert.Equal(t, http.StatusNotImplemented, w.Result().StatusCode)
} }
@@ -386,7 +386,7 @@ func TestPrivateServePluginRequest(t *testing.T) {
request = mux.SetURLVars(request, map[string]string{"plugin_id": "id"}) request = mux.SetURLVars(request, map[string]string{"plugin_id": "id"})
th.App.ch.srv.servePluginRequest(recorder, request, handler) th.App.ch.servePluginRequest(recorder, request, handler)
}) })
} }
@@ -409,7 +409,7 @@ func TestHandlePluginRequest(t *testing.T) {
var assertions func(*http.Request) var assertions func(*http.Request)
router := mux.NewRouter() router := mux.NewRouter()
router.HandleFunc("/plugins/{plugin_id:[A-Za-z0-9\\_\\-\\.]+}/{anything:.*}", func(_ http.ResponseWriter, r *http.Request) { router.HandleFunc("/plugins/{plugin_id:[A-Za-z0-9\\_\\-\\.]+}/{anything:.*}", func(_ http.ResponseWriter, r *http.Request) {
th.App.ch.srv.servePluginRequest(nil, r, func(_ *plugin.Context, _ http.ResponseWriter, r *http.Request) { th.App.ch.servePluginRequest(nil, r, func(_ *plugin.Context, _ http.ResponseWriter, r *http.Request) {
assertions(r) assertions(r)
}) })
}) })
@@ -621,7 +621,7 @@ func TestPluginSync(t *testing.T) {
appErr = th.App.DeletePublicKey("pub_key") appErr = th.App.DeletePublicKey("pub_key")
checkNoError(t, appErr) checkNoError(t, appErr)
appErr = th.App.RemovePlugin("testplugin") appErr = th.App.ch.RemovePlugin("testplugin")
checkNoError(t, appErr) checkNoError(t, appErr)
}) })
}) })
@@ -758,7 +758,7 @@ func TestProcessPrepackagedPlugins(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, pluginBytes) require.NotNil(t, pluginBytes)
manifest, appErr := th.App.installPluginLocally(bytes.NewReader(pluginBytes), nil, installPluginLocallyAlways) manifest, appErr := th.App.ch.installPluginLocally(bytes.NewReader(pluginBytes), nil, installPluginLocallyAlways)
require.Nil(t, appErr) require.Nil(t, appErr)
require.Equal(t, "testplugin", manifest.Id) require.Equal(t, "testplugin", manifest.Id)
@@ -785,7 +785,7 @@ func TestProcessPrepackagedPlugins(t *testing.T) {
require.Len(t, pluginStatus, 1) require.Len(t, pluginStatus, 1)
require.Equal(t, pluginStatus[0].PluginId, "testplugin") require.Equal(t, pluginStatus[0].PluginId, "testplugin")
appErr = th.App.RemovePlugin("testplugin") appErr = th.App.ch.RemovePlugin("testplugin")
checkNoError(t, appErr) checkNoError(t, appErr)
pluginStatus, err = env.Statuses() pluginStatus, err = env.Statuses()
@@ -866,7 +866,7 @@ func TestProcessPrepackagedPlugins(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, pluginBytes) require.NotNil(t, pluginBytes)
manifest, appErr := th.App.installPluginLocally(bytes.NewReader(pluginBytes), nil, installPluginLocallyAlways) manifest, appErr := th.App.ch.installPluginLocally(bytes.NewReader(pluginBytes), nil, installPluginLocallyAlways)
require.Nil(t, appErr) require.Nil(t, appErr)
require.Equal(t, "testplugin", manifest.Id) require.Equal(t, "testplugin", manifest.Id)
@@ -896,7 +896,7 @@ func TestProcessPrepackagedPlugins(t *testing.T) {
require.Len(t, pluginStatus, 1) require.Len(t, pluginStatus, 1)
require.Equal(t, pluginStatus[0].PluginId, "testplugin") require.Equal(t, pluginStatus[0].PluginId, "testplugin")
appErr = th.App.RemovePlugin("testplugin") appErr = th.App.ch.RemovePlugin("testplugin")
checkNoError(t, appErr) checkNoError(t, appErr)
pluginStatus, err = env.Statuses() pluginStatus, err = env.Statuses()

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

@@ -142,9 +142,6 @@ type Server struct {
configStore *config.Store configStore *config.Store
postActionCookieSecret []byte postActionCookieSecret []byte
pluginCommands []*PluginCommand
pluginCommandsLock sync.RWMutex
telemetryService *telemetry.TelemetryService telemetryService *telemetry.TelemetryService
userService *users.UserService userService *users.UserService
teamService *teams.TeamService teamService *teams.TeamService
@@ -213,6 +210,7 @@ func NewServer(options ...Option) (*Server, error) {
licenseListeners: map[string]func(*model.License, *model.License){}, licenseListeners: map[string]func(*model.License, *model.License){},
hashSeed: maphash.MakeSeed(), hashSeed: maphash.MakeSeed(),
uploadLockMap: map[string]bool{}, uploadLockMap: map[string]bool{},
timezones: timezones.New(),
products: make(map[string]Product), products: make(map[string]Product),
} }
@@ -245,6 +243,12 @@ func NewServer(options ...Option) (*Server, error) {
mlog.Error("Could not initiate logging", mlog.Err(err)) mlog.Error("Could not initiate logging", mlog.Err(err))
} }
subpath, err := utils.GetSubpathFromConfig(s.Config())
if err != nil {
return nil, errors.Wrap(err, "failed to parse SiteURL subpath")
}
s.Router = s.RootRouter.PathPrefix(subpath).Subrouter()
// This is called after initLogging() to avoid a race condition. // This is called after initLogging() to avoid a race condition.
mlog.Info("Server is initializing...", mlog.String("go_version", runtime.Version())) mlog.Info("Server is initializing...", mlog.String("go_version", runtime.Version()))
@@ -253,9 +257,9 @@ func NewServer(options ...Option) (*Server, error) {
// Step 3: Initialize products. // Step 3: Initialize products.
// Depends on s.httpService. // Depends on s.httpService.
for name, initializer := range products { for name, initializer := range products {
prod, err := initializer(s) prod, err2 := initializer(s)
if err != nil { if err2 != nil {
return nil, errors.Wrapf(err, "error initializing product: %s", name) return nil, errors.Wrapf(err2, "error initializing product: %s", name)
} }
s.products[name] = prod s.products[name] = prod
@@ -280,8 +284,8 @@ func NewServer(options ...Option) (*Server, error) {
// At the moment we only have this implementation // At the moment we only have this implementation
// in the future the cache provider will be built based on the loaded config // in the future the cache provider will be built based on the loaded config
s.CacheProvider = cache.NewProvider() s.CacheProvider = cache.NewProvider()
if err := s.CacheProvider.Connect(); err != nil { if err2 := s.CacheProvider.Connect(); err2 != nil {
return nil, errors.Wrapf(err, "Unable to connect to cache provider") return nil, errors.Wrapf(err2, "Unable to connect to cache provider")
} }
// It is important to initialize the hub only after the global logger is set // It is important to initialize the hub only after the global logger is set
@@ -326,7 +330,6 @@ func NewServer(options ...Option) (*Server, error) {
} }
} }
var err error
s.Store, err = s.newStore() s.Store, err = s.newStore()
if err != nil { if err != nil {
return nil, errors.Wrap(err, "cannot create store") return nil, errors.Wrap(err, "cannot create store")
@@ -532,17 +535,6 @@ func NewServer(options ...Option) (*Server, error) {
return nil, errors.Wrapf(err, "unable to ensure first run timestamp") return nil, errors.Wrapf(err, "unable to ensure first run timestamp")
} }
subpath, err := utils.GetSubpathFromConfig(s.Config())
if err != nil {
return nil, errors.Wrap(err, "failed to parse SiteURL subpath")
}
s.Router = s.RootRouter.PathPrefix(subpath).Subrouter()
pluginsRoute := s.Router.PathPrefix("/plugins/{plugin_id:[A-Za-z0-9\\_\\-\\.]+}").Subrouter()
pluginsRoute.HandleFunc("", s.ServePluginRequest)
pluginsRoute.HandleFunc("/public/{public_file:.*}", s.ServePluginPublicRequest)
pluginsRoute.HandleFunc("/{anything:.*}", s.ServePluginRequest)
// If configured with a subpath, redirect 404s at the root back into the subpath. // If configured with a subpath, redirect 404s at the root back into the subpath.
if subpath != "/" { if subpath != "/" {
s.RootRouter.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { s.RootRouter.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -580,7 +572,6 @@ func NewServer(options ...Option) (*Server, error) {
} }
} }
s.timezones = timezones.New()
// Start email batching because it's not like the other jobs // Start email batching because it's not like the other jobs
s.AddConfigListener(func(_, _ *model.Config) { s.AddConfigListener(func(_, _ *model.Config) {
s.EmailService.InitEmailBatching() s.EmailService.InitEmailBatching()

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

@@ -327,7 +327,7 @@ func TestPublicFilesRequest(t *testing.T) {
require.NotNil(t, manifest) require.NotNil(t, manifest)
require.True(t, activated) require.True(t, activated)
th.App.SetPluginsEnvironment(env) th.App.Channels().SetPluginsEnvironment(env)
req, _ := http.NewRequest("GET", "/plugins/com.mattermost.sample/public/hello.html", nil) req, _ := http.NewRequest("GET", "/plugins/com.mattermost.sample/public/hello.html", nil)
res := httptest.NewRecorder() res := httptest.NewRecorder()