[MM-27535] User invite limits for MM Cloud (#15197)
* Add a config for MM User Limit * Adding graceful errors for if an administrator invites people passed their user limit * Including changed vendor files * Adding unit test * Fix a bug * Push up working tests (Thanks Joram) * Add more cases, clean up logs in code * One more case * Refactoring based on PR comments * Updating i18n * Some changes based on PR review * Remove a comment * Bring back some translations that were somehow removed Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
@@ -537,6 +537,7 @@ type AppIface interface {
|
||||
GetEmojiByName(emojiName string) (*model.Emoji, *model.AppError)
|
||||
GetEmojiImage(emojiId string) ([]byte, string, *model.AppError)
|
||||
GetEmojiList(page, perPage int, sort string) ([]*model.Emoji, *model.AppError)
|
||||
GetErrorListForEmailsOverLimit(emailList []string, cloudUserLimit int64) ([]string, []*model.EmailInviteWithError, *model.AppError)
|
||||
GetFile(fileId string) ([]byte, *model.AppError)
|
||||
GetFileInfo(fileId string) (*model.FileInfo, *model.AppError)
|
||||
GetFileInfos(page, perPage int, opt *model.GetFileInfosOptions) ([]*model.FileInfo, *model.AppError)
|
||||
|
||||
@@ -5069,6 +5069,28 @@ func (a *OpenTracingAppLayer) GetEnvironmentConfig() map[string]interface{} {
|
||||
return resultVar0
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) GetErrorListForEmailsOverLimit(emailList []string, cloudUserLimit int64) ([]string, []*model.EmailInviteWithError, *model.AppError) {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetErrorListForEmailsOverLimit")
|
||||
|
||||
a.ctx = newCtx
|
||||
a.app.Srv().Store.SetContext(newCtx)
|
||||
defer func() {
|
||||
a.app.Srv().Store.SetContext(origCtx)
|
||||
a.ctx = origCtx
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
resultVar0, resultVar1, resultVar2 := a.app.GetErrorListForEmailsOverLimit(emailList, cloudUserLimit)
|
||||
|
||||
if resultVar2 != nil {
|
||||
span.LogFields(spanlog.Error(resultVar2))
|
||||
ext.Error.Set(span, true)
|
||||
}
|
||||
|
||||
return resultVar0, resultVar1, resultVar2
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) GetFile(fileId string) ([]byte, *model.AppError) {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetFile")
|
||||
|
||||
42
app/team.go
42
app/team.go
@@ -1127,6 +1127,47 @@ func (a *App) prepareInviteNewUsersToTeam(teamId, senderId string) (*model.User,
|
||||
return user, team, nil
|
||||
}
|
||||
|
||||
func genEmailInviteWithErrorList(emailList []string) []*model.EmailInviteWithError {
|
||||
invitesNotSent := make([]*model.EmailInviteWithError, len(emailList))
|
||||
for i := range emailList {
|
||||
invite := &model.EmailInviteWithError{
|
||||
Email: emailList[i],
|
||||
Error: model.NewAppError("inviteUsersToTeam", "api.team.invite_members.limit_reached.app_error", map[string]interface{}{"Addresses": emailList[i]}, "", http.StatusBadRequest),
|
||||
}
|
||||
invitesNotSent[i] = invite
|
||||
}
|
||||
return invitesNotSent
|
||||
}
|
||||
|
||||
func (a *App) GetErrorListForEmailsOverLimit(emailList []string, cloudUserLimit int64) ([]string, []*model.EmailInviteWithError, *model.AppError) {
|
||||
var invitesNotSent []*model.EmailInviteWithError
|
||||
if cloudUserLimit <= 0 {
|
||||
return emailList, invitesNotSent, nil
|
||||
}
|
||||
systemUserCount, _ := a.Srv().Store.User().Count(model.UserCountOptions{})
|
||||
remainingUsers := cloudUserLimit - systemUserCount
|
||||
if remainingUsers <= 0 {
|
||||
// No remaining users so all fail
|
||||
invitesNotSent = genEmailInviteWithErrorList(emailList)
|
||||
emailList = nil
|
||||
} else if remainingUsers < int64(len(emailList)) {
|
||||
// Trim the email list to only invite as many users as are remaining in subscription
|
||||
// Set graceful errors for the remaining email addresses
|
||||
emailsAboveLimit := emailList[remainingUsers:]
|
||||
invitesNotSent = genEmailInviteWithErrorList(emailsAboveLimit)
|
||||
// If 1 user remaining we have to prevent 0:0 reslicing
|
||||
if remainingUsers == 1 {
|
||||
email := emailList[0]
|
||||
emailList = nil
|
||||
emailList = append(emailList, email)
|
||||
} else {
|
||||
emailList = emailList[:(remainingUsers - 1)]
|
||||
}
|
||||
}
|
||||
|
||||
return emailList, invitesNotSent, nil
|
||||
}
|
||||
|
||||
func (a *App) InviteNewUsersToTeamGracefully(emailList []string, teamId, senderId string) ([]*model.EmailInviteWithError, *model.AppError) {
|
||||
if !*a.Config().ServiceSettings.EnableEmailInvitations {
|
||||
return nil, model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.disabled.app_error", nil, "", http.StatusNotImplemented)
|
||||
@@ -1136,7 +1177,6 @@ func (a *App) InviteNewUsersToTeamGracefully(emailList []string, teamId, senderI
|
||||
err := model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.no_one.app_error", nil, "", http.StatusBadRequest)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
user, team, err := a.prepareInviteNewUsersToTeam(teamId, senderId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
Ссылка в новой задаче
Block a user