* When service setting flag is on, self hosted workspaces can initiate process for self-serve sign up
* Add hosted_customer api.
Этот коммит содержится в:
Nathaniel Allred
2022-11-29 13:32:08 -06:00
коммит произвёл GitHub
родитель 2455de99ff
Коммит 4f3f6e6496
12 изменённых файлов: 249 добавлений и 1 удалений

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

@@ -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 Обычный файл
Просмотреть файл

@@ -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 Обычный файл
Просмотреть файл

@@ -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)
})
}