[CLD-6894] Add 60, 30, and 7 day reminder emails for Cloud Renewals (#25883)

* Add email notifications for Cloud Renewals

* Updates

* Updates

* Update app-layers

* make build-templates

* Add ability to set an env variable as a unix timestamp in s as the current date when getting DaysToExpiration

* Add a mechanism to ensure at least one admin receives every email

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
Co-authored-by: Gabe Jackson <3694686+gabrieljackson@users.noreply.github.com>
Этот коммит содержится в:
Nick Misasi
2024-01-11 13:07:41 -05:00
коммит произвёл GitHub
родитель 04cf1ed114
Коммит aafe7439af
15 изменённых файлов: 889 добавлений и 1 удалений

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

@@ -8,11 +8,13 @@ import (
"fmt"
"io"
"net/http"
"strconv"
"time"
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/mlog"
"github.com/mattermost/mattermost/server/v8/channels/product"
"github.com/mattermost/mattermost/server/v8/channels/store"
"github.com/mattermost/mattermost/server/v8/einterfaces"
)
@@ -266,3 +268,98 @@ func (a *App) SendSubscriptionHistoryEvent(userID string) (*model.SubscriptionHi
}
return a.Cloud().CreateOrUpdateSubscriptionHistoryEvent(userID, int(userCount))
}
func (a *App) DoSubscriptionRenewalCheck() {
if !a.License().IsCloud() || !a.Config().FeatureFlags.CloudAnnualRenewals {
return
}
subscription, err := a.Cloud().GetSubscription("")
if err != nil {
a.Log().Error("Error getting subscription", mlog.Err(err))
return
}
if subscription == nil {
a.Log().Error("Subscription not found")
return
}
sysVar, err := a.Srv().Store().System().GetByName(model.CloudRenewalEmail)
if err != nil {
// We only care about the error if it wasn't a not found error
if _, ok := err.(*store.ErrNotFound); !ok {
a.Log().Error(err.Error())
}
}
prevSentEmail := int64(0)
if sysVar != nil {
// We don't care about parse errors because it's possible the value is empty, and we've already defaulted to 0
prevSentEmail, _ = strconv.ParseInt(sysVar.Value, 10, 64)
}
if subscription.WillRenew == "true" {
// They've already completed the renewal process so no need to email them.
// We can zero out the system variable so that this process will work again next year
if prevSentEmail != 0 {
sysVar.Value = "0"
err = a.Srv().Store().System().SaveOrUpdate(sysVar)
if err != nil {
a.Log().Error("Error saving system variable", mlog.Err(err))
}
}
return
}
var emailFunc func(email, locale, siteURL string) error
daysToExpiration := subscription.DaysToExpiration()
// Only send the email if within the period and it's not already been sent
// This allows the email to send on day 59 if for whatever reason it was unable to on day 60
if daysToExpiration <= 60 && daysToExpiration > 30 && prevSentEmail != 60 {
emailFunc = a.Srv().EmailService.SendCloudRenewalEmail60
prevSentEmail = 60
} else if daysToExpiration <= 30 && daysToExpiration > 7 && prevSentEmail != 30 {
emailFunc = a.Srv().EmailService.SendCloudRenewalEmail30
prevSentEmail = 30
} else if daysToExpiration <= 7 && daysToExpiration > 3 && prevSentEmail != 7 {
emailFunc = a.Srv().EmailService.SendCloudRenewalEmail7
prevSentEmail = 7
}
if emailFunc == nil {
return
}
sysAdmins, aErr := a.getSysAdminsEmailRecipients()
if aErr != nil {
a.Log().Error("Error getting sys admins", mlog.Err(aErr))
return
}
numFailed := 0
for _, admin := range sysAdmins {
err = emailFunc(admin.Email, admin.Locale, *a.Config().ServiceSettings.SiteURL)
if err != nil {
a.Log().Error("Error sending renewal email", mlog.Err(err))
numFailed += 1
}
}
if numFailed == len(sysAdmins) {
// If all emails failed, we don't want to update the system variable
return
}
updatedSysVar := &model.System{
Name: model.CloudRenewalEmail,
Value: strconv.FormatInt(prevSentEmail, 10),
}
err = a.Srv().Store().System().SaveOrUpdate(updatedSysVar)
if err != nil {
a.Log().Error("Error saving system variable", mlog.Err(err))
}
}