[MM-42713] - Remove cloud user limit restrictions (#19835)
* [MM-42713] - Remove cloud user limit restrictions * remove unused code * fix translations * feedback impl-1 * enterprise code clean up * feedback impl-2 * fix mocks * fix translations Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
67d57fc400
Коммит
fa56ee9d9a
@@ -36,9 +36,6 @@ func (api *API) InitCloud() {
|
||||
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/{invoice_id:in_[A-Za-z0-9]+}/pdf", api.APISessionRequired(getSubscriptionInvoicePDF)).Methods("GET")
|
||||
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.APISessionRequired(getSubscriptionStats)).Methods("GET")
|
||||
api.BaseRoutes.Cloud.Handle("/subscription", api.APISessionRequired(changeSubscription)).Methods("PUT")
|
||||
|
||||
// POST /api/v4/cloud/webhook
|
||||
@@ -115,18 +112,6 @@ func changeSubscription(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
w.Write(json)
|
||||
}
|
||||
|
||||
func getSubscriptionStats(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
s, err := c.App.GetSubscriptionStats()
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
stats, _ := json.Marshal(s)
|
||||
|
||||
w.Write([]byte(string(stats)))
|
||||
}
|
||||
|
||||
func getCloudProducts(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.Cloud {
|
||||
c.Err = model.NewAppError("Api4.getCloudProducts", "api.cloud.license_error", nil, "", http.StatusNotImplemented)
|
||||
@@ -464,49 +449,3 @@ func handleCWSWebhook(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
ReturnStatusOK(w)
|
||||
}
|
||||
|
||||
func sendAdminUpgradeRequestEmail(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.Cloud {
|
||||
c.Err = model.NewAppError("Api4.sendAdminUpgradeRequestEmail", "api.cloud.license_error", nil, "", http.StatusNotImplemented)
|
||||
return
|
||||
}
|
||||
|
||||
user, appErr := c.App.GetUser(c.AppContext.Session().UserId)
|
||||
if appErr != nil {
|
||||
c.Err = model.NewAppError("Api4.sendAdminUpgradeRequestEmail", appErr.Id, nil, appErr.Error(), appErr.StatusCode)
|
||||
return
|
||||
}
|
||||
|
||||
sub, err := c.App.Cloud().GetSubscription(c.AppContext.Session().UserId)
|
||||
if err != nil {
|
||||
c.Err = model.NewAppError("Api4.sendAdminUpgradeRequestEmail", "api.cloud.request_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if appErr = c.App.SendAdminUpgradeRequestEmail(user.Username, sub, model.InviteLimitation); appErr != nil {
|
||||
c.Err = model.NewAppError("Api4.sendAdminUpgradeRequestEmail", appErr.Id, nil, appErr.Error(), appErr.StatusCode)
|
||||
return
|
||||
}
|
||||
|
||||
ReturnStatusOK(w)
|
||||
}
|
||||
|
||||
func sendAdminUpgradeRequestEmailOnJoin(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.Cloud {
|
||||
c.Err = model.NewAppError("Api4.sendAdminUpgradeRequestEmailOnJoin", "api.cloud.license_error", nil, "", http.StatusNotImplemented)
|
||||
return
|
||||
}
|
||||
|
||||
sub, err := c.App.Cloud().GetSubscription("")
|
||||
if err != nil {
|
||||
c.Err = model.NewAppError("Api4.sendAdminUpgradeRequestEmailOnJoin", "api.cloud.request_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if appErr := c.App.SendAdminUpgradeRequestEmail("", sub, model.JoinLimitation); appErr != nil {
|
||||
c.Err = model.NewAppError("Api4.sendAdminUpgradeRequestEmail", appErr.Id, nil, appErr.Error(), appErr.StatusCode)
|
||||
return
|
||||
}
|
||||
|
||||
ReturnStatusOK(w)
|
||||
}
|
||||
|
||||
44
api4/team.go
44
api4/team.go
@@ -1293,34 +1293,12 @@ func inviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
auditRec.AddMeta("emails", emailList)
|
||||
|
||||
if graceful {
|
||||
cloudUserLimit := *c.App.Config().ExperimentalSettings.CloudUserLimit
|
||||
var invitesOverLimit []*model.EmailInviteWithError
|
||||
if c.App.Channels().License() != nil && *c.App.Channels().License().Features.Cloud && cloudUserLimit > 0 {
|
||||
subscription, subErr := c.App.Cloud().GetSubscription(c.AppContext.Session().UserId)
|
||||
if subErr != nil {
|
||||
c.Err = model.NewAppError(
|
||||
"Api4.inviteUsersToTeam",
|
||||
"api.team.cloud.subscription.error",
|
||||
nil,
|
||||
subErr.Error(),
|
||||
http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if subscription == nil || subscription.IsPaidTier != "true" {
|
||||
emailList, invitesOverLimit, _ = c.App.GetErrorListForEmailsOverLimit(emailList, cloudUserLimit)
|
||||
}
|
||||
}
|
||||
|
||||
var invitesWithError []*model.EmailInviteWithError
|
||||
var err *model.AppError
|
||||
if emailList != nil {
|
||||
invitesWithError, err = c.App.InviteNewUsersToTeamGracefully(emailList, c.Params.TeamId, c.AppContext.Session().UserId, "")
|
||||
}
|
||||
|
||||
if len(invitesOverLimit) > 0 {
|
||||
invitesWithError = append(invitesWithError, invitesOverLimit...)
|
||||
}
|
||||
|
||||
if invitesWithError != nil {
|
||||
errList := make([]string, 0, len(invitesWithError))
|
||||
for _, inv := range invitesWithError {
|
||||
@@ -1414,24 +1392,6 @@ func inviteGuestsToChannels(c *Context, w http.ResponseWriter, r *http.Request)
|
||||
auditRec.AddMeta("channels", guestsInvite.Channels)
|
||||
|
||||
if graceful {
|
||||
cloudUserLimit := *c.App.Config().ExperimentalSettings.CloudUserLimit
|
||||
var invitesOverLimit []*model.EmailInviteWithError
|
||||
if c.App.Channels().License() != nil && *c.App.Channels().License().Features.Cloud && cloudUserLimit > 0 && c.IsSystemAdmin() {
|
||||
subscription, err := c.App.Cloud().GetSubscription(c.AppContext.Session().UserId)
|
||||
if err != nil {
|
||||
c.Err = model.NewAppError(
|
||||
"Api4.inviteGuestsToChannel",
|
||||
"api.team.cloud.subscription.error",
|
||||
nil,
|
||||
err.Error(),
|
||||
http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if subscription == nil || subscription.IsPaidTier != "true" {
|
||||
guestsInvite.Emails, invitesOverLimit, _ = c.App.GetErrorListForEmailsOverLimit(guestsInvite.Emails, cloudUserLimit)
|
||||
}
|
||||
}
|
||||
|
||||
var invitesWithError []*model.EmailInviteWithError
|
||||
var err *model.AppError
|
||||
|
||||
@@ -1439,10 +1399,6 @@ func inviteGuestsToChannels(c *Context, w http.ResponseWriter, r *http.Request)
|
||||
invitesWithError, err = c.App.InviteGuestsToChannelsGracefully(c.Params.TeamId, &guestsInvite, c.AppContext.Session().UserId)
|
||||
}
|
||||
|
||||
if len(invitesOverLimit) > 0 {
|
||||
invitesWithError = append(invitesWithError, invitesOverLimit...)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
errList := make([]string, 0, len(invitesWithError))
|
||||
for _, inv := range invitesWithError {
|
||||
|
||||
30
api4/user.go
30
api4/user.go
@@ -159,15 +159,6 @@ func createUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// New user created, check cloud limits and send emails if needed
|
||||
// Soft fail on error since user is already created
|
||||
if ruser != nil {
|
||||
err = c.App.CheckAndSendUserLimitWarningEmails(c.AppContext)
|
||||
if err != nil {
|
||||
c.LogErrorByCode(err)
|
||||
}
|
||||
}
|
||||
|
||||
auditRec.Success()
|
||||
auditRec.AddMeta("user", ruser) // overwrite meta
|
||||
|
||||
@@ -1468,18 +1459,6 @@ func updateUserActive(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// if non cloud instances, isOverLimit is false and no error
|
||||
isAtLimit, err := c.App.CheckCloudAccountAtLimit()
|
||||
if err != nil {
|
||||
c.Err = model.NewAppError("updateUserActive", "api.user.update_active.cloud_at_limit_check_error", nil, "userId="+c.Params.UserId, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if active && isAtLimit {
|
||||
c.Err = model.NewAppError("updateUserActive", "api.user.update_active.cloud_at_or_over_limit_check_overcapacity", nil, "userId="+c.Params.UserId, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if _, err = c.App.UpdateActive(c.AppContext, user, active); err != nil {
|
||||
c.Err = err
|
||||
}
|
||||
@@ -1498,15 +1477,6 @@ func updateUserActive(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
message := model.NewWebSocketEvent(model.WebsocketEventUserActivationStatusChange, "", "", "", nil)
|
||||
c.App.Publish(message)
|
||||
|
||||
// If activating, run cloud check for limit overages
|
||||
if active {
|
||||
emailErr := c.App.CheckAndSendUserLimitWarningEmails(c.AppContext)
|
||||
if emailErr != nil {
|
||||
c.Err = emailErr
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
ReturnStatusOK(w)
|
||||
}
|
||||
|
||||
|
||||
@@ -2183,46 +2183,6 @@ func assertWebsocketEventUserUpdatedWithEmail(t *testing.T, client *model.WebSoc
|
||||
}
|
||||
|
||||
func TestUpdateUserActive(t *testing.T) {
|
||||
t.Run("not activating more users when cloud license users at limit", func(t *testing.T) {
|
||||
// create 5 active users
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
cloudMock := &mocks.CloudInterface{}
|
||||
cloudMock.Mock.On(
|
||||
"GetSubscription", mock.Anything,
|
||||
).Return(&model.Subscription{
|
||||
ID: "MySubscriptionID",
|
||||
CustomerID: "MyCustomer",
|
||||
ProductID: "SomeProductId",
|
||||
AddOns: []string{},
|
||||
StartAt: 1000000000,
|
||||
EndAt: 2000000000,
|
||||
CreateAt: 1000000000,
|
||||
Seats: 100,
|
||||
DNS: "some.dns.server",
|
||||
IsPaidTier: "false",
|
||||
}, nil)
|
||||
|
||||
th.App.Srv().SetLicense(model.NewTestLicense("cloud"))
|
||||
th.App.Srv().Cloud = cloudMock
|
||||
|
||||
user := th.BasicUser
|
||||
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.TeamSettings.EnableUserDeactivation = true
|
||||
*cfg.ExperimentalSettings.CloudUserLimit = 4
|
||||
})
|
||||
|
||||
// deactivate 5th user, now we have 4 active users and are at limit
|
||||
_, err := th.SystemAdminClient.UpdateUserActive(user.Id, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
// try and reactivate 5th user, not allowed because it exceeds the set cloud user limit
|
||||
resp, err := th.SystemAdminClient.UpdateUserActive(user.Id, true)
|
||||
CheckErrorMessage(t, err, "Unable to activate more users as the cloud account is over capacity.")
|
||||
CheckBadRequestStatus(t, resp)
|
||||
})
|
||||
t.Run("basic tests", func(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
Ссылка в новой задаче
Block a user