MM-40818: Refactor product initialization to happen late (#19658)

This is more of a general refactor of the initialization
process which should allow us to pass services more
easily.

The changes are minimal to keep the scope limited.
For now, the objective is to pass the file service
to the Channels product. For that, it was required
to move some of the enterprise interfaces under Channels
from Server.

We also create a filestore field in the server to
avoid creating filestore reference every time
we make a filestore operation. This will be later
passed on to the Channels product.

Also removed an unnecessary test. 
The test was working so far because we were creating
the filebackend every time for every request. But
we should go via UpdateConfig call which would fail,
were we to assign an invalid filestore name.

So we were actually testing for a different thing.
Therefore, removed the test.

```release-note
NONE
```
Этот коммит содержится в:
Agniva De Sarker
2022-03-03 12:22:10 +05:30
коммит произвёл GitHub
родитель 768fe43d3a
Коммит ab8de49f0a
17 изменённых файлов: 119 добавлений и 200 удалений

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

@@ -153,7 +153,7 @@ func TestSyncLdap(t *testing.T) {
includeRemovedMembers = args[1].(bool) includeRemovedMembers = args[1].(bool)
ready <- true ready <- true
} }
th.App.Srv().Ldap = ldapMock th.App.Channels().Ldap = ldapMock
th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
_, err := client.SyncLdap(false) _, err := client.SyncLdap(false)

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

