github.com/jlevesy/mattermost-server@v5.3.2-0.20181003190404-7468f35cb0c8+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 success, licenseStr := utils.ValidateLicense(licenseBytes) 50 if !success { 51 return nil, model.NewAppError("addLicense", model.INVALID_LICENSE_ERROR, nil, "", http.StatusBadRequest) 52 } 53 license := model.LicenseFromJson(strings.NewReader(licenseStr)) 54 55 result := <-a.Srv.Store.User().AnalyticsUniqueUserCount("") 56 if result.Err != nil { 57 return nil, model.NewAppError("addLicense", "api.license.add_license.invalid_count.app_error", nil, result.Err.Error(), http.StatusBadRequest) 58 } 59 uniqueUserCount := result.Data.(int64) 60 61 if uniqueUserCount > int64(*license.Features.Users) { 62 return nil, model.NewAppError("addLicense", "api.license.add_license.unique_users.app_error", map[string]interface{}{"Users": *license.Features.Users, "Count": uniqueUserCount}, "", http.StatusBadRequest) 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 89 a.ReloadConfig() 90 a.InvalidateAllCaches() 91 92 // start job server if necessary - this handles the edge case where a license file is uploaded, but the job server 93 // doesn't start until the server is restarted, which prevents the 'run job now' buttons in system console from 94 // functioning as expected 95 if *a.Config().JobSettings.RunJobs { 96 a.Jobs.StartWorkers() 97 } 98 if *a.Config().JobSettings.RunScheduler { 99 a.Jobs.StartSchedulers() 100 } 101 102 return license, nil 103 } 104 105 // License returns the currently active license or nil if the application is unlicensed. 106 func (a *App) License() *model.License { 107 license, _ := a.licenseValue.Load().(*model.License) 108 return license 109 } 110 111 func (a *App) SetLicense(license *model.License) bool { 112 defer func() { 113 for _, listener := range a.licenseListeners { 114 listener() 115 } 116 }() 117 118 if license != nil { 119 license.Features.SetDefaults() 120 121 if !license.IsExpired() { 122 a.licenseValue.Store(license) 123 a.clientLicenseValue.Store(utils.GetClientLicense(license)) 124 return true 125 } 126 } 127 128 a.licenseValue.Store((*model.License)(nil)) 129 a.clientLicenseValue.Store(map[string]string(nil)) 130 return false 131 } 132 133 func (a *App) ValidateAndSetLicenseBytes(b []byte) { 134 if success, licenseStr := utils.ValidateLicense(b); success { 135 license := model.LicenseFromJson(strings.NewReader(licenseStr)) 136 a.SetLicense(license) 137 return 138 } 139 140 mlog.Warn("No valid enterprise license found") 141 } 142 143 func (a *App) SetClientLicense(m map[string]string) { 144 a.clientLicenseValue.Store(m) 145 } 146 147 func (a *App) ClientLicense() map[string]string { 148 if clientLicense, _ := a.clientLicenseValue.Load().(map[string]string); clientLicense != nil { 149 return clientLicense 150 } 151 return map[string]string{"IsLicensed": "false"} 152 } 153 154 func (a *App) RemoveLicense() *model.AppError { 155 if license, _ := a.licenseValue.Load().(*model.License); license == nil { 156 return nil 157 } 158 159 sysVar := &model.System{} 160 sysVar.Name = model.SYSTEM_ACTIVE_LICENSE_ID 161 sysVar.Value = "" 162 163 if result := <-a.Srv.Store.System().SaveOrUpdate(sysVar); result.Err != nil { 164 return result.Err 165 } 166 167 a.SetLicense(nil) 168 a.ReloadConfig() 169 170 a.InvalidateAllCaches() 171 172 return nil 173 } 174 175 func (a *App) AddLicenseListener(listener func()) string { 176 id := model.NewId() 177 a.licenseListeners[id] = listener 178 return id 179 } 180 181 func (a *App) RemoveLicenseListener(id string) { 182 delete(a.licenseListeners, id) 183 } 184 185 func (a *App) GetClientLicenseEtag(useSanitized bool) string { 186 value := "" 187 188 lic := a.ClientLicense() 189 190 if useSanitized { 191 lic = a.GetSanitizedClientLicense() 192 } 193 194 for k, v := range lic { 195 value += fmt.Sprintf("%s:%s;", k, v) 196 } 197 198 return model.Etag(fmt.Sprintf("%x", md5.Sum([]byte(value)))) 199 } 200 201 func (a *App) GetSanitizedClientLicense() map[string]string { 202 sanitizedLicense := make(map[string]string) 203 204 for k, v := range a.ClientLicense() { 205 sanitizedLicense[k] = v 206 } 207 208 delete(sanitizedLicense, "Id") 209 delete(sanitizedLicense, "Name") 210 delete(sanitizedLicense, "Email") 211 delete(sanitizedLicense, "PhoneNumber") 212 delete(sanitizedLicense, "IssuedAt") 213 delete(sanitizedLicense, "StartsAt") 214 delete(sanitizedLicense, "ExpiresAt") 215 216 return sanitizedLicense 217 }