summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--api/license.go2
-rw-r--r--app/license.go42
-rw-r--r--model/config.go5
-rw-r--r--store/sql_webhook_store_test.go2
-rw-r--r--utils/license.go27
-rw-r--r--utils/license_test.go28
7 files changed, 97 insertions, 11 deletions
diff --git a/.gitignore b/.gitignore
index 6ab3cf0a4..99c3a72f8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,8 @@ node_modules
/dist
/webapp/dist
npm-debug.log
+mattermost.mattermost-license
+config/mattermost.mattermost-license
web/static/js/bundle*.js
web/static/js/bundle*.js.map
diff --git a/api/license.go b/api/license.go
index ea5de20d4..0e9eb6027 100644
--- a/api/license.go
+++ b/api/license.go
@@ -68,6 +68,8 @@ func addLicense(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
} else {
+ app.ReloadConfig()
+ app.InvalidateAllCaches()
c.LogAudit("success")
w.Write([]byte(license.ToJson()))
}
diff --git a/app/license.go b/app/license.go
index 1efaf85d5..6b448b19d 100644
--- a/app/license.go
+++ b/app/license.go
@@ -4,6 +4,7 @@
package app
import (
+ "os"
"strings"
l4g "github.com/alecthomas/log4go"
@@ -21,13 +22,36 @@ func LoadLicense() {
}
if len(licenseId) != 26 {
- l4g.Info(utils.T("mattermost.load_license.find.warn"))
- return
+ // Lets attempt to load the file from disk since it was missing from the DB
+ fileName := utils.GetLicenseFileLocation(*utils.Cfg.ServiceSettings.LicenseFileLocation)
+
+ if _, err := os.Stat(fileName); err == nil {
+ l4g.Info("License key has not been uploaded. Loading license key from disk at %v", fileName)
+ licenseBytes := utils.GetLicenseFileFromDisk(fileName)
+
+ if success, licenseStr := utils.ValidateLicense(licenseBytes); success {
+ licenseFileFromDisk := model.LicenseFromJson(strings.NewReader(licenseStr))
+ licenseId = licenseFileFromDisk.Id
+ if _, err := SaveLicense(licenseBytes); err != nil {
+ l4g.Info("Failed to save license key loaded from disk err=%v", err.Error())
+ return
+ }
+ } else {
+ l4g.Error("Found license key at %v but it appears to be invalid.", fileName)
+ return
+ }
+
+ } else {
+ l4g.Info(utils.T("mattermost.load_license.find.warn"))
+ l4g.Debug("We could not find the license key in the database or on disk at %v", fileName)
+ return
+ }
}
if result := <-Srv.Store.License().Get(licenseId); result.Err == nil {
record := result.Data.(*model.LicenseRecord)
utils.LoadLicense([]byte(record.Bytes))
+ l4g.Info("License key valid unlocking enterprise features.")
} else {
l4g.Info(utils.T("mattermost.load_license.find.warn"))
}
@@ -58,16 +82,16 @@ func SaveLicense(licenseBytes []byte) (*model.License, *model.AppError) {
record.Bytes = string(licenseBytes)
rchan := Srv.Store.License().Save(record)
- sysVar := &model.System{}
- sysVar.Name = model.SYSTEM_ACTIVE_LICENSE_ID
- sysVar.Value = license.Id
- schan := Srv.Store.System().SaveOrUpdate(sysVar)
-
if result := <-rchan; result.Err != nil {
RemoveLicense()
return nil, model.NewLocAppError("addLicense", "api.license.add_license.save.app_error", nil, "err="+result.Err.Error())
}
+ sysVar := &model.System{}
+ sysVar.Name = model.SYSTEM_ACTIVE_LICENSE_ID
+ sysVar.Value = license.Id
+ schan := Srv.Store.System().SaveOrUpdate(sysVar)
+
if result := <-schan; result.Err != nil {
RemoveLicense()
return nil, model.NewLocAppError("addLicense", "api.license.add_license.save_active.app_error", nil, "")
@@ -76,10 +100,6 @@ func SaveLicense(licenseBytes []byte) (*model.License, *model.AppError) {
return nil, model.NewLocAppError("addLicense", model.INVALID_LICENSE_ERROR, nil, "")
}
- ReloadConfig()
-
- InvalidateAllCaches()
-
return license, nil
}
diff --git a/model/config.go b/model/config.go
index 4486b64ad..e26bf90f1 100644
--- a/model/config.go
+++ b/model/config.go
@@ -111,6 +111,7 @@ const (
type ServiceSettings struct {
SiteURL *string
+ LicenseFileLocation *string
ListenAddress string
ConnectionSecurity *string
TLSCertFile *string
@@ -497,6 +498,10 @@ func (o *Config) SetDefaults() {
*o.ServiceSettings.SiteURL = SERVICE_SETTINGS_DEFAULT_SITE_URL
}
+ if o.ServiceSettings.LicenseFileLocation == nil {
+ o.ServiceSettings.LicenseFileLocation = new(string)
+ }
+
if o.ServiceSettings.EnableLinkPreviews == nil {
o.ServiceSettings.EnableLinkPreviews = new(bool)
*o.ServiceSettings.EnableLinkPreviews = false
diff --git a/store/sql_webhook_store_test.go b/store/sql_webhook_store_test.go
index 6cfe36450..fbaf4bc82 100644
--- a/store/sql_webhook_store_test.go
+++ b/store/sql_webhook_store_test.go
@@ -5,6 +5,7 @@ package store
import (
"testing"
+ "time"
"net/http"
@@ -31,6 +32,7 @@ func TestWebhookStoreUpdateIncoming(t *testing.T) {
previousUpdatedAt := o1.UpdateAt
o1.DisplayName = "TestHook"
+ time.Sleep(10 * time.Millisecond)
if result := (<-store.Webhook().UpdateIncoming(o1)); result.Err != nil {
t.Fatal("updation of incoming hook failed", result.Err)
diff --git a/utils/license.go b/utils/license.go
index 5ec94386d..f0763d741 100644
--- a/utils/license.go
+++ b/utils/license.go
@@ -12,6 +12,8 @@ import (
"encoding/base64"
"encoding/pem"
"fmt"
+ "io/ioutil"
+ "os"
"strconv"
"strings"
@@ -112,6 +114,31 @@ func ValidateLicense(signed []byte) (bool, string) {
return true, string(plaintext)
}
+func GetLicenseFileFromDisk(fileName string) []byte {
+ file, err := os.Open(fileName)
+ if err != nil {
+ l4g.Error("Failed to open license key from disk at %v err=%v", fileName, err.Error())
+ return nil
+ }
+ defer file.Close()
+
+ licenseBytes, err := ioutil.ReadAll(file)
+ if err != nil {
+ l4g.Error("Failed to read license key from disk at %v err=%v", fileName, err.Error())
+ return nil
+ }
+
+ return licenseBytes
+}
+
+func GetLicenseFileLocation(fileLocation string) string {
+ if fileLocation == "" {
+ return FindDir("config") + "mattermost.mattermost-license"
+ } else {
+ return fileLocation
+ }
+}
+
func getClientLicense(l *model.License) map[string]string {
props := make(map[string]string)
diff --git a/utils/license_test.go b/utils/license_test.go
index 6508172d5..5c0122bc0 100644
--- a/utils/license_test.go
+++ b/utils/license_test.go
@@ -66,3 +66,31 @@ func TestClientLicenseEtag(t *testing.T) {
t.Fatal("etags should not match")
}
}
+
+func TestGetLicenseFileLocation(t *testing.T) {
+ fileName := GetLicenseFileLocation("")
+ if len(fileName) == 0 {
+ t.Fatal("invalid default file name")
+ }
+
+ fileName = GetLicenseFileLocation("mattermost.mattermost-license")
+ if fileName != "mattermost.mattermost-license" {
+ t.Fatal("invalid file name")
+ }
+}
+
+func TestGetLicenseFileFromDisk(t *testing.T) {
+ fileBytes := GetLicenseFileFromDisk("thisfileshouldnotexist.mattermost-license")
+ if len(fileBytes) > 0 {
+ t.Fatal("invalid bytes")
+ }
+
+ fileBytes = GetLicenseFileFromDisk(FindConfigFile("config.json"))
+ if len(fileBytes) == 0 { // a valid bytes but should be a fail license
+ t.Fatal("invalid bytes")
+ }
+
+ if success, _ := ValidateLicense(fileBytes); success {
+ t.Fatal("should have been an invalid file")
+ }
+}