From d43c06ea75ab477b83a3a868645a7cb6d8290c25 Mon Sep 17 00:00:00 2001 From: Nathaniel Allred Date: Fri, 17 Jun 2022 11:13:22 -0500 Subject: [PATCH] remove freemium feature flag (#20491) --- api4/cloud.go | 16 --------- api4/cloud_test.go | 80 ++---------------------------------------- api4/config_test.go | 6 ---- api4/team.go | 8 ++--- api4/team_test.go | 14 -------- app/app_iface.go | 2 +- app/integrations.go | 4 --- app/plugin_test.go | 12 ------- app/usage.go | 6 +--- i18n/en.json | 4 --- model/feature_flags.go | 3 -- 11 files changed, 9 insertions(+), 146 deletions(-) diff --git a/api4/cloud.go b/api4/cloud.go index 3660282960..38eb008886 100644 --- a/api4/cloud.go +++ b/api4/cloud.go @@ -138,11 +138,6 @@ func requestCloudTrial(c *Context, w http.ResponseWriter, r *http.Request) { return } - if !c.App.Config().FeatureFlags.CloudFree { - c.Err = model.NewAppError("Api4.requestCloudTrial", "api.cloud.cloud_free_feature_flag_off_error", nil, "", http.StatusInternalServerError) - return - } - currentSubscription, appErr := c.App.Cloud().GetSubscription(c.AppContext.Session().UserId) if appErr != nil { c.Err = model.NewAppError("Api4.requestCloudTrial", "api.cloud.app_error", nil, appErr.Error(), http.StatusInternalServerError) @@ -255,17 +250,6 @@ func getCloudLimits(c *Context, w http.ResponseWriter, r *http.Request) { return } - if !c.App.Config().FeatureFlags.CloudFree { - emptyLimits := &model.ProductLimits{} - json, err := json.Marshal(emptyLimits) - if err != nil { - c.Err = model.NewAppError("Api4.getCloudLimits", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) - } - - w.Write(json) - return - } - limits, err := c.App.Cloud().GetCloudLimits(c.AppContext.Session().UserId) if err != nil { c.Err = model.NewAppError("Api4.getCloudLimits", "api.cloud.request_error", nil, err.Error(), http.StatusInternalServerError) diff --git a/api4/cloud_test.go b/api4/cloud_test.go index e360174872..7d0a7a0d48 100644 --- a/api4/cloud_test.go +++ b/api4/cloud_test.go @@ -7,7 +7,6 @@ import ( "errors" "net/http" "net/http/httptest" - "os" "testing" "github.com/stretchr/testify/mock" @@ -18,31 +17,10 @@ import ( ) func Test_getCloudLimits(t *testing.T) { - t.Run("feature flag off returns empty limits", func(t *testing.T) { - th := Setup(t).InitBasic() - defer th.TearDown() - - os.Setenv("MM_FEATUREFLAGS_CLOUDFREE", "false") - defer os.Unsetenv("MM_FEATUREFLAGS_CLOUDFREE") - th.App.ReloadConfig() - - th.App.Srv().SetLicense(model.NewTestLicense("cloud")) - th.Client.Login(th.BasicUser.Email, th.BasicUser.Password) - - limits, r, err := th.Client.GetProductLimits() - require.NoError(t, err) - require.Equal(t, limits, &model.ProductLimits{}) - require.Equal(t, http.StatusOK, r.StatusCode, "Expected 200 OK") - }) - t.Run("no license returns not implemented", func(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() - os.Setenv("MM_FEATUREFLAGS_CLOUDFREE", "true") - defer os.Unsetenv("MM_FEATUREFLAGS_CLOUDFREE") - th.App.ReloadConfig() - th.App.Srv().RemoveLicense() th.Client.Login(th.BasicUser.Email, th.BasicUser.Password) @@ -57,10 +35,6 @@ func Test_getCloudLimits(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() - os.Setenv("MM_FEATUREFLAGS_CLOUDFREE", "true") - defer os.Unsetenv("MM_FEATUREFLAGS_CLOUDFREE") - th.App.ReloadConfig() - th.App.Srv().SetLicense(model.NewTestLicense()) th.Client.Login(th.BasicUser.Email, th.BasicUser.Password) @@ -75,9 +49,6 @@ func Test_getCloudLimits(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() - os.Setenv("MM_FEATUREFLAGS_CLOUDFREE", "true") - defer os.Unsetenv("MM_FEATUREFLAGS_CLOUDFREE") - th.App.ReloadConfig() th.App.Srv().SetLicense(model.NewTestLicense("cloud")) cloud := &mocks.CloudInterface{} @@ -109,13 +80,10 @@ func Test_getCloudLimits(t *testing.T) { require.Equal(t, http.StatusUnauthorized, r.StatusCode, "Expected 401 Unauthorized") }) - t.Run("good request with cloud server and feature flag returns response", func(t *testing.T) { + t.Run("good request with cloud server", func(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() - os.Setenv("MM_FEATUREFLAGS_CLOUDFREE", "true") - defer os.Unsetenv("MM_FEATUREFLAGS_CLOUDFREE") - th.App.ReloadConfig() th.App.Srv().SetLicense(model.NewTestLicense("cloud")) cloud := &mocks.CloudInterface{} @@ -163,10 +131,6 @@ func Test_requestTrial(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() - os.Setenv("MM_FEATUREFLAGS_CLOUDFREE", "true") - defer os.Unsetenv("MM_FEATUREFLAGS_CLOUDFREE") - th.App.ReloadConfig() - th.Client.Login(th.BasicUser.Email, th.BasicUser.Password) th.App.Srv().SetLicense(model.NewTestLicense("cloud")) @@ -188,44 +152,10 @@ func Test_requestTrial(t *testing.T) { require.Equal(t, http.StatusForbidden, r.StatusCode, "403 Forbidden") }) - t.Run("cloudFree feature flag FALSE and Admin user are UNABLE to request the trial", func(t *testing.T) { + t.Run("ADMIN user are ABLE to request the trial", func(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() - os.Setenv("MM_FEATUREFLAGS_CLOUDFREE", "false") - defer os.Unsetenv("MM_FEATUREFLAGS_CLOUDFREE") - th.App.ReloadConfig() - - th.Client.Login(th.BasicUser.Email, th.BasicUser.Password) - - th.App.Srv().SetLicense(model.NewTestLicense("cloud")) - - cloud := mocks.CloudInterface{} - - cloud.Mock.On("GetSubscription", mock.Anything).Return(subscription, nil) - cloud.Mock.On("RequestCloudTrial", mock.Anything, mock.Anything, "").Return(subscription, nil) - - cloudImpl := th.App.Srv().Cloud - defer func() { - th.App.Srv().Cloud = cloudImpl - }() - th.App.Srv().Cloud = &cloud - - subscriptionChanged, r, err := th.SystemAdminClient.RequestCloudTrial(&newValidBusinessEmail) - - require.Error(t, err) - require.Nil(t, subscriptionChanged) - require.Equal(t, http.StatusInternalServerError, r.StatusCode, "Expected 500 Internal Server Error") - }) - - t.Run("cloudFree feature flag TRUE and ADMIN user are ABLE to request the trial", func(t *testing.T) { - th := Setup(t).InitBasic() - defer th.TearDown() - - os.Setenv("MM_FEATUREFLAGS_CLOUDFREE", "true") - defer os.Unsetenv("MM_FEATUREFLAGS_CLOUDFREE") - th.App.ReloadConfig() - th.Client.Login(th.BasicUser.Email, th.BasicUser.Password) th.App.Srv().SetLicense(model.NewTestLicense("cloud")) @@ -248,17 +178,13 @@ func Test_requestTrial(t *testing.T) { require.Equal(t, http.StatusOK, r.StatusCode, "Status OK") }) - t.Run("cloudFree feature flag TRUE and ADMIN user are ABLE to request the trial with valid business email", func(t *testing.T) { + t.Run("ADMIN user are ABLE to request the trial with valid business email", func(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() // patch the customer with the additional contact updated with the valid business email newValidBusinessEmail.Email = *model.NewString("valid.email@mattermost.com") - os.Setenv("MM_FEATUREFLAGS_CLOUDFREE", "true") - defer os.Unsetenv("MM_FEATUREFLAGS_CLOUDFREE") - th.App.ReloadConfig() - th.Client.Login(th.BasicUser.Email, th.BasicUser.Password) th.App.Srv().SetLicense(model.NewTestLicense("cloud")) diff --git a/api4/config_test.go b/api4/config_test.go index 629ccc690b..ff3054cc41 100644 --- a/api4/config_test.go +++ b/api4/config_test.go @@ -252,9 +252,6 @@ func TestUpdateConfig(t *testing.T) { t.Run("Should not be able to save config if the new config exceeds Freemium limits", func(t *testing.T) { th.App.Srv().SetLicense(model.NewTestLicense("cloud")) defer th.App.Srv().RemoveLicense() - os.Setenv("MM_FEATUREFLAGS_CLOUDFREE", "true") - defer os.Unsetenv("MM_FEATUREFLAGS_CLOUDFREE") - th.App.ReloadConfig() cloud := &mocks.CloudInterface{} cloudImpl := th.App.Srv().Cloud @@ -857,9 +854,6 @@ func TestPatchConfig(t *testing.T) { t.Run("Should not be able to save config if the new config exceeds Freemium limits", func(t *testing.T) { th.App.Srv().SetLicense(model.NewTestLicense("cloud")) defer th.App.Srv().RemoveLicense() - os.Setenv("MM_FEATUREFLAGS_CLOUDFREE", "true") - defer os.Unsetenv("MM_FEATUREFLAGS_CLOUDFREE") - th.App.ReloadConfig() cloud := &mocks.CloudInterface{} cloudImpl := th.App.Srv().Cloud diff --git a/api4/team.go b/api4/team.go index 8b3da9b822..afb7e72999 100644 --- a/api4/team.go +++ b/api4/team.go @@ -95,8 +95,8 @@ func createTeam(c *Context, w http.ResponseWriter, r *http.Request) { return } - // Freemium enabled, on a cloud license. We must check limits before allowing to create - if c.App.Config().FeatureFlags != nil && c.App.Config().FeatureFlags.CloudFree && (c.App.Channels().License() != nil && c.App.Channels().License().Features != nil && *c.App.Channels().License().Features.Cloud) { + // On a cloud license, we must check limits before allowing to create + if c.App.Channels().License() != nil && c.App.Channels().License().Features != nil && *c.App.Channels().License().Features.Cloud { limits, err := c.App.Cloud().GetCloudLimits(c.AppContext.Session().UserId) if err != nil { c.Err = model.NewAppError("Api4.createTeam", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) @@ -281,8 +281,8 @@ func restoreTeam(c *Context, w http.ResponseWriter, r *http.Request) { c.SetPermissionError(model.PermissionManageTeam) return } - // Freemium enabled, on a cloud license. We must check limits before allowing to restore - if c.App.Config().FeatureFlags != nil && c.App.Config().FeatureFlags.CloudFree && (c.App.Channels().License() != nil && c.App.Channels().License().Features != nil && *c.App.Channels().License().Features.Cloud) { + // On a cloud license, we must check limits before allowing to restore + if c.App.Channels().License() != nil && c.App.Channels().License().Features != nil && *c.App.Channels().License().Features.Cloud { limits, err := c.App.Cloud().GetCloudLimits(c.AppContext.Session().UserId) if err != nil { c.Err = model.NewAppError("Api4.restoreTeam", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) diff --git a/api4/team_test.go b/api4/team_test.go index 079c5fbc06..e063f2162b 100644 --- a/api4/team_test.go +++ b/api4/team_test.go @@ -9,7 +9,6 @@ import ( "encoding/json" "fmt" "net/http" - "os" "strconv" "strings" "testing" @@ -95,9 +94,6 @@ func TestCreateTeam(t *testing.T) { }) t.Run("cloud limit reached returns 400", func(t *testing.T) { - os.Setenv("MM_FEATUREFLAGS_CLOUDFREE", "true") - defer os.Unsetenv("MM_FEATUREFLAGS_CLOUDFREE") - th.App.ReloadConfig() th.App.Srv().SetLicense(model.NewTestLicense("cloud")) cloud := &mocks.CloudInterface{} @@ -119,10 +115,6 @@ func TestCreateTeam(t *testing.T) { }) t.Run("cloud below limit returns 200", func(t *testing.T) { - os.Setenv("MM_FEATUREFLAGS_CLOUDFREE", "true") - defer os.Unsetenv("MM_FEATUREFLAGS_CLOUDFREE") - th.App.ReloadConfig() - defer th.App.ReloadConfig() th.App.Srv().SetLicense(model.NewTestLicense("cloud")) cloud := &mocks.CloudInterface{} @@ -636,9 +628,6 @@ func TestRestoreTeam(t *testing.T) { t.Run("cloud limit reached returns 400", func(t *testing.T) { // Create an archived team to be restored later team := createTeam(t, true, model.TeamOpen) - os.Setenv("MM_FEATUREFLAGS_CLOUDFREE", "true") - defer os.Unsetenv("MM_FEATUREFLAGS_CLOUDFREE") - th.App.ReloadConfig() th.App.Srv().SetLicense(model.NewTestLicense("cloud")) cloud := &mocks.CloudInterface{} @@ -660,9 +649,6 @@ func TestRestoreTeam(t *testing.T) { }) t.Run("cloud below limit returns 200", func(t *testing.T) { - os.Setenv("MM_FEATUREFLAGS_CLOUDFREE", "true") - defer os.Unsetenv("MM_FEATUREFLAGS_CLOUDFREE") - th.App.ReloadConfig() th.App.Srv().SetLicense(model.NewTestLicense("cloud")) cloud := &mocks.CloudInterface{} diff --git a/app/app_iface.go b/app/app_iface.go index ac8461ea26..4355db7376 100644 --- a/app/app_iface.go +++ b/app/app_iface.go @@ -68,7 +68,7 @@ type AppIface interface { // If includeRemovedMembers is true, then channel members who left or were removed from the channel will // be included; otherwise, they will be excluded. ChannelMembersToAdd(since int64, channelID *string, includeRemovedMembers bool) ([]*model.UserChannelIDPair, *model.AppError) - // CheckFreemiumLimitsForConfigSave returns an error if the configuration being saved violates the Cloud Freemium limits + // CheckFreemiumLimitsForConfigSave returns an error if the configuration being saved violates a cloud plan's limits CheckFreemiumLimitsForConfigSave(oldConfig, newConfig *model.Config) *model.AppError // CheckProviderAttributes returns the empty string if the patch can be applied without // overriding attributes set by the user's login provider; otherwise, the name of the offending diff --git a/app/integrations.go b/app/integrations.go index 149bcefcc1..2c747e0b7f 100644 --- a/app/integrations.go +++ b/app/integrations.go @@ -70,10 +70,6 @@ func (ch *Channels) getInstalledIntegrations() ([]*model.InstalledIntegration, * } func (a *App) checkIfIntegrationsMeetFreemiumLimits(originalPluginIds []string) *model.AppError { - if !a.Config().FeatureFlags.CloudFree { - return nil - } - if a.License() == nil || !*a.License().Features.Cloud { return nil } diff --git a/app/plugin_test.go b/app/plugin_test.go index 0cba49671a..552d373a44 100644 --- a/app/plugin_test.go +++ b/app/plugin_test.go @@ -973,9 +973,6 @@ func TestEnablePluginWithCloudLimits(t *testing.T) { th := Setup(t) defer th.TearDown() - os.Setenv("MM_FEATUREFLAGS_CLOUDFREE", "true") - defer os.Unsetenv("MM_FEATUREFLAGS_CLOUDFREE") - th.App.ReloadConfig() th.App.Srv().SetLicense(model.NewTestLicense("cloud")) th.App.UpdateConfig(func(cfg *model.Config) { @@ -1033,15 +1030,6 @@ func TestEnablePluginWithCloudLimits(t *testing.T) { appErr = th.App.EnablePlugin("testplugin2") checkError(t, appErr) - os.Unsetenv("MM_FEATUREFLAGS_CLOUDFREE") - th.App.ReloadConfig() - appErr = th.App.EnablePlugin("testplugin2") - checkNoError(t, appErr) - os.Setenv("MM_FEATUREFLAGS_CLOUDFREE", "true") - th.App.ReloadConfig() - appErr = th.App.EnablePlugin("testplugin2") - checkError(t, appErr) - // Let enable succeed if a CWS error occurs cloud = &mocks.CloudInterface{} th.App.Srv().Cloud = cloud diff --git a/app/usage.go b/app/usage.go index 17cf74edad..761d398994 100644 --- a/app/usage.go +++ b/app/usage.go @@ -10,12 +10,8 @@ import ( "github.com/mattermost/mattermost-server/v6/utils" ) -// CheckFreemiumLimitsForConfigSave returns an error if the configuration being saved violates the Cloud Freemium limits +// CheckFreemiumLimitsForConfigSave returns an error if the configuration being saved violates a cloud plan's limits func (a *App) CheckFreemiumLimitsForConfigSave(oldConfig, newConfig *model.Config) *model.AppError { - if !a.Config().FeatureFlags.CloudFree { - return nil - } - appErr := a.checkIntegrationLimitsForConfigSave(oldConfig, newConfig) if appErr != nil { return appErr diff --git a/i18n/en.json b/i18n/en.json index f167d9bff5..04d1dbf921 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -467,10 +467,6 @@ "id": "api.cloud.app_error", "translation": "Internal error during cloud api request." }, - { - "id": "api.cloud.cloud_free_feature_flag_off_error", - "translation": "CloudFree feature flag is off." - }, { "id": "api.cloud.cws_webhook_event_missing_error", "translation": "Webhook event was not handled. Either it is missing or it is not valid." diff --git a/model/feature_flags.go b/model/feature_flags.go index 1f241f0107..81aeb2a8be 100644 --- a/model/feature_flags.go +++ b/model/feature_flags.go @@ -65,8 +65,6 @@ type FeatureFlags struct { InsightsEnabled bool - CloudFree bool - CommandPalette bool AdvancedTextEditor bool @@ -92,7 +90,6 @@ func (f *FeatureFlags) SetDefaults() { f.UseCaseOnboarding = true f.GraphQL = false f.InsightsEnabled = false - f.CloudFree = false f.CommandPalette = false f.AdvancedTextEditor = true f.CallsEnabled = true