[MM-31497] - Prevent end users from inviting people and exceeding the free tier limits (#16786)
* [MM-31497] - Prevent end users from inviting people and exceeding the free tier limits * Update error * Commit forgotten code * Chnage impl-1 * Change impl-2 * Remove test * Include tier status * Renable permissions check * Change endpoint name * Update endpoint * Update api4/cloud.go Co-authored-by: Maria A Nunez <maria.nunez@mattermost.com> * Add test for new endpoint * Format code Co-authored-by: Mattermod <mattermod@users.noreply.github.com> Co-authored-by: Maria A Nunez <maria.nunez@mattermost.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
d489868f28
Коммит
ddd9439706
@@ -35,6 +35,7 @@ func (api *API) InitCloud() {
|
|||||||
api.BaseRoutes.Cloud.Handle("/subscription", api.ApiSessionRequired(getSubscription)).Methods("GET")
|
api.BaseRoutes.Cloud.Handle("/subscription", api.ApiSessionRequired(getSubscription)).Methods("GET")
|
||||||
api.BaseRoutes.Cloud.Handle("/subscription/invoices", api.ApiSessionRequired(getInvoicesForSubscription)).Methods("GET")
|
api.BaseRoutes.Cloud.Handle("/subscription/invoices", api.ApiSessionRequired(getInvoicesForSubscription)).Methods("GET")
|
||||||
api.BaseRoutes.Cloud.Handle("/subscription/invoices/{invoice_id:in_[A-Za-z0-9]+}/pdf", api.ApiSessionRequired(getSubscriptionInvoicePDF)).Methods("GET")
|
api.BaseRoutes.Cloud.Handle("/subscription/invoices/{invoice_id:in_[A-Za-z0-9]+}/pdf", api.ApiSessionRequired(getSubscriptionInvoicePDF)).Methods("GET")
|
||||||
|
api.BaseRoutes.Cloud.Handle("/subscription/stats", api.ApiSessionRequired(getSubscriptionStats)).Methods("GET")
|
||||||
|
|
||||||
// POST /api/v4/cloud/webhook
|
// POST /api/v4/cloud/webhook
|
||||||
api.BaseRoutes.Cloud.Handle("/webhook", api.CloudApiKeyRequired(handleCWSWebhook)).Methods("POST")
|
api.BaseRoutes.Cloud.Handle("/webhook", api.CloudApiKeyRequired(handleCWSWebhook)).Methods("POST")
|
||||||
@@ -67,6 +68,36 @@ func getSubscription(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
w.Write(json)
|
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)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
subscription, appErr := c.App.Cloud().GetSubscription()
|
||||||
|
|
||||||
|
if appErr != nil {
|
||||||
|
c.Err = model.NewAppError("Api4.getSubscriptionStats", "api.cloud.request_error", nil, appErr.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
count, err := c.App.Srv().Store.User().Count(model.UserCountOptions{})
|
||||||
|
if err != nil {
|
||||||
|
c.Err = model.NewAppError("Api4.getSubscriptionStats", "app.user.get_total_users_count.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cloudUserLimit := *c.App.Config().ExperimentalSettings.CloudUserLimit
|
||||||
|
|
||||||
|
s := cloudUserLimit - count
|
||||||
|
|
||||||
|
stats, _ := json.Marshal(model.SubscriptionStats{
|
||||||
|
RemainingSeats: int(s),
|
||||||
|
IsPaidTier: subscription.IsPaidTier,
|
||||||
|
})
|
||||||
|
|
||||||
|
w.Write([]byte(string(stats)))
|
||||||
|
}
|
||||||
|
|
||||||
func getCloudProducts(c *Context, w http.ResponseWriter, r *http.Request) {
|
func getCloudProducts(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.Cloud {
|
if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.Cloud {
|
||||||
c.Err = model.NewAppError("Api4.getCloudProducts", "api.cloud.license_error", nil, "", http.StatusNotImplemented)
|
c.Err = model.NewAppError("Api4.getCloudProducts", "api.cloud.license_error", nil, "", http.StatusNotImplemented)
|
||||||
|
|||||||
@@ -1205,7 +1205,7 @@ func inviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
if graceful {
|
if graceful {
|
||||||
cloudUserLimit := *c.App.Config().ExperimentalSettings.CloudUserLimit
|
cloudUserLimit := *c.App.Config().ExperimentalSettings.CloudUserLimit
|
||||||
var invitesOverLimit []*model.EmailInviteWithError
|
var invitesOverLimit []*model.EmailInviteWithError
|
||||||
if c.App.Srv().License() != nil && *c.App.Srv().License().Features.Cloud && cloudUserLimit > 0 && c.IsSystemAdmin() {
|
if c.App.Srv().License() != nil && *c.App.Srv().License().Features.Cloud && cloudUserLimit > 0 {
|
||||||
subscription, subErr := c.App.Cloud().GetSubscription()
|
subscription, subErr := c.App.Cloud().GetSubscription()
|
||||||
if subErr != nil {
|
if subErr != nil {
|
||||||
c.Err = subErr
|
c.Err = subErr
|
||||||
|
|||||||
@@ -5752,6 +5752,18 @@ func (c *Client4) GetSubscription() (*Subscription, *Response) {
|
|||||||
return subscription, BuildResponse(r)
|
return subscription, BuildResponse(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client4) GetSubscriptionStats() (*SubscriptionStats, *Response) {
|
||||||
|
r, appErr := c.DoApiGet(c.GetCloudRoute()+"/subscription/stats", "")
|
||||||
|
if appErr != nil {
|
||||||
|
return nil, BuildErrorResponse(r, appErr)
|
||||||
|
}
|
||||||
|
defer closeBody(r)
|
||||||
|
|
||||||
|
var stats *SubscriptionStats
|
||||||
|
json.NewDecoder(r.Body).Decode(&stats)
|
||||||
|
return stats, BuildResponse(r)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client4) GetInvoicesForSubscription() ([]*Invoice, *Response) {
|
func (c *Client4) GetInvoicesForSubscription() ([]*Invoice, *Response) {
|
||||||
r, appErr := c.DoApiGet(c.GetCloudRoute()+"/subscription/invoices", "")
|
r, appErr := c.DoApiGet(c.GetCloudRoute()+"/subscription/invoices", "")
|
||||||
if appErr != nil {
|
if appErr != nil {
|
||||||
|
|||||||
@@ -128,3 +128,8 @@ type FailedPayment struct {
|
|||||||
LastFour int `json:"last_four"`
|
LastFour int `json:"last_four"`
|
||||||
FailureMessage string `json:"failure_message"`
|
FailureMessage string `json:"failure_message"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SubscriptionStats struct {
|
||||||
|
RemainingSeats int `json:"remaining_seats"`
|
||||||
|
IsPaidTier string `json:"is_paid_tier"`
|
||||||
|
}
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user