[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>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
6b388871a9
Коммит
0dad204007
@@ -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
|
||||
|
||||
20
app/cloud.go
20
app/cloud.go
@@ -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++
|
||||
|
||||
16
app/email.go
16
app/email.go
@@ -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))
|
||||
|
||||
Ссылка в новой задаче
Block a user