github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/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  	"bytes"
     8  	"errors"
     9  	"net/http"
    10  	"os"
    11  	"strings"
    12  
    13  	"github.com/mattermost/mattermost-server/v5/mlog"
    14  	"github.com/mattermost/mattermost-server/v5/model"
    15  	"github.com/mattermost/mattermost-server/v5/utils"
    16  )
    17  
    18  const (
    19  	requestTrialURL = "https://customers.mattermost.com/api/v1/trials"
    20  	LicenseEnv      = "MM_LICENSE"
    21  )
    22  
    23  func (s *Server) LoadLicense() {
    24  	// ENV var overrides all other sources of license.
    25  	licenseStr := os.Getenv(LicenseEnv)
    26  	if licenseStr != "" {
    27  		if s.ValidateAndSetLicenseBytes([]byte(licenseStr)) {
    28  			mlog.Info("License key from ENV is valid, unlocking enterprise features.")
    29  		}
    30  		return
    31  	}
    32  
    33  	licenseId := ""
    34  	props, err := s.Store.System().Get()
    35  	if err == nil {
    36  		licenseId = props[model.SYSTEM_ACTIVE_LICENSE_ID]
    37  	}
    38  
    39  	if !model.IsValidId(licenseId) {
    40  		// Lets attempt to load the file from disk since it was missing from the DB
    41  		license, licenseBytes := utils.GetAndValidateLicenseFileFromDisk(*s.Config().ServiceSettings.LicenseFileLocation)
    42  
    43  		if license != nil {
    44  			if _, err = s.SaveLicense(licenseBytes); err != nil {
    45  				mlog.Info("Failed to save license key loaded from disk.", mlog.Err(err))
    46  			} else {
    47  				licenseId = license.Id
    48  			}
    49  		}
    50  	}
    51  
    52  	record, nErr := s.Store.License().Get(licenseId)
    53  	if nErr != nil {
    54  		mlog.Info("License key from https://mattermost.com required to unlock enterprise features.")
    55  		s.SetLicense(nil)
    56  		return
    57  	}
    58  
    59  	s.ValidateAndSetLicenseBytes([]byte(record.Bytes))
    60  	mlog.Info("License key valid unlocking enterprise features.")
    61  }
    62  
    63  func (s *Server) SaveLicense(licenseBytes []byte) (*model.License, *model.AppError) {
    64  	success, licenseStr := utils.ValidateLicense(licenseBytes)
    65  	if !success {
    66  		return nil, model.NewAppError("addLicense", model.INVALID_LICENSE_ERROR, nil, "", http.StatusBadRequest)
    67  	}
    68  	license := model.LicenseFromJson(strings.NewReader(licenseStr))
    69  
    70  	uniqueUserCount, err := s.Store.User().Count(model.UserCountOptions{})
    71  	if err != nil {
    72  		return nil, model.NewAppError("addLicense", "api.license.add_license.invalid_count.app_error", nil, err.Error(), http.StatusBadRequest)
    73  	}
    74  
    75  	if uniqueUserCount > int64(*license.Features.Users) {
    76  		return nil, model.NewAppError("addLicense", "api.license.add_license.unique_users.app_error", map[string]interface{}{"Users": *license.Features.Users, "Count": uniqueUserCount}, "", http.StatusBadRequest)
    77  	}
    78  
    79  	if license != nil && license.IsExpired() {
    80  		return nil, model.NewAppError("addLicense", model.EXPIRED_LICENSE_ERROR, nil, "", http.StatusBadRequest)
    81  	}
    82  
    83  	if ok := s.SetLicense(license); !ok {
    84  		return nil, model.NewAppError("addLicense", model.EXPIRED_LICENSE_ERROR, nil, "", http.StatusBadRequest)
    85  	}
    86  
    87  	record := &model.LicenseRecord{}
    88  	record.Id = license.Id
    89  	record.Bytes = string(licenseBytes)
    90  
    91  	_, nErr := s.Store.License().Save(record)
    92  	if nErr != nil {
    93  		s.RemoveLicense()
    94  		var appErr *model.AppError
    95  		switch {
    96  		case errors.As(nErr, &appErr):
    97  			return nil, appErr
    98  		default:
    99  			return nil, model.NewAppError("addLicense", "api.license.add_license.save.app_error", nil, err.Error(), http.StatusInternalServerError)
   100  		}
   101  	}
   102  
   103  	sysVar := &model.System{}
   104  	sysVar.Name = model.SYSTEM_ACTIVE_LICENSE_ID
   105  	sysVar.Value = license.Id
   106  	if err := s.Store.System().SaveOrUpdate(sysVar); err != nil {
   107  		s.RemoveLicense()
   108  		return nil, model.NewAppError("addLicense", "api.license.add_license.save_active.app_error", nil, "", http.StatusInternalServerError)
   109  	}
   110  
   111  	s.ReloadConfig()
   112  	s.InvalidateAllCaches()
   113  
   114  	// start job server if necessary - this handles the edge case where a license file is uploaded, but the job server
   115  	// doesn't start until the server is restarted, which prevents the 'run job now' buttons in system console from
   116  	// functioning as expected
   117  	if *s.Config().JobSettings.RunJobs && s.Jobs != nil && s.Jobs.Workers != nil {
   118  		s.Jobs.StartWorkers()
   119  	}
   120  	if *s.Config().JobSettings.RunScheduler && s.Jobs != nil && s.Jobs.Schedulers != nil {
   121  		s.Jobs.StartSchedulers()
   122  	}
   123  
   124  	return license, nil
   125  }
   126  
   127  func (s *Server) SetLicense(license *model.License) bool {
   128  	oldLicense := s.licenseValue.Load()
   129  
   130  	defer func() {
   131  		for _, listener := range s.licenseListeners {
   132  			if oldLicense == nil {
   133  				listener(nil, license)
   134  			} else {
   135  				listener(oldLicense.(*model.License), license)
   136  			}
   137  		}
   138  	}()
   139  
   140  	if license != nil {
   141  		license.Features.SetDefaults()
   142  
   143  		s.licenseValue.Store(license)
   144  		s.clientLicenseValue.Store(utils.GetClientLicense(license))
   145  		return true
   146  	}
   147  
   148  	s.licenseValue.Store((*model.License)(nil))
   149  	s.clientLicenseValue.Store(map[string]string(nil))
   150  	return false
   151  }
   152  
   153  func (s *Server) ValidateAndSetLicenseBytes(b []byte) bool {
   154  	if success, licenseStr := utils.ValidateLicense(b); success {
   155  		license := model.LicenseFromJson(strings.NewReader(licenseStr))
   156  		s.SetLicense(license)
   157  		return true
   158  	}
   159  
   160  	mlog.Warn("No valid enterprise license found")
   161  	return false
   162  }
   163  
   164  func (s *Server) SetClientLicense(m map[string]string) {
   165  	s.clientLicenseValue.Store(m)
   166  }
   167  
   168  func (s *Server) ClientLicense() map[string]string {
   169  	if clientLicense, _ := s.clientLicenseValue.Load().(map[string]string); clientLicense != nil {
   170  		return clientLicense
   171  	}
   172  	return map[string]string{"IsLicensed": "false"}
   173  }
   174  
   175  func (s *Server) RemoveLicense() *model.AppError {
   176  	if license, _ := s.licenseValue.Load().(*model.License); license == nil {
   177  		return nil
   178  	}
   179  
   180  	mlog.Info("Remove license.", mlog.String("id", model.SYSTEM_ACTIVE_LICENSE_ID))
   181  
   182  	sysVar := &model.System{}
   183  	sysVar.Name = model.SYSTEM_ACTIVE_LICENSE_ID
   184  	sysVar.Value = ""
   185  
   186  	if err := s.Store.System().SaveOrUpdate(sysVar); err != nil {
   187  		return err
   188  	}
   189  
   190  	s.SetLicense(nil)
   191  	s.ReloadConfig()
   192  	s.InvalidateAllCaches()
   193  
   194  	return nil
   195  }
   196  
   197  func (s *Server) AddLicenseListener(listener func(oldLicense, newLicense *model.License)) string {
   198  	id := model.NewId()
   199  	s.licenseListeners[id] = listener
   200  	return id
   201  }
   202  
   203  func (s *Server) RemoveLicenseListener(id string) {
   204  	delete(s.licenseListeners, id)
   205  }
   206  
   207  func (s *Server) GetSanitizedClientLicense() map[string]string {
   208  	sanitizedLicense := make(map[string]string)
   209  
   210  	for k, v := range s.ClientLicense() {
   211  		sanitizedLicense[k] = v
   212  	}
   213  
   214  	delete(sanitizedLicense, "Id")
   215  	delete(sanitizedLicense, "Name")
   216  	delete(sanitizedLicense, "Email")
   217  	delete(sanitizedLicense, "IssuedAt")
   218  	delete(sanitizedLicense, "StartsAt")
   219  	delete(sanitizedLicense, "ExpiresAt")
   220  	delete(sanitizedLicense, "SkuName")
   221  	delete(sanitizedLicense, "SkuShortName")
   222  
   223  	return sanitizedLicense
   224  }
   225  
   226  // RequestTrialLicense request a trial license from the mattermost offical license server
   227  func (s *Server) RequestTrialLicense(trialRequest *model.TrialLicenseRequest) *model.AppError {
   228  	resp, err := http.Post(requestTrialURL, "application/json", bytes.NewBuffer([]byte(trialRequest.ToJson())))
   229  	if err != nil {
   230  		return model.NewAppError("RequestTrialLicense", "api.license.request_trial_license.app_error", nil, err.Error(), http.StatusBadRequest)
   231  	}
   232  	defer resp.Body.Close()
   233  	licenseResponse := model.MapFromJson(resp.Body)
   234  
   235  	if _, ok := licenseResponse["license"]; !ok {
   236  		return model.NewAppError("RequestTrialLicense", "api.license.request_trial_license.app_error", nil, licenseResponse["message"], http.StatusBadRequest)
   237  	}
   238  
   239  	if _, err := s.SaveLicense([]byte(licenseResponse["license"])); err != nil {
   240  		return err
   241  	}
   242  
   243  	s.ReloadConfig()
   244  	s.InvalidateAllCaches()
   245  
   246  	return nil
   247  }