Mm 47422 signup token (#21662)
* When service setting flag is on, self hosted workspaces can initiate process for self-serve sign up * Add hosted_customer api.
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
2455de99ff
Коммит
4f3f6e6496
@@ -140,6 +140,8 @@ type Routes struct {
|
||||
|
||||
Usage *mux.Router // 'api/v4/usage'
|
||||
|
||||
HostedCustomer *mux.Router // 'api/v4/hosted_customer'
|
||||
|
||||
Drafts *mux.Router // 'api/v4/drafts'
|
||||
}
|
||||
|
||||
@@ -267,6 +269,8 @@ func Init(srv *app.Server) (*API, error) {
|
||||
|
||||
api.BaseRoutes.Usage = api.BaseRoutes.APIRoot.PathPrefix("/usage").Subrouter()
|
||||
|
||||
api.BaseRoutes.HostedCustomer = api.BaseRoutes.APIRoot.PathPrefix("/hosted_customer").Subrouter()
|
||||
|
||||
api.BaseRoutes.Drafts = api.BaseRoutes.APIRoot.PathPrefix("/drafts").Subrouter()
|
||||
|
||||
api.InitUser()
|
||||
@@ -312,6 +316,7 @@ func Init(srv *app.Server) (*API, error) {
|
||||
api.InitExport()
|
||||
api.InitInsights()
|
||||
api.InitUsage()
|
||||
api.InitHostedCustomer()
|
||||
api.InitDrafts()
|
||||
if err := api.InitGraphQL(); err != nil {
|
||||
return nil, err
|
||||
|
||||
73
api4/hosted_customer.go
Обычный файл
73
api4/hosted_customer.go
Обычный файл
@@ -0,0 +1,73 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package api4
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/model"
|
||||
)
|
||||
|
||||
// APIs for self-hosted workspaces to communicate with the backing customer & payments system.
|
||||
// Endpoints for cloud installations should not go in this file.
|
||||
func (api *API) InitHostedCustomer() {
|
||||
|
||||
// POST /api/v4/hosted_customer/bootstrap
|
||||
api.BaseRoutes.HostedCustomer.Handle("/bootstrap", api.APISessionRequired(selfHostedBootstrap)).Methods("POST")
|
||||
}
|
||||
|
||||
func ensureSelfHostedAdmin(c *Context, where string) {
|
||||
license := c.App.Channels().License()
|
||||
|
||||
if license.IsCloud() {
|
||||
c.Err = model.NewAppError(where, "api.cloud.license_error", nil, "Cloud installations do not use this endpoint", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleWriteBilling) {
|
||||
c.SetPermissionError(model.PermissionSysconsoleWriteBilling)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func checkSelfHostedFirstTimePurchaseEnabled(c *Context) bool {
|
||||
config := c.App.Config()
|
||||
if config == nil {
|
||||
return false
|
||||
}
|
||||
enabled := config.ServiceSettings.SelfHostedFirstTimePurchase
|
||||
return enabled != nil && *enabled
|
||||
}
|
||||
|
||||
func selfHostedBootstrap(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
where := "Api4.selfHostedBootstrap"
|
||||
if !checkSelfHostedFirstTimePurchaseEnabled(c) {
|
||||
c.Err = model.NewAppError(where, "api.cloud.app_error", nil, "", http.StatusNotImplemented)
|
||||
return
|
||||
}
|
||||
ensureSelfHostedAdmin(c, where)
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
user, userErr := c.App.GetUser(c.AppContext.Session().UserId)
|
||||
if userErr != nil {
|
||||
c.Err = userErr
|
||||
return
|
||||
}
|
||||
|
||||
signupProgress, err := c.App.Cloud().BootstrapSelfHostedSignup(model.BootstrapSelfHostedSignupRequest{Email: user.Email})
|
||||
if err != nil {
|
||||
c.Err = model.NewAppError(where, "api.cloud.app_error", nil, "", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
json, err := json.Marshal(signupProgress)
|
||||
if err != nil {
|
||||
c.Err = model.NewAppError(where, "api.cloud.app_error", nil, "", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(json)
|
||||
}
|
||||
100
api4/hosted_customer_test.go
Обычный файл
100
api4/hosted_customer_test.go
Обычный файл
@@ -0,0 +1,100 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package api4
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/einterfaces/mocks"
|
||||
"github.com/mattermost/mattermost-server/v6/model"
|
||||
)
|
||||
|
||||
var valFalse = false
|
||||
var valTrue = true
|
||||
|
||||
func TestSelfHostedBootstrap(t *testing.T) {
|
||||
t.Run("feature flag off returns not implemented", func(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
th.Client.Login(th.SystemAdminUser.Email, th.SystemAdminUser.Password)
|
||||
|
||||
os.Setenv("MM_SERVICESETTINGS_SELFHOSTEDFIRSTTIMEPURCHASE", "false")
|
||||
defer os.Unsetenv("MM_SERVICESETTINGS_SELFHOSTEDFIRSTTIMEPURCHASE")
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.SelfHostedFirstTimePurchase = &valFalse })
|
||||
th.App.ReloadConfig()
|
||||
|
||||
_, r, err := th.Client.BootstrapSelfHostedSignup(model.BootstrapSelfHostedSignupRequest{Email: th.SystemAdminUser.Email})
|
||||
|
||||
require.Equal(t, http.StatusNotImplemented, r.StatusCode)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("cloud instances not allowed to bootstrap self-hosted signup", func(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
th.Client.Login(th.SystemAdminUser.Email, th.SystemAdminUser.Password)
|
||||
|
||||
th.App.Srv().SetLicense(model.NewTestLicense("cloud"))
|
||||
os.Setenv("MM_SERVICESETTINGS_SELFHOSTEDFIRSTTIMEPURCHASE", "true")
|
||||
defer os.Unsetenv("MM_SERVICESETTINGS_SELFHOSTEDFIRSTTIMEPURCHASE")
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.SelfHostedFirstTimePurchase = &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)
|
||||
})
|
||||
|
||||
t.Run("non-admins not allowed to bootstrap self-hosted signup", func(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
th.Client.Login(th.BasicUser.Email, th.BasicUser.Password)
|
||||
|
||||
os.Setenv("MM_SERVICESETTINGS_SELFHOSTEDFIRSTTIMEPURCHASE", "true")
|
||||
defer os.Unsetenv("MM_SERVICESETTINGS_SELFHOSTEDFIRSTTIMEPURCHASE")
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.SelfHostedFirstTimePurchase = &valTrue })
|
||||
th.App.ReloadConfig()
|
||||
|
||||
_, r, err := th.Client.BootstrapSelfHostedSignup(model.BootstrapSelfHostedSignupRequest{Email: th.SystemAdminUser.Email})
|
||||
|
||||
require.Equal(t, http.StatusForbidden, r.StatusCode)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("self-hosted admins can bootstrap self-hosted signup", func(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
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.SelfHostedFirstTimePurchase = &valTrue })
|
||||
th.App.ReloadConfig()
|
||||
cloud := mocks.CloudInterface{}
|
||||
|
||||
cloud.Mock.On("BootstrapSelfHostedSignup", mock.Anything).Return(&model.BootstrapSelfHostedSignupResponse{Progress: "START"}, nil)
|
||||
|
||||
cloudImpl := th.App.Srv().Cloud
|
||||
defer func() {
|
||||
th.App.Srv().Cloud = cloudImpl
|
||||
}()
|
||||
th.App.Srv().Cloud = &cloud
|
||||
|
||||
response, r, err := th.Client.BootstrapSelfHostedSignup(model.BootstrapSelfHostedSignupRequest{Email: th.SystemAdminUser.Email})
|
||||
|
||||
require.Equal(t, http.StatusOK, r.StatusCode)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "START", response.Progress)
|
||||
})
|
||||
}
|
||||
Ссылка в новой задаче
Block a user