From 4b6e73c1c4c150f9fe308d0497814195d0d19641 Mon Sep 17 00:00:00 2001 From: Nick Misasi Date: Thu, 27 May 2021 09:12:47 -0400 Subject: [PATCH] [MM-35625] Add controller for changing cloud subscription (#17676) * Add a controller for changing subscription * Changes for PR * Another change * Fix pipeline Co-authored-by: Mattermod --- api4/cloud.go | 42 +++++++++++++++++++++++++++++ einterfaces/cloud.go | 2 ++ einterfaces/mocks/CloudInterface.go | 23 ++++++++++++++++ model/cloud.go | 4 +++ 4 files changed, 71 insertions(+) diff --git a/api4/cloud.go b/api4/cloud.go index ba69abc44b..133c38ae04 100644 --- a/api4/cloud.go +++ b/api4/cloud.go @@ -39,6 +39,7 @@ func (api *API) InitCloud() { api.BaseRoutes.Cloud.Handle("/subscription/limitreached/invite", api.ApiSessionRequired(sendAdminUpgradeRequestEmail)).Methods("POST") api.BaseRoutes.Cloud.Handle("/subscription/limitreached/join", api.ApiHandler(sendAdminUpgradeRequestEmailOnJoin)).Methods("POST") api.BaseRoutes.Cloud.Handle("/subscription/stats", api.ApiHandler(getSubscriptionStats)).Methods("GET") + api.BaseRoutes.Cloud.Handle("/subscription", api.ApiSessionRequired(changeSubscription)).Methods("PUT") // POST /api/v4/cloud/webhook api.BaseRoutes.Cloud.Handle("/webhook", api.CloudApiKeyRequired(handleCWSWebhook)).Methods("POST") @@ -70,6 +71,47 @@ func getSubscription(c *Context, w http.ResponseWriter, r *http.Request) { w.Write(json) } +func changeSubscription(c *Context, w http.ResponseWriter, r *http.Request) { + if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.Cloud { + c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.license_error", nil, "", http.StatusInternalServerError) + return + } + + if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_WRITE_BILLING) { + c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_BILLING) + return + } + + bodyBytes, err := ioutil.ReadAll(r.Body) + if err != nil { + c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.app_error", nil, err.Error(), http.StatusBadRequest) + return + } + + var subscriptionChange *model.SubscriptionChange + if err = json.Unmarshal(bodyBytes, &subscriptionChange); err != nil { + c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.app_error", nil, err.Error(), http.StatusBadRequest) + } + + currentSubscription, appErr := c.App.Cloud().GetSubscription(c.AppContext.Session().UserId) + if appErr != nil { + c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.app_error", nil, appErr.Error(), http.StatusInternalServerError) + return + } + + changedSub, err := c.App.Cloud().ChangeSubscription(c.AppContext.Session().UserId, currentSubscription.ID, subscriptionChange) + if err != nil { + c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + } + + json, err := json.Marshal(changedSub) + if err != nil { + c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) + } + + w.Write(json) +} + func getSubscriptionStats(c *Context, w http.ResponseWriter, r *http.Request) { if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.Cloud { c.Err = model.NewAppError("Api4.getSubscriptionStats", "api.cloud.license_error", nil, "", http.StatusInternalServerError) diff --git a/einterfaces/cloud.go b/einterfaces/cloud.go index 771989b83f..4650b36ebe 100644 --- a/einterfaces/cloud.go +++ b/einterfaces/cloud.go @@ -20,4 +20,6 @@ type CloudInterface interface { GetSubscription(userID string) (*model.Subscription, error) GetInvoicesForSubscription(userID string) ([]*model.Invoice, error) GetInvoicePDF(userID, invoiceID string) ([]byte, string, error) + + ChangeSubscription(userID, subscriptionID string, subscriptionChange *model.SubscriptionChange) (*model.Subscription, error) } diff --git a/einterfaces/mocks/CloudInterface.go b/einterfaces/mocks/CloudInterface.go index 1f80e8abb8..89d65ca7cf 100644 --- a/einterfaces/mocks/CloudInterface.go +++ b/einterfaces/mocks/CloudInterface.go @@ -14,6 +14,29 @@ type CloudInterface struct { mock.Mock } +// ChangeSubscription provides a mock function with given fields: userID, subscriptionID, subscriptionChange +func (_m *CloudInterface) ChangeSubscription(userID string, subscriptionID string, subscriptionChange *model.SubscriptionChange) (*model.Subscription, error) { + ret := _m.Called(userID, subscriptionID, subscriptionChange) + + var r0 *model.Subscription + if rf, ok := ret.Get(0).(func(string, string, *model.SubscriptionChange) *model.Subscription); ok { + r0 = rf(userID, subscriptionID, subscriptionChange) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.Subscription) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(string, string, *model.SubscriptionChange) error); ok { + r1 = rf(userID, subscriptionID, subscriptionChange) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // ConfirmCustomerPayment provides a mock function with given fields: userID, confirmRequest func (_m *CloudInterface) ConfirmCustomerPayment(userID string, confirmRequest *model.ConfirmPaymentMethodRequest) error { ret := _m.Called(userID, confirmRequest) diff --git a/model/cloud.go b/model/cloud.go index b9596cc294..66c9dd4462 100644 --- a/model/cloud.go +++ b/model/cloud.go @@ -156,3 +156,7 @@ type SubscriptionStats struct { IsPaidTier string `json:"is_paid_tier"` IsFreeTrial string `json:"is_free_trial"` } + +type SubscriptionChange struct { + ProductID string `json:"product_id"` +}