From 9d8597b399c2dd22e48b723cadc63a6759b11d4b Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Fri, 24 Mar 2023 15:11:17 -0400 Subject: [PATCH 01/11] add self hostded expansion mm-server parts. --- model/hosted_customer.go | 10 ++++++ server/channels/api4/hosted_customer.go | 42 +++++++++++++++++++------ server/channels/einterfaces/cloud.go | 1 + 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/model/hosted_customer.go b/model/hosted_customer.go index 4f1917bdaf..d2856eab45 100644 --- a/model/hosted_customer.go +++ b/model/hosted_customer.go @@ -32,6 +32,11 @@ type SelfHostedConfirmPaymentMethodRequest struct { Subscription CreateSubscriptionRequest `json:"subscription"` } +type SelfHostedExpansionConfirmPaymentMethodRequest struct { + StripeSetupIntentID string `json:"stripe_setup_intent_id"` + ExpandRequest SelfHostedExpansionRequest `json:"expand_request"` +} + // SelfHostedSignupPaymentResponse contains feels needed for self hosted signup to confirm payment and receive license. type SelfHostedSignupCustomerResponse struct { CustomerId string `json:"customer_id"` @@ -58,3 +63,8 @@ type SelfHostedBillingAccessRequest struct { type SelfHostedBillingAccessResponse struct { Token string `json:"token"` } + +type SelfHostedExpansionRequest struct { + Seats int `json:"seats"` + LicenseId string `json:"license_id"` +} diff --git a/server/channels/api4/hosted_customer.go b/server/channels/api4/hosted_customer.go index 4792969c15..3662582891 100644 --- a/server/channels/api4/hosted_customer.go +++ b/server/channels/api4/hosted_customer.go @@ -65,9 +65,18 @@ func checkSelfHostedPurchaseEnabled(c *Context) bool { return enabled != nil && *enabled } +func checkSelfHostedExpansionEnabled(c *Context) bool { + config := c.App.Config() + if config == nil { + return false + } + enabled := config.ServiceSettings.SelfHostedExpansion + return enabled != nil && *enabled +} + func selfHostedBootstrap(c *Context, w http.ResponseWriter, r *http.Request) { const where = "Api4.selfHostedBootstrap" - if !checkSelfHostedPurchaseEnabled(c) { + if !checkSelfHostedPurchaseEnabled(c) && !checkSelfHostedExpansionEnabled(c) { c.Err = model.NewAppError(where, "api.cloud.app_error", nil, "", http.StatusNotImplemented) return } @@ -151,25 +160,40 @@ func selfHostedConfirm(c *Context, w http.ResponseWriter, r *http.Request) { return } + expand := r.URL.Query().Get("expand") == "true" + bodyBytes, err := io.ReadAll(r.Body) if err != nil { c.Err = model.NewAppError(where, "api.cloud.app_error", nil, "", http.StatusBadRequest).Wrap(err) return } - var confirm model.SelfHostedConfirmPaymentMethodRequest - err = json.Unmarshal(bodyBytes, &confirm) - if err != nil { - c.Err = model.NewAppError(where, "api.cloud.request_error", nil, "", http.StatusBadRequest).Wrap(err) - return - } - user, userErr := c.App.GetUser(c.AppContext.Session().UserId) if userErr != nil { c.Err = userErr return } - confirmResponse, err := c.App.Cloud().ConfirmSelfHostedSignup(confirm, user.Email) + + var confirmResponse *model.SelfHostedSignupConfirmResponse + if expand { + var confirm model.SelfHostedExpansionConfirmPaymentMethodRequest + err = json.Unmarshal(bodyBytes, &confirm) + if err != nil { + c.Err = model.NewAppError(where, "api.cloud.request_error", nil, "", http.StatusBadRequest).Wrap(err) + return + } + + confirmResponse, err = c.App.Cloud().ConfirmSelfHostedExpansion(confirm, user.Email) + } else { + var confirm model.SelfHostedConfirmPaymentMethodRequest + err = json.Unmarshal(bodyBytes, &confirm) + if err != nil { + c.Err = model.NewAppError(where, "api.cloud.request_error", nil, "", http.StatusBadRequest).Wrap(err) + return + } + + confirmResponse, err = c.App.Cloud().ConfirmSelfHostedSignup(confirm, user.Email) + } if err != nil { if confirmResponse != nil { c.App.NotifySelfHostedSignupProgress(confirmResponse.Progress, user.Id) diff --git a/server/channels/einterfaces/cloud.go b/server/channels/einterfaces/cloud.go index b5d6a75b68..8d92474cc8 100644 --- a/server/channels/einterfaces/cloud.go +++ b/server/channels/einterfaces/cloud.go @@ -37,6 +37,7 @@ type CloudInterface interface { BootstrapSelfHostedSignup(req model.BootstrapSelfHostedSignupRequest) (*model.BootstrapSelfHostedSignupResponse, error) CreateCustomerSelfHostedSignup(req model.SelfHostedCustomerForm, requesterEmail string) (*model.SelfHostedSignupCustomerResponse, error) ConfirmSelfHostedSignup(req model.SelfHostedConfirmPaymentMethodRequest, requesterEmail string) (*model.SelfHostedSignupConfirmResponse, error) + ConfirmSelfHostedExpansion(req model.SelfHostedExpansionConfirmPaymentMethodRequest, requesterEmail string) (*model.SelfHostedSignupConfirmResponse, error) ConfirmSelfHostedSignupLicenseApplication() error GetSelfHostedInvoices() ([]*model.Invoice, error) GetSelfHostedInvoicePDF(invoiceID string) ([]byte, string, error) From ff01fabc32821268dc3810846ec13d7e8e09df7f Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Fri, 24 Mar 2023 16:30:26 -0400 Subject: [PATCH 02/11] add mocks. --- plugin/api_timer_layer_generated.go | 2 +- plugin/hooks_timer_layer_generated.go | 2 +- .../einterfaces/mocks/CloudInterface.go | 23 +++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/plugin/api_timer_layer_generated.go b/plugin/api_timer_layer_generated.go index a084188c62..c54c6ac7bb 100644 --- a/plugin/api_timer_layer_generated.go +++ b/plugin/api_timer_layer_generated.go @@ -11,8 +11,8 @@ import ( "net/http" timePkg "time" - "github.com/mattermost/mattermost-server/v6/server/channels/einterfaces" "github.com/mattermost/mattermost-server/v6/model" + "github.com/mattermost/mattermost-server/v6/server/channels/einterfaces" ) type apiTimerLayer struct { diff --git a/plugin/hooks_timer_layer_generated.go b/plugin/hooks_timer_layer_generated.go index 6093048d54..87e79ca7e6 100644 --- a/plugin/hooks_timer_layer_generated.go +++ b/plugin/hooks_timer_layer_generated.go @@ -11,8 +11,8 @@ import ( "net/http" timePkg "time" - "github.com/mattermost/mattermost-server/v6/server/channels/einterfaces" "github.com/mattermost/mattermost-server/v6/model" + "github.com/mattermost/mattermost-server/v6/server/channels/einterfaces" ) type hooksTimerLayer struct { diff --git a/server/channels/einterfaces/mocks/CloudInterface.go b/server/channels/einterfaces/mocks/CloudInterface.go index db7c86acc2..b287dc0680 100644 --- a/server/channels/einterfaces/mocks/CloudInterface.go +++ b/server/channels/einterfaces/mocks/CloudInterface.go @@ -88,6 +88,29 @@ func (_m *CloudInterface) ConfirmCustomerPayment(userID string, confirmRequest * return r0 } +// ConfirmSelfHostedExpansion provides a mock function with given fields: req, requesterEmail +func (_m *CloudInterface) ConfirmSelfHostedExpansion(req model.SelfHostedExpansionConfirmPaymentMethodRequest, requesterEmail string) (*model.SelfHostedSignupConfirmResponse, error) { + ret := _m.Called(req, requesterEmail) + + var r0 *model.SelfHostedSignupConfirmResponse + if rf, ok := ret.Get(0).(func(model.SelfHostedExpansionConfirmPaymentMethodRequest, string) *model.SelfHostedSignupConfirmResponse); ok { + r0 = rf(req, requesterEmail) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.SelfHostedSignupConfirmResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(model.SelfHostedExpansionConfirmPaymentMethodRequest, string) error); ok { + r1 = rf(req, requesterEmail) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // ConfirmSelfHostedSignup provides a mock function with given fields: req, requesterEmail func (_m *CloudInterface) ConfirmSelfHostedSignup(req model.SelfHostedConfirmPaymentMethodRequest, requesterEmail string) (*model.SelfHostedSignupConfirmResponse, error) { ret := _m.Called(req, requesterEmail) From 336176f8cb59621b6d1d784080fc85e7e5451277 Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Mon, 27 Mar 2023 11:12:08 -0400 Subject: [PATCH 03/11] remove get customer by license id functionality in favor of a check in CWS. --- model/hosted_customer.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/model/hosted_customer.go b/model/hosted_customer.go index d2856eab45..8d83d2792c 100644 --- a/model/hosted_customer.go +++ b/model/hosted_customer.go @@ -68,3 +68,7 @@ type SelfHostedExpansionRequest struct { Seats int `json:"seats"` LicenseId string `json:"license_id"` } + +type GetSelfHostedCustomerRequest struct { + LicenseID string `json:"license_id"` +} From a8a71d5deee66b7ca7087b63a7c0c75708471e94 Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Tue, 28 Mar 2023 10:44:27 -0400 Subject: [PATCH 04/11] Remove unused request struct. --- model/hosted_customer.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/model/hosted_customer.go b/model/hosted_customer.go index ea293b0ef2..2337a48569 100644 --- a/model/hosted_customer.go +++ b/model/hosted_customer.go @@ -69,7 +69,3 @@ type SelfHostedExpansionRequest struct { Seats int `json:"seats"` LicenseId string `json:"license_id"` } - -type GetSelfHostedCustomerRequest struct { - LicenseID string `json:"license_id"` -} From dd7e84aca2de629265ba39de7b07a51e20f8825f Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Tue, 28 Mar 2023 14:46:27 -0400 Subject: [PATCH 05/11] Add missing checks for self hosted expansion config enabled. --- server/channels/api4/hosted_customer.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/channels/api4/hosted_customer.go b/server/channels/api4/hosted_customer.go index e5ab945611..b82fb8719f 100644 --- a/server/channels/api4/hosted_customer.go +++ b/server/channels/api4/hosted_customer.go @@ -114,7 +114,7 @@ func selfHostedCustomer(c *Context, w http.ResponseWriter, r *http.Request) { if c.Err != nil { return } - if !checkSelfHostedPurchaseEnabled(c) { + if !checkSelfHostedPurchaseEnabled(c) && !checkSelfHostedExpansionEnabled(c) { c.Err = model.NewAppError(where, "api.cloud.app_error", nil, "", http.StatusNotImplemented) return } @@ -157,7 +157,7 @@ func selfHostedConfirm(c *Context, w http.ResponseWriter, r *http.Request) { if c.Err != nil { return } - if !checkSelfHostedPurchaseEnabled(c) { + if !checkSelfHostedPurchaseEnabled(c) && !checkSelfHostedExpansionEnabled(c) { c.Err = model.NewAppError(where, "api.cloud.app_error", nil, "", http.StatusNotImplemented) return } From 451f169fea3de84226896269bdf7c981f3254773 Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Wed, 12 Apr 2023 14:12:28 -0400 Subject: [PATCH 06/11] use a more generic model for self hosted confirm payment method. --- server/channels/api4/hosted_customer.go | 3 +-- server/channels/einterfaces/cloud.go | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/server/channels/api4/hosted_customer.go b/server/channels/api4/hosted_customer.go index b82fb8719f..31cc047085 100644 --- a/server/channels/api4/hosted_customer.go +++ b/server/channels/api4/hosted_customer.go @@ -177,8 +177,8 @@ func selfHostedConfirm(c *Context, w http.ResponseWriter, r *http.Request) { } var confirmResponse *model.SelfHostedSignupConfirmResponse + var confirm model.SelfHostedConfirmPaymentMethodRequest if expand { - var confirm model.SelfHostedExpansionConfirmPaymentMethodRequest err = json.Unmarshal(bodyBytes, &confirm) if err != nil { c.Err = model.NewAppError(where, "api.cloud.request_error", nil, "", http.StatusBadRequest).Wrap(err) @@ -187,7 +187,6 @@ func selfHostedConfirm(c *Context, w http.ResponseWriter, r *http.Request) { confirmResponse, err = c.App.Cloud().ConfirmSelfHostedExpansion(confirm, user.Email) } else { - var confirm model.SelfHostedConfirmPaymentMethodRequest err = json.Unmarshal(bodyBytes, &confirm) if err != nil { c.Err = model.NewAppError(where, "api.cloud.request_error", nil, "", http.StatusBadRequest).Wrap(err) diff --git a/server/channels/einterfaces/cloud.go b/server/channels/einterfaces/cloud.go index 8d92474cc8..d8c261aa6d 100644 --- a/server/channels/einterfaces/cloud.go +++ b/server/channels/einterfaces/cloud.go @@ -37,7 +37,7 @@ type CloudInterface interface { BootstrapSelfHostedSignup(req model.BootstrapSelfHostedSignupRequest) (*model.BootstrapSelfHostedSignupResponse, error) CreateCustomerSelfHostedSignup(req model.SelfHostedCustomerForm, requesterEmail string) (*model.SelfHostedSignupCustomerResponse, error) ConfirmSelfHostedSignup(req model.SelfHostedConfirmPaymentMethodRequest, requesterEmail string) (*model.SelfHostedSignupConfirmResponse, error) - ConfirmSelfHostedExpansion(req model.SelfHostedExpansionConfirmPaymentMethodRequest, requesterEmail string) (*model.SelfHostedSignupConfirmResponse, error) + ConfirmSelfHostedExpansion(req model.SelfHostedConfirmPaymentMethodRequest, requesterEmail string) (*model.SelfHostedSignupConfirmResponse, error) ConfirmSelfHostedSignupLicenseApplication() error GetSelfHostedInvoices() ([]*model.Invoice, error) GetSelfHostedInvoicePDF(invoiceID string) ([]byte, string, error) From 4bd37013638986119628f50396f925c69e8893ec Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Wed, 12 Apr 2023 14:15:11 -0400 Subject: [PATCH 07/11] remove new model in favor of making self hosted confirm payment method request more generic. --- model/hosted_customer.go | 10 +++------- server/channels/einterfaces/mocks/CloudInterface.go | 6 +++--- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/model/hosted_customer.go b/model/hosted_customer.go index 2337a48569..f4cb8b999f 100644 --- a/model/hosted_customer.go +++ b/model/hosted_customer.go @@ -29,13 +29,9 @@ type SelfHostedCustomerForm struct { } type SelfHostedConfirmPaymentMethodRequest struct { - StripeSetupIntentID string `json:"stripe_setup_intent_id"` - Subscription CreateSubscriptionRequest `json:"subscription"` -} - -type SelfHostedExpansionConfirmPaymentMethodRequest struct { - StripeSetupIntentID string `json:"stripe_setup_intent_id"` - ExpandRequest SelfHostedExpansionRequest `json:"expand_request"` + StripeSetupIntentID string `json:"stripe_setup_intent_id"` + Subscription *CreateSubscriptionRequest `json:"subscription"` + ExpandRequest *SelfHostedExpansionRequest `json:"expand_request"` } // SelfHostedSignupPaymentResponse contains feels needed for self hosted signup to confirm payment and receive license. diff --git a/server/channels/einterfaces/mocks/CloudInterface.go b/server/channels/einterfaces/mocks/CloudInterface.go index b287dc0680..9b133ce079 100644 --- a/server/channels/einterfaces/mocks/CloudInterface.go +++ b/server/channels/einterfaces/mocks/CloudInterface.go @@ -89,11 +89,11 @@ func (_m *CloudInterface) ConfirmCustomerPayment(userID string, confirmRequest * } // ConfirmSelfHostedExpansion provides a mock function with given fields: req, requesterEmail -func (_m *CloudInterface) ConfirmSelfHostedExpansion(req model.SelfHostedExpansionConfirmPaymentMethodRequest, requesterEmail string) (*model.SelfHostedSignupConfirmResponse, error) { +func (_m *CloudInterface) ConfirmSelfHostedExpansion(req model.SelfHostedConfirmPaymentMethodRequest, requesterEmail string) (*model.SelfHostedSignupConfirmResponse, error) { ret := _m.Called(req, requesterEmail) var r0 *model.SelfHostedSignupConfirmResponse - if rf, ok := ret.Get(0).(func(model.SelfHostedExpansionConfirmPaymentMethodRequest, string) *model.SelfHostedSignupConfirmResponse); ok { + if rf, ok := ret.Get(0).(func(model.SelfHostedConfirmPaymentMethodRequest, string) *model.SelfHostedSignupConfirmResponse); ok { r0 = rf(req, requesterEmail) } else { if ret.Get(0) != nil { @@ -102,7 +102,7 @@ func (_m *CloudInterface) ConfirmSelfHostedExpansion(req model.SelfHostedExpansi } var r1 error - if rf, ok := ret.Get(1).(func(model.SelfHostedExpansionConfirmPaymentMethodRequest, string) error); ok { + if rf, ok := ret.Get(1).(func(model.SelfHostedConfirmPaymentMethodRequest, string) error); ok { r1 = rf(req, requesterEmail) } else { r1 = ret.Error(1) From dab14be745b97a8b1934a8e73ffa6a0103f9053d Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Wed, 12 Apr 2023 14:44:33 -0400 Subject: [PATCH 08/11] fix mocks --- server/channels/einterfaces/mocks/CloudInterface.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/channels/einterfaces/mocks/CloudInterface.go b/server/channels/einterfaces/mocks/CloudInterface.go index d308239e23..74236d2038 100644 --- a/server/channels/einterfaces/mocks/CloudInterface.go +++ b/server/channels/einterfaces/mocks/CloudInterface.go @@ -99,6 +99,10 @@ func (_m *CloudInterface) ConfirmSelfHostedExpansion(req model.SelfHostedConfirm ret := _m.Called(req, requesterEmail) var r0 *model.SelfHostedSignupConfirmResponse + var r1 error + if rf, ok := ret.Get(0).(func(model.SelfHostedConfirmPaymentMethodRequest, string) (*model.SelfHostedSignupConfirmResponse, error)); ok { + return rf(req, requesterEmail) + } if rf, ok := ret.Get(0).(func(model.SelfHostedConfirmPaymentMethodRequest, string) *model.SelfHostedSignupConfirmResponse); ok { r0 = rf(req, requesterEmail) } else { @@ -107,7 +111,6 @@ func (_m *CloudInterface) ConfirmSelfHostedExpansion(req model.SelfHostedConfirm } } - var r1 error if rf, ok := ret.Get(1).(func(model.SelfHostedConfirmPaymentMethodRequest, string) error); ok { r1 = rf(req, requesterEmail) } else { From a1605d51f6f29e8eb3e16362cbbc5dcd2f4abbb8 Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Mon, 17 Apr 2023 16:02:00 -0400 Subject: [PATCH 09/11] Remove checks for self hosted expansion featue flags/configs, add copy of the self hosted confirm handler specifically for expansions. --- server/channels/api4/hosted_customer.go | 124 +++++++++++++++++------- 1 file changed, 91 insertions(+), 33 deletions(-) diff --git a/server/channels/api4/hosted_customer.go b/server/channels/api4/hosted_customer.go index 53204e58ad..9942dcabf7 100644 --- a/server/channels/api4/hosted_customer.go +++ b/server/channels/api4/hosted_customer.go @@ -32,6 +32,8 @@ func (api *API) InitHostedCustomer() { api.BaseRoutes.HostedCustomer.Handle("/customer", api.APISessionRequired(selfHostedCustomer)).Methods("POST") // POST /api/v4/hosted_customer/confirm api.BaseRoutes.HostedCustomer.Handle("/confirm", api.APISessionRequired(selfHostedConfirm)).Methods("POST") + // POST /api.v4/hosted_customer/confirm-expand + api.BaseRoutes.HostedCustomer.Handle("/confirm-expand", api.APISessionRequired(selfHostedConfirmExpand)).Methods("POST") // GET /api/v4/hosted_customer/invoices api.BaseRoutes.HostedCustomer.Handle("/invoices", api.APISessionRequired(selfHostedInvoices)).Methods("GET") // GET /api/v4/hosted_customer/invoices/{invoice_id:in_[A-Za-z0-9]+}/pdf @@ -68,18 +70,9 @@ func checkSelfHostedPurchaseEnabled(c *Context) bool { return enabled != nil && *enabled } -func checkSelfHostedExpansionEnabled(c *Context) bool { - config := c.App.Config() - if config == nil { - return false - } - enabled := config.ServiceSettings.SelfHostedExpansion - return enabled != nil && *enabled -} - func selfHostedBootstrap(c *Context, w http.ResponseWriter, r *http.Request) { const where = "Api4.selfHostedBootstrap" - if !checkSelfHostedPurchaseEnabled(c) && !checkSelfHostedExpansionEnabled(c) { + if !checkSelfHostedPurchaseEnabled(c) { c.Err = model.NewAppError(where, "api.cloud.app_error", nil, "", http.StatusNotImplemented) return } @@ -115,7 +108,7 @@ func selfHostedCustomer(c *Context, w http.ResponseWriter, r *http.Request) { if c.Err != nil { return } - if !checkSelfHostedPurchaseEnabled(c) && !checkSelfHostedExpansionEnabled(c) { + if !checkSelfHostedPurchaseEnabled(c) { c.Err = model.NewAppError(where, "api.cloud.app_error", nil, "", http.StatusNotImplemented) return } @@ -158,44 +151,31 @@ func selfHostedConfirm(c *Context, w http.ResponseWriter, r *http.Request) { if c.Err != nil { return } - if !checkSelfHostedPurchaseEnabled(c) && !checkSelfHostedExpansionEnabled(c) { + if !checkSelfHostedPurchaseEnabled(c) { c.Err = model.NewAppError(where, "api.cloud.app_error", nil, "", http.StatusNotImplemented) return } - expand := r.URL.Query().Get("expand") == "true" - bodyBytes, err := io.ReadAll(r.Body) if err != nil { c.Err = model.NewAppError(where, "api.cloud.app_error", nil, "", http.StatusBadRequest).Wrap(err) return } + var confirm model.SelfHostedConfirmPaymentMethodRequest + err = json.Unmarshal(bodyBytes, &confirm) + if err != nil { + c.Err = model.NewAppError(where, "api.cloud.request_error", nil, "", http.StatusBadRequest).Wrap(err) + return + } + user, userErr := c.App.GetUser(c.AppContext.Session().UserId) if userErr != nil { c.Err = userErr return } - var confirmResponse *model.SelfHostedSignupConfirmResponse - var confirm model.SelfHostedConfirmPaymentMethodRequest - if expand { - err = json.Unmarshal(bodyBytes, &confirm) - if err != nil { - c.Err = model.NewAppError(where, "api.cloud.request_error", nil, "", http.StatusBadRequest).Wrap(err) - return - } - - confirmResponse, err = c.App.Cloud().ConfirmSelfHostedExpansion(confirm, user.Email) - } else { - err = json.Unmarshal(bodyBytes, &confirm) - if err != nil { - c.Err = model.NewAppError(where, "api.cloud.request_error", nil, "", http.StatusBadRequest).Wrap(err) - return - } - - confirmResponse, err = c.App.Cloud().ConfirmSelfHostedSignup(confirm, user.Email) - } + confirmResponse, err := c.App.Cloud().ConfirmSelfHostedSignup(confirm, user.Email) if err != nil { if confirmResponse != nil { c.App.NotifySelfHostedSignupProgress(confirmResponse.Progress, user.Id) @@ -348,3 +328,81 @@ func handleSubscribeToNewsletter(c *Context, w http.ResponseWriter, r *http.Requ ReturnStatusOK(w) } + +func selfHostedConfirmExpand(c *Context, w http.ResponseWriter, r *http.Request) { + const where = "Api4.selfHostedConfirmExpand" + + ensureSelfHostedAdmin(c, where) + if c.Err != nil { + return + } + + if !checkSelfHostedPurchaseEnabled(c) { + c.Err = model.NewAppError(where, "api.cloud.app_error", nil, "", http.StatusNotImplemented) + return + } + + bodyBytes, err := io.ReadAll(r.Body) + if err != nil { + c.Err = model.NewAppError(where, "api.cloud.app_error", nil, "", http.StatusBadRequest).Wrap(err) + return + } + + var confirm model.SelfHostedConfirmPaymentMethodRequest + err = json.Unmarshal(bodyBytes, &confirm) + if err != nil { + c.Err = model.NewAppError(where, "api.cloud.request_error", nil, "", http.StatusBadRequest).Wrap(err) + return + } + + user, userErr := c.App.GetUser(c.AppContext.Session().UserId) + if userErr != nil { + c.Err = userErr + return + } + + confirmResponse, err := c.App.Cloud().ConfirmSelfHostedExpansion(confirm, user.Email) + if err != nil { + if confirmResponse != nil { + c.App.NotifySelfHostedSignupProgress(confirmResponse.Progress, user.Id) + } + + if err.Error() == fmt.Sprintf("%d", http.StatusUnprocessableEntity) { + c.Err = model.NewAppError(where, "api.cloud.app_error", nil, "", http.StatusUnprocessableEntity).Wrap(err) + return + } + c.Err = model.NewAppError(where, "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) + return + } + + license, err := c.App.Srv().Platform().SaveLicense([]byte(confirmResponse.License)) + + // dealing with an AppError + if !(reflect.ValueOf(err).Kind() == reflect.Ptr && reflect.ValueOf(err).IsNil()) { + if confirmResponse != nil { + c.App.NotifySelfHostedSignupProgress(confirmResponse.Progress, user.Id) + } + c.Err = model.NewAppError(where, "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) + return + } + clientResponse, err := json.Marshal(model.SelfHostedSignupConfirmClientResponse{ + License: utils.GetClientLicense(license), + Progress: confirmResponse.Progress, + }) + if err != nil { + if confirmResponse != nil { + c.App.NotifySelfHostedSignupProgress(confirmResponse.Progress, user.Id) + } + c.Err = model.NewAppError(where, "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) + return + } + + go func() { + err := c.App.Cloud().ConfirmSelfHostedSignupLicenseApplication() + if err != nil { + c.Logger.Warn("Unable to confirm license application", mlog.Err(err)) + } + }() + + _, _ = w.Write(clientResponse) +} From f0ed400732d226ee66e257c97bb28d307396cb22 Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Tue, 18 Apr 2023 13:47:35 -0400 Subject: [PATCH 10/11] remove use of reflection to detect app err. --- server/channels/api4/hosted_customer.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/server/channels/api4/hosted_customer.go b/server/channels/api4/hosted_customer.go index 5a6ceda767..5affb6c1b1 100644 --- a/server/channels/api4/hosted_customer.go +++ b/server/channels/api4/hosted_customer.go @@ -188,9 +188,8 @@ func selfHostedConfirm(c *Context, w http.ResponseWriter, r *http.Request) { c.Err = model.NewAppError(where, "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return } - license, err := c.App.Srv().Platform().SaveLicense([]byte(confirmResponse.License)) - // dealing with an AppError - if !(reflect.ValueOf(err).Kind() == reflect.Ptr && reflect.ValueOf(err).IsNil()) { + license, appErr := c.App.Srv().Platform().SaveLicense([]byte(confirmResponse.License)) + if appErr != nil { if confirmResponse != nil { c.App.NotifySelfHostedSignupProgress(confirmResponse.Progress, user.Id) } From 3ca789979aed94e9fbb4c5668785e9b86a12f71f Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Wed, 19 Apr 2023 09:23:45 -0400 Subject: [PATCH 11/11] remove other use of relfection to determine error. --- server/channels/api4/hosted_customer.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/server/channels/api4/hosted_customer.go b/server/channels/api4/hosted_customer.go index 5affb6c1b1..c7beef7ebd 100644 --- a/server/channels/api4/hosted_customer.go +++ b/server/channels/api4/hosted_customer.go @@ -10,7 +10,6 @@ import ( "fmt" "io" "net/http" - "reflect" "time" "github.com/pkg/errors" @@ -374,10 +373,9 @@ func selfHostedConfirmExpand(c *Context, w http.ResponseWriter, r *http.Request) return } - license, err := c.App.Srv().Platform().SaveLicense([]byte(confirmResponse.License)) - + license, appErr := c.App.Srv().Platform().SaveLicense([]byte(confirmResponse.License)) // dealing with an AppError - if !(reflect.ValueOf(err).Kind() == reflect.Ptr && reflect.ValueOf(err).IsNil()) { + if appErr != nil { if confirmResponse != nil { c.App.NotifySelfHostedSignupProgress(confirmResponse.Progress, user.Id) }