summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/apitestlib.go5
-rw-r--r--api/license.go7
-rw-r--r--api/license_test.go8
-rw-r--r--api/user.go4
-rw-r--r--api4/apitestlib.go5
-rw-r--r--api4/oauth_test.go62
-rw-r--r--api4/system.go6
-rw-r--r--app/admin.go3
-rw-r--r--app/app.go24
-rw-r--r--app/apptestlib.go5
-rw-r--r--app/config.go2
-rw-r--r--app/email.go3
-rw-r--r--app/file.go3
-rw-r--r--app/license.go105
-rw-r--r--app/license_test.go75
-rw-r--r--app/role.go6
-rw-r--r--app/session_test.go9
-rw-r--r--cmd/platform/jobserver.go2
-rw-r--r--jobs/server.go33
-rw-r--r--jobs/server_test.go39
-rw-r--r--utils/authorization.go20
-rw-r--r--utils/config.go31
-rw-r--r--utils/config_test.go2
-rw-r--r--utils/file_backend.go4
-rw-r--r--utils/file_backend_test.go2
-rw-r--r--utils/license.go135
-rw-r--r--utils/license_test.go67
-rw-r--r--utils/mail.go12
-rw-r--r--utils/mail_test.go6
29 files changed, 256 insertions, 429 deletions
diff --git a/api/apitestlib.go b/api/apitestlib.go
index bae00927a..47691b2dd 100644
--- a/api/apitestlib.go
+++ b/api/apitestlib.go
@@ -118,9 +118,10 @@ func setupTestHelper(enterprise bool) *TestHelper {
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableOpenServer = true })
- utils.SetIsLicensed(enterprise)
if enterprise {
- utils.License().Features.SetDefaults()
+ th.App.SetLicense(model.NewTestLicense())
+ } else {
+ th.App.SetLicense(nil)
}
return th
diff --git a/api/license.go b/api/license.go
index 8eb7803e1..432442ad6 100644
--- a/api/license.go
+++ b/api/license.go
@@ -9,7 +9,6 @@ import (
"net/http"
"github.com/mattermost/mattermost-server/model"
- "github.com/mattermost/mattermost-server/utils"
)
func (api *API) InitLicense() {
@@ -83,7 +82,7 @@ func removeLicense(c *Context, w http.ResponseWriter, r *http.Request) {
func getClientLicenceConfig(c *Context, w http.ResponseWriter, r *http.Request) {
useSanitizedLicense := !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM)
- etag := utils.GetClientLicenseEtag(useSanitizedLicense)
+ etag := c.App.GetClientLicenseEtag(useSanitizedLicense)
if c.HandleEtag(etag, "Get Client License Config", w, r) {
return
}
@@ -91,9 +90,9 @@ func getClientLicenceConfig(c *Context, w http.ResponseWriter, r *http.Request)
var clientLicense map[string]string
if useSanitizedLicense {
- clientLicense = utils.ClientLicense()
+ clientLicense = c.App.ClientLicense()
} else {
- clientLicense = utils.GetSanitizedClientLicense()
+ clientLicense = c.App.GetSanitizedClientLicense()
}
w.Header().Set(model.HEADER_ETAG_SERVER, etag)
diff --git a/api/license_test.go b/api/license_test.go
index 50d73101d..47586151a 100644
--- a/api/license_test.go
+++ b/api/license_test.go
@@ -5,8 +5,6 @@ package api
import (
"testing"
-
- "github.com/mattermost/mattermost-server/utils"
)
func TestGetLicenceConfig(t *testing.T) {
@@ -32,7 +30,7 @@ func TestGetLicenceConfig(t *testing.T) {
t.Fatal("cache should be empty")
}
- utils.SetClientLicense(map[string]string{"IsLicensed": "true"})
+ th.App.SetClientLicense(map[string]string{"IsLicensed": "true"})
if cache_result, err := Client.GetClientLicenceConfig(result.Etag); err != nil {
t.Fatal(err)
@@ -40,7 +38,7 @@ func TestGetLicenceConfig(t *testing.T) {
t.Fatal("result should not be empty")
}
- utils.SetClientLicense(map[string]string{"SomeFeature": "true", "IsLicensed": "true"})
+ th.App.SetClientLicense(map[string]string{"SomeFeature": "true", "IsLicensed": "true"})
if cache_result, err := Client.GetClientLicenceConfig(result.Etag); err != nil {
t.Fatal(err)
@@ -48,6 +46,6 @@ func TestGetLicenceConfig(t *testing.T) {
t.Fatal("result should not be empty")
}
- utils.SetClientLicense(map[string]string{"IsLicensed": "false"})
+ th.App.SetClientLicense(map[string]string{"IsLicensed": "false"})
}
}
diff --git a/api/user.go b/api/user.go
index 440ea5858..ad4f12ef3 100644
--- a/api/user.go
+++ b/api/user.go
@@ -299,9 +299,9 @@ func getInitialLoad(c *Context, w http.ResponseWriter, r *http.Request) {
il.ClientCfg = c.App.ClientConfig()
if c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) {
- il.LicenseCfg = utils.ClientLicense()
+ il.LicenseCfg = c.App.ClientLicense()
} else {
- il.LicenseCfg = utils.GetSanitizedClientLicense()
+ il.LicenseCfg = c.App.GetSanitizedClientLicense()
}
w.Write([]byte(il.ToJson()))
diff --git a/api4/apitestlib.go b/api4/apitestlib.go
index b55ce7cbf..db43a6512 100644
--- a/api4/apitestlib.go
+++ b/api4/apitestlib.go
@@ -125,9 +125,10 @@ func setupTestHelper(enterprise bool) *TestHelper {
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableOpenServer = true })
- utils.SetIsLicensed(enterprise)
if enterprise {
- utils.License().Features.SetDefaults()
+ th.App.SetLicense(model.NewTestLicense())
+ } else {
+ th.App.SetLicense(nil)
}
th.Client = th.CreateClient()
diff --git a/api4/oauth_test.go b/api4/oauth_test.go
index 8dd602456..c871dafff 100644
--- a/api4/oauth_test.go
+++ b/api4/oauth_test.go
@@ -18,14 +18,7 @@ func TestCreateOAuthApp(t *testing.T) {
Client := th.Client
AdminClient := th.SystemAdminClient
- enableOAuth := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
- adminOnly := *th.App.Config().ServiceSettings.EnableOnlyAdminIntegrations
- defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = adminOnly })
- }()
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = true })
- th.App.SetDefaultRolesBasedOnConfig()
oapp := &model.OAuthApp{Name: GenerateTestAppName(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}, IsTrusted: true}
@@ -42,12 +35,10 @@ func TestCreateOAuthApp(t *testing.T) {
}
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
- th.App.SetDefaultRolesBasedOnConfig()
_, resp = Client.CreateOAuthApp(oapp)
CheckForbiddenStatus(t, resp)
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
rapp, resp = Client.CreateOAuthApp(oapp)
CheckNoError(t, resp)
CheckCreatedStatus(t, resp)
@@ -86,14 +77,7 @@ func TestUpdateOAuthApp(t *testing.T) {
Client := th.Client
AdminClient := th.SystemAdminClient
- enableOAuth := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
- adminOnly := *th.App.Config().ServiceSettings.EnableOnlyAdminIntegrations
- defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = adminOnly })
- }()
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = true })
- th.App.SetDefaultRolesBasedOnConfig()
oapp := &model.OAuthApp{
Name: "oapp",
@@ -172,7 +156,6 @@ func TestUpdateOAuthApp(t *testing.T) {
th.LoginBasic()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
_, resp = Client.UpdateOAuthApp(oapp)
CheckForbiddenStatus(t, resp)
@@ -199,15 +182,8 @@ func TestGetOAuthApps(t *testing.T) {
Client := th.Client
AdminClient := th.SystemAdminClient
- enableOAuth := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
- adminOnly := *th.App.Config().ServiceSettings.EnableOnlyAdminIntegrations
- defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = adminOnly })
- }()
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = true })
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
oapp := &model.OAuthApp{Name: GenerateTestAppName(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}}
@@ -251,7 +227,6 @@ func TestGetOAuthApps(t *testing.T) {
}
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
- th.App.SetDefaultRolesBasedOnConfig()
_, resp = Client.GetOAuthApps(0, 1000)
CheckForbiddenStatus(t, resp)
@@ -272,15 +247,8 @@ func TestGetOAuthApp(t *testing.T) {
Client := th.Client
AdminClient := th.SystemAdminClient
- enableOAuth := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
- adminOnly := *th.App.Config().ServiceSettings.EnableOnlyAdminIntegrations
- defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = adminOnly })
- }()
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = true })
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
oapp := &model.OAuthApp{Name: GenerateTestAppName(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}}
@@ -320,7 +288,6 @@ func TestGetOAuthApp(t *testing.T) {
CheckForbiddenStatus(t, resp)
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
- th.App.SetDefaultRolesBasedOnConfig()
_, resp = Client.GetOAuthApp(rapp2.Id)
CheckForbiddenStatus(t, resp)
@@ -347,15 +314,8 @@ func TestGetOAuthAppInfo(t *testing.T) {
Client := th.Client
AdminClient := th.SystemAdminClient
- enableOAuth := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
- adminOnly := *th.App.Config().ServiceSettings.EnableOnlyAdminIntegrations
- defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = adminOnly })
- }()
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = true })
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
oapp := &model.OAuthApp{Name: GenerateTestAppName(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}}
@@ -395,7 +355,6 @@ func TestGetOAuthAppInfo(t *testing.T) {
CheckNoError(t, resp)
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
- th.App.SetDefaultRolesBasedOnConfig()
_, resp = Client.GetOAuthAppInfo(rapp2.Id)
CheckNoError(t, resp)
@@ -422,15 +381,8 @@ func TestDeleteOAuthApp(t *testing.T) {
Client := th.Client
AdminClient := th.SystemAdminClient
- enableOAuth := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
- adminOnly := *th.App.Config().ServiceSettings.EnableOnlyAdminIntegrations
- defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = adminOnly })
- }()
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = true })
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
oapp := &model.OAuthApp{Name: GenerateTestAppName(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}}
@@ -465,7 +417,6 @@ func TestDeleteOAuthApp(t *testing.T) {
CheckNoError(t, resp)
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
_, resp = Client.DeleteOAuthApp(rapp.Id)
CheckForbiddenStatus(t, resp)
@@ -490,15 +441,8 @@ func TestRegenerateOAuthAppSecret(t *testing.T) {
Client := th.Client
AdminClient := th.SystemAdminClient
- enableOAuth := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
- adminOnly := *th.App.Config().ServiceSettings.EnableOnlyAdminIntegrations
- defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
- th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = adminOnly })
- }()
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = true })
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
oapp := &model.OAuthApp{Name: GenerateTestAppName(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}}
@@ -537,7 +481,6 @@ func TestRegenerateOAuthAppSecret(t *testing.T) {
CheckNoError(t, resp)
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false })
- th.App.SetDefaultRolesBasedOnConfig()
_, resp = Client.RegenerateOAuthAppSecret(rapp.Id)
CheckForbiddenStatus(t, resp)
@@ -622,12 +565,7 @@ func TestAuthorizeOAuthApp(t *testing.T) {
Client := th.Client
AdminClient := th.SystemAdminClient
- enableOAuth := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
- defer func() {
- th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
- }()
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = true })
- th.App.SetDefaultRolesBasedOnConfig()
oapp := &model.OAuthApp{Name: GenerateTestAppName(), Homepage: "https://nowhere.com", Description: "test", CallbackUrls: []string{"https://nowhere.com"}}
diff --git a/api4/system.go b/api4/system.go
index 43b941247..061ffe094 100644
--- a/api4/system.go
+++ b/api4/system.go
@@ -266,7 +266,7 @@ func getClientLicense(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- etag := utils.GetClientLicenseEtag(true)
+ etag := c.App.GetClientLicenseEtag(true)
if c.HandleEtag(etag, "Get Client License", w, r) {
return
}
@@ -274,9 +274,9 @@ func getClientLicense(c *Context, w http.ResponseWriter, r *http.Request) {
var clientLicense map[string]string
if c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) {
- clientLicense = utils.ClientLicense()
+ clientLicense = c.App.ClientLicense()
} else {
- clientLicense = utils.GetSanitizedClientLicense()
+ clientLicense = c.App.GetSanitizedClientLicense()
}
w.Header().Set(model.HEADER_ETAG_SERVER, etag)
diff --git a/app/admin.go b/app/admin.go
index b838ed3bd..154fa8899 100644
--- a/app/admin.go
+++ b/app/admin.go
@@ -237,7 +237,8 @@ func (a *App) TestEmail(userId string, cfg *model.Config) *model.AppError {
return err
} else {
T := utils.GetUserTranslations(user.Locale)
- if err := utils.SendMailUsingConfig(user.Email, T("api.admin.test_email.subject"), T("api.admin.test_email.body"), cfg); err != nil {
+ license := a.License()
+ if err := utils.SendMailUsingConfig(user.Email, T("api.admin.test_email.subject"), T("api.admin.test_email.body"), cfg, license != nil && *license.Features.Compliance); err != nil {
return err
}
}
diff --git a/app/app.go b/app/app.go
index 3c37ec252..dd5deb342 100644
--- a/app/app.go
+++ b/app/app.go
@@ -59,6 +59,10 @@ type App struct {
configFile string
configListeners map[string]func(*model.Config, *model.Config)
+ licenseValue atomic.Value
+ clientLicenseValue atomic.Value
+ licenseListeners map[string]func()
+
newStore func() store.Store
htmlTemplateWatcher *utils.HTMLTemplateWatcher
@@ -88,18 +92,16 @@ func New(options ...Option) (*App, error) {
panic("Only one App should exist at a time. Did you forget to call Shutdown()?")
}
- // TODO: remove this once utils global license state is eliminated
- utils.SetLicense(nil)
-
app := &App{
goroutineExitSignal: make(chan struct{}, 1),
Srv: &Server{
Router: mux.NewRouter(),
},
- sessionCache: utils.NewLru(model.SESSION_CACHE_SIZE),
- configFile: "config.json",
- configListeners: make(map[string]func(*model.Config, *model.Config)),
- clientConfig: make(map[string]string),
+ sessionCache: utils.NewLru(model.SESSION_CACHE_SIZE),
+ configFile: "config.json",
+ configListeners: make(map[string]func(*model.Config, *model.Config)),
+ clientConfig: make(map[string]string),
+ licenseListeners: map[string]func(){},
}
for _, option := range options {
@@ -123,9 +125,9 @@ func New(options ...Option) (*App, error) {
app.configListenerId = app.AddConfigListener(func(_, _ *model.Config) {
app.configOrLicenseListener()
})
- app.licenseListenerId = utils.AddLicenseListener(app.configOrLicenseListener)
+ app.licenseListenerId = app.AddLicenseListener(app.configOrLicenseListener)
app.regenerateClientConfig()
- app.SetDefaultRolesBasedOnConfig()
+ app.setDefaultRolesBasedOnConfig()
l4g.Info(utils.T("api.server.new_server.init.info"))
@@ -166,7 +168,7 @@ func New(options ...Option) (*App, error) {
func (a *App) configOrLicenseListener() {
a.regenerateClientConfig()
- a.SetDefaultRolesBasedOnConfig()
+ a.setDefaultRolesBasedOnConfig()
}
func (a *App) Shutdown() {
@@ -188,7 +190,7 @@ func (a *App) Shutdown() {
}
a.RemoveConfigListener(a.configListenerId)
- utils.RemoveLicenseListener(a.licenseListenerId)
+ a.RemoveLicenseListener(a.licenseListenerId)
l4g.Info(utils.T("api.server.stop_server.stopped.info"))
a.DisableConfigWatch()
diff --git a/app/apptestlib.go b/app/apptestlib.go
index 016a68bec..c7846c9b5 100644
--- a/app/apptestlib.go
+++ b/app/apptestlib.go
@@ -106,9 +106,10 @@ func setupTestHelper(enterprise bool) *TestHelper {
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableOpenServer = true })
- utils.SetIsLicensed(enterprise)
if enterprise {
- utils.License().Features.SetDefaults()
+ th.App.SetLicense(model.NewTestLicense())
+ } else {
+ th.App.SetLicense(nil)
}
return th
diff --git a/app/config.go b/app/config.go
index 55be24352..b4925e8fb 100644
--- a/app/config.go
+++ b/app/config.go
@@ -201,7 +201,7 @@ func (a *App) AsymmetricSigningKey() *ecdsa.PrivateKey {
}
func (a *App) regenerateClientConfig() {
- a.clientConfig = utils.GenerateClientConfig(a.Config(), a.DiagnosticId())
+ a.clientConfig = utils.GenerateClientConfig(a.Config(), a.DiagnosticId(), a.License())
if key := a.AsymmetricSigningKey(); key != nil {
der, _ := x509.MarshalPKIXPublicKey(&key.PublicKey)
a.clientConfig["AsymmetricSigningPublicKey"] = base64.StdEncoding.EncodeToString(der)
diff --git a/app/email.go b/app/email.go
index b809b972d..89de2ae65 100644
--- a/app/email.go
+++ b/app/email.go
@@ -316,5 +316,6 @@ func (a *App) NewEmailTemplate(name, locale string) *utils.HTMLTemplate {
}
func (a *App) SendMail(to, subject, htmlBody string) *model.AppError {
- return utils.SendMailUsingConfig(to, subject, htmlBody, a.Config())
+ license := a.License()
+ return utils.SendMailUsingConfig(to, subject, htmlBody, a.Config(), license != nil && *license.Features.Compliance)
}
diff --git a/app/file.go b/app/file.go
index d66c64adb..bb20585bb 100644
--- a/app/file.go
+++ b/app/file.go
@@ -58,7 +58,8 @@ const (
)
func (a *App) FileBackend() (utils.FileBackend, *model.AppError) {
- return utils.NewFileBackend(&a.Config().FileSettings)
+ license := a.License()
+ return utils.NewFileBackend(&a.Config().FileSettings, license != nil && *license.Features.Compliance)
}
func (a *App) ReadFile(path string) ([]byte, *model.AppError) {
diff --git a/app/license.go b/app/license.go
index 7402b5c22..efb725a20 100644
--- a/app/license.go
+++ b/app/license.go
@@ -4,16 +4,19 @@
package app
import (
+ "crypto/md5"
+ "fmt"
"net/http"
"strings"
l4g "github.com/alecthomas/log4go"
+
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/utils"
)
func (a *App) LoadLicense() {
- utils.RemoveLicense()
+ a.SetLicense(nil)
licenseId := ""
if result := <-a.Srv.Store.System().Get(); result.Err == nil {
@@ -36,7 +39,7 @@ func (a *App) LoadLicense() {
if result := <-a.Srv.Store.License().Get(licenseId); result.Err == nil {
record := result.Data.(*model.LicenseRecord)
- utils.LoadLicense([]byte(record.Bytes))
+ a.ValidateAndSetLicenseBytes([]byte(record.Bytes))
l4g.Info("License key valid unlocking enterprise features.")
} else {
l4g.Info(utils.T("mattermost.load_license.find.warn"))
@@ -104,33 +107,113 @@ func (a *App) SaveLicense(licenseBytes []byte) (*model.License, *model.AppError)
// License returns the currently active license or nil if the application is unlicensed.
func (a *App) License() *model.License {
- if utils.IsLicensed() {
- return utils.License()
- }
- return nil
+ license, _ := a.licenseValue.Load().(*model.License)
+ return license
}
func (a *App) SetLicense(license *model.License) bool {
- ok := utils.SetLicense(license)
- a.SetDefaultRolesBasedOnConfig()
- return ok
+ defer func() {
+ a.setDefaultRolesBasedOnConfig()
+ for _, listener := range a.licenseListeners {
+ listener()
+ }
+ }()
+
+ if license != nil {
+ license.Features.SetDefaults()
+
+ if !license.IsExpired() {
+ a.licenseValue.Store(license)
+ a.clientLicenseValue.Store(utils.GetClientLicense(license))
+ return true
+ }
+ }
+
+ a.licenseValue.Store((*model.License)(nil))
+ a.SetClientLicense(map[string]string{"IsLicensed": "false"})
+ return false
+}
+
+func (a *App) ValidateAndSetLicenseBytes(b []byte) {
+ if success, licenseStr := utils.ValidateLicense(b); success {
+ license := model.LicenseFromJson(strings.NewReader(licenseStr))
+ a.SetLicense(license)
+ return
+ }
+
+ l4g.Warn(utils.T("utils.license.load_license.invalid.warn"))
+}
+
+func (a *App) SetClientLicense(m map[string]string) {
+ a.clientLicenseValue.Store(m)
+}
+
+func (a *App) ClientLicense() map[string]string {
+ clientLicense, _ := a.clientLicenseValue.Load().(map[string]string)
+ return clientLicense
}
func (a *App) RemoveLicense() *model.AppError {
- utils.RemoveLicense()
+ if license, _ := a.licenseValue.Load().(*model.License); license == nil {
+ return nil
+ }
sysVar := &model.System{}
sysVar.Name = model.SYSTEM_ACTIVE_LICENSE_ID
sysVar.Value = ""
if result := <-a.Srv.Store.System().SaveOrUpdate(sysVar); result.Err != nil {
- utils.RemoveLicense()
return result.Err
}
+ a.SetLicense(nil)
a.ReloadConfig()
a.InvalidateAllCaches()
return nil
}
+
+func (a *App) AddLicenseListener(listener func()) string {
+ id := model.NewId()
+ a.licenseListeners[id] = listener
+ return id
+}
+
+func (a *App) RemoveLicenseListener(id string) {
+ delete(a.licenseListeners, id)
+}
+
+func (a *App) GetClientLicenseEtag(useSanitized bool) string {
+ value := ""
+
+ lic := a.ClientLicense()
+
+ if useSanitized {
+ lic = a.GetSanitizedClientLicense()
+ }
+
+ for k, v := range lic {
+ value += fmt.Sprintf("%s:%s;", k, v)
+ }
+
+ return model.Etag(fmt.Sprintf("%x", md5.Sum([]byte(value))))
+}
+
+func (a *App) GetSanitizedClientLicense() map[string]string {
+ sanitizedLicense := make(map[string]string)
+
+ for k, v := range a.ClientLicense() {
+ sanitizedLicense[k] = v
+ }
+
+ delete(sanitizedLicense, "Id")
+ delete(sanitizedLicense, "Name")
+ delete(sanitizedLicense, "Email")
+ delete(sanitizedLicense, "PhoneNumber")
+ delete(sanitizedLicense, "IssuedAt")
+ delete(sanitizedLicense, "StartsAt")
+ delete(sanitizedLicense, "ExpiresAt")
+
+ return sanitizedLicense
+}
diff --git a/app/license_test.go b/app/license_test.go
index 5b73d9d18..f86d604d1 100644
--- a/app/license_test.go
+++ b/app/license_test.go
@@ -4,8 +4,9 @@
package app
import (
- //"github.com/mattermost/mattermost-server/model"
"testing"
+
+ "github.com/mattermost/mattermost-server/model"
)
func TestLoadLicense(t *testing.T) {
@@ -37,3 +38,75 @@ func TestRemoveLicense(t *testing.T) {
t.Fatal("should have removed license")
}
}
+
+func TestSetLicense(t *testing.T) {
+ th := Setup()
+ defer th.TearDown()
+
+ l1 := &model.License{}
+ l1.Features = &model.Features{}
+ l1.Customer = &model.Customer{}
+ l1.StartsAt = model.GetMillis() - 1000
+ l1.ExpiresAt = model.GetMillis() + 100000
+ if ok := th.App.SetLicense(l1); !ok {
+ t.Fatal("license should have worked")
+ }
+
+ l2 := &model.License{}
+ l2.Features = &model.Features{}
+ l2.Customer = &model.Customer{}
+ l2.StartsAt = model.GetMillis() - 1000
+ l2.ExpiresAt = model.GetMillis() - 100
+ if ok := th.App.SetLicense(l2); ok {
+ t.Fatal("license should have failed")
+ }
+
+ l3 := &model.License{}
+ l3.Features = &model.Features{}
+ l3.Customer = &model.Customer{}
+ l3.StartsAt = model.GetMillis() + 10000
+ l3.ExpiresAt = model.GetMillis() + 100000
+ if ok := th.App.SetLicense(l3); !ok {
+ t.Fatal("license should have passed")
+ }
+}
+
+func TestClientLicenseEtag(t *testing.T) {
+ th := Setup()
+ defer th.TearDown()
+
+ etag1 := th.App.GetClientLicenseEtag(false)
+
+ th.App.SetClientLicense(map[string]string{"SomeFeature": "true", "IsLicensed": "true"})
+
+ etag2 := th.App.GetClientLicenseEtag(false)
+ if etag1 == etag2 {
+ t.Fatal("etags should not match")
+ }
+
+ th.App.SetClientLicense(map[string]string{"SomeFeature": "true", "IsLicensed": "false"})
+
+ etag3 := th.App.GetClientLicenseEtag(false)
+ if etag2 == etag3 {
+ t.Fatal("etags should not match")
+ }
+}
+
+func TestGetSanitizedClientLicense(t *testing.T) {
+ th := Setup()
+ defer th.TearDown()
+
+ l1 := &model.License{}
+ l1.Features = &model.Features{}
+ l1.Customer = &model.Customer{}
+ l1.Customer.Name = "TestName"
+ l1.StartsAt = model.GetMillis() - 1000
+ l1.ExpiresAt = model.GetMillis() + 100000
+ th.App.SetLicense(l1)
+
+ m := th.App.GetSanitizedClientLicense()
+
+ if _, ok := m["Name"]; ok {
+ t.Fatal("should have been sanatized")
+ }
+}
diff --git a/app/role.go b/app/role.go
index 5f39dd623..9f271ea7a 100644
--- a/app/role.go
+++ b/app/role.go
@@ -12,8 +12,6 @@ func (a *App) Role(id string) *model.Role {
return a.roles[id]
}
-// Updates the roles based on the app config and the global license check. You may need to invoke
-// this when license changes are made.
-func (a *App) SetDefaultRolesBasedOnConfig() {
- a.roles = utils.DefaultRolesBasedOnConfig(a.Config())
+func (a *App) setDefaultRolesBasedOnConfig() {
+ a.roles = utils.DefaultRolesBasedOnConfig(a.Config(), a.License() != nil)
}
diff --git a/app/session_test.go b/app/session_test.go
index 09d81f4ac..bf8198a4e 100644
--- a/app/session_test.go
+++ b/app/session_test.go
@@ -6,11 +6,10 @@ package app
import (
"testing"
- "github.com/mattermost/mattermost-server/model"
- "github.com/mattermost/mattermost-server/utils"
-
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+
+ "github.com/mattermost/mattermost-server/model"
)
func TestCache(t *testing.T) {
@@ -111,7 +110,7 @@ func TestGetSessionIdleTimeoutInMinutes(t *testing.T) {
assert.Nil(t, err)
// Test regular session with license off, should not timeout
- *utils.License().Features.Compliance = false
+ th.App.SetLicense(nil)
session = &model.Session{
UserId: model.NewId(),
@@ -125,7 +124,7 @@ func TestGetSessionIdleTimeoutInMinutes(t *testing.T) {
_, err = th.App.GetSession(session.Token)
assert.Nil(t, err)
- *utils.License().Features.Compliance = true
+ th.App.SetLicense(model.NewTestLicense("compliance"))
// Test regular session with timeout set to 0, should not timeout
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.SessionIdleTimeoutInMinutes = 0 })
diff --git a/cmd/platform/jobserver.go b/cmd/platform/jobserver.go
index e664136c0..044ee6b6a 100644
--- a/cmd/platform/jobserver.go
+++ b/cmd/platform/jobserver.go
@@ -35,7 +35,7 @@ func jobserverCmdF(cmd *cobra.Command, args []string) {
defer l4g.Close()
defer a.Shutdown()
- a.Jobs.LoadLicense()
+ a.LoadLicense()
// Run jobs
l4g.Info("Starting Mattermost job server")
diff --git a/jobs/server.go b/jobs/server.go
index 4015d581e..01cf821dc 100644
--- a/jobs/server.go
+++ b/jobs/server.go
@@ -4,12 +4,9 @@
package jobs
import (
- l4g "github.com/alecthomas/log4go"
-
ejobs "github.com/mattermost/mattermost-server/einterfaces/jobs"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/store"
- "github.com/mattermost/mattermost-server/utils"
)
type ConfigService interface {
@@ -50,36 +47,6 @@ func (srv *JobServer) Config() *model.Config {
return srv.ConfigService.Config()
}
-func (srv *JobServer) LoadLicense() {
- licenseId := ""
- if result := <-srv.Store.System().Get(); result.Err == nil {
- props := result.Data.(model.StringMap)
- licenseId = props[model.SYSTEM_ACTIVE_LICENSE_ID]
- }
-
- var licenseBytes []byte
-
- if len(licenseId) != 26 {
- // Lets attempt to load the file from disk since it was missing from the DB
- _, licenseBytes = utils.GetAndValidateLicenseFileFromDisk(*srv.ConfigService.Config().ServiceSettings.LicenseFileLocation)
- } else {
- if result := <-srv.Store.License().Get(licenseId); result.Err == nil {
- record := result.Data.(*model.LicenseRecord)
- licenseBytes = []byte(record.Bytes)
- l4g.Info("License key valid unlocking enterprise features.")
- } else {
- l4g.Info(utils.T("mattermost.load_license.find.warn"))
- }
- }
-
- if licenseBytes != nil {
- utils.LoadLicense(licenseBytes)
- l4g.Info("License key valid unlocking enterprise features.")
- } else {
- l4g.Info(utils.T("mattermost.load_license.find.warn"))
- }
-}
-
func (srv *JobServer) StartWorkers() {
srv.Workers = srv.InitWorkers().Start()
}
diff --git a/jobs/server_test.go b/jobs/server_test.go
deleted file mode 100644
index 3b5ef6f3d..000000000
--- a/jobs/server_test.go
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
-// See License.txt for license information.
-
-package jobs
-
-import (
- "testing"
-
- "github.com/mattermost/mattermost-server/model"
- "github.com/mattermost/mattermost-server/store"
- "github.com/mattermost/mattermost-server/store/storetest"
- "github.com/mattermost/mattermost-server/utils"
-)
-
-func TestJobServer_LoadLicense(t *testing.T) {
- if utils.T == nil {
- utils.TranslationsPreInit()
- }
-
- mockStore := &storetest.Store{}
- defer mockStore.AssertExpectations(t)
-
- server := &JobServer{
- Store: mockStore,
- }
-
- mockStore.SystemStore.On("Get").Return(storetest.NewStoreChannel(store.StoreResult{
- Data: model.StringMap{
- model.SYSTEM_ACTIVE_LICENSE_ID: "thelicenseid00000000000000",
- },
- }))
- mockStore.LicenseStore.On("Get", "thelicenseid00000000000000").Return(storetest.NewStoreChannel(store.StoreResult{
- Data: &model.LicenseRecord{
- Id: "thelicenseid00000000000000",
- },
- }))
-
- server.LoadLicense()
-}
diff --git a/utils/authorization.go b/utils/authorization.go
index 39a0d606c..42815b807 100644
--- a/utils/authorization.go
+++ b/utils/authorization.go
@@ -7,7 +7,7 @@ import (
"github.com/mattermost/mattermost-server/model"
)
-func DefaultRolesBasedOnConfig(cfg *model.Config) map[string]*model.Role {
+func DefaultRolesBasedOnConfig(cfg *model.Config, isLicensed bool) map[string]*model.Role {
roles := make(map[string]*model.Role)
for id, role := range model.DefaultRoles {
copy := &model.Role{}
@@ -15,7 +15,7 @@ func DefaultRolesBasedOnConfig(cfg *model.Config) map[string]*model.Role {
roles[id] = copy
}
- if IsLicensed() {
+ if isLicensed {
switch *cfg.TeamSettings.RestrictPublicChannelCreation {
case model.PERMISSIONS_ALL:
roles[model.TEAM_USER_ROLE_ID].Permissions = append(
@@ -35,7 +35,7 @@ func DefaultRolesBasedOnConfig(cfg *model.Config) map[string]*model.Role {
)
}
- if IsLicensed() {
+ if isLicensed {
switch *cfg.TeamSettings.RestrictPublicChannelManagement {
case model.PERMISSIONS_ALL:
roles[model.TEAM_USER_ROLE_ID].Permissions = append(
@@ -64,7 +64,7 @@ func DefaultRolesBasedOnConfig(cfg *model.Config) map[string]*model.Role {
)
}
- if IsLicensed() {
+ if isLicensed {
switch *cfg.TeamSettings.RestrictPublicChannelDeletion {
case model.PERMISSIONS_ALL:
roles[model.TEAM_USER_ROLE_ID].Permissions = append(
@@ -93,7 +93,7 @@ func DefaultRolesBasedOnConfig(cfg *model.Config) map[string]*model.Role {
)
}
- if IsLicensed() {
+ if isLicensed {
switch *cfg.TeamSettings.RestrictPrivateChannelCreation {
case model.PERMISSIONS_ALL:
roles[model.TEAM_USER_ROLE_ID].Permissions = append(
@@ -113,7 +113,7 @@ func DefaultRolesBasedOnConfig(cfg *model.Config) map[string]*model.Role {
)
}
- if IsLicensed() {
+ if isLicensed {
switch *cfg.TeamSettings.RestrictPrivateChannelManagement {
case model.PERMISSIONS_ALL:
roles[model.TEAM_USER_ROLE_ID].Permissions = append(
@@ -142,7 +142,7 @@ func DefaultRolesBasedOnConfig(cfg *model.Config) map[string]*model.Role {
)
}
- if IsLicensed() {
+ if isLicensed {
switch *cfg.TeamSettings.RestrictPrivateChannelDeletion {
case model.PERMISSIONS_ALL:
roles[model.TEAM_USER_ROLE_ID].Permissions = append(
@@ -172,7 +172,7 @@ func DefaultRolesBasedOnConfig(cfg *model.Config) map[string]*model.Role {
}
// Restrict permissions for Private Channel Manage Members
- if IsLicensed() {
+ if isLicensed {
switch *cfg.TeamSettings.RestrictPrivateChannelManageMembers {
case model.PERMISSIONS_ALL:
roles[model.CHANNEL_USER_ROLE_ID].Permissions = append(
@@ -214,7 +214,7 @@ func DefaultRolesBasedOnConfig(cfg *model.Config) map[string]*model.Role {
}
// Grant permissions for inviting and adding users to a team.
- if IsLicensed() {
+ if isLicensed {
if *cfg.TeamSettings.RestrictTeamInvite == model.PERMISSIONS_TEAM_ADMIN {
roles[model.TEAM_ADMIN_ROLE_ID].Permissions = append(
roles[model.TEAM_ADMIN_ROLE_ID].Permissions,
@@ -236,7 +236,7 @@ func DefaultRolesBasedOnConfig(cfg *model.Config) map[string]*model.Role {
)
}
- if IsLicensed() {
+ if isLicensed {
switch *cfg.ServiceSettings.RestrictPostDelete {
case model.PERMISSIONS_DELETE_POST_ALL:
roles[model.CHANNEL_USER_ROLE_ID].Permissions = append(
diff --git a/utils/config.go b/utils/config.go
index 9e962eef4..0669d63e4 100644
--- a/utils/config.go
+++ b/utils/config.go
@@ -342,7 +342,7 @@ func LoadConfig(fileName string) (config *model.Config, configPath string, appEr
return config, configPath, nil
}
-func GenerateClientConfig(c *model.Config, diagnosticId string) map[string]string {
+func GenerateClientConfig(c *model.Config, diagnosticId string, license *model.License) map[string]string {
props := make(map[string]string)
props["Version"] = model.CurrentVersion
@@ -456,18 +456,17 @@ func GenerateClientConfig(c *model.Config, diagnosticId string) map[string]strin
props["PluginsEnabled"] = strconv.FormatBool(*c.PluginSettings.Enable)
- if IsLicensed() {
- License := License()
+ if license != nil {
props["ExperimentalTownSquareIsReadOnly"] = strconv.FormatBool(*c.TeamSettings.ExperimentalTownSquareIsReadOnly)
props["ExperimentalEnableAuthenticationTransfer"] = strconv.FormatBool(*c.ServiceSettings.ExperimentalEnableAuthenticationTransfer)
- if *License.Features.CustomBrand {
+ if *license.Features.CustomBrand {
props["EnableCustomBrand"] = strconv.FormatBool(*c.TeamSettings.EnableCustomBrand)
props["CustomBrandText"] = *c.TeamSettings.CustomBrandText
props["CustomDescriptionText"] = *c.TeamSettings.CustomDescriptionText
}
- if *License.Features.LDAP {
+ if *license.Features.LDAP {
props["EnableLdap"] = strconv.FormatBool(*c.LdapSettings.Enable)
props["LdapLoginFieldName"] = *c.LdapSettings.LoginFieldName
props["LdapNicknameAttributeSet"] = strconv.FormatBool(*c.LdapSettings.NicknameAttribute != "")
@@ -478,16 +477,16 @@ func GenerateClientConfig(c *model.Config, diagnosticId string) map[string]strin
props["LdapLoginButtonTextColor"] = *c.LdapSettings.LoginButtonTextColor
}
- if *License.Features.MFA {
+ if *license.Features.MFA {
props["EnableMultifactorAuthentication"] = strconv.FormatBool(*c.ServiceSettings.EnableMultifactorAuthentication)
props["EnforceMultifactorAuthentication"] = strconv.FormatBool(*c.ServiceSettings.EnforceMultifactorAuthentication)
}
- if *License.Features.Compliance {
+ if *license.Features.Compliance {
props["EnableCompliance"] = strconv.FormatBool(*c.ComplianceSettings.Enable)
}
- if *License.Features.SAML {
+ if *license.Features.SAML {
props["EnableSaml"] = strconv.FormatBool(*c.SamlSettings.Enable)
props["SamlLoginButtonText"] = *c.SamlSettings.LoginButtonText
props["SamlFirstNameAttributeSet"] = strconv.FormatBool(*c.SamlSettings.FirstNameAttribute != "")
@@ -498,23 +497,23 @@ func GenerateClientConfig(c *model.Config, diagnosticId string) map[string]strin
props["SamlLoginButtonTextColor"] = *c.SamlSettings.LoginButtonTextColor
}
- if *License.Features.Cluster {
+ if *license.Features.Cluster {
props["EnableCluster"] = strconv.FormatBool(*c.ClusterSettings.Enable)
}
- if *License.Features.Cluster {
+ if *license.Features.Cluster {
props["EnableMetrics"] = strconv.FormatBool(*c.MetricsSettings.Enable)
}
- if *License.Features.GoogleOAuth {
+ if *license.Features.GoogleOAuth {
props["EnableSignUpWithGoogle"] = strconv.FormatBool(c.GoogleSettings.Enable)
}
- if *License.Features.Office365OAuth {
+ if *license.Features.Office365OAuth {
props["EnableSignUpWithOffice365"] = strconv.FormatBool(c.Office365Settings.Enable)
}
- if *License.Features.PasswordRequirements {
+ if *license.Features.PasswordRequirements {
props["PasswordMinimumLength"] = fmt.Sprintf("%v", *c.PasswordSettings.MinimumLength)
props["PasswordRequireLowercase"] = strconv.FormatBool(*c.PasswordSettings.Lowercase)
props["PasswordRequireUppercase"] = strconv.FormatBool(*c.PasswordSettings.Uppercase)
@@ -522,7 +521,7 @@ func GenerateClientConfig(c *model.Config, diagnosticId string) map[string]strin
props["PasswordRequireSymbol"] = strconv.FormatBool(*c.PasswordSettings.Symbol)
}
- if *License.Features.Announcement {
+ if *license.Features.Announcement {
props["EnableBanner"] = strconv.FormatBool(*c.AnnouncementSettings.EnableBanner)
props["BannerText"] = *c.AnnouncementSettings.BannerText
props["BannerColor"] = *c.AnnouncementSettings.BannerColor
@@ -530,14 +529,14 @@ func GenerateClientConfig(c *model.Config, diagnosticId string) map[string]strin
props["AllowBannerDismissal"] = strconv.FormatBool(*c.AnnouncementSettings.AllowBannerDismissal)
}
- if *License.Features.ThemeManagement {
+ if *license.Features.ThemeManagement {
props["EnableThemeSelection"] = strconv.FormatBool(*c.ThemeSettings.EnableThemeSelection)
props["DefaultTheme"] = *c.ThemeSettings.DefaultTheme
props["AllowCustomThemes"] = strconv.FormatBool(*c.ThemeSettings.AllowCustomThemes)
props["AllowedThemes"] = strings.Join(c.ThemeSettings.AllowedThemes, ",")
}
- if *License.Features.DataRetention {
+ if *license.Features.DataRetention {
props["DataRetentionEnableMessageDeletion"] = strconv.FormatBool(*c.DataRetentionSettings.EnableMessageDeletion)
props["DataRetentionMessageRetentionDays"] = strconv.FormatInt(int64(*c.DataRetentionSettings.MessageRetentionDays), 10)
props["DataRetentionEnableFileDeletion"] = strconv.FormatBool(*c.DataRetentionSettings.EnableFileDeletion)
diff --git a/utils/config_test.go b/utils/config_test.go
index 9abc56d5e..5809422f1 100644
--- a/utils/config_test.go
+++ b/utils/config_test.go
@@ -197,7 +197,7 @@ func TestGetClientConfig(t *testing.T) {
cfg, _, err := LoadConfig("config.json")
require.Nil(t, err)
- configMap := GenerateClientConfig(cfg, "")
+ configMap := GenerateClientConfig(cfg, "", nil)
if configMap["EmailNotificationContentsType"] != *cfg.EmailSettings.EmailNotificationContentsType {
t.Fatal("EmailSettings.EmailNotificationContentsType not exposed to client config")
}
diff --git a/utils/file_backend.go b/utils/file_backend.go
index c7a6c5591..42af7f604 100644
--- a/utils/file_backend.go
+++ b/utils/file_backend.go
@@ -22,7 +22,7 @@ type FileBackend interface {
RemoveDirectory(path string) *model.AppError
}
-func NewFileBackend(settings *model.FileSettings) (FileBackend, *model.AppError) {
+func NewFileBackend(settings *model.FileSettings, enableComplianceFeatures bool) (FileBackend, *model.AppError) {
switch *settings.DriverName {
case model.IMAGE_DRIVER_S3:
return &S3FileBackend{
@@ -33,7 +33,7 @@ func NewFileBackend(settings *model.FileSettings) (FileBackend, *model.AppError)
signV2: settings.AmazonS3SignV2 != nil && *settings.AmazonS3SignV2,
region: settings.AmazonS3Region,
bucket: settings.AmazonS3Bucket,
- encrypt: settings.AmazonS3SSE != nil && *settings.AmazonS3SSE && IsLicensed() && *License().Features.Compliance,
+ encrypt: settings.AmazonS3SSE != nil && *settings.AmazonS3SSE && enableComplianceFeatures,
trace: settings.AmazonS3Trace != nil && *settings.AmazonS3Trace,
}, nil
case model.IMAGE_DRIVER_LOCAL:
diff --git a/utils/file_backend_test.go b/utils/file_backend_test.go
index 76cd1f4a8..46f75574e 100644
--- a/utils/file_backend_test.go
+++ b/utils/file_backend_test.go
@@ -63,7 +63,7 @@ func TestS3FileBackendTestSuite(t *testing.T) {
func (s *FileBackendTestSuite) SetupTest() {
TranslationsPreInit()
- backend, err := NewFileBackend(&s.settings)
+ backend, err := NewFileBackend(&s.settings, true)
require.Nil(s.T(), err)
s.backend = backend
}
diff --git a/utils/license.go b/utils/license.go
index 2aaa2a549..2853a58d0 100644
--- a/utils/license.go
+++ b/utils/license.go
@@ -5,28 +5,21 @@ package utils
import (
"crypto"
- "crypto/md5"
"crypto/rsa"
"crypto/sha512"
"crypto/x509"
"encoding/base64"
"encoding/pem"
- "fmt"
"io/ioutil"
"os"
"strconv"
"strings"
- "sync/atomic"
l4g "github.com/alecthomas/log4go"
"github.com/mattermost/mattermost-server/model"
)
-var isLicensedInt32 int32
-var licenseValue atomic.Value
-var clientLicenseValue atomic.Value
-
var publicKey []byte = []byte(`-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyZmShlU8Z8HdG0IWSZ8r
tSyzyxrXkJjsFUf0Ke7bm/TLtIggRdqOcUF3XEWqQk5RGD5vuq7Rlg1zZqMEBk8N
@@ -37,92 +30,6 @@ a0v85XL6i9ote2P+fLZ3wX9EoioHzgdgB7arOxY50QRJO7OyCqpKFKv6lRWTXuSt
hwIDAQAB
-----END PUBLIC KEY-----`)
-func init() {
- SetLicense(nil)
-}
-
-func IsLicensed() bool {
- return atomic.LoadInt32(&isLicensedInt32) == 1
-}
-
-func SetIsLicensed(v bool) {
- if v {
- atomic.StoreInt32(&isLicensedInt32, 1)
- } else {
- atomic.StoreInt32(&isLicensedInt32, 0)
- }
-}
-
-func License() *model.License {
- return licenseValue.Load().(*model.License)
-}
-
-func SetClientLicense(m map[string]string) {
- clientLicenseValue.Store(m)
-}
-
-func ClientLicense() map[string]string {
- return clientLicenseValue.Load().(map[string]string)
-}
-
-func LoadLicense(licenseBytes []byte) {
- if success, licenseStr := ValidateLicense(licenseBytes); success {
- license := model.LicenseFromJson(strings.NewReader(licenseStr))
- SetLicense(license)
- return
- }
-
- l4g.Warn(T("utils.license.load_license.invalid.warn"))
-}
-
-var licenseListeners = map[string]func(){}
-
-func AddLicenseListener(listener func()) string {
- id := model.NewId()
- licenseListeners[id] = listener
- return id
-}
-
-func RemoveLicenseListener(id string) {
- delete(licenseListeners, id)
-}
-
-func SetLicense(license *model.License) bool {
- defer func() {
- for _, listener := range licenseListeners {
- listener()
- }
- }()
-
- if license == nil {
- SetIsLicensed(false)
- license = &model.License{
- Features: new(model.Features),
- }
- license.Features.SetDefaults()
- licenseValue.Store(license)
-
- SetClientLicense(map[string]string{"IsLicensed": "false"})
-
- return false
- } else {
- license.Features.SetDefaults()
-
- if !license.IsExpired() {
- licenseValue.Store(license)
- SetIsLicensed(true)
- clientLicenseValue.Store(getClientLicense(license))
- return true
- }
-
- return false
- }
-}
-
-func RemoveLicense() {
- SetLicense(nil)
-}
-
func ValidateLicense(signed []byte) (bool, string) {
decoded := make([]byte, base64.StdEncoding.DecodedLen(len(signed)))
@@ -213,12 +120,12 @@ func GetLicenseFileLocation(fileLocation string) string {
}
}
-func getClientLicense(l *model.License) map[string]string {
+func GetClientLicense(l *model.License) map[string]string {
props := make(map[string]string)
- props["IsLicensed"] = strconv.FormatBool(IsLicensed())
+ props["IsLicensed"] = strconv.FormatBool(l != nil)
- if IsLicensed() {
+ if l != nil {
props["Id"] = l.Id
props["Users"] = strconv.Itoa(*l.Features.Users)
props["LDAP"] = strconv.FormatBool(*l.Features.LDAP)
@@ -248,39 +155,3 @@ func getClientLicense(l *model.License) map[string]string {
return props
}
-
-func GetClientLicenseEtag(useSanitized bool) string {
- value := ""
-
- lic := ClientLicense()
-
- if useSanitized {
- lic = GetSanitizedClientLicense()
- }
-
- for k, v := range lic {
- value += fmt.Sprintf("%s:%s;", k, v)
- }
-
- return model.Etag(fmt.Sprintf("%x", md5.Sum([]byte(value))))
-}
-
-func GetSanitizedClientLicense() map[string]string {
- sanitizedLicense := make(map[string]string)
-
- for k, v := range ClientLicense() {
- sanitizedLicense[k] = v
- }
-
- if IsLicensed() {
- delete(sanitizedLicense, "Id")
- delete(sanitizedLicense, "Name")
- delete(sanitizedLicense, "Email")
- delete(sanitizedLicense, "PhoneNumber")
- delete(sanitizedLicense, "IssuedAt")
- delete(sanitizedLicense, "StartsAt")
- delete(sanitizedLicense, "ExpiresAt")
- }
-
- return sanitizedLicense
-}
diff --git a/utils/license_test.go b/utils/license_test.go
index 9771ec497..c2d1b4c05 100644
--- a/utils/license_test.go
+++ b/utils/license_test.go
@@ -5,87 +5,20 @@ package utils
import (
"testing"
-
- "github.com/mattermost/mattermost-server/model"
)
-func TestSetLicense(t *testing.T) {
- l1 := &model.License{}
- l1.Features = &model.Features{}
- l1.Customer = &model.Customer{}
- l1.StartsAt = model.GetMillis() - 1000
- l1.ExpiresAt = model.GetMillis() + 100000
- if ok := SetLicense(l1); !ok {
- t.Fatal("license should have worked")
- }
-
- l2 := &model.License{}
- l2.Features = &model.Features{}
- l2.Customer = &model.Customer{}
- l2.StartsAt = model.GetMillis() - 1000
- l2.ExpiresAt = model.GetMillis() - 100
- if ok := SetLicense(l2); ok {
- t.Fatal("license should have failed")
- }
-
- l3 := &model.License{}
- l3.Features = &model.Features{}
- l3.Customer = &model.Customer{}
- l3.StartsAt = model.GetMillis() + 10000
- l3.ExpiresAt = model.GetMillis() + 100000
- if ok := SetLicense(l3); !ok {
- t.Fatal("license should have passed")
- }
-}
-
func TestValidateLicense(t *testing.T) {
b1 := []byte("junk")
if ok, _ := ValidateLicense(b1); ok {
t.Fatal("should have failed - bad license")
}
- LoadLicense(b1)
-
b2 := []byte("junkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunk")
if ok, _ := ValidateLicense(b2); ok {
t.Fatal("should have failed - bad license")
}
}
-func TestClientLicenseEtag(t *testing.T) {
- etag1 := GetClientLicenseEtag(false)
-
- SetClientLicense(map[string]string{"SomeFeature": "true", "IsLicensed": "true"})
-
- etag2 := GetClientLicenseEtag(false)
- if etag1 == etag2 {
- t.Fatal("etags should not match")
- }
-
- SetClientLicense(map[string]string{"SomeFeature": "true", "IsLicensed": "false"})
-
- etag3 := GetClientLicenseEtag(false)
- if etag2 == etag3 {
- t.Fatal("etags should not match")
- }
-}
-
-func TestGetSanitizedClientLicense(t *testing.T) {
- l1 := &model.License{}
- l1.Features = &model.Features{}
- l1.Customer = &model.Customer{}
- l1.Customer.Name = "TestName"
- l1.StartsAt = model.GetMillis() - 1000
- l1.ExpiresAt = model.GetMillis() + 100000
- SetLicense(l1)
-
- m := GetSanitizedClientLicense()
-
- if _, ok := m["Name"]; ok {
- t.Fatal("should have been sanatized")
- }
-}
-
func TestGetLicenseFileLocation(t *testing.T) {
fileName := GetLicenseFileLocation("")
if len(fileName) == 0 {
diff --git a/utils/mail.go b/utils/mail.go
index 4c8a505af..633f97818 100644
--- a/utils/mail.go
+++ b/utils/mail.go
@@ -105,17 +105,17 @@ func TestConnection(config *model.Config) {
defer c.Close()
}
-func SendMailUsingConfig(to, subject, htmlBody string, config *model.Config) *model.AppError {
+func SendMailUsingConfig(to, subject, htmlBody string, config *model.Config, enableComplianceFeatures bool) *model.AppError {
fromMail := mail.Address{Name: config.EmailSettings.FeedbackName, Address: config.EmailSettings.FeedbackEmail}
- return sendMail(to, to, fromMail, subject, htmlBody, nil, nil, config)
+ return sendMail(to, to, fromMail, subject, htmlBody, nil, nil, config, enableComplianceFeatures)
}
// allows for sending an email with attachments and differing MIME/SMTP recipients
-func SendMailUsingConfigAdvanced(mimeTo, smtpTo string, from mail.Address, subject, htmlBody string, attachments []*model.FileInfo, mimeHeaders map[string]string, config *model.Config) *model.AppError {
- return sendMail(mimeTo, smtpTo, from, subject, htmlBody, attachments, mimeHeaders, config)
+func SendMailUsingConfigAdvanced(mimeTo, smtpTo string, from mail.Address, subject, htmlBody string, attachments []*model.FileInfo, mimeHeaders map[string]string, config *model.Config, enableComplianceFeatures bool) *model.AppError {
+ return sendMail(mimeTo, smtpTo, from, subject, htmlBody, attachments, mimeHeaders, config, enableComplianceFeatures)
}
-func sendMail(mimeTo, smtpTo string, from mail.Address, subject, htmlBody string, attachments []*model.FileInfo, mimeHeaders map[string]string, config *model.Config) *model.AppError {
+func sendMail(mimeTo, smtpTo string, from mail.Address, subject, htmlBody string, attachments []*model.FileInfo, mimeHeaders map[string]string, config *model.Config, enableComplianceFeatures bool) *model.AppError {
if !config.EmailSettings.SendEmailNotifications || len(config.EmailSettings.SMTPServer) == 0 {
return nil
}
@@ -151,7 +151,7 @@ func sendMail(mimeTo, smtpTo string, from mail.Address, subject, htmlBody string
m.AddAlternative("text/html", htmlMessage)
if attachments != nil {
- fileBackend, err := NewFileBackend(&config.FileSettings)
+ fileBackend, err := NewFileBackend(&config.FileSettings, enableComplianceFeatures)
if err != nil {
return err
}
diff --git a/utils/mail_test.go b/utils/mail_test.go
index 207fe32a5..703420441 100644
--- a/utils/mail_test.go
+++ b/utils/mail_test.go
@@ -50,7 +50,7 @@ func TestSendMailUsingConfig(t *testing.T) {
//Delete all the messages before check the sample email
DeleteMailBox(emailTo)
- if err := SendMailUsingConfig(emailTo, emailSubject, emailBody, cfg); err != nil {
+ if err := SendMailUsingConfig(emailTo, emailSubject, emailBody, cfg, true); err != nil {
t.Log(err)
t.Fatal("Should connect to the STMP Server")
} else {
@@ -95,7 +95,7 @@ func TestSendMailUsingConfigAdvanced(t *testing.T) {
DeleteMailBox(smtpTo)
// create a file that will be attached to the email
- fileBackend, err := NewFileBackend(&cfg.FileSettings)
+ fileBackend, err := NewFileBackend(&cfg.FileSettings, true)
assert.Nil(t, err)
fileContents := []byte("hello world")
fileName := "file.txt"
@@ -111,7 +111,7 @@ func TestSendMailUsingConfigAdvanced(t *testing.T) {
headers := make(map[string]string)
headers["TestHeader"] = "TestValue"
- if err := SendMailUsingConfigAdvanced(mimeTo, smtpTo, from, emailSubject, emailBody, attachments, headers, cfg); err != nil {
+ if err := SendMailUsingConfigAdvanced(mimeTo, smtpTo, from, emailSubject, emailBody, attachments, headers, cfg, true); err != nil {
t.Log(err)
t.Fatal("Should connect to the STMP Server")
} else {