Move some more atomic values under Channels (#18837)

* Move some more atomic values under Channels

The following fields were moved:

```
asymmetricSigningKey atomic.Value
clientConfig         atomic.Value
clientConfigHash     atomic.Value
limitedClientConfig  atomic.Value
```

And also moved the initialization order from NewServer
to Channels.Start to better reflect the order of things.

Removed AsymmetricSigningKey from ConfigService
as it was no longer used.

Removed calling regenerateClientConfig during startup explicitly
because it was anyways called from ensureAsymmetricSigningKey.

https://community-daily.mattermost.com/boards/workspace/zyoahc9uapdn3xdptac6jb69ic/285b80a3-257d-41f6-8cf4-ed80ca9d92e5/495cdb4d-c13a-4992-8eb9-80cfee2819a4?c=87df1e15-588e-49ff-8bd1-ffa9651b8c82
```release-note
NONE
```

* Fix lint error

```release-note
NONE
```
Этот коммит содержится в:
Agniva De Sarker
2021-10-26 00:05:11 +05:30
коммит произвёл GitHub
родитель a499d2f378
Коммит 6bc6243131
4 изменённых файлов: 47 добавлений и 57 удалений

Просмотреть файл

@@ -4,8 +4,11 @@
package app package app
import ( import (
"sync/atomic"
"github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/services/imageproxy" "github.com/mattermost/mattermost-server/v6/services/imageproxy"
"github.com/pkg/errors"
) )
// Channels contains all channels related state. // Channels contains all channels related state.
@@ -14,6 +17,11 @@ type Channels struct {
imageProxy *imageproxy.ImageProxy imageProxy *imageproxy.ImageProxy
asymmetricSigningKey atomic.Value
clientConfig atomic.Value
clientConfigHash atomic.Value
limitedClientConfig atomic.Value
// cached counts that are used during notice condition validation // cached counts that are used during notice condition validation
cachedPostCount int64 cachedPostCount int64
cachedUserCount int64 cachedUserCount int64
@@ -35,10 +43,13 @@ func NewChannels(s *Server) (*Channels, error) {
}, nil }, nil
} }
func (c *Channels) Start() error { func (ch *Channels) Start() error {
if err := ch.ensureAsymmetricSigningKey(); err != nil {
return errors.Wrapf(err, "unable to ensure asymmetric signing key")
}
return nil return nil
} }
func (c *Channels) Stop() error { func (*Channels) Stop() error {
return nil return nil
} }

Просмотреть файл

