MM-11120 Adding setting to disable email invitations and rate limiting. (#9063)

* Adding setting to disable email invitations.

* Adding a setting and rate limiting for email invite sending.

* Modifying email rate limit to 20/user/hour

* Adding EnableEmailInvitations to client side config and command.
Этот коммит содержится в:
Christopher Speller
2018-07-10 01:54:25 -07:00
коммит произвёл Carlos Tadeu Panato Junior
родитель 951e4ad984
Коммит 74e5d8ae66
10 изменённых файлов: 100 добавлений и 6 удалений

Просмотреть файл

@@ -17,6 +17,7 @@ import (
"github.com/gorilla/mux"
"github.com/pkg/errors"
"github.com/throttled/throttled"
"github.com/mattermost/mattermost-server/einterfaces"
ejobs "github.com/mattermost/mattermost-server/einterfaces/jobs"
@@ -46,7 +47,8 @@ type App struct {
IsPluginSandboxSupported bool
pluginStatuses map[string]*model.PluginStatus
EmailBatching *EmailBatchingJob
EmailBatching *EmailBatchingJob
EmailRateLimiter *throttled.GCRARateLimiter
Hubs []*Hub
HubsStopCheckingForDeadlock chan bool
@@ -185,6 +187,10 @@ func New(options ...Option) (outApp *App, outErr error) {
})
if err := app.SetupInviteEmailRateLimiting(); err != nil {
return nil, err
}
mlog.Info("Server is initializing...")
app.initEnterprise()

Просмотреть файл

@@ -28,7 +28,7 @@ func (me *InvitePeopleProvider) GetTrigger() string {
func (me *InvitePeopleProvider) GetCommand(a *App, T goi18n.TranslateFunc) *model.Command {
autoComplete := true
if !a.Config().EmailSettings.SendEmailNotifications || !*a.Config().TeamSettings.EnableUserCreation {
if !a.Config().EmailSettings.SendEmailNotifications || !*a.Config().TeamSettings.EnableUserCreation || !*a.Config().ServiceSettings.EnableEmailInvitations {
autoComplete = false
}
return &model.Command{
@@ -49,6 +49,10 @@ func (me *InvitePeopleProvider) DoCommand(a *App, args *model.CommandArgs, messa
return &model.CommandResponse{ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL, Text: args.T("api.command.invite_people.invite_off")}
}
if !*a.Config().ServiceSettings.EnableEmailInvitations {
return &model.CommandResponse{ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL, Text: args.T("api.command.invite_people.email_invitations_off")}
}
emailList := strings.Fields(message)
for i := len(emailList) - 1; i >= 0; i-- {

Просмотреть файл

@@ -10,12 +10,41 @@ import (
"net/http"
"github.com/nicksnyder/go-i18n/i18n"
"github.com/pkg/errors"
"github.com/throttled/throttled"
"github.com/throttled/throttled/store/memstore"
"github.com/mattermost/mattermost-server/mlog"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/utils"
)
const (
emailRateLimitingMemstoreSize = 65536
emailRateLimitingPerHour = 20
emailRateLimitingMaxBurst = 20
)
func (a *App) SetupInviteEmailRateLimiting() error {
store, err := memstore.New(emailRateLimitingMemstoreSize)
if err != nil {
return errors.Wrap(err, "Unable to setup email rate limiting memstore.")
}
quota := throttled.RateQuota{
MaxRate: throttled.PerHour(emailRateLimitingPerHour),
MaxBurst: emailRateLimitingMaxBurst,
}
rateLimiter, err := throttled.NewGCRARateLimiter(store, quota)
if err != nil || rateLimiter == nil {
return errors.Wrap(err, "Unable to setup email rate limiting GCRA rate limiter.")
}
a.EmailRateLimiter = rateLimiter
return nil
}
func (a *App) SendChangeUsernameEmail(oldUsername, newUsername, email, locale, siteURL string) *model.AppError {
T := utils.GetUserTranslations(locale)
@@ -247,7 +276,24 @@ func (a *App) SendMfaChangeEmail(email string, activated bool, locale, siteURL s
return nil
}
func (a *App) SendInviteEmails(team *model.Team, senderName string, invites []string, siteURL string) {
func (a *App) SendInviteEmails(team *model.Team, senderName string, senderUserId string, invites []string, siteURL string) {
if a.EmailRateLimiter == nil {
a.Log.Error("Email invite not sent, rate limiting could not be setup.", mlog.String("user_id", senderUserId), mlog.String("team_id", team.Id))
return
}
rateLimited, result, err := a.EmailRateLimiter.RateLimit(senderUserId, len(invites))
if rateLimited {
a.Log.Error("Invite emails rate limited.",
mlog.String("user_id", senderUserId),
mlog.String("team_id", team.Id),
mlog.String("retry_after", result.RetryAfter.String()),
mlog.Err(err))
return
} else if err != nil {
a.Log.Error("Error rate limiting invite email.", mlog.String("user_id", senderUserId), mlog.String("team_id", team.Id), mlog.Err(err))
return
}
for _, invite := range invites {
if len(invite) > 0 {
senderRole := utils.T("api.team.invite_members.member")

Просмотреть файл

@@ -805,6 +805,10 @@ func (a *App) postRemoveFromTeamMessage(user *model.User, channel *model.Channel
}
func (a *App) InviteNewUsersToTeam(emailList []string, teamId, senderId string) *model.AppError {
if !*a.Config().ServiceSettings.EnableEmailInvitations {
return model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.disabled.app_error", nil, "", http.StatusNotImplemented)
}
if len(emailList) == 0 {
err := model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.no_one.app_error", nil, "", http.StatusBadRequest)
return err
@@ -842,7 +846,7 @@ func (a *App) InviteNewUsersToTeam(emailList []string, teamId, senderId string)
}
nameFormat := *a.Config().TeamSettings.TeammateNameDisplay
a.SendInviteEmails(team, user.GetDisplayName(nameFormat), emailList, a.GetSiteURL())
a.SendInviteEmails(team, user.GetDisplayName(nameFormat), user.Id, emailList, a.GetSiteURL())
return nil
}