Skip to content

Commit

Permalink
Revert "MM-53879: Fix recursive loading of license (#24200)" (#24498) (
Browse files Browse the repository at this point in the history
…#24503)

Automatic Merge
  • Loading branch information
agnivade committed Sep 7, 2023
1 parent 9366748 commit 9d2d035
Show file tree
Hide file tree
Showing 15 changed files with 165 additions and 31 deletions.
6 changes: 5 additions & 1 deletion server/channels/api4/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,11 @@ func invalidateCaches(c *Context, w http.ResponseWriter, r *http.Request) {
return
}

c.App.Srv().InvalidateAllCaches()
appErr := c.App.Srv().InvalidateAllCaches()
if appErr != nil {
c.Err = appErr
return
}

auditRec.Success()

Expand Down
3 changes: 2 additions & 1 deletion server/channels/api4/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3902,7 +3902,8 @@ func TestLoginWithLag(t *testing.T) {
_, _, err := th.Client.Login(context.Background(), th.BasicUser.Email, th.BasicUser.Password)
require.NoError(t, err)

th.App.Srv().InvalidateAllCaches()
appErr = th.App.Srv().InvalidateAllCaches()
require.Nil(t, appErr)

session, appErr := th.App.GetSession(th.Client.AuthToken)
require.Nil(t, appErr)
Expand Down
4 changes: 2 additions & 2 deletions server/channels/app/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ func (a *App) GetClusterStatus() []*model.ClusterInfo {
return infos
}

func (s *Server) InvalidateAllCaches() {
s.platform.InvalidateAllCaches()
func (s *Server) InvalidateAllCaches() *model.AppError {
return s.platform.InvalidateAllCaches()
}

func (s *Server) InvalidateAllCachesSkipSend() {
Expand Down
4 changes: 4 additions & 0 deletions server/channels/app/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ func (s *Server) License() *model.License {
return s.platform.License()
}

func (s *Server) LoadLicense() {
s.platform.LoadLicense()
}

func (s *Server) SaveLicense(licenseBytes []byte) (*model.License, *model.AppError) {
return s.platform.SaveLicense(licenseBytes)
}
Expand Down
109 changes: 109 additions & 0 deletions server/channels/app/license_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

package app

import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/mattermost/mattermost/server/public/model"
)

func TestLoadLicense(t *testing.T) {
th := Setup(t)
defer th.TearDown()

th.App.Srv().LoadLicense()
require.Nil(t, th.App.Srv().License(), "shouldn't have a valid license")
}

func TestSaveLicense(t *testing.T) {
th := Setup(t)
defer th.TearDown()

b1 := []byte("junk")

_, err := th.App.Srv().SaveLicense(b1)
require.NotNil(t, err, "shouldn't have saved license")
}

func TestRemoveLicense(t *testing.T) {
th := Setup(t)
defer th.TearDown()

err := th.App.Srv().RemoveLicense()
require.Nil(t, err, "should have removed license")
}

func TestSetLicense(t *testing.T) {
th := Setup(t)
defer th.TearDown()

l1 := &model.License{}
l1.Features = &model.Features{}
l1.Customer = &model.Customer{}
l1.StartsAt = model.GetMillis() - 1000
l1.ExpiresAt = model.GetMillis() + 100000
ok := th.App.Srv().SetLicense(l1)
require.True(t, ok, "license should have worked")

l3 := &model.License{}
l3.Features = &model.Features{}
l3.Customer = &model.Customer{}
l3.StartsAt = model.GetMillis() + 10000
l3.ExpiresAt = model.GetMillis() + 100000
ok = th.App.Srv().SetLicense(l3)
require.True(t, ok, "license should have passed")
}

func TestGetSanitizedClientLicense(t *testing.T) {
th := Setup(t)
defer th.TearDown()

setLicense(th, nil)

m := th.App.Srv().GetSanitizedClientLicense()

_, ok := m["Name"]
assert.False(t, ok)
_, ok = m["SkuName"]
assert.False(t, ok)
}

func TestGenerateRenewalToken(t *testing.T) {
th := Setup(t)
defer th.TearDown()

t.Run("renewal token generated correctly", func(t *testing.T) {
setLicense(th, nil)
token, appErr := th.App.Srv().GenerateRenewalToken(JWTDefaultTokenExpiration)
require.Nil(t, appErr)
require.NotEmpty(t, token)
})

t.Run("return error if there is no active license", func(t *testing.T) {
th.App.Srv().SetLicense(nil)
_, appErr := th.App.Srv().GenerateRenewalToken(JWTDefaultTokenExpiration)
require.NotNil(t, appErr)
})
}

func setLicense(th *TestHelper, customer *model.Customer) {
l1 := &model.License{}
l1.Features = &model.Features{}
if customer != nil {
l1.Customer = customer
} else {
l1.Customer = &model.Customer{}
l1.Customer.Name = "TestName"
l1.Customer.Email = "test@example.com"
}
l1.SkuName = "SKU NAME"
l1.SkuShortName = "SKU SHORT NAME"
l1.StartsAt = model.GetMillis() - 1000
l1.ExpiresAt = model.GetMillis() + 100000
th.App.Srv().SetLicense(l1)
}
3 changes: 2 additions & 1 deletion server/channels/app/notification_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ func TestSendNotifications(t *testing.T) {

_, appErr = th.App.UpdateActive(th.Context, th.BasicUser2, false)
require.Nil(t, appErr)
th.App.Srv().InvalidateAllCaches()
appErr = th.App.Srv().InvalidateAllCaches()
require.Nil(t, appErr)

post3, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
UserId: th.BasicUser.Id,
Expand Down
4 changes: 3 additions & 1 deletion server/channels/app/oauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,9 @@ func (a *App) DeleteOAuthApp(appID string) *model.AppError {
return model.NewAppError("DeleteOAuthApp", "app.oauth.delete_app.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
}

a.Srv().InvalidateAllCaches()
if err := a.Srv().InvalidateAllCaches(); err != nil {
mlog.Warn("error in invalidating cache", mlog.Err(err))
}

return nil
}
Expand Down
24 changes: 4 additions & 20 deletions server/channels/app/platform/cluster_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ func (ps *PlatformService) RegisterClusterHandlers() {
ps.clusterIFace.RegisterClusterMessageHandler(model.ClusterEventPublish, ps.ClusterPublishHandler)
ps.clusterIFace.RegisterClusterMessageHandler(model.ClusterEventUpdateStatus, ps.ClusterUpdateStatusHandler)
ps.clusterIFace.RegisterClusterMessageHandler(model.ClusterEventInvalidateAllCaches, ps.ClusterInvalidateAllCachesHandler)
ps.clusterIFace.RegisterClusterMessageHandler(model.ClusterEventLoadLicense, ps.LoadLicenseClusterHandler)
ps.clusterIFace.RegisterClusterMessageHandler(model.ClusterEventInvalidateCacheForChannelMembersNotifyProps, ps.clusterInvalidateCacheForChannelMembersNotifyPropHandler)
ps.clusterIFace.RegisterClusterMessageHandler(model.ClusterEventInvalidateCacheForChannelByName, ps.clusterInvalidateCacheForChannelByNameHandler)
ps.clusterIFace.RegisterClusterMessageHandler(model.ClusterEventInvalidateCacheForUser, ps.clusterInvalidateCacheForUserHandler)
Expand Down Expand Up @@ -156,27 +155,10 @@ func (ps *PlatformService) InvalidateAllCachesSkipSend() {
ps.Store.Webhook().ClearCaches()

linkCache.Purge()
ps.LoadLicense()
}

func (ps *PlatformService) LoadLicenseClusterHandler(_ *model.ClusterMessage) {
ps.loadLicense()
}

func (ps *PlatformService) TriggerLoadLicense() {
ps.loadLicense()

if ps.clusterIFace != nil {
msg := &model.ClusterMessage{
Event: model.ClusterEventLoadLicense,
SendType: model.ClusterSendReliable,
WaitForAllToSend: true,
}

ps.clusterIFace.SendClusterMessage(msg)
}
}

func (ps *PlatformService) InvalidateAllCaches() {
func (ps *PlatformService) InvalidateAllCaches() *model.AppError {
debug.FreeOSMemory()
ps.InvalidateAllCachesSkipSend()

Expand All @@ -190,4 +172,6 @@ func (ps *PlatformService) InvalidateAllCaches() {

ps.clusterIFace.SendClusterMessage(msg)
}

return nil
}
5 changes: 4 additions & 1 deletion server/channels/app/platform/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (ps *PlatformService) License() *model.License {
return ps.licenseValue.Load()
}

func (ps *PlatformService) loadLicense() {
func (ps *PlatformService) LoadLicense() {
// ENV var overrides all other sources of license.
licenseStr := os.Getenv(LicenseEnv)
if licenseStr != "" {
Expand Down Expand Up @@ -326,6 +326,9 @@ func (ps *PlatformService) RequestTrialLicense(trialRequest *model.TrialLicenseR
return err
}

ps.ReloadConfig()
ps.InvalidateAllCaches()

return nil
}

Expand Down
8 changes: 8 additions & 0 deletions server/channels/app/platform/license_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ import (
"github.com/mattermost/mattermost/server/public/model"
)

func TestLoadLicense(t *testing.T) {
th := Setup(t)
defer th.TearDown()

th.Service.LoadLicense()
require.Nil(t, th.Service.License(), "shouldn't have a valid license")
}

func TestSaveLicense(t *testing.T) {
th := Setup(t)
defer th.TearDown()
Expand Down
10 changes: 7 additions & 3 deletions server/channels/app/platform/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ func New(sc ServiceConfig, options ...Option) (*PlatformService, error) {

// Step 7: Init License
if model.BuildEnterpriseReady == "true" {
ps.TriggerLoadLicense()
ps.LoadLicense()
}

// Step 8: Init Metrics Server depends on step 6 (store) and 7 (license)
Expand Down Expand Up @@ -348,7 +348,9 @@ func (ps *PlatformService) Start() error {
message := model.NewWebSocketEvent(model.WebsocketEventConfigChanged, "", "", "", nil, "")

message.Add("config", ps.ClientConfigWithComputed())
ps.Publish(message)
ps.Go(func() {
ps.Publish(message)
})

if err := ps.ReconfigureLogger(); err != nil {
mlog.Error("Error re-configuring logging after config change", mlog.Err(err))
Expand All @@ -361,7 +363,9 @@ func (ps *PlatformService) Start() error {

message := model.NewWebSocketEvent(model.WebsocketEventLicenseChanged, "", "", "", nil, "")
message.Add("license", ps.GetSanitizedClientLicense())
ps.Publish(message)
ps.Go(func() {
ps.Publish(message)
})

})
return nil
Expand Down
9 changes: 9 additions & 0 deletions server/channels/app/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ func NewServer(options ...Option) (*Server, error) {
// Depends on step 1 (s.Platform must be non-nil)
s.initEnterprise()

// Needed to run before loading license.
s.userService, err = users.New(users.ServiceConfig{
UserStore: s.Store().User(),
SessionStore: s.Store().Session(),
Expand All @@ -220,6 +221,11 @@ func NewServer(options ...Option) (*Server, error) {
return nil, errors.Wrapf(err, "unable to create users service")
}

if model.BuildEnterpriseReady == "true" {
// Dependent on user service
s.LoadLicense()
}

s.licenseWrapper = &licenseWrapper{
srv: s,
}
Expand Down Expand Up @@ -1376,6 +1382,8 @@ func (s *Server) sendLicenseUpForRenewalEmail(users map[string]*model.User, lice
}

func (s *Server) doLicenseExpirationCheck() {
s.LoadLicense()

// This takes care of a rare edge case reported here https://mattermost.atlassian.net/browse/MM-40962
// To reproduce that case locally, attach a license to a server that was started with enterprise enabled
// Then restart using BUILD_ENTERPRISE=false make restart-server to enter Team Edition
Expand All @@ -1385,6 +1393,7 @@ func (s *Server) doLicenseExpirationCheck() {
}

license := s.License()

if license == nil {
mlog.Debug("License cannot be found.")
return
Expand Down
4 changes: 4 additions & 0 deletions server/cmd/mattermost/commands/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ func initDBCommandContext(configDSN string, readOnlyConfigStore bool, options ..

a := app.New(app.ServerConnector(s.Channels()))

if model.BuildEnterpriseReady == "true" {
a.Srv().LoadLicense()
}

return a, nil
}

Expand Down
2 changes: 2 additions & 0 deletions server/cmd/mattermost/commands/jobserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ func jobserverCmdF(command *cobra.Command, args []string) error {
}
defer a.Srv().Shutdown()

a.Srv().LoadLicense()

// Run jobs
mlog.Info("Starting Mattermost job server")
defer mlog.Info("Stopped Mattermost job server")
Expand Down
1 change: 0 additions & 1 deletion server/public/model/cluster_message.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ const (
ClusterEventPublish ClusterEvent = "publish"
ClusterEventUpdateStatus ClusterEvent = "update_status"
ClusterEventInvalidateAllCaches ClusterEvent = "inv_all_caches"
ClusterEventLoadLicense ClusterEvent = "load_license"
ClusterEventInvalidateCacheForReactions ClusterEvent = "inv_reactions"
ClusterEventInvalidateCacheForChannelMembersNotifyProps ClusterEvent = "inv_channel_members_notify_props"
ClusterEventInvalidateCacheForChannelByName ClusterEvent = "inv_channel_name"
Expand Down

0 comments on commit 9d2d035

Please sign in to comment.