2020-10-26 13:24:26 -04:00
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package app
import (
2021-02-16 15:03:08 +03:00
"fmt"
"net/http"
2021-02-24 17:37:24 +03:00
"time"
2021-02-16 15:03:08 +03:00
2021-05-11 13:00:44 +03:00
"github.com/mattermost/mattermost-server/v5/app/request"
2020-10-26 13:24:26 -04:00
"github.com/mattermost/mattermost-server/v5/model"
2021-03-05 09:18:37 +01:00
"github.com/mattermost/mattermost-server/v5/shared/mlog"
2020-10-26 13:24:26 -04:00
)
2020-11-25 15:45:15 -05:00
func ( a * App ) getSysAdminsEmailRecipients ( ) ( [ ] * model . User , * model . AppError ) {
userOptions := & model . UserGetOptions {
Page : 0 ,
PerPage : 100 ,
2021-07-12 20:05:36 +02:00
Role : model . SystemAdminRoleId ,
2020-11-25 15:45:15 -05:00
Inactive : false ,
}
return a . GetUsers ( userOptions )
}
2021-02-16 15:03:08 +03:00
// 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.
2021-02-24 17:37:24 +03:00
func ( a * App ) SendAdminUpgradeRequestEmail ( username string , subscription * model . Subscription , action string ) * model . AppError {
2021-02-16 15:03:08 +03:00
if a . Srv ( ) . License ( ) == nil || ( a . Srv ( ) . License ( ) != nil && ! * a . Srv ( ) . License ( ) . Features . Cloud ) {
return nil
}
if subscription != nil && subscription . IsPaidTier == "true" {
return nil
}
2021-02-24 17:37:24 +03:00
year , month , day := time . Now ( ) . Date ( )
key := fmt . Sprintf ( "%s-%d-%s-%d" , action , day , month , year )
2021-02-16 15:03:08 +03:00
if a . Srv ( ) . EmailService . PerDayEmailRateLimiter == nil {
2021-02-24 17:37:24 +03:00
return model . NewAppError ( "app.SendAdminUpgradeRequestEmail" , "app.email.no_rate_limiter.app_error" , nil , fmt . Sprintf ( "for key=%s" , key ) , http . StatusInternalServerError )
2021-02-16 15:03:08 +03:00
}
2021-02-24 17:37:24 +03:00
// rate limit based on combination of date and action as key
rateLimited , result , err := a . Srv ( ) . EmailService . PerDayEmailRateLimiter . RateLimit ( key , 1 )
2021-02-16 15:03:08 +03:00
if err != nil {
2021-02-24 17:37:24 +03:00
return model . NewAppError ( "app.SendAdminUpgradeRequestEmail" , "app.email.setup_rate_limiter.app_error" , nil , fmt . Sprintf ( "for key=%s, error=%v" , key , err ) , http . StatusInternalServerError )
2021-02-16 15:03:08 +03:00
}
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 ( ) } ,
2021-02-24 17:37:24 +03:00
fmt . Sprintf ( "key=%s, retry_after_secs=%f, reset_after_secs=%f" ,
key , result . RetryAfter . Seconds ( ) , result . ResetAfter . Seconds ( ) ) ,
2021-02-16 15:03:08 +03:00
http . StatusRequestEntityTooLarge )
}
sysAdmins , e := a . getSysAdminsEmailRecipients ( )
if e != nil {
return e
}
// we want to at least have one email sent out to an admin
countNotOks := 0
for admin := range sysAdmins {
2021-02-24 17:37:24 +03:00
ok , err := a . Srv ( ) . EmailService . SendUpgradeEmail ( username , sysAdmins [ admin ] . Email , sysAdmins [ admin ] . Locale , * a . Config ( ) . ServiceSettings . SiteURL , action )
2021-02-16 15:03:08 +03:00
if ! ok || err != nil {
a . Log ( ) . Error ( "Error sending upgrade request email" , mlog . Err ( err ) )
countNotOks ++
}
}
// if not even one admin got an email, we consider that this operation errored
if countNotOks == len ( sysAdmins ) {
return model . NewAppError ( "app.SendAdminUpgradeRequestEmail" , "app.user.send_emails.app_error" , nil , "" , http . StatusInternalServerError )
}
return nil
}
2021-06-07 17:38:33 +03:00
func ( a * App ) GetSubscriptionStats ( ) ( * model . SubscriptionStats , * model . AppError ) {
if a . Srv ( ) . License ( ) == nil || ! * a . Srv ( ) . License ( ) . Features . Cloud {
return nil , model . NewAppError ( "app.GetSubscriptionStats" , "api.cloud.license_error" , nil , "" , http . StatusInternalServerError )
}
subscription , appErr := a . Cloud ( ) . GetSubscription ( "" )
if appErr != nil {
return nil , model . NewAppError ( "app.GetSubscriptionStats" , "api.cloud.request_error" , nil , appErr . Error ( ) , http . StatusInternalServerError )
}
count , err := a . Srv ( ) . Store . User ( ) . Count ( model . UserCountOptions { } )
if err != nil {
return nil , model . NewAppError ( "app.GetSubscriptionStats" , "app.user.get_total_users_count.app_error" , nil , err . Error ( ) , http . StatusInternalServerError )
}
cloudUserLimit := * a . Config ( ) . ExperimentalSettings . CloudUserLimit
s := cloudUserLimit - count
return & model . SubscriptionStats {
RemainingSeats : int ( s ) ,
IsPaidTier : subscription . IsPaidTier ,
} , nil
}
func ( a * App ) CheckCloudAccountAtLimit ( ) ( bool , * model . AppError ) {
if a . Srv ( ) . License ( ) == nil || ( a . Srv ( ) . License ( ) != nil && ! * a . Srv ( ) . License ( ) . Features . Cloud ) {
// Not cloud instance, so no at limit checks
return false , nil
}
stats , err := a . GetSubscriptionStats ( )
if err != nil {
return false , err
}
if stats . IsPaidTier == "true" {
return false , nil
}
if stats . RemainingSeats < 1 {
return true , nil
}
return false , nil
}
2021-05-11 13:00:44 +03:00
func ( a * App ) CheckAndSendUserLimitWarningEmails ( c * request . Context ) * model . AppError {
2020-10-26 13:24:26 -04:00
if a . Srv ( ) . License ( ) == nil || ( a . Srv ( ) . License ( ) != nil && ! * a . Srv ( ) . License ( ) . Features . Cloud ) {
// Not cloud instance, do nothing
return nil
}
2021-05-11 13:00:44 +03:00
subscription , err := a . Cloud ( ) . GetSubscription ( c . Session ( ) . UserId )
2021-03-05 09:23:39 +01:00
if err != nil {
return model . NewAppError (
"app.CheckAndSendUserLimitWarningEmails" ,
"api.cloud.get_subscription.error" ,
nil ,
err . Error ( ) ,
http . StatusInternalServerError )
2020-10-26 13:24:26 -04:00
}
if subscription != nil && subscription . IsPaidTier == "true" {
// Paid subscription, do nothing
return nil
}
cloudUserLimit := * a . Config ( ) . ExperimentalSettings . CloudUserLimit
systemUserCount , _ := a . Srv ( ) . Store . User ( ) . Count ( model . UserCountOptions { } )
remainingUsers := cloudUserLimit - systemUserCount
if remainingUsers > 0 {
return nil
}
2021-03-05 09:23:39 +01:00
sysAdmins , appErr := a . getSysAdminsEmailRecipients ( )
if appErr != nil {
return model . NewAppError (
"app.CheckAndSendUserLimitWarningEmails" ,
"api.cloud.get_admins_emails.error" ,
nil ,
appErr . Error ( ) ,
http . StatusInternalServerError )
2020-10-26 13:24:26 -04:00
}
// -1 means they are 1 user over the limit - we only want to send the email for the 11th user
if remainingUsers == - 1 {
// Over limit by 1 user
for admin := range sysAdmins {
2021-03-05 09:23:39 +01:00
_ , appErr := a . Srv ( ) . EmailService . SendOverUserLimitWarningEmail ( sysAdmins [ admin ] . Email , sysAdmins [ admin ] . Locale , * a . Config ( ) . ServiceSettings . SiteURL )
if appErr != nil {
a . Log ( ) . Error (
"Error sending user limit warning email to admin" ,
mlog . String ( "username" , sysAdmins [ admin ] . Username ) ,
mlog . Err ( err ) ,
)
}
2020-10-26 13:24:26 -04:00
}
} else if remainingUsers == 0 {
// At limit
for admin := range sysAdmins {
2021-07-19 18:26:06 +03:00
_ , err := a . Srv ( ) . EmailService . SendAtUserLimitWarningEmail ( sysAdmins [ admin ] . Email , sysAdmins [ admin ] . Locale , * a . Config ( ) . ServiceSettings . SiteURL )
if err != nil {
2021-03-05 09:23:39 +01:00
a . Log ( ) . Error (
"Error sending user limit warning email to admin" ,
mlog . String ( "username" , sysAdmins [ admin ] . Username ) ,
mlog . Err ( err ) ,
)
}
2020-10-26 13:24:26 -04:00
}
}
return nil
}
2020-11-25 15:45:15 -05:00
func ( a * App ) SendPaymentFailedEmail ( failedPayment * model . FailedPayment ) * model . AppError {
sysAdmins , err := a . getSysAdminsEmailRecipients ( )
if err != nil {
return err
}
for _ , admin := range sysAdmins {
_ , err := a . Srv ( ) . EmailService . SendPaymentFailedEmail ( admin . Email , admin . Locale , failedPayment , * a . Config ( ) . ServiceSettings . SiteURL )
if err != nil {
a . Log ( ) . Error ( "Error sending payment failed email" , mlog . Err ( err ) )
}
}
return nil
}
2020-12-03 16:02:43 -05:00
// SendNoCardPaymentFailedEmail
func ( a * App ) SendNoCardPaymentFailedEmail ( ) * model . AppError {
sysAdmins , err := a . getSysAdminsEmailRecipients ( )
if err != nil {
return err
}
for _ , admin := range sysAdmins {
err := a . Srv ( ) . EmailService . SendNoCardPaymentFailedEmail ( admin . Email , admin . Locale , * a . Config ( ) . ServiceSettings . SiteURL )
if err != nil {
a . Log ( ) . Error ( "Error sending payment failed email" , mlog . Err ( err ) )
}
}
return nil
}
2021-04-14 11:36:36 -04:00
func ( a * App ) SendCloudTrialEndWarningEmail ( trialEndDate , siteURL string ) * model . AppError {
sysAdmins , e := a . getSysAdminsEmailRecipients ( )
if e != nil {
return e
}
// we want to at least have one email sent out to an admin
countNotOks := 0
for admin := range sysAdmins {
2021-04-23 21:45:47 +03:00
name := sysAdmins [ admin ] . FirstName
if name == "" {
name = sysAdmins [ admin ] . Username
}
err := a . Srv ( ) . EmailService . SendCloudTrialEndWarningEmail ( sysAdmins [ admin ] . Email , name , trialEndDate , sysAdmins [ admin ] . Locale , siteURL )
2021-04-14 11:36:36 -04:00
if err != nil {
a . Log ( ) . Error ( "Error sending trial ending warning to" , mlog . String ( "email" , sysAdmins [ admin ] . Email ) , mlog . Err ( err ) )
countNotOks ++
}
}
// if not even one admin got an email, we consider that this operation errored
if countNotOks == len ( sysAdmins ) {
return model . NewAppError ( "app.SendCloudTrialEndWarningEmail" , "app.user.send_emails.app_error" , nil , "" , http . StatusInternalServerError )
}
return nil
}
2021-04-23 21:45:47 +03:00
func ( a * App ) SendCloudTrialEndedEmail ( ) * model . AppError {
sysAdmins , e := a . getSysAdminsEmailRecipients ( )
if e != nil {
return e
}
// we want to at least have one email sent out to an admin
countNotOks := 0
for admin := range sysAdmins {
name := sysAdmins [ admin ] . FirstName
if name == "" {
name = sysAdmins [ admin ] . Username
}
err := a . Srv ( ) . EmailService . SendCloudTrialEndedEmail ( sysAdmins [ admin ] . Email , name , sysAdmins [ admin ] . Locale , * a . Config ( ) . ServiceSettings . SiteURL )
if err != nil {
a . Log ( ) . Error ( "Error sending trial ended email to" , mlog . String ( "email" , sysAdmins [ admin ] . Email ) , mlog . Err ( err ) )
countNotOks ++
}
}
// if not even one admin got an email, we consider that this operation errored
if countNotOks == len ( sysAdmins ) {
return model . NewAppError ( "app.SendCloudTrialEndedEmail" , "app.user.send_emails.app_error" , nil , "" , http . StatusInternalServerError )
}
return nil
}