@@ -75,15 +75,15 @@ func (a *App) ReloadConfig() error {
} }
func (a *App) ClientConfig() map[string]string { func (a *App) ClientConfig() map[string]string {
return a.Srv().clientConfig.Load().(map[string]string) return a.ch.clientConfig.Load().(map[string]string)
} }
func (a *App) ClientConfigHash() string { func (a *App) ClientConfigHash() string {
return a.Srv().ClientConfigHash() return a.ch.ClientConfigHash()
} }
func (a *App) LimitedClientConfig() map[string]string { func (a *App) LimitedClientConfig() map[string]string {
return a.Srv().limitedClientConfig.Load().(map[string]string) return a.ch.limitedClientConfig.Load().(map[string]string)
} }
// Registers a function with a given listener to be called when the config is reloaded and may have changed. The function // Registers a function with a given listener to be called when the config is reloaded and may have changed. The function
@@ -168,14 +168,14 @@ func (s *Server) ensurePostActionCookieSecret() error {
// ensureAsymmetricSigningKey ensures that an asymmetric signing key exists and future calls to // ensureAsymmetricSigningKey ensures that an asymmetric signing key exists and future calls to
// AsymmetricSigningKey will always return a valid signing key. // AsymmetricSigningKey will always return a valid signing key.
func (s *Server) ensureAsymmetricSigningKey() error { func (ch *Channels) ensureAsymmetricSigningKey() error {
if s.AsymmetricSigningKey() != nil { if ch.AsymmetricSigningKey() != nil {
return nil return nil
} }
var key *model.SystemAsymmetricSigningKey var key *model.SystemAsymmetricSigningKey
value, err := s.Store.System().GetByName(model.SystemAsymmetricSigningKeyKey) value, err := ch.srv.Store.System().GetByName(model.SystemAsymmetricSigningKeyKey)
if err == nil { if err == nil {
if err := json.Unmarshal([]byte(value.Value), &key); err != nil { if err := json.Unmarshal([]byte(value.Value), &key); err != nil {
return err return err
@@ -205,7 +205,7 @@ func (s *Server) ensureAsymmetricSigningKey() error {
} }
system.Value = string(v) system.Value = string(v)
// If we were able to save the key, use it, otherwise log the error. // If we were able to save the key, use it, otherwise log the error.
if err = s.Store.System().Save(system); err != nil { if err = ch.srv.Store.System().Save(system); err != nil {
mlog.Warn("Failed to save AsymmetricSigningKey", mlog.Err(err)) mlog.Warn("Failed to save AsymmetricSigningKey", mlog.Err(err))
} else { } else {
key = newKey key = newKey
@@ -215,7 +215,7 @@ func (s *Server) ensureAsymmetricSigningKey() error {
// If we weren't able to save a new key above, another server must have beat us to it. Get the // If we weren't able to save a new key above, another server must have beat us to it. Get the
// key from the database, and if that fails, error out. // key from the database, and if that fails, error out.
if key == nil { if key == nil {
value, err := s.Store.System().GetByName(model.SystemAsymmetricSigningKeyKey) value, err := ch.srv.Store.System().GetByName(model.SystemAsymmetricSigningKeyKey)
if err != nil { if err != nil {
return err return err
} }
@@ -232,7 +232,7 @@ func (s *Server) ensureAsymmetricSigningKey() error {
default: default:
return fmt.Errorf("unknown curve: " + key.ECDSAKey.Curve) return fmt.Errorf("unknown curve: " + key.ECDSAKey.Curve)
} }
s.asymmetricSigningKey.Store(&ecdsa.PrivateKey{ ch.asymmetricSigningKey.Store(&ecdsa.PrivateKey{
PublicKey: ecdsa.PublicKey{ PublicKey: ecdsa.PublicKey{
Curve: curve, Curve: curve,
X: key.ECDSAKey.X, X: key.ECDSAKey.X,
@@ -240,7 +240,7 @@ func (s *Server) ensureAsymmetricSigningKey() error {
}, },
D: key.ECDSAKey.D, D: key.ECDSAKey.D,
}) })
s.regenerateClientConfig() ch.regenerateClientConfig()
return nil return nil
} }
@@ -283,15 +283,15 @@ func (s *Server) ensureFirstServerRunTimestamp() error {
} }
// AsymmetricSigningKey will return a private key that can be used for asymmetric signing. // AsymmetricSigningKey will return a private key that can be used for asymmetric signing.
func (s *Server) AsymmetricSigningKey() *ecdsa.PrivateKey { func (ch *Channels) AsymmetricSigningKey() *ecdsa.PrivateKey {
if key := s.asymmetricSigningKey.Load(); key != nil { if key := ch.asymmetricSigningKey.Load(); key != nil {
return key.(*ecdsa.PrivateKey) return key.(*ecdsa.PrivateKey)
} }
return nil return nil
} }
func (a *App) AsymmetricSigningKey() *ecdsa.PrivateKey { func (a *App) AsymmetricSigningKey() *ecdsa.PrivateKey {
return a.Srv().AsymmetricSigningKey() return a.ch.AsymmetricSigningKey()
} }
func (s *Server) PostActionCookieSecret() []byte { func (s *Server) PostActionCookieSecret() []byte {
@@ -302,12 +302,12 @@ func (a *App) PostActionCookieSecret() []byte {
return a.Srv().PostActionCookieSecret() return a.Srv().PostActionCookieSecret()
} }
func (s *Server) regenerateClientConfig() { func (ch *Channels) regenerateClientConfig() {
clientConfig := config.GenerateClientConfig(s.Config(), s.TelemetryId(), s.License()) clientConfig := config.GenerateClientConfig(ch.srv.Config(), ch.srv.TelemetryId(), ch.srv.License())
limitedClientConfig := config.GenerateLimitedClientConfig(s.Config(), s.TelemetryId(), s.License()) limitedClientConfig := config.GenerateLimitedClientConfig(ch.srv.Config(), ch.srv.TelemetryId(), ch.srv.License())
if clientConfig["EnableCustomTermsOfService"] == "true" { if clientConfig["EnableCustomTermsOfService"] == "true" {
termsOfService, err := s.Store.TermsOfService().GetLatest(true) termsOfService, err := ch.srv.Store.TermsOfService().GetLatest(true)
if err != nil { if err != nil {
mlog.Err(err) mlog.Err(err)
} else { } else {
@@ -316,16 +316,16 @@ func (s *Server) regenerateClientConfig() {
} }
} }
if key := s.AsymmetricSigningKey(); key != nil { if key := ch.AsymmetricSigningKey(); key != nil {
der, _ := x509.MarshalPKIXPublicKey(&key.PublicKey) der, _ := x509.MarshalPKIXPublicKey(&key.PublicKey)
clientConfig["AsymmetricSigningPublicKey"] = base64.StdEncoding.EncodeToString(der) clientConfig["AsymmetricSigningPublicKey"] = base64.StdEncoding.EncodeToString(der)
limitedClientConfig["AsymmetricSigningPublicKey"] = base64.StdEncoding.EncodeToString(der) limitedClientConfig["AsymmetricSigningPublicKey"] = base64.StdEncoding.EncodeToString(der)
} }
clientConfigJSON, _ := json.Marshal(clientConfig) clientConfigJSON, _ := json.Marshal(clientConfig)
s.clientConfig.Store(clientConfig) ch.clientConfig.Store(clientConfig)
s.limitedClientConfig.Store(limitedClientConfig) ch.limitedClientConfig.Store(limitedClientConfig)
s.clientConfigHash.Store(fmt.Sprintf("%x", md5.Sum(clientConfigJSON))) ch.clientConfigHash.Store(fmt.Sprintf("%x", md5.Sum(clientConfigJSON)))
} }
func (a *App) GetCookieDomain() string { func (a *App) GetCookieDomain() string {
@@ -342,30 +342,25 @@ func (a *App) GetSiteURL() string {
} }
// ClientConfigWithComputed gets the configuration in a format suitable for sending to the client. // ClientConfigWithComputed gets the configuration in a format suitable for sending to the client.
func (s *Server) ClientConfigWithComputed() map[string]string { func (a *App) ClientConfigWithComputed() map[string]string {
respCfg := map[string]string{} respCfg := map[string]string{}
for k, v := range s.clientConfig.Load().(map[string]string) { for k, v := range a.ch.clientConfig.Load().(map[string]string) {
respCfg[k] = v respCfg[k] = v
} }
// These properties are not configurable, but nevertheless represent configuration expected // These properties are not configurable, but nevertheless represent configuration expected
// by the client. // by the client.
respCfg["NoAccounts"] = strconv.FormatBool(s.userService.IsFirstUserAccount()) respCfg["NoAccounts"] = strconv.FormatBool(a.ch.srv.userService.IsFirstUserAccount())
respCfg["MaxPostSize"] = strconv.Itoa(s.MaxPostSize()) respCfg["MaxPostSize"] = strconv.Itoa(a.ch.srv.MaxPostSize())
respCfg["UpgradedFromTE"] = strconv.FormatBool(s.isUpgradedFromTE()) respCfg["UpgradedFromTE"] = strconv.FormatBool(a.ch.srv.isUpgradedFromTE())
respCfg["InstallationDate"] = "" respCfg["InstallationDate"] = ""
if installationDate, err := s.getSystemInstallDate(); err == nil { if installationDate, err := a.ch.srv.getSystemInstallDate(); err == nil {
respCfg["InstallationDate"] = strconv.FormatInt(installationDate, 10) respCfg["InstallationDate"] = strconv.FormatInt(installationDate, 10)
} }
return respCfg return respCfg
} }
// ClientConfigWithComputed gets the configuration in a format suitable for sending to the client.
func (a *App) ClientConfigWithComputed() map[string]string {
return a.Srv().ClientConfigWithComputed()
}
// LimitedClientConfigWithComputed gets the configuration in a format suitable for sending to the client. // LimitedClientConfigWithComputed gets the configuration in a format suitable for sending to the client.
func (a *App) LimitedClientConfigWithComputed() map[string]string { func (a *App) LimitedClientConfigWithComputed() map[string]string {
respCfg := map[string]string{} respCfg := map[string]string{}

Просмотреть файл

@@ -150,11 +150,6 @@ type Server struct {
pluginCommands []*PluginCommand pluginCommands []*PluginCommand
pluginCommandsLock sync.RWMutex pluginCommandsLock sync.RWMutex
asymmetricSigningKey atomic.Value
clientConfig atomic.Value
clientConfigHash atomic.Value
limitedClientConfig atomic.Value
telemetryService *telemetry.TelemetryService telemetryService *telemetry.TelemetryService
userService *users.UserService userService *users.UserService
teamService *teams.TeamService teamService *teams.TeamService
@@ -447,17 +442,19 @@ func NewServer(options ...Option) (*Server, error) {
} }
s.configListenerId = s.AddConfigListener(func(_, _ *model.Config) { s.configListenerId = s.AddConfigListener(func(_, _ *model.Config) {
s.configOrLicenseListener() ch := s.Channels()
ch.regenerateClientConfig()
message := model.NewWebSocketEvent(model.WebsocketEventConfigChanged, "", "", "", nil) message := model.NewWebSocketEvent(model.WebsocketEventConfigChanged, "", "", "", nil)
message.Add("config", s.ClientConfigWithComputed()) appInstance := New(ServerConnector(ch))
message.Add("config", appInstance.ClientConfigWithComputed())
s.Go(func() { s.Go(func() {
s.Publish(message) s.Publish(message)
}) })
}) })
s.licenseListenerId = s.AddLicenseListener(func(oldLicense, newLicense *model.License) { s.licenseListenerId = s.AddLicenseListener(func(oldLicense, newLicense *model.License) {
s.configOrLicenseListener() s.Channels().regenerateClientConfig()
message := model.NewWebSocketEvent(model.WebsocketEventLicenseChanged, "", "", "", nil) message := model.NewWebSocketEvent(model.WebsocketEventLicenseChanged, "", "", "", nil)
message.Add("license", s.GetSanitizedClientLicense()) message.Add("license", s.GetSanitizedClientLicense())
@@ -503,10 +500,6 @@ func NewServer(options ...Option) (*Server, error) {
s.Cluster.StartInterNodeCommunication() s.Cluster.StartInterNodeCommunication()
} }
if err = s.ensureAsymmetricSigningKey(); err != nil {
return nil, errors.Wrapf(err, "unable to ensure asymmetric signing key")
}
if err = s.ensurePostActionCookieSecret(); err != nil { if err = s.ensurePostActionCookieSecret(); err != nil {
return nil, errors.Wrapf(err, "unable to ensure PostAction cookie secret") return nil, errors.Wrapf(err, "unable to ensure PostAction cookie secret")
} }
@@ -519,8 +512,6 @@ func NewServer(options ...Option) (*Server, error) {
return nil, errors.Wrapf(err, "unable to ensure first run timestamp") return nil, errors.Wrapf(err, "unable to ensure first run timestamp")
} }
s.regenerateClientConfig()
subpath, err := utils.GetSubpathFromConfig(s.Config()) subpath, err := utils.GetSubpathFromConfig(s.Config())
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to parse SiteURL subpath") return nil, errors.Wrap(err, "failed to parse SiteURL subpath")
@@ -1914,12 +1905,8 @@ func (s *Server) ClusterHealthScore() int {
return s.Cluster.HealthScore() return s.Cluster.HealthScore()
} }
func (s *Server) configOrLicenseListener() { func (ch *Channels) ClientConfigHash() string {
s.regenerateClientConfig() return ch.clientConfigHash.Load().(string)
}
func (s *Server) ClientConfigHash() string {
return s.clientConfigHash.Load().(string)
} }
func (s *Server) initJobs() { func (s *Server) initJobs() {

Просмотреть файл

@@ -4,8 +4,6 @@
package configservice package configservice
import ( import (
"crypto/ecdsa"
"github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/mattermost-server/v6/model"
) )
@@ -14,5 +12,4 @@ type ConfigService interface {
Config() *model.Config Config() *model.Config
AddConfigListener(func(old, current *model.Config)) string AddConfigListener(func(old, current *model.Config)) string
RemoveConfigListener(string) RemoveConfigListener(string)
AsymmetricSigningKey() *ecdsa.PrivateKey
} }