[MM-32691] - Send email when the users are not able to join a workspace (#16958)

* [MM-32691] - Send email when the users are not able to join a workspace

* Revert "[MM-32691] - Send email when the users are not able to join a workspace"

This reverts commit 3c11643c7c6867d992743a15675f0099df4f4e4d.

* Feeback impl-1

* use date as key for rate limiting

* Fix tests

* Translations

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
Allan Guwatudde
2021-02-24 17:37:24 +03:00
коммит произвёл GitHub
родитель 6b388871a9
Коммит 0dad204007
9 изменённых файлов: 110 добавлений и 26 удалений

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

@@ -267,7 +267,7 @@ type AppIface interface {
SearchAllTeams(searchOpts *model.TeamSearch) ([]*model.Team, int64, *model.AppError)
// SendAdminUpgradeRequestEmail takes the username of user trying to alert admins and then applies rate limit of n (number of admins) emails per user per day
// before sending the emails.
SendAdminUpgradeRequestEmail(username string, subscription *model.Subscription) *model.AppError
SendAdminUpgradeRequestEmail(username string, subscription *model.Subscription, action string) *model.AppError
// SendNoCardPaymentFailedEmail
SendNoCardPaymentFailedEmail() *model.AppError
// ServePluginPublicRequest serves public plugin files

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

@@ -6,6 +6,7 @@ package app
import (
"fmt"
"net/http"
"time"
"github.com/mattermost/mattermost-server/v5/mlog"
"github.com/mattermost/mattermost-server/v5/model"
@@ -23,7 +24,7 @@ func (a *App) getSysAdminsEmailRecipients() ([]*model.User, *model.AppError) {
// SendAdminUpgradeRequestEmail takes the username of user trying to alert admins and then applies rate limit of n (number of admins) emails per user per day
// before sending the emails.
func (a *App) SendAdminUpgradeRequestEmail(username string, subscription *model.Subscription) *model.AppError {
func (a *App) SendAdminUpgradeRequestEmail(username string, subscription *model.Subscription, action string) *model.AppError {
if a.Srv().License() == nil || (a.Srv().License() != nil && !*a.Srv().License().Features.Cloud) {
return nil
}
@@ -32,21 +33,24 @@ func (a *App) SendAdminUpgradeRequestEmail(username string, subscription *model.
return nil
}
year, month, day := time.Now().Date()
key := fmt.Sprintf("%s-%d-%s-%d", action, day, month, year)
if a.Srv().EmailService.PerDayEmailRateLimiter == nil {
return model.NewAppError("app.SendAdminUpgradeRequestEmail", "app.email.no_rate_limiter.app_error", nil, fmt.Sprintf("for username=%s", username), http.StatusInternalServerError)
return model.NewAppError("app.SendAdminUpgradeRequestEmail", "app.email.no_rate_limiter.app_error", nil, fmt.Sprintf("for key=%s", key), http.StatusInternalServerError)
}
// rate limit based on username as key
rateLimited, result, err := a.Srv().EmailService.PerDayEmailRateLimiter.RateLimit(username, 1)
// rate limit based on combination of date and action as key
rateLimited, result, err := a.Srv().EmailService.PerDayEmailRateLimiter.RateLimit(key, 1)
if err != nil {
return model.NewAppError("app.SendAdminUpgradeRequestEmail", "app.email.setup_rate_limiter.app_error", nil, fmt.Sprintf("username=%s, error=%v", username, err), http.StatusInternalServerError)
return model.NewAppError("app.SendAdminUpgradeRequestEmail", "app.email.setup_rate_limiter.app_error", nil, fmt.Sprintf("for key=%s, error=%v", key, err), http.StatusInternalServerError)
}
if rateLimited {
return model.NewAppError("app.SendAdminUpgradeRequestEmail",
"app.email.rate_limit_exceeded.app_error", map[string]interface{}{"RetryAfter": result.RetryAfter.String(), "ResetAfter": result.ResetAfter.String()},
fmt.Sprintf("username=%s, retry_after_secs=%f, reset_after_secs=%f",
username, result.RetryAfter.Seconds(), result.ResetAfter.Seconds()),
fmt.Sprintf("key=%s, retry_after_secs=%f, reset_after_secs=%f",
key, result.RetryAfter.Seconds(), result.ResetAfter.Seconds()),
http.StatusRequestEntityTooLarge)
}
@@ -59,7 +63,7 @@ func (a *App) SendAdminUpgradeRequestEmail(username string, subscription *model.
countNotOks := 0
for admin := range sysAdmins {
ok, err := a.Srv().EmailService.SendUpgradeEmail(username, sysAdmins[admin].Email, sysAdmins[admin].Locale, *a.Config().ServiceSettings.SiteURL)
ok, err := a.Srv().EmailService.SendUpgradeEmail(username, sysAdmins[admin].Email, sysAdmins[admin].Locale, *a.Config().ServiceSettings.SiteURL, action)
if !ok || err != nil {
a.Log().Error("Error sending upgrade request email", mlog.Err(err))
countNotOks++

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

@@ -634,14 +634,20 @@ func (es *EmailService) SendAtUserLimitWarningEmail(email string, locale string,
}
// SendUpgradeEmail formats an email template and sends an email to an admin specified in the email arg
func (es *EmailService) SendUpgradeEmail(user, email, locale, siteURL string) (bool, *model.AppError) {
func (es *EmailService) SendUpgradeEmail(user, email, locale, siteURL, action string) (bool, *model.AppError) {
T := utils.GetUserTranslations(locale)
subject := T("api.templates.upgrade_request_subject")
bodyPage := es.newEmailTemplate("cloud_upgrade_request_email", locale)
bodyPage.Props["Title"] = T("api.templates.upgrade_request_title", map[string]interface{}{"UserName": user})
bodyPage.Props["Info4"] = T("api.templates.upgrade_request_info4")
if action == model.InviteLimitation {
bodyPage.Props["Title"] = T("api.templates.upgrade_request_title", map[string]interface{}{"UserName": user})
bodyPage.Props["Info4"] = T("api.templates.upgrade_request_info4")
} else {
bodyPage.Props["Title"] = T("api.templates.upgrade_request_title2")
bodyPage.Props["Info4"] = T("api.templates.upgrade_request_info4_2")
}
subject := T("api.templates.upgrade_request_subject")
bodyPage.Props["Info5"] = T("api.templates.at_limit_info5")
bodyPage.Props["BillingPath"] = "admin_console/billing/subscription"
bodyPage.Props["SiteURL"] = siteURL

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

@@ -85,14 +85,51 @@ func TestSendAdminUpgradeRequestEmail(t *testing.T) {
*cfg.ExperimentalSettings.CloudUserLimit = 10
})
err := th.App.SendAdminUpgradeRequestEmail(th.BasicUser.Username, mockSubscription)
err := th.App.SendAdminUpgradeRequestEmail(th.BasicUser.Username, mockSubscription, model.InviteLimitation)
require.Nil(t, err)
err = th.App.SendAdminUpgradeRequestEmail(th.BasicUser2.Username, mockSubscription)
require.Nil(t, err)
// other attempts by the same user or other users to send emails are blocked by rate limiter
err = th.App.SendAdminUpgradeRequestEmail(th.BasicUser.Username, mockSubscription, model.InviteLimitation)
require.NotNil(t, err)
assert.Equal(t, err.Id, "app.email.rate_limit_exceeded.app_error")
// second attempt by the same user to send emails is blocked by rate limiter
err = th.App.SendAdminUpgradeRequestEmail(th.BasicUser.Username, mockSubscription)
err = th.App.SendAdminUpgradeRequestEmail(th.BasicUser2.Username, mockSubscription, model.InviteLimitation)
require.NotNil(t, err)
assert.Equal(t, err.Id, "app.email.rate_limit_exceeded.app_error")
}
func TestSendAdminUpgradeRequestEmailOnJoin(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
th.App.Srv().SetLicense(model.NewTestLicense("cloud"))
mockSubscription := &model.Subscription{
ID: "MySubscriptionID",
CustomerID: "MyCustomer",
ProductID: "SomeProductId",
AddOns: []string{},
StartAt: 1000000000,
EndAt: 2000000000,
CreateAt: 1000000000,
Seats: 100,
DNS: "some.dns.server",
IsPaidTier: "false",
}
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.ExperimentalSettings.CloudUserLimit = 10
})
err := th.App.SendAdminUpgradeRequestEmail(th.BasicUser.Username, mockSubscription, model.JoinLimitation)
require.Nil(t, err)
// other attempts by the same user or other users to send emails are blocked by rate limiter
err = th.App.SendAdminUpgradeRequestEmail(th.BasicUser.Username, mockSubscription, model.JoinLimitation)
require.NotNil(t, err)
assert.Equal(t, err.Id, "app.email.rate_limit_exceeded.app_error")
err = th.App.SendAdminUpgradeRequestEmail(th.BasicUser2.Username, mockSubscription, model.JoinLimitation)
require.NotNil(t, err)
assert.Equal(t, err.Id, "app.email.rate_limit_exceeded.app_error")
}

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

@@ -13264,7 +13264,7 @@ func (a *OpenTracingAppLayer) SendAckToPushProxy(ack *model.PushNotificationAck)
return resultVar0
}
func (a *OpenTracingAppLayer) SendAdminUpgradeRequestEmail(username string, subscription *model.Subscription) *model.AppError {
func (a *OpenTracingAppLayer) SendAdminUpgradeRequestEmail(username string, subscription *model.Subscription, action string) *model.AppError {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SendAdminUpgradeRequestEmail")
@@ -13276,7 +13276,7 @@ func (a *OpenTracingAppLayer) SendAdminUpgradeRequestEmail(username string, subs
}()
defer span.Finish()
resultVar0 := a.app.SendAdminUpgradeRequestEmail(username, subscription)
resultVar0 := a.app.SendAdminUpgradeRequestEmail(username, subscription, action)
if resultVar0 != nil {
span.LogFields(spanlog.Error(resultVar0))