From 0ab490845aed0ce3b58cbffd8ec35be237abda1c Mon Sep 17 00:00:00 2001 From: Corey Hulen Date: Wed, 16 Aug 2017 09:51:45 -0700 Subject: PLT-6226 Fixing races with licensing (#7213) * PLT-6226 Fixing races with licensing * Fixing build issue * Fixing licensing issue * removing commented code --- utils/authorization.go | 18 +++++------ utils/config.go | 5 ++- utils/license.go | 83 +++++++++++++++++++++++++++++++++++++------------- utils/license_test.go | 4 +-- utils/password.go | 2 +- 5 files changed, 77 insertions(+), 35 deletions(-) (limited to 'utils') diff --git a/utils/authorization.go b/utils/authorization.go index 6f01d7820..e0e587d71 100644 --- a/utils/authorization.go +++ b/utils/authorization.go @@ -11,7 +11,7 @@ func SetDefaultRolesBasedOnConfig() { // Reset the roles to default to make this logic easier model.InitalizeRoles() - if IsLicensed { + if IsLicensed() { switch *Cfg.TeamSettings.RestrictPublicChannelCreation { case model.PERMISSIONS_ALL: model.ROLE_TEAM_USER.Permissions = append( @@ -33,7 +33,7 @@ func SetDefaultRolesBasedOnConfig() { ) } - if IsLicensed { + if IsLicensed() { switch *Cfg.TeamSettings.RestrictPublicChannelManagement { case model.PERMISSIONS_ALL: model.ROLE_TEAM_USER.Permissions = append( @@ -65,7 +65,7 @@ func SetDefaultRolesBasedOnConfig() { ) } - if IsLicensed { + if IsLicensed() { switch *Cfg.TeamSettings.RestrictPublicChannelDeletion { case model.PERMISSIONS_ALL: model.ROLE_TEAM_USER.Permissions = append( @@ -97,7 +97,7 @@ func SetDefaultRolesBasedOnConfig() { ) } - if IsLicensed { + if IsLicensed() { switch *Cfg.TeamSettings.RestrictPrivateChannelCreation { case model.PERMISSIONS_ALL: model.ROLE_TEAM_USER.Permissions = append( @@ -119,7 +119,7 @@ func SetDefaultRolesBasedOnConfig() { ) } - if IsLicensed { + if IsLicensed() { switch *Cfg.TeamSettings.RestrictPrivateChannelManagement { case model.PERMISSIONS_ALL: model.ROLE_TEAM_USER.Permissions = append( @@ -151,7 +151,7 @@ func SetDefaultRolesBasedOnConfig() { ) } - if IsLicensed { + if IsLicensed() { switch *Cfg.TeamSettings.RestrictPrivateChannelDeletion { case model.PERMISSIONS_ALL: model.ROLE_TEAM_USER.Permissions = append( @@ -184,7 +184,7 @@ func SetDefaultRolesBasedOnConfig() { } // Restrict permissions for Private Channel Manage Members - if IsLicensed { + if IsLicensed() { switch *Cfg.TeamSettings.RestrictPrivateChannelManageMembers { case model.PERMISSIONS_ALL: model.ROLE_CHANNEL_USER.Permissions = append( @@ -229,7 +229,7 @@ func SetDefaultRolesBasedOnConfig() { } // Grant permissions for inviting and adding users to a team. - if IsLicensed { + if IsLicensed() { if *Cfg.TeamSettings.RestrictTeamInvite == model.PERMISSIONS_TEAM_ADMIN { model.ROLE_TEAM_ADMIN.Permissions = append( model.ROLE_TEAM_ADMIN.Permissions, @@ -251,7 +251,7 @@ func SetDefaultRolesBasedOnConfig() { ) } - if IsLicensed { + if IsLicensed() { switch *Cfg.ServiceSettings.RestrictPostDelete { case model.PERMISSIONS_DELETE_POST_ALL: model.ROLE_CHANNEL_USER.Permissions = append( diff --git a/utils/config.go b/utils/config.go index c0c7ecc20..187af4125 100644 --- a/utils/config.go +++ b/utils/config.go @@ -489,7 +489,10 @@ func getClientConfig(c *model.Config) map[string]string { props["DiagnosticId"] = CfgDiagnosticId props["DiagnosticsEnabled"] = strconv.FormatBool(*c.LogSettings.EnableDiagnostics) - if IsLicensed { + if IsLicensed() { + + License := License() + if *License.Features.CustomBrand { props["EnableCustomBrand"] = strconv.FormatBool(*c.TeamSettings.EnableCustomBrand) props["CustomBrandText"] = *c.TeamSettings.CustomBrandText diff --git a/utils/license.go b/utils/license.go index e28a43e29..d0abc612d 100644 --- a/utils/license.go +++ b/utils/license.go @@ -16,17 +16,16 @@ import ( "os" "strconv" "strings" + "sync/atomic" l4g "github.com/alecthomas/log4go" "github.com/mattermost/platform/model" ) -var IsLicensed bool = false -var License *model.License = &model.License{ - Features: new(model.Features), -} -var ClientLicense map[string]string = map[string]string{"IsLicensed": "false"} +var isLicensedInt32 int32 +var licenseValue atomic.Value +var clientLicenseValue atomic.Value var publicKey []byte = []byte(`-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyZmShlU8Z8HdG0IWSZ8r @@ -38,6 +37,34 @@ a0v85XL6i9ote2P+fLZ3wX9EoioHzgdgB7arOxY50QRJO7OyCqpKFKv6lRWTXuSt hwIDAQAB -----END PUBLIC KEY-----`) +func init() { + SetLicense(nil) +} + +func IsLicensed() bool { + return atomic.LoadInt32(&isLicensedInt32) == 1 +} + +func SetIsLicensed(v bool) { + if v { + atomic.StoreInt32(&isLicensedInt32, 1) + } else { + atomic.StoreInt32(&isLicensedInt32, 0) + } +} + +func License() *model.License { + return licenseValue.Load().(*model.License) +} + +func SetClientLicense(m map[string]string) { + clientLicenseValue.Store(m) +} + +func ClientLicense() map[string]string { + return clientLicenseValue.Load().(map[string]string) +} + func LoadLicense(licenseBytes []byte) { if success, licenseStr := ValidateLicense(licenseBytes); success { license := model.LicenseFromJson(strings.NewReader(licenseStr)) @@ -49,23 +76,35 @@ func LoadLicense(licenseBytes []byte) { } func SetLicense(license *model.License) bool { - license.Features.SetDefaults() - if !license.IsExpired() { - License = license - IsLicensed = true - ClientLicense = getClientLicense(license) - ClientCfg = getClientConfig(Cfg) - return true - } + if license == nil { + SetIsLicensed(false) + license = &model.License{ + Features: new(model.Features), + } + license.Features.SetDefaults() + licenseValue.Store(license) - return false + SetClientLicense(map[string]string{"IsLicensed": "false"}) + + return false + } else { + license.Features.SetDefaults() + + if !license.IsExpired() { + licenseValue.Store(license) + SetIsLicensed(true) + clientLicenseValue.Store(getClientLicense(license)) + ClientCfg = getClientConfig(Cfg) + return true + } + + return false + } } func RemoveLicense() { - License = &model.License{} - IsLicensed = false - ClientLicense = getClientLicense(License) + SetLicense(nil) ClientCfg = getClientConfig(Cfg) } @@ -162,9 +201,9 @@ func GetLicenseFileLocation(fileLocation string) string { func getClientLicense(l *model.License) map[string]string { props := make(map[string]string) - props["IsLicensed"] = strconv.FormatBool(IsLicensed) + props["IsLicensed"] = strconv.FormatBool(IsLicensed()) - if IsLicensed { + if IsLicensed() { props["Id"] = l.Id props["Users"] = strconv.Itoa(*l.Features.Users) props["LDAP"] = strconv.FormatBool(*l.Features.LDAP) @@ -195,7 +234,7 @@ func getClientLicense(l *model.License) map[string]string { func GetClientLicenseEtag(useSanitized bool) string { value := "" - lic := ClientLicense + lic := ClientLicense() if useSanitized { lic = GetSanitizedClientLicense() @@ -211,11 +250,11 @@ func GetClientLicenseEtag(useSanitized bool) string { func GetSanitizedClientLicense() map[string]string { sanitizedLicense := make(map[string]string) - for k, v := range ClientLicense { + for k, v := range ClientLicense() { sanitizedLicense[k] = v } - if IsLicensed { + if IsLicensed() { delete(sanitizedLicense, "Id") delete(sanitizedLicense, "Name") delete(sanitizedLicense, "Email") diff --git a/utils/license_test.go b/utils/license_test.go index 289262f4c..1d948b02f 100644 --- a/utils/license_test.go +++ b/utils/license_test.go @@ -54,14 +54,14 @@ func TestValidateLicense(t *testing.T) { func TestClientLicenseEtag(t *testing.T) { etag1 := GetClientLicenseEtag(false) - ClientLicense["SomeFeature"] = "true" + SetClientLicense(map[string]string{"SomeFeature": "true", "IsLicensed": "true"}) etag2 := GetClientLicenseEtag(false) if etag1 == etag2 { t.Fatal("etags should not match") } - ClientLicense["SomeFeature"] = "false" + SetClientLicense(map[string]string{"SomeFeature": "true", "IsLicensed": "false"}) etag3 := GetClientLicenseEtag(false) if etag2 == etag3 { diff --git a/utils/password.go b/utils/password.go index 6aa785df8..7c2ca538b 100644 --- a/utils/password.go +++ b/utils/password.go @@ -15,7 +15,7 @@ func IsPasswordValid(password string) *model.AppError { isError := false min := model.PASSWORD_MINIMUM_LENGTH - if IsLicensed && *License.Features.PasswordRequirements { + if IsLicensed() && *License().Features.PasswordRequirements { if len(password) < *Cfg.PasswordSettings.MinimumLength || len(password) > model.PASSWORD_MAXIMUM_LENGTH { isError = true } -- cgit v1.2.3-1-g7c22