@@ -56,7 +56,7 @@ func TestSamlCompleteCSRFPass(t *testing.T) {
func TestSamlResetId(t *testing.T) { func TestSamlResetId(t *testing.T) {
th := SetupEnterprise(t).InitBasic() th := SetupEnterprise(t).InitBasic()
defer th.TearDown() defer th.TearDown()
th.App.Srv().Saml = &mocks.SamlInterface{} th.App.Channels().Saml = &mocks.SamlInterface{}
user := th.BasicUser user := th.BasicUser
_, appErr := th.App.UpdateUserAuth(user.Id, &model.UserAuth{ _, appErr := th.App.UpdateUserAuth(user.Id, &model.UserAuth{

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

@@ -95,11 +95,7 @@ func generateSupportPacket(c *Context, w http.ResponseWriter, r *http.Request) {
now := time.Now() now := time.Now()
outputZipFilename := fmt.Sprintf("mattermost_support_packet_%s.zip", now.Format("2006-01-02-03-04")) outputZipFilename := fmt.Sprintf("mattermost_support_packet_%s.zip", now.Format("2006-01-02-03-04"))
fileStorageBackend, fileBackendErr := c.App.FileBackend() fileStorageBackend := c.App.FileBackend()
if fileBackendErr != nil {
c.Err = fileBackendErr
return
}
// We do this incase we get concurrent requests, we will always have a unique directory. // We do this incase we get concurrent requests, we will always have a unique directory.
// This is to avoid the situation where we try to write to the same directory while we are trying to delete it (further down) // This is to avoid the situation where we try to write to the same directory while we are trying to delete it (further down)

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

@@ -57,20 +57,6 @@ func TestGetPing(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, model.StatusOk, status) assert.Equal(t, model.StatusOk, status)
}) })
t.Run("unhealthy", func(t *testing.T) {
oldDriver := th.App.Config().FileSettings.DriverName
badDriver := "badDriverName"
th.App.Config().FileSettings.DriverName = &badDriver
defer func() {
th.App.Config().FileSettings.DriverName = oldDriver
}()
status, resp, err := client.GetPingWithServerStatus()
require.Error(t, err)
CheckInternalErrorStatus(t, resp)
assert.Equal(t, model.StatusUnhealthy, status)
})
}, "with server status") }, "with server status")
th.TestForAllClients(t, func(t *testing.T, client *model.Client4) { th.TestForAllClients(t, func(t *testing.T, client *model.Client4) {

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

@@ -6503,7 +6503,7 @@ func TestPatchAndUpdateWithProviderAttributes(t *testing.T) {
mock.Anything, // *model.User mock.Anything, // *model.User
mock.Anything, // *model.Patch mock.Anything, // *model.Patch
).Return("") ).Return("")
th.App.Srv().Ldap = ldapMock th.App.Channels().Ldap = ldapMock
// CheckProviderAttributes should be called for both Patch and Update // CheckProviderAttributes should be called for both Patch and Update
th.SystemAdminClient.PatchUser(user.Id, &model.UserPatch{}) th.SystemAdminClient.PatchUser(user.Id, &model.UserPatch{})
ldapMock.AssertNumberOfCalls(t, "CheckProviderAttributes", 1) ldapMock.AssertNumberOfCalls(t, "CheckProviderAttributes", 1)
@@ -6524,7 +6524,7 @@ func TestPatchAndUpdateWithProviderAttributes(t *testing.T) {
ldapMock.Mock.On( ldapMock.Mock.On(
"CheckProviderAttributes", mock.Anything, mock.Anything, mock.Anything, "CheckProviderAttributes", mock.Anything, mock.Anything, mock.Anything,
).Return("") ).Return("")
th.App.Srv().Ldap = ldapMock th.App.Channels().Ldap = ldapMock
th.SystemAdminClient.PatchUser(user.Id, &model.UserPatch{}) th.SystemAdminClient.PatchUser(user.Id, &model.UserPatch{})
ldapMock.AssertNumberOfCalls(t, "CheckProviderAttributes", 1) ldapMock.AssertNumberOfCalls(t, "CheckProviderAttributes", 1)
th.SystemAdminClient.UpdateUser(user) th.SystemAdminClient.UpdateUser(user)
@@ -6538,7 +6538,7 @@ func TestPatchAndUpdateWithProviderAttributes(t *testing.T) {
samlMock.Mock.On( samlMock.Mock.On(
"CheckProviderAttributes", mock.Anything, mock.Anything, mock.Anything, "CheckProviderAttributes", mock.Anything, mock.Anything, mock.Anything,
).Return("") ).Return("")
th.App.Srv().Saml = samlMock th.App.Channels().Saml = samlMock
th.SystemAdminClient.PatchUser(user.Id, &model.UserPatch{}) th.SystemAdminClient.PatchUser(user.Id, &model.UserPatch{})
samlMock.AssertNumberOfCalls(t, "CheckProviderAttributes", 1) samlMock.AssertNumberOfCalls(t, "CheckProviderAttributes", 1)
th.SystemAdminClient.UpdateUser(user) th.SystemAdminClient.UpdateUser(user)

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

@@ -110,7 +110,7 @@ func (a *App) SearchEngine() *searchengine.Broker {
return a.ch.srv.SearchEngine return a.ch.srv.SearchEngine
} }
func (a *App) Ldap() einterfaces.LdapInterface { func (a *App) Ldap() einterfaces.LdapInterface {
return a.ch.srv.Ldap return a.ch.Ldap
} }
func (a *App) MessageExport() einterfaces.MessageExportInterface { func (a *App) MessageExport() einterfaces.MessageExportInterface {
return a.ch.MessageExport return a.ch.MessageExport
@@ -119,10 +119,10 @@ func (a *App) Metrics() einterfaces.MetricsInterface {
return a.ch.srv.Metrics return a.ch.srv.Metrics
} }
func (a *App) Notification() einterfaces.NotificationInterface { func (a *App) Notification() einterfaces.NotificationInterface {
return a.ch.srv.Notification return a.ch.Notification
} }
func (a *App) Saml() einterfaces.SamlInterface { func (a *App) Saml() einterfaces.SamlInterface {
return a.ch.srv.Saml return a.ch.Saml
} }
func (a *App) Cloud() einterfaces.CloudInterface { func (a *App) Cloud() einterfaces.CloudInterface {
return a.ch.srv.Cloud return a.ch.srv.Cloud

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

@@ -527,7 +527,7 @@ type AppIface interface {
ExportPermissions(w io.Writer) error ExportPermissions(w io.Writer) error
ExtractContentFromFileInfo(fileInfo *model.FileInfo) error ExtractContentFromFileInfo(fileInfo *model.FileInfo) error
FetchSamlMetadataFromIdp(url string) ([]byte, *model.AppError) FetchSamlMetadataFromIdp(url string) ([]byte, *model.AppError)
FileBackend() (filestore.FileBackend, *model.AppError) FileBackend() filestore.FileBackend
FileExists(path string) (bool, *model.AppError) FileExists(path string) (bool, *model.AppError)
FileModTime(path string) (time.Time, *model.AppError) FileModTime(path string) (time.Time, *model.AppError)
FileSize(path string) (int64, *model.AppError) FileSize(path string) (int64, *model.AppError)

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

@@ -75,6 +75,9 @@ type Channels struct {
Compliance einterfaces.ComplianceInterface Compliance einterfaces.ComplianceInterface
DataRetention einterfaces.DataRetentionInterface DataRetention einterfaces.DataRetentionInterface
MessageExport einterfaces.MessageExportInterface MessageExport einterfaces.MessageExportInterface
Saml einterfaces.SamlInterface
Notification einterfaces.NotificationInterface
Ldap einterfaces.LdapInterface
// These are used to prevent concurrent upload requests // These are used to prevent concurrent upload requests
// for a given upload session which could cause inconsistencies // for a given upload session which could cause inconsistencies
@@ -145,6 +148,24 @@ func NewChannels(s *Server, services map[ServiceKey]interface{}) (*Channels, err
if accountMigrationInterface != nil { if accountMigrationInterface != nil {
ch.AccountMigration = accountMigrationInterface(New(ServerConnector(ch))) ch.AccountMigration = accountMigrationInterface(New(ServerConnector(ch)))
} }
if ldapInterface != nil {
ch.Ldap = ldapInterface(New(ServerConnector(ch)))
}
if notificationInterface != nil {
ch.Notification = notificationInterface(New(ServerConnector(ch)))
}
if samlInterfaceNew != nil {
ch.Saml = samlInterfaceNew(New(ServerConnector(ch)))
if err := ch.Saml.ConfigureSP(); err != nil {
mlog.Error("An error occurred while configuring SAML Service Provider", mlog.Err(err))
}
ch.AddConfigListener(func(_, _ *model.Config) {
if err := ch.Saml.ConfigureSP(); err != nil {
mlog.Error("An error occurred while configuring SAML Service Provider", mlog.Err(err))
}
})
}
var imgErr error var imgErr error
ch.imgDecoder, imgErr = imaging.NewDecoder(imaging.DecoderOptions{ ch.imgDecoder, imgErr = imaging.NewDecoder(imaging.DecoderOptions{

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

@@ -110,7 +110,7 @@ func (s *Server) ConfigStore() *configWrapper {
} }
func (a *App) Config() *model.Config { func (a *App) Config() *model.Config {
return a.Srv().Config() return a.ch.cfgSvc.Config()
} }
func (s *Server) EnvironmentConfig(filter func(reflect.StructField) bool) map[string]interface{} { func (s *Server) EnvironmentConfig(filter func(reflect.StructField) bool) map[string]interface{} {

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

@@ -6,9 +6,7 @@ package app
import ( import (
"github.com/mattermost/mattermost-server/v6/einterfaces" "github.com/mattermost/mattermost-server/v6/einterfaces"
ejobs "github.com/mattermost/mattermost-server/v6/einterfaces/jobs" ejobs "github.com/mattermost/mattermost-server/v6/einterfaces/jobs"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/services/searchengine" "github.com/mattermost/mattermost-server/v6/services/searchengine"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
) )
var accountMigrationInterface func(*App) einterfaces.AccountMigrationInterface var accountMigrationInterface func(*App) einterfaces.AccountMigrationInterface
@@ -65,9 +63,9 @@ func RegisterJobsElasticsearchIndexerInterface(f func(*Server) ejobs.IndexerJobI
jobsElasticsearchIndexerInterface = f jobsElasticsearchIndexerInterface = f
} }
var jobsLdapSyncInterface func(*Server) ejobs.LdapSyncInterface var jobsLdapSyncInterface func(*App) ejobs.LdapSyncInterface
func RegisterJobsLdapSyncInterface(f func(*Server) ejobs.LdapSyncInterface) { func RegisterJobsLdapSyncInterface(f func(*App) ejobs.LdapSyncInterface) {
jobsLdapSyncInterface = f jobsLdapSyncInterface = f
} }
@@ -77,9 +75,9 @@ func RegisterJobsCloudInterface(f func(*Server) ejobs.CloudJobInterface) {
jobsCloudInterface = f jobsCloudInterface = f
} }
var ldapInterface func(*Server) einterfaces.LdapInterface var ldapInterface func(*App) einterfaces.LdapInterface
func RegisterLdapInterface(f func(*Server) einterfaces.LdapInterface) { func RegisterLdapInterface(f func(*App) einterfaces.LdapInterface) {
ldapInterface = f ldapInterface = f
} }
@@ -101,15 +99,15 @@ func RegisterMetricsInterface(f func(*Server) einterfaces.MetricsInterface) {
metricsInterface = f metricsInterface = f
} }
var samlInterfaceNew func(*Server) einterfaces.SamlInterface var samlInterfaceNew func(*App) einterfaces.SamlInterface
func RegisterNewSamlInterface(f func(*Server) einterfaces.SamlInterface) { func RegisterNewSamlInterface(f func(*App) einterfaces.SamlInterface) {
samlInterfaceNew = f samlInterfaceNew = f
} }
var notificationInterface func(*Server) einterfaces.NotificationInterface var notificationInterface func(*App) einterfaces.NotificationInterface
func RegisterNotificationInterface(f func(*Server) einterfaces.NotificationInterface) { func RegisterNotificationInterface(f func(*App) einterfaces.NotificationInterface) {
notificationInterface = f notificationInterface = f
} }
@@ -135,27 +133,6 @@ func (s *Server) initEnterprise() {
s.LicenseManager = licenseInterface(s) s.LicenseManager = licenseInterface(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)
if err := s.Saml.ConfigureSP(); err != nil {
mlog.Error("An error occurred while configuring SAML Service Provider", mlog.Err(err))
}
s.AddConfigListener(func(_, cfg *model.Config) {
if err := s.Saml.ConfigureSP(); err != nil {
mlog.Error("An error occurred while configuring SAML Service Provider", mlog.Err(err))
}
})
}
if cloudInterface != nil { if cloudInterface != nil {
s.Cloud = cloudInterface(s) s.Cloud = cloudInterface(s)
} }

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

@@ -57,7 +57,7 @@ func TestSAMLSettings(t *testing.T) {
saml2.Mock.On("ConfigureSP").Return(nil) saml2.Mock.On("ConfigureSP").Return(nil)
saml2.Mock.On("GetMetadata").Return("samlTwo", nil) saml2.Mock.On("GetMetadata").Return("samlTwo", nil)
if tc.setNewInterface { if tc.setNewInterface {
RegisterNewSamlInterface(func(_ *Server) einterfaces.SamlInterface { RegisterNewSamlInterface(func(_ *App) einterfaces.SamlInterface {
return saml2 return saml2
}) })
} else { } else {
@@ -89,10 +89,10 @@ func TestSAMLSettings(t *testing.T) {
} }
if tc.isNil { if tc.isNil {
assert.Nil(t, th.App.Srv().Saml) assert.Nil(t, th.App.Channels().Saml)
} else { } else {
assert.NotNil(t, th.App.Srv().Saml) assert.NotNil(t, th.App.Channels().Saml)
metadata, err := th.App.Srv().Saml.GetMetadata() metadata, err := th.App.Channels().Saml.GetMetadata()
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, tc.metadata, metadata) assert.Equal(t, tc.metadata, metadata)
} }

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

@@ -47,7 +47,7 @@ const (
maxContentExtractionSize = 1024 * 1024 // 1MB maxContentExtractionSize = 1024 * 1024 // 1MB
) )
func (a *App) FileBackend() (filestore.FileBackend, *model.AppError) { func (a *App) FileBackend() filestore.FileBackend {
return a.Srv().FileBackend() return a.Srv().FileBackend()
} }
@@ -72,11 +72,7 @@ func connectionTestErrorToAppError(connTestErr error) *model.AppError {
} }
func (a *App) TestFileStoreConnection() *model.AppError { func (a *App) TestFileStoreConnection() *model.AppError {
backend, err := a.FileBackend() nErr := a.FileBackend().TestConnection()
if err != nil {
return err
}
nErr := backend.TestConnection()
if nErr != nil { if nErr != nil {
return connectionTestErrorToAppError(nErr) return connectionTestErrorToAppError(nErr)
} }
@@ -101,11 +97,7 @@ func (a *App) ReadFile(path string) ([]byte, *model.AppError) {
} }
func (s *Server) fileReader(path string) (filestore.ReadCloseSeeker, *model.AppError) { func (s *Server) fileReader(path string) (filestore.ReadCloseSeeker, *model.AppError) {
backend, err := s.FileBackend() result, nErr := s.FileBackend().Reader(path)
if err != nil {
return nil, err
}
result, nErr := backend.Reader(path)
if nErr != nil { if nErr != nil {
return nil, model.NewAppError("FileReader", "api.file.file_reader.app_error", nil, nErr.Error(), http.StatusInternalServerError) return nil, model.NewAppError("FileReader", "api.file.file_reader.app_error", nil, nErr.Error(), http.StatusInternalServerError)
} }
@@ -122,11 +114,7 @@ func (a *App) FileExists(path string) (bool, *model.AppError) {
} }
func (s *Server) fileExists(path string) (bool, *model.AppError) { func (s *Server) fileExists(path string) (bool, *model.AppError) {
backend, err := s.FileBackend() result, nErr := s.FileBackend().FileExists(path)
if err != nil {
return false, err
}
result, nErr := backend.FileExists(path)
if nErr != nil { if nErr != nil {
return false, model.NewAppError("FileExists", "api.file.file_exists.app_error", nil, nErr.Error(), http.StatusInternalServerError) return false, model.NewAppError("FileExists", "api.file.file_exists.app_error", nil, nErr.Error(), http.StatusInternalServerError)
} }
@@ -134,11 +122,7 @@ func (s *Server) fileExists(path string) (bool, *model.AppError) {
} }
func (a *App) FileSize(path string) (int64, *model.AppError) { func (a *App) FileSize(path string) (int64, *model.AppError) {
backend, err := a.FileBackend() size, nErr := a.FileBackend().FileSize(path)
if err != nil {
return 0, err
}
size, nErr := backend.FileSize(path)
if nErr != nil { if nErr != nil {
return 0, model.NewAppError("FileSize", "api.file.file_size.app_error", nil, nErr.Error(), http.StatusInternalServerError) return 0, model.NewAppError("FileSize", "api.file.file_size.app_error", nil, nErr.Error(), http.StatusInternalServerError)
} }
@@ -146,11 +130,7 @@ func (a *App) FileSize(path string) (int64, *model.AppError) {
} }
func (a *App) FileModTime(path string) (time.Time, *model.AppError) { func (a *App) FileModTime(path string) (time.Time, *model.AppError) {
backend, err := a.FileBackend() modTime, nErr := a.FileBackend().FileModTime(path)
if err != nil {
return time.Time{}, err
}
modTime, nErr := backend.FileModTime(path)
if nErr != nil { if nErr != nil {
return time.Time{}, model.NewAppError("FileModTime", "api.file.file_mod_time.app_error", nil, nErr.Error(), http.StatusInternalServerError) return time.Time{}, model.NewAppError("FileModTime", "api.file.file_mod_time.app_error", nil, nErr.Error(), http.StatusInternalServerError)
} }
@@ -159,11 +139,7 @@ func (a *App) FileModTime(path string) (time.Time, *model.AppError) {
} }
func (a *App) MoveFile(oldPath, newPath string) *model.AppError { func (a *App) MoveFile(oldPath, newPath string) *model.AppError {
backend, err := a.FileBackend() nErr := a.FileBackend().MoveFile(oldPath, newPath)
if err != nil {
return err
}
nErr := backend.MoveFile(oldPath, newPath)
if nErr != nil { if nErr != nil {
return model.NewAppError("MoveFile", "api.file.move_file.app_error", nil, nErr.Error(), http.StatusInternalServerError) return model.NewAppError("MoveFile", "api.file.move_file.app_error", nil, nErr.Error(), http.StatusInternalServerError)
} }
@@ -175,12 +151,7 @@ func (a *App) WriteFile(fr io.Reader, path string) (int64, *model.AppError) {
} }
func (s *Server) writeFile(fr io.Reader, path string) (int64, *model.AppError) { func (s *Server) writeFile(fr io.Reader, path string) (int64, *model.AppError) {
backend, err := s.FileBackend() result, nErr := s.FileBackend().WriteFile(fr, path)
if err != nil {
return 0, err
}
result, nErr := backend.WriteFile(fr, path)
if nErr != nil { if nErr != nil {
return result, model.NewAppError("WriteFile", "api.file.write_file.app_error", nil, nErr.Error(), http.StatusInternalServerError) return result, model.NewAppError("WriteFile", "api.file.write_file.app_error", nil, nErr.Error(), http.StatusInternalServerError)
} }
@@ -188,12 +159,7 @@ func (s *Server) writeFile(fr io.Reader, path string) (int64, *model.AppError) {
} }
func (a *App) AppendFile(fr io.Reader, path string) (int64, *model.AppError) { func (a *App) AppendFile(fr io.Reader, path string) (int64, *model.AppError) {
backend, err := a.FileBackend() result, nErr := a.FileBackend().AppendFile(fr, path)
if err != nil {
return 0, err
}
result, nErr := backend.AppendFile(fr, path)
if nErr != nil { if nErr != nil {
return result, model.NewAppError("AppendFile", "api.file.append_file.app_error", nil, nErr.Error(), http.StatusInternalServerError) return result, model.NewAppError("AppendFile", "api.file.append_file.app_error", nil, nErr.Error(), http.StatusInternalServerError)
} }
@@ -205,11 +171,7 @@ func (a *App) RemoveFile(path string) *model.AppError {
} }
func (s *Server) removeFile(path string) *model.AppError { func (s *Server) removeFile(path string) *model.AppError {
backend, err := s.FileBackend() nErr := s.FileBackend().RemoveFile(path)
if err != nil {
return err
}
nErr := backend.RemoveFile(path)
if nErr != nil { if nErr != nil {
return model.NewAppError("RemoveFile", "api.file.remove_file.app_error", nil, nErr.Error(), http.StatusInternalServerError) return model.NewAppError("RemoveFile", "api.file.remove_file.app_error", nil, nErr.Error(), http.StatusInternalServerError)
} }
@@ -221,11 +183,7 @@ func (a *App) ListDirectory(path string) ([]string, *model.AppError) {
} }
func (s *Server) listDirectory(path string) ([]string, *model.AppError) { func (s *Server) listDirectory(path string) ([]string, *model.AppError) {
backend, err := s.FileBackend() paths, nErr := s.FileBackend().ListDirectory(path)
if err != nil {
return nil, err
}
paths, nErr := backend.ListDirectory(path)
if nErr != nil { if nErr != nil {
return nil, model.NewAppError("ListDirectory", "api.file.list_directory.app_error", nil, nErr.Error(), http.StatusInternalServerError) return nil, model.NewAppError("ListDirectory", "api.file.list_directory.app_error", nil, nErr.Error(), http.StatusInternalServerError)
} }
@@ -234,11 +192,7 @@ func (s *Server) listDirectory(path string) ([]string, *model.AppError) {
} }
func (a *App) RemoveDirectory(path string) *model.AppError { func (a *App) RemoveDirectory(path string) *model.AppError {
backend, err := a.FileBackend() nErr := a.FileBackend().RemoveDirectory(path)
if err != nil {
return err
}
nErr := backend.RemoveDirectory(path)
if nErr != nil { if nErr != nil {
return model.NewAppError("RemoveDirectory", "api.file.remove_directory.app_error", nil, nErr.Error(), http.StatusInternalServerError) return model.NewAppError("RemoveDirectory", "api.file.remove_directory.app_error", nil, nErr.Error(), http.StatusInternalServerError)
} }

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

@@ -557,7 +557,7 @@ func (a *App) BuildPushNotificationMessage(contentsConfig string, post *model.Po
var msg *model.PushNotification var msg *model.PushNotification
notificationInterface := a.Srv().Notification notificationInterface := a.ch.Notification
if (notificationInterface == nil || notificationInterface.CheckLicense() != nil) && contentsConfig == model.IdLoadedNotification { if (notificationInterface == nil || notificationInterface.CheckLicense() != nil) && contentsConfig == model.IdLoadedNotification {
contentsConfig = model.GenericNotification contentsConfig = model.GenericNotification
} }

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

@@ -4013,7 +4013,7 @@ func (a *OpenTracingAppLayer) FetchSamlMetadataFromIdp(url string) ([]byte, *mod
return resultVar0, resultVar1 return resultVar0, resultVar1
} }
func (a *OpenTracingAppLayer) FileBackend() (filestore.FileBackend, *model.AppError) { func (a *OpenTracingAppLayer) FileBackend() filestore.FileBackend {
origCtx := a.ctx origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.FileBackend") span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.FileBackend")
@@ -4025,14 +4025,9 @@ func (a *OpenTracingAppLayer) FileBackend() (filestore.FileBackend, *model.AppEr
}() }()
defer span.Finish() defer span.Finish()
resultVar0, resultVar1 := a.app.FileBackend() resultVar0 := a.app.FileBackend()
if resultVar1 != nil { return resultVar0
span.LogFields(spanlog.Error(resultVar1))
ext.Error.Set(span, true)
}
return resultVar0, resultVar1
} }
func (a *OpenTracingAppLayer) FileExists(path string) (bool, *model.AppError) { func (a *OpenTracingAppLayer) FileExists(path string) (bool, *model.AppError) {

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

@@ -159,6 +159,7 @@ type Server struct {
searchLicenseListenerId string searchLicenseListenerId string
loggerLicenseListenerId string loggerLicenseListenerId string
configStore *configWrapper configStore *configWrapper
filestore filestore.FileBackend
telemetryService *telemetry.TelemetryService telemetryService *telemetry.TelemetryService
userService *users.UserService userService *users.UserService
@@ -184,10 +185,7 @@ type Server struct {
Cluster einterfaces.ClusterInterface Cluster einterfaces.ClusterInterface
Cloud einterfaces.CloudInterface Cloud einterfaces.CloudInterface
Metrics einterfaces.MetricsInterface Metrics einterfaces.MetricsInterface
Notification einterfaces.NotificationInterface
LicenseManager einterfaces.LicenseInterface LicenseManager einterfaces.LicenseInterface
Saml einterfaces.SamlInterface
Ldap einterfaces.LdapInterface
CacheProvider cache.Provider CacheProvider cache.Provider
@@ -257,27 +255,8 @@ func NewServer(options ...Option) (*Server, error) {
mlog.Info("Server is initializing...", mlog.String("go_version", runtime.Version())) mlog.Info("Server is initializing...", mlog.String("go_version", runtime.Version()))
s.httpService = httpservice.MakeHTTPService(s) s.httpService = httpservice.MakeHTTPService(s)
s.licenseWrapper = &licenseWrapper{
srv: s,
}
serviceMap := map[ServiceKey]interface{}{ // Step 3: Search Engine
ConfigKey: s.configStore,
LicenseKey: s.licenseWrapper,
}
// Step 3: Initialize products.
// Depends on s.httpService.
for name, initializer := range products {
prod, err2 := initializer(s, serviceMap)
if err2 != nil {
return nil, errors.Wrapf(err2, "error initializing product: %s", name)
}
s.products[name] = prod
}
// Step 4: Search Engine
// Depends on Step 1 (config). // Depends on Step 1 (config).
searchEngine := searchengine.NewBroker(s.Config()) searchEngine := searchengine.NewBroker(s.Config())
bleveEngine := bleveengine.NewBleveEngine(s.Config()) bleveEngine := bleveengine.NewBleveEngine(s.Config())
@@ -287,12 +266,11 @@ func NewServer(options ...Option) (*Server, error) {
searchEngine.RegisterBleveEngine(bleveEngine) searchEngine.RegisterBleveEngine(bleveEngine)
s.SearchEngine = searchEngine s.SearchEngine = searchEngine
// Step 5: Init Enterprise // Step 4: Init Enterprise
// Depends on step 3 (s.Channels() must be non-nil) // Depends on step 3 (s.SearchEngine must be non-nil)
// and step 4 (s.SearchEngine must be non-nil)
s.initEnterprise() s.initEnterprise()
// Step 6: Cache provider. // Step 5: Cache provider.
// 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()
@@ -300,12 +278,8 @@ func NewServer(options ...Option) (*Server, error) {
return nil, errors.Wrapf(err2, "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 // Step 6: Store.
// to avoid race conditions while logging from inside the hub. // Depends on Step 1 (config), 4 (metrics, cluster) and 5 (cacheProvider).
s.HubStart()
// Step 7: Store.
// Depends on Step 1 (config), 5 (metrics, cluster) and 6 (cacheProvider).
if s.newStore == nil { if s.newStore == nil {
s.newStore = func() (store.Store, error) { s.newStore = func() (store.Store, error) {
s.sqlStore = sqlstore.New(s.Config().SqlSettings, s.Metrics) s.sqlStore = sqlstore.New(s.Config().SqlSettings, s.Metrics)
@@ -347,6 +321,42 @@ func NewServer(options ...Option) (*Server, error) {
return nil, errors.Wrap(err, "cannot create store") return nil, errors.Wrap(err, "cannot create store")
} }
if model.BuildEnterpriseReady == "true" {
s.LoadLicense()
}
license := s.License()
// Step 7: Initialize filestore
backend, err := filestore.NewFileBackend(s.Config().FileSettings.ToFileBackendSettings(license != nil && *license.Features.Compliance))
if err != nil {
return nil, errors.Wrap(err, "failed to initialize filebackend")
}
s.filestore = backend
s.licenseWrapper = &licenseWrapper{
srv: s,
}
serviceMap := map[ServiceKey]interface{}{
ConfigKey: s.configStore,
LicenseKey: s.licenseWrapper,
}
// Step 8: Initialize products.
// Depends on s.httpService.
for name, initializer := range products {
prod, err2 := initializer(s, serviceMap)
if err2 != nil {
return nil, errors.Wrapf(err2, "error initializing product: %s", name)
}
s.products[name] = prod
}
// It is important to initialize the hub only after the global logger is set
// to avoid race conditions while logging from inside the hub.
// Step 9: Hub depends on s.Channels() (step 8)
s.HubStart()
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Everything below this is not order sensitive and safe to be moved around. // Everything below this is not order sensitive and safe to be moved around.
// If you are adding a new field that is non-channels specific, please add // If you are adding a new field that is non-channels specific, please add
@@ -503,10 +513,6 @@ func NewServer(options ...Option) (*Server, error) {
} }
s.EmailService = emailService s.EmailService = emailService
if model.BuildEnterpriseReady == "true" {
s.LoadLicense()
}
s.setupFeatureFlags() s.setupFeatureFlags()
s.initJobs() s.initJobs()
@@ -560,7 +566,6 @@ func NewServer(options ...Option) (*Server, error) {
mlog.Info("Printing current working", mlog.String("directory", pwd)) mlog.Info("Printing current working", mlog.String("directory", pwd))
mlog.Info("Loaded config", mlog.String("source", s.configStore.String())) mlog.Info("Loaded config", mlog.String("source", s.configStore.String()))
license := s.License()
allowAdvancedLogging := license != nil && *license.Features.AdvancedLogging allowAdvancedLogging := license != nil && *license.Features.AdvancedLogging
if s.Audit == nil { if s.Audit == nil {
@@ -1172,18 +1177,13 @@ func (s *Server) Start() error {
mlog.Error("Mail server connection test is failed", mlog.Err(err)) mlog.Error("Mail server connection test is failed", mlog.Err(err))
} }
backend, appErr := s.FileBackend() err := s.FileBackend().TestConnection()
if appErr != nil { if err != nil {
mlog.Error("Problem with file storage settings", mlog.Err(appErr)) if _, ok := err.(*filestore.S3FileBackendNoBucketError); ok {
} else { err = s.FileBackend().(*filestore.S3FileBackend).MakeBucket()
err := backend.TestConnection() }
if err != nil { if err != nil {
if _, ok := err.(*filestore.S3FileBackendNoBucketError); ok { mlog.Error("Problem with file storage settings", mlog.Err(err))
err = backend.(*filestore.S3FileBackend).MakeBucket()
}
if err != nil {
mlog.Error("Problem with file storage settings", mlog.Err(err))
}
} }
} }
@@ -1227,9 +1227,9 @@ func (s *Server) Start() error {
if *s.Config().RateLimitSettings.Enable { if *s.Config().RateLimitSettings.Enable {
mlog.Info("RateLimiter is enabled") mlog.Info("RateLimiter is enabled")
rateLimiter, err := NewRateLimiter(&s.Config().RateLimitSettings, s.Config().ServiceSettings.TrustedProxyIPHeader) rateLimiter, err2 := NewRateLimiter(&s.Config().RateLimitSettings, s.Config().ServiceSettings.TrustedProxyIPHeader)
if err != nil { if err2 != nil {
return err return err2
} }
s.RateLimiter = rateLimiter s.RateLimiter = rateLimiter
@@ -1850,13 +1850,8 @@ func (s *Server) stopSearchEngine() {
} }
} }
func (s *Server) FileBackend() (filestore.FileBackend, *model.AppError) { func (s *Server) FileBackend() filestore.FileBackend {
license := s.License() return s.filestore
backend, err := filestore.NewFileBackend(s.Config().FileSettings.ToFileBackendSettings(license != nil && *license.Features.Compliance))
if err != nil {
return nil, model.NewAppError("FileBackend", "api.file.no_driver.app_error", nil, err.Error(), http.StatusInternalServerError)
}
return backend, nil
} }
func (s *Server) TotalWebsocketConnections() int { func (s *Server) TotalWebsocketConnections() int {
@@ -1904,7 +1899,7 @@ func (s *Server) initJobs() {
} }
if jobsLdapSyncInterface != nil { if jobsLdapSyncInterface != nil {
builder := jobsLdapSyncInterface(s) builder := jobsLdapSyncInterface(New(ServerConnector(s.Channels())))
s.Jobs.RegisterJobType(model.JobTypeLdapSync, builder.MakeWorker(), builder.MakeScheduler()) s.Jobs.RegisterJobType(model.JobTypeLdapSync, builder.MakeWorker(), builder.MakeScheduler())
} }
@@ -2189,7 +2184,7 @@ func (a *App) generateSupportPacketYaml() (*model.FileData, string) {
} }
// Here we are getting information regarding LDAP // Here we are getting information regarding LDAP
ldapInterface := a.ch.srv.Ldap ldapInterface := a.ch.Ldap
var vendorName, vendorVersion string var vendorName, vendorVersion string
if ldapInterface != nil { if ldapInterface != nil {
vendorName, vendorVersion = ldapInterface.GetVendorNameAndVendorVersion() vendorName, vendorVersion = ldapInterface.GetVendorNameAndVendorVersion()
@@ -2270,11 +2265,7 @@ func (s *Server) GetDefaultProfileImage(user *model.User) ([]byte, *model.AppErr
} }
func (s *Server) ReadFile(path string) ([]byte, *model.AppError) { func (s *Server) ReadFile(path string) ([]byte, *model.AppError) {
backend, err := s.FileBackend() result, nErr := s.FileBackend().ReadFile(path)
if err != nil {
return nil, err
}
result, nErr := backend.ReadFile(path)
if nErr != nil { if nErr != nil {
return nil, model.NewAppError("ReadFile", "api.file.read_file.app_error", nil, nErr.Error(), http.StatusInternalServerError) return nil, model.NewAppError("ReadFile", "api.file.read_file.app_error", nil, nErr.Error(), http.StatusInternalServerError)
} }

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

@@ -191,9 +191,7 @@ func TestStartServerNoS3Bucket(t *testing.T) {
defer s.Shutdown() defer s.Shutdown()
// ensure that a new bucket was created // ensure that a new bucket was created
backend, appErr := s.FileBackend() err = s.FileBackend().(*filestore.S3FileBackend).TestConnection()
require.Nil(t, appErr)
err = backend.(*filestore.S3FileBackend).TestConnection()
require.NoError(t, err) require.NoError(t, err)
} }

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

@@ -338,6 +338,7 @@ func TestHubConnIndexInactive(t *testing.T) {
} }
func TestReliableWebSocketSend(t *testing.T) { func TestReliableWebSocketSend(t *testing.T) {
t.Skip("MM-42033")
testCluster := &testlib.FakeClusterInterface{} testCluster := &testlib.FakeClusterInterface{}
th := SetupWithClusterMock(t, testCluster) th := SetupWithClusterMock(t, testCluster)