diff --git a/api4/cloud.go b/api4/cloud.go index a0d3a9b257..6967a79936 100644 --- a/api4/cloud.go +++ b/api4/cloud.go @@ -755,7 +755,12 @@ func handleCWSWebhook(c *Context, w http.ResponseWriter, r *http.Request) { } func handleCheckCWSConnection(c *Context, w http.ResponseWriter, r *http.Request) { - if err := c.App.Cloud().CheckCWSConnection(c.AppContext.Session().UserId); err != nil { + cloud := c.App.Cloud() + if cloud == nil { + c.Err = model.NewAppError("Api4.handleCWSHealthCheck", "api.server.cws.needs_enterprise_edition", nil, "", http.StatusBadRequest) + return + } + if err := cloud.CheckCWSConnection(c.AppContext.Session().UserId); err != nil { c.Err = model.NewAppError("Api4.handleCWSHealthCheck", "api.server.cws.health_check.app_error", nil, "CWS Server is not available.", http.StatusInternalServerError) return } diff --git a/api4/hosted_customer.go b/api4/hosted_customer.go index 9c76b33efc..8203bdedea 100644 --- a/api4/hosted_customer.go +++ b/api4/hosted_customer.go @@ -36,6 +36,12 @@ func (api *API) InitHostedCustomer() { } func ensureSelfHostedAdmin(c *Context, where string) { + cloud := c.App.Cloud() + if cloud == nil { + c.Err = model.NewAppError(where, "api.server.cws.needs_enterprise_edition", nil, "", http.StatusBadRequest) + return + } + license := c.App.Channels().License() if license.IsCloud() { diff --git a/api4/hosted_customer_test.go b/api4/hosted_customer_test.go index dd895c5675..1a072e04db 100644 --- a/api4/hosted_customer_test.go +++ b/api4/hosted_customer_test.go @@ -22,6 +22,13 @@ func TestSelfHostedBootstrap(t *testing.T) { t.Run("feature flag off returns not implemented", func(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() + cloud := mocks.CloudInterface{} + + cloudImpl := th.App.Srv().Cloud + defer func() { + th.App.Srv().Cloud = cloudImpl + }() + th.App.Srv().Cloud = &cloud th.Client.Login(th.SystemAdminUser.Email, th.SystemAdminUser.Password) @@ -39,6 +46,13 @@ func TestSelfHostedBootstrap(t *testing.T) { t.Run("cloud instances not allowed to bootstrap self-hosted signup", func(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() + cloud := mocks.CloudInterface{} + + cloudImpl := th.App.Srv().Cloud + defer func() { + th.App.Srv().Cloud = cloudImpl + }() + th.App.Srv().Cloud = &cloud th.Client.Login(th.SystemAdminUser.Email, th.SystemAdminUser.Password) @@ -57,6 +71,13 @@ func TestSelfHostedBootstrap(t *testing.T) { t.Run("non-admins not allowed to bootstrap self-hosted signup", func(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() + cloud := mocks.CloudInterface{} + + cloudImpl := th.App.Srv().Cloud + defer func() { + th.App.Srv().Cloud = cloudImpl + }() + th.App.Srv().Cloud = &cloud th.Client.Login(th.BasicUser.Email, th.BasicUser.Password) @@ -97,4 +118,27 @@ func TestSelfHostedBootstrap(t *testing.T) { require.NoError(t, err) require.Equal(t, "START", response.Progress) }) + + t.Run("team edition returns bad request instead of panicking", func(t *testing.T) { + th := Setup(t).InitBasic() + defer th.TearDown() + + cloudImpl := th.App.Srv().Cloud + defer func() { + th.App.Srv().Cloud = cloudImpl + }() + th.App.Srv().Cloud = nil + + th.Client.Login(th.SystemAdminUser.Email, th.SystemAdminUser.Password) + + os.Setenv("MM_SERVICESETTINGS_SELFHOSTEDFIRSTTIMEPURCHASE", "true") + defer os.Unsetenv("MM_SERVICESETTINGS_SELFHOSTEDFIRSTTIMEPURCHASE") + th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.SelfHostedPurchase = &valTrue }) + th.App.ReloadConfig() + + _, r, err := th.Client.BootstrapSelfHostedSignup(model.BootstrapSelfHostedSignupRequest{Email: th.SystemAdminUser.Email}) + + require.Equal(t, http.StatusBadRequest, r.StatusCode) + require.Error(t, err) + }) } diff --git a/i18n/en.json b/i18n/en.json index d19140cbe4..e8e07b9b1c 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -2579,6 +2579,10 @@ "id": "api.server.cws.health_check.app_error", "translation": "CWS Server is not available." }, + { + "id": "api.server.cws.needs_enterprise_edition", + "translation": "Service only available in Mattermost Enterprise edition" + }, { "id": "api.server.hosted_signup_unavailable.error", "translation": "Portal unavailable for self-hosted signup."