github.com/coincircle/mattermost-server@v4.8.1-0.20180321182714-9d701c704416+incompatible/app/license.go (about)

     1  // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package app
     5  
     6  import (
     7  	"crypto/md5"
     8  	"fmt"
     9  	"net/http"
    10  	"strings"
    11  
    12  	l4g "github.com/alecthomas/log4go"
    13  
    14  	"github.com/mattermost/mattermost-server/model"
    15  	"github.com/mattermost/mattermost-server/utils"
    16  )
    17  
    18  func (a *App) LoadLicense() {
    19  	a.SetLicense(nil)
    20  
    21  	licenseId := ""
    22  	if result := <-a.Srv.Store.System().Get(); result.Err == nil {
    23  		props := result.Data.(model.StringMap)
    24  		licenseId = props[model.SYSTEM_ACTIVE_LICENSE_ID]
    25  	}
    26  
    27  	if len(licenseId) != 26 {
    28  		// Lets attempt to load the file from disk since it was missing from the DB
    29  		license, licenseBytes := utils.GetAndValidateLicenseFileFromDisk(*a.Config().ServiceSettings.LicenseFileLocation)
    30  
    31  		if license != nil {
    32  			if _, err := a.SaveLicense(licenseBytes); err != nil {
    33  				l4g.Info("Failed to save license key loaded from disk err=%v", err.Error())
    34  			} else {
    35  				licenseId = license.Id
    36  			}
    37  		}
    38  	}
    39  
    40  	if result := <-a.Srv.Store.License().Get(licenseId); result.Err == nil {
    41  		record := result.Data.(*model.LicenseRecord)
    42  		a.ValidateAndSetLicenseBytes([]byte(record.Bytes))
    43  		l4g.Info("License key valid unlocking enterprise features.")
    44  	} else {
    45  		l4g.Info(utils.T("mattermost.load_license.find.warn"))
    46  	}
    47  }
    48  
    49  func (a *App) SaveLicense(licenseBytes []byte) (*model.License, *model.AppError) {
    50  	var license *model.License
    51  
    52  	if success, licenseStr := utils.ValidateLicense(licenseBytes); success {
    53  		license = model.LicenseFromJson(strings.NewReader(licenseStr))
    54  
    55  		if result := <-a.Srv.Store.User().AnalyticsUniqueUserCount(""); result.Err != nil {
    56  			return nil, model.NewAppError("addLicense", "api.license.add_license.invalid_count.app_error", nil, result.Err.Error(), http.StatusBadRequest)
    57  		} else {
    58  			uniqueUserCount := result.Data.(int64)
    59  
    60  			if uniqueUserCount > int64(*license.Features.Users) {
    61  				return nil, model.NewAppError("addLicense", "api.license.add_license.unique_users.app_error", map[string]interface{}{"Users": *license.Features.Users, "Count": uniqueUserCount}, "", http.StatusBadRequest)
    62  			}
    63  		}
    64  
    65  		if ok := a.SetLicense(license); !ok {
    66  			return nil, model.NewAppError("addLicense", model.EXPIRED_LICENSE_ERROR, nil, "", http.StatusBadRequest)
    67  		}
    68  
    69  		record := &model.LicenseRecord{}
    70  		record.Id = license.Id
    71  		record.Bytes = string(licenseBytes)
    72  		rchan := a.Srv.Store.License().Save(record)
    73  
    74  		if result := <-rchan; result.Err != nil {
    75  			a.RemoveLicense()
    76  			return nil, model.NewAppError("addLicense", "api.license.add_license.save.app_error", nil, "err="+result.Err.Error(), http.StatusInternalServerError)
    77  		}
    78  
    79  		sysVar := &model.System{}
    80  		sysVar.Name = model.SYSTEM_ACTIVE_LICENSE_ID
    81  		sysVar.Value = license.Id
    82  		schan := a.Srv.Store.System().SaveOrUpdate(sysVar)
    83  
    84  		if result := <-schan; result.Err != nil {
    85  			a.RemoveLicense()
    86  			return nil, model.NewAppError("addLicense", "api.license.add_license.save_active.app_error", nil, "", http.StatusInternalServerError)
    87  		}
    88  	} else {
    89  		return nil, model.NewAppError("addLicense", model.INVALID_LICENSE_ERROR, nil, "", http.StatusBadRequest)
    90  	}
    91  
    92  	a.ReloadConfig()
    93  	a.InvalidateAllCaches()
    94  
    95  	// start job server if necessary - this handles the edge case where a license file is uploaded, but the job server
    96  	// doesn't start until the server is restarted, which prevents the 'run job now' buttons in system console from
    97  	// functioning as expected
    98  	if *a.Config().JobSettings.RunJobs {
    99  		a.Jobs.StartWorkers()
   100  	}
   101  	if *a.Config().JobSettings.RunScheduler {
   102  		a.Jobs.StartSchedulers()
   103  	}
   104  
   105  	return license, nil
   106  }
   107  
   108  // License returns the currently active license or nil if the application is unlicensed.
   109  func (a *App) License() *model.License {
   110  	license, _ := a.licenseValue.Load().(*model.License)
   111  	return license
   112  }
   113  
   114  func (a *App) SetLicense(license *model.License) bool {
   115  	defer func() {
   116  		a.setDefaultRolesBasedOnConfig()
   117  		for _, listener := range a.licenseListeners {
   118  			listener()
   119  		}
   120  	}()
   121  
   122  	if license != nil {
   123  		license.Features.SetDefaults()
   124  
   125  		if !license.IsExpired() {
   126  			a.licenseValue.Store(license)
   127  			a.clientLicenseValue.Store(utils.GetClientLicense(license))
   128  			return true
   129  		}
   130  	}
   131  
   132  	a.licenseValue.Store((*model.License)(nil))
   133  	a.clientLicenseValue.Store(map[string]string(nil))
   134  	return false
   135  }
   136  
   137  func (a *App) ValidateAndSetLicenseBytes(b []byte) {
   138  	if success, licenseStr := utils.ValidateLicense(b); success {
   139  		license := model.LicenseFromJson(strings.NewReader(licenseStr))
   140  		a.SetLicense(license)
   141  		return
   142  	}
   143  
   144  	l4g.Warn(utils.T("utils.license.load_license.invalid.warn"))
   145  }
   146  
   147  func (a *App) SetClientLicense(m map[string]string) {
   148  	a.clientLicenseValue.Store(m)
   149  }
   150  
   151  func (a *App) ClientLicense() map[string]string {
   152  	if clientLicense, _ := a.clientLicenseValue.Load().(map[string]string); clientLicense != nil {
   153  		return clientLicense
   154  	}
   155  	return map[string]string{"IsLicensed": "false"}
   156  }
   157  
   158  func (a *App) RemoveLicense() *model.AppError {
   159  	if license, _ := a.licenseValue.Load().(*model.License); license == nil {
   160  		return nil
   161  	}
   162  
   163  	sysVar := &model.System{}
   164  	sysVar.Name = model.SYSTEM_ACTIVE_LICENSE_ID
   165  	sysVar.Value = ""
   166  
   167  	if result := <-a.Srv.Store.System().SaveOrUpdate(sysVar); result.Err != nil {
   168  		return result.Err
   169  	}
   170  
   171  	a.SetLicense(nil)
   172  	a.ReloadConfig()
   173  
   174  	a.InvalidateAllCaches()
   175  
   176  	return nil
   177  }
   178  
   179  func (a *App) AddLicenseListener(listener func()) string {
   180  	id := model.NewId()
   181  	a.licenseListeners[id] = listener
   182  	return id
   183  }
   184  
   185  func (a *App) RemoveLicenseListener(id string) {
   186  	delete(a.licenseListeners, id)
   187  }
   188  
   189  func (a *App) GetClientLicenseEtag(useSanitized bool) string {
   190  	value := ""
   191  
   192  	lic := a.ClientLicense()
   193  
   194  	if useSanitized {
   195  		lic = a.GetSanitizedClientLicense()
   196  	}
   197  
   198  	for k, v := range lic {
   199  		value += fmt.Sprintf("%s:%s;", k, v)
   200  	}
   201  
   202  	return model.Etag(fmt.Sprintf("%x", md5.Sum([]byte(value))))
   203  }
   204  
   205  func (a *App) GetSanitizedClientLicense() map[string]string {
   206  	sanitizedLicense := make(map[string]string)
   207  
   208  	for k, v := range a.ClientLicense() {
   209  		sanitizedLicense[k] = v
   210  	}
   211  
   212  	delete(sanitizedLicense, "Id")
   213  	delete(sanitizedLicense, "Name")
   214  	delete(sanitizedLicense, "Email")
   215  	delete(sanitizedLicense, "PhoneNumber")
   216  	delete(sanitizedLicense, "IssuedAt")
   217  	delete(sanitizedLicense, "StartsAt")
   218  	delete(sanitizedLicense, "ExpiresAt")
   219  
   220  	return sanitizedLicense
   221  }