github.com/vnforks/kid/v5@v5.22.1-0.20200408055009-b89d99c65676/app/license.go (about)

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