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