Move enterprise features under Channels (#19010)

* Move enterprise features under Channels

We move the EE features which are Channels related.

While here, we also move some code under *Server.Start()
from NewServer.

```release-note
NONE
```

* move saml and ldap back to server

```release-note
NONE
```

* fix test

```release-note
NONE
```

* try again

```release-note
NONE
```
Этот коммит содержится в:
Agniva De Sarker
2021-11-25 10:07:43 +05:30
коммит произвёл GitHub
родитель 189d447591
Коммит 5ab3ad9bfd
7 изменённых файлов: 115 добавлений и 104 удалений

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

@@ -95,16 +95,16 @@ func (a *App) NotificationsLog() *mlog.Logger {
}
func (a *App) AccountMigration() einterfaces.AccountMigrationInterface {
return a.ch.srv.AccountMigration
return a.ch.AccountMigration
}
func (a *App) Cluster() einterfaces.ClusterInterface {
return a.ch.srv.Cluster
}
func (a *App) Compliance() einterfaces.ComplianceInterface {
return a.ch.srv.Compliance
return a.ch.Compliance
}
func (a *App) DataRetention() einterfaces.DataRetentionInterface {
return a.ch.srv.DataRetention
return a.ch.DataRetention
}
func (a *App) SearchEngine() *searchengine.Broker {
return a.ch.srv.SearchEngine
@@ -113,7 +113,7 @@ func (a *App) Ldap() einterfaces.LdapInterface {
return a.ch.srv.Ldap
}
func (a *App) MessageExport() einterfaces.MessageExportInterface {
return a.ch.srv.MessageExport
return a.ch.MessageExport
}
func (a *App) Metrics() einterfaces.MetricsInterface {
return a.ch.srv.Metrics

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

@@ -8,6 +8,7 @@ import (
"sync/atomic"
"github.com/mattermost/mattermost-server/v6/app/request"
"github.com/mattermost/mattermost-server/v6/einterfaces"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/plugin"
"github.com/mattermost/mattermost-server/v6/services/imageproxy"
@@ -18,6 +19,8 @@ import (
type Channels struct {
srv *Server
postActionCookieSecret []byte
pluginCommandsLock sync.RWMutex
pluginCommands []*PluginCommand
pluginsLock sync.RWMutex
@@ -37,6 +40,11 @@ type Channels struct {
cachedDBMSVersion string
// previously fetched notices
cachedNotices model.ProductNotices
AccountMigration einterfaces.AccountMigrationInterface
Compliance einterfaces.ComplianceInterface
DataRetention einterfaces.DataRetentionInterface
MessageExport einterfaces.MessageExportInterface
}
func init() {
@@ -50,6 +58,23 @@ func NewChannels(s *Server) (*Channels, error) {
srv: s,
imageProxy: imageproxy.MakeImageProxy(s, s.httpService, s.Log),
}
// We are passing a partially filled Channels struct so that the enterprise
// methods can have access to app methods.
// Otherwise, passing server would mean it has to call s.Channels(),
// which would be nil at this point.
if complianceInterface != nil {
ch.Compliance = complianceInterface(New(ServerConnector(ch)))
}
if messageExportInterface != nil {
ch.MessageExport = messageExportInterface(New(ServerConnector(ch)))
}
if dataRetentionInterface != nil {
ch.DataRetention = dataRetentionInterface(New(ServerConnector(ch)))
}
if accountMigrationInterface != nil {
ch.AccountMigration = accountMigrationInterface(New(ServerConnector(ch)))
}
// Setup routes.
pluginsRoute := ch.srv.Router.PathPrefix("/plugins/{plugin_id:[A-Za-z0-9\\_\\-\\.]+}").Subrouter()
pluginsRoute.HandleFunc("", ch.ServePluginRequest)
@@ -75,6 +100,10 @@ func (ch *Channels) Start() error {
if err := ch.ensureAsymmetricSigningKey(); err != nil {
return errors.Wrapf(err, "unable to ensure asymmetric signing key")
}
if err := ch.ensurePostActionCookieSecret(); err != nil {
return errors.Wrapf(err, "unable to ensure PostAction cookie secret")
}
return nil
}

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

@@ -109,14 +109,14 @@ func (a *App) RemoveConfigListener(id string) {
// ensurePostActionCookieSecret ensures that the key for encrypting PostActionCookie exists
// and future calls to PostActionCookieSecret will always return a valid key, same on all
// servers in the cluster
func (s *Server) ensurePostActionCookieSecret() error {
if s.postActionCookieSecret != nil {
func (ch *Channels) ensurePostActionCookieSecret() error {
if ch.postActionCookieSecret != nil {
return nil
}
var secret *model.SystemPostActionCookieSecret
value, err := s.Store.System().GetByName(model.SystemPostActionCookieSecretKey)
value, err := ch.srv.Store.System().GetByName(model.SystemPostActionCookieSecretKey)
if err == nil {
if err := json.Unmarshal([]byte(value.Value), &secret); err != nil {
return err
@@ -142,7 +142,7 @@ func (s *Server) ensurePostActionCookieSecret() error {
}
system.Value = string(v)
// If we were able to save the key, use it, otherwise log the error.
if err = s.Store.System().Save(system); err != nil {
if err = ch.srv.Store.System().Save(system); err != nil {
mlog.Warn("Failed to save PostActionCookieSecret", mlog.Err(err))
} else {
secret = newSecret
@@ -152,7 +152,7 @@ func (s *Server) ensurePostActionCookieSecret() error {
// If we weren't able to save a new key above, another server must have beat us to it. Get the
// key from the database, and if that fails, error out.
if secret == nil {
value, err := s.Store.System().GetByName(model.SystemPostActionCookieSecretKey)
value, err := ch.srv.Store.System().GetByName(model.SystemPostActionCookieSecretKey)
if err != nil {
return err
}
@@ -162,7 +162,7 @@ func (s *Server) ensurePostActionCookieSecret() error {
}
}
s.postActionCookieSecret = secret.Secret
ch.postActionCookieSecret = secret.Secret
return nil
}
@@ -294,12 +294,12 @@ func (a *App) AsymmetricSigningKey() *ecdsa.PrivateKey {
return a.ch.AsymmetricSigningKey()
}
func (s *Server) PostActionCookieSecret() []byte {
return s.postActionCookieSecret
func (ch *Channels) PostActionCookieSecret() []byte {
return ch.postActionCookieSecret
}
func (a *App) PostActionCookieSecret() []byte {
return a.Srv().PostActionCookieSecret()
return a.ch.PostActionCookieSecret()
}
func (ch *Channels) regenerateClientConfig() {

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

@@ -12,9 +12,9 @@ import (
"github.com/mattermost/mattermost-server/v6/shared/mlog"
)
var accountMigrationInterface func(*Server) einterfaces.AccountMigrationInterface
var accountMigrationInterface func(*App) einterfaces.AccountMigrationInterface
func RegisterAccountMigrationInterface(f func(*Server) einterfaces.AccountMigrationInterface) {
func RegisterAccountMigrationInterface(f func(*App) einterfaces.AccountMigrationInterface) {
accountMigrationInterface = f
}
@@ -24,9 +24,9 @@ func RegisterClusterInterface(f func(*Server) einterfaces.ClusterInterface) {
clusterInterface = f
}
var complianceInterface func(*Server) einterfaces.ComplianceInterface
var complianceInterface func(*App) einterfaces.ComplianceInterface
func RegisterComplianceInterface(f func(*Server) einterfaces.ComplianceInterface) {
func RegisterComplianceInterface(f func(*App) einterfaces.ComplianceInterface) {
complianceInterface = f
}
@@ -36,9 +36,9 @@ func RegisterFixCRTChannelUnreadsJobInterface(f func(*Server) tjobs.FixCRTChanne
fixCRTChannelUnreadsJobInterface = f
}
var dataRetentionInterface func(*Server) einterfaces.DataRetentionInterface
var dataRetentionInterface func(*App) einterfaces.DataRetentionInterface
func RegisterDataRetentionInterface(f func(*Server) einterfaces.DataRetentionInterface) {
func RegisterDataRetentionInterface(f func(*App) einterfaces.DataRetentionInterface) {
dataRetentionInterface = f
}
@@ -163,9 +163,9 @@ func RegisterLdapInterface(f func(*Server) einterfaces.LdapInterface) {
ldapInterface = f
}
var messageExportInterface func(*Server) einterfaces.MessageExportInterface
var messageExportInterface func(*App) einterfaces.MessageExportInterface
func RegisterMessageExportInterface(f func(*Server) einterfaces.MessageExportInterface) {
func RegisterMessageExportInterface(f func(*App) einterfaces.MessageExportInterface) {
messageExportInterface = f
}
@@ -203,15 +203,7 @@ func (s *Server) initEnterprise() {
if metricsInterface != nil {
s.Metrics = metricsInterface(s)
}
if complianceInterface != nil {
s.Compliance = complianceInterface(s)
}
if messageExportInterface != nil {
s.MessageExport = messageExportInterface(s)
}
if dataRetentionInterface != nil {
s.DataRetention = dataRetentionInterface(s)
}
if clusterInterface != nil {
s.Cluster = clusterInterface(s)
}
@@ -223,15 +215,14 @@ func (s *Server) initEnterprise() {
s.LicenseManager = licenseInterface(s)
}
if accountMigrationInterface != nil {
s.AccountMigration = accountMigrationInterface(s)
}
if ldapInterface != nil {
s.Ldap = ldapInterface(s)
}
if notificationInterface != nil {
s.Notification = notificationInterface(s)
}
if samlInterfaceNew != nil {
mlog.Debug("Loading SAML2 library")
s.Saml = samlInterfaceNew(s)
@@ -244,6 +235,7 @@ func (s *Server) initEnterprise() {
}
})
}
if cloudInterface != nil {
s.Cloud = cloudInterface(s)
}

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

@@ -57,7 +57,7 @@ func TestSAMLSettings(t *testing.T) {
saml2.Mock.On("ConfigureSP").Return(nil)
saml2.Mock.On("GetMetadata").Return("samlTwo", nil)
if tc.setNewInterface {
RegisterNewSamlInterface(func(s *Server) einterfaces.SamlInterface {
RegisterNewSamlInterface(func(_ *Server) einterfaces.SamlInterface {
return saml2
})
} else {

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

@@ -140,7 +140,6 @@ type Server struct {
searchLicenseListenerId string
loggerLicenseListenerId string
configStore *config.Store
postActionCookieSecret []byte
telemetryService *telemetry.TelemetryService
userService *users.UserService
@@ -163,17 +162,13 @@ type Server struct {
SearchEngine *searchengine.Broker
AccountMigration einterfaces.AccountMigrationInterface
Cluster einterfaces.ClusterInterface
Compliance einterfaces.ComplianceInterface
DataRetention einterfaces.DataRetentionInterface
Ldap einterfaces.LdapInterface
MessageExport einterfaces.MessageExportInterface
Cloud einterfaces.CloudInterface
Metrics einterfaces.MetricsInterface
Notification einterfaces.NotificationInterface
Saml einterfaces.SamlInterface
LicenseManager einterfaces.LicenseInterface
Cluster einterfaces.ClusterInterface
Cloud einterfaces.CloudInterface
Metrics einterfaces.MetricsInterface
Notification einterfaces.NotificationInterface
LicenseManager einterfaces.LicenseInterface
Saml einterfaces.SamlInterface
Ldap einterfaces.LdapInterface
CacheProvider cache.Provider
@@ -207,11 +202,14 @@ func NewServer(options ...Option) (*Server, error) {
goroutineExitSignal: make(chan struct{}, 1),
RootRouter: rootRouter,
LocalRouter: localRouter,
licenseListeners: map[string]func(*model.License, *model.License){},
hashSeed: maphash.MakeSeed(),
uploadLockMap: map[string]bool{},
timezones: timezones.New(),
products: make(map[string]Product),
WebSocketRouter: &WebSocketRouter{
handlers: make(map[string]webSocketHandler),
},
licenseListeners: map[string]func(*model.License, *model.License){},
hashSeed: maphash.MakeSeed(),
uploadLockMap: map[string]bool{},
timezones: timezones.New(),
products: make(map[string]Product),
}
for _, option := range options {
@@ -523,18 +521,6 @@ func NewServer(options ...Option) (*Server, error) {
s.Cluster.StartInterNodeCommunication()
}
if err = s.ensurePostActionCookieSecret(); err != nil {
return nil, errors.Wrapf(err, "unable to ensure PostAction cookie secret")
}
if err = s.ensureInstallationDate(); err != nil {
return nil, errors.Wrapf(err, "unable to ensure installation date")
}
if err = s.ensureFirstServerRunTimestamp(); err != nil {
return nil, errors.Wrapf(err, "unable to ensure first run timestamp")
}
// If configured with a subpath, redirect 404s at the root back into the subpath.
if subpath != "/" {
s.RootRouter.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -543,35 +529,10 @@ func NewServer(options ...Option) (*Server, error) {
})
}
s.WebSocketRouter = &WebSocketRouter{
handlers: make(map[string]webSocketHandler),
}
mailConfig := s.MailServiceConfig()
if nErr := mail.TestConnection(mailConfig); nErr != nil {
mlog.Error("Mail server connection test is failed", mlog.Err(nErr))
}
if _, err = url.ParseRequestURI(*s.Config().ServiceSettings.SiteURL); err != nil {
mlog.Error("SiteURL must be set. Some features will operate incorrectly if the SiteURL is not set. See documentation for details: http://about.mattermost.com/default-site-url")
}
backend, appErr := s.FileBackend()
if appErr != nil {
mlog.Error("Problem with file storage settings", mlog.Err(appErr))
} else {
nErr := backend.TestConnection()
if nErr != nil {
if _, ok := nErr.(*filestore.S3FileBackendNoBucketError); ok {
nErr = backend.(*filestore.S3FileBackend).MakeBucket()
}
if nErr != nil {
mlog.Error("Problem with file storage settings", mlog.Err(nErr))
}
}
}
// Start email batching because it's not like the other jobs
s.AddConfigListener(func(_, _ *model.Config) {
s.EmailService.InitEmailBatching()
@@ -596,10 +557,6 @@ func NewServer(options ...Option) (*Server, error) {
mlog.Info("Printing current working", mlog.String("directory", pwd))
mlog.Info("Loaded config", mlog.String("source", s.configStore.String()))
s.checkPushNotificationServerURL()
s.ReloadConfig()
license := s.License()
allowAdvancedLogging := license != nil && *license.Features.AdvancedLogging
@@ -624,10 +581,6 @@ func NewServer(options ...Option) (*Server, error) {
s.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableDeveloper = true })
}
if err = s.Store.Status().ResetAll(); err != nil {
mlog.Error("Error to reset the server status.", mlog.Err(err))
}
if s.startMetrics {
s.SetupMetricsServer()
}
@@ -663,11 +616,10 @@ func NewServer(options ...Option) (*Server, error) {
return s, nil
}
c := request.EmptyContext()
s.AddConfigListener(func(oldConfig *model.Config, newConfig *model.Config) {
s.AddConfigListener(func(old, new *model.Config) {
appInstance := New(ServerConnector(s.Channels()))
if *oldConfig.GuestAccountsSettings.Enable && !*newConfig.GuestAccountsSettings.Enable {
if appErr := appInstance.DeactivateGuests(c); appErr != nil {
if *old.GuestAccountsSettings.Enable && !*new.GuestAccountsSettings.Enable {
if appErr := appInstance.DeactivateGuests(request.EmptyContext()); appErr != nil {
mlog.Error("Unable to deactivate guest accounts", mlog.Err(appErr))
}
}
@@ -676,7 +628,7 @@ func NewServer(options ...Option) (*Server, error) {
// Disable active guest accounts on first run if guest accounts are disabled
if !*s.Config().GuestAccountsSettings.Enable {
appInstance := New(ServerConnector(s.Channels()))
if appErr := appInstance.DeactivateGuests(c); appErr != nil {
if appErr := appInstance.DeactivateGuests(request.EmptyContext()); appErr != nil {
mlog.Error("Unable to deactivate guest accounts", mlog.Err(appErr))
}
}
@@ -685,7 +637,7 @@ func NewServer(options ...Option) (*Server, error) {
s.Go(func() {
appInstance := New(ServerConnector(s.Channels()))
s.runLicenseExpirationCheckJob()
runCheckAdminSupportStatusJob(appInstance, c)
runCheckAdminSupportStatusJob(appInstance, request.EmptyContext())
runDNDStatusExpireJob(appInstance)
})
s.runJobs()
@@ -759,7 +711,7 @@ func (s *Server) runJobs() {
runCommandWebhookCleanupJob(s)
})
if complianceI := s.Compliance; complianceI != nil {
if complianceI := s.Channels().Compliance; complianceI != nil {
complianceI.StartComplianceDailyJob()
}
@@ -1208,6 +1160,40 @@ func (s *Server) Start() error {
}
}
if err := s.ensureInstallationDate(); err != nil {
return errors.Wrapf(err, "unable to ensure installation date")
}
if err := s.ensureFirstServerRunTimestamp(); err != nil {
return errors.Wrapf(err, "unable to ensure first run timestamp")
}
if err := s.Store.Status().ResetAll(); err != nil {
mlog.Error("Error to reset the server status.", mlog.Err(err))
}
if err := mail.TestConnection(s.MailServiceConfig()); err != nil {
mlog.Error("Mail server connection test is failed", mlog.Err(err))
}
backend, appErr := s.FileBackend()
if appErr != nil {
mlog.Error("Problem with file storage settings", mlog.Err(appErr))
} else {
err := backend.TestConnection()
if err != nil {
if _, ok := err.(*filestore.S3FileBackendNoBucketError); ok {
err = backend.(*filestore.S3FileBackend).MakeBucket()
}
if err != nil {
mlog.Error("Problem with file storage settings", mlog.Err(err))
}
}
}
s.checkPushNotificationServerURL()
s.ReloadConfig()
mlog.Info("Starting Server...")
var handler http.Handler = s.RootRouter
@@ -2178,7 +2164,7 @@ func (a *App) generateSupportPacketYaml() (*model.FileData, string) {
}
// Here we are getting information regarding LDAP
ldapInterface := a.Srv().Ldap
ldapInterface := a.ch.srv.Ldap
var vendorName, vendorVersion string
if ldapInterface != nil {
vendorName, vendorVersion = ldapInterface.GetVendorNameAndVendorVersion()

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

@@ -182,11 +182,15 @@ func TestStartServerNoS3Bucket(t *testing.T) {
AmazonS3PathPrefix: model.NewString(""),
AmazonS3SSL: model.NewBool(false),
}
*cfg.ServiceSettings.ListenAddress = ":0"
})
return nil
})
require.NoError(t, err)
require.NoError(t, s.Start())
defer s.Shutdown()
// ensure that a new bucket was created
backend, appErr := s.FileBackend()
require.Nil(t, appErr)