1
0
mirror of https://github.com/bitwarden/server.git synced 2024-11-21 12:05:42 +01:00

License expiration email for self-hosted org/premium accounts

This commit is contained in:
Matt Portune 2020-05-18 16:06:34 -04:00
parent e71617886a
commit 2cf7f18858
8 changed files with 62 additions and 0 deletions

View File

@ -0,0 +1,18 @@
{{#>FullHtmlLayout}}
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
<tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
<td class="content-block" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0 0 10px; -webkit-text-size-adjust: none;" valign="top">
{{#if IsOrganization}}
This email is to notify you that your Bitwarden organization license has expired and must be updated for continued use. See the following article for details about replacing your license file:
{{else}}
This email is to notify you that your Bitwarden premium license has expired and must be updated for continued use. See the following article for details about replacing your license file:
{{/if}}
</td>
</tr>
<tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
<td class="content-block last" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0; -webkit-text-size-adjust: none;" valign="top">
{{{link 'https://bitwarden.com/help/article/licensing-on-premise/'}}}
</td>
</tr>
</table>
{{/FullHtmlLayout}}

View File

@ -0,0 +1,9 @@
{{#>BasicTextLayout}}
{{#if IsOrganization}}
This email is to notify you that your Bitwarden organization license has expired and must be updated for continued use. See the following article for details about replacing your license file:
{{else}}
This email is to notify you that your Bitwarden premium license has expired and must be updated for continued use. See the following article for details about replacing your license file:
{{/if}}
https://bitwarden.com/help/article/licensing-on-premise/
{{/BasicTextLayout}}

View File

@ -0,0 +1,7 @@
namespace Bit.Core.Models.Mail
{
public class LicenseExpiredViewModel : BaseMailModel
{
public bool IsOrganization { get; set; }
}
}

View File

@ -25,6 +25,7 @@ namespace Bit.Core.Services
bool mentionInvoices);
Task SendPaymentFailedAsync(string email, decimal amount, bool mentionInvoices);
Task SendAddedCreditAsync(string email, decimal amount);
Task SendLicenseExpiredAsync(IEnumerable<string> emails, bool isOrganization);
Task SendNewDeviceLoggedInEmail(string email, string deviceType, DateTime timestamp, string ip);
Task SendRecoverTwoFactorEmail(string email, DateTime timestamp, string ip);
}

View File

@ -278,6 +278,18 @@ namespace Bit.Core.Services
message.Category = "AddedCredit";
await _mailDeliveryService.SendEmailAsync(message);
}
public async Task SendLicenseExpiredAsync(IEnumerable<string> emails, bool isOrganization)
{
var message = CreateDefaultMessage("License Expired", emails);
var model = new LicenseExpiredViewModel
{
IsOrganization = isOrganization
};
await AddMessageContentAsync(message, "LicenseExpired", model);
message.Category = "LicenseExpired";
await _mailDeliveryService.SendEmailAsync(message);
}
public async Task SendNewDeviceLoggedInEmail(string email, string deviceType, DateTime timestamp, string ip)
{

View File

@ -24,6 +24,7 @@ namespace Bit.Core.Services
private readonly IUserRepository _userRepository;
private readonly IOrganizationRepository _organizationRepository;
private readonly IOrganizationUserRepository _organizationUserRepository;
private readonly IMailService _mailService;
private readonly ILogger<LicensingService> _logger;
private IDictionary<Guid, DateTime> _userCheckCache = new Dictionary<Guid, DateTime>();
@ -32,6 +33,7 @@ namespace Bit.Core.Services
IUserRepository userRepository,
IOrganizationRepository organizationRepository,
IOrganizationUserRepository organizationUserRepository,
IMailService mailService,
IWebHostEnvironment environment,
ILogger<LicensingService> logger,
GlobalSettings globalSettings)
@ -39,6 +41,7 @@ namespace Bit.Core.Services
_userRepository = userRepository;
_organizationRepository = organizationRepository;
_organizationUserRepository = organizationUserRepository;
_mailService = mailService;
_logger = logger;
_globalSettings = globalSettings;
@ -124,6 +127,8 @@ namespace Bit.Core.Services
org.ExpirationDate = license?.Expires ?? DateTime.UtcNow;
org.RevisionDate = DateTime.UtcNow;
await _organizationRepository.ReplaceAsync(org);
await _mailService.SendLicenseExpiredAsync(new List<string> {org.BillingEmail}, true);
}
public async Task ValidateUsersAsync()
@ -213,6 +218,8 @@ namespace Bit.Core.Services
user.PremiumExpirationDate = license?.Expires ?? DateTime.UtcNow;
user.RevisionDate = DateTime.UtcNow;
await _userRepository.ReplaceAsync(user);
await _mailService.SendLicenseExpiredAsync(new List<string> {user.Email}, false);
}
public bool VerifyLicense(ILicense license)

View File

@ -88,6 +88,11 @@ namespace Bit.Core.Services
return Task.FromResult(0);
}
public Task SendLicenseExpiredAsync(IEnumerable<string> emails, bool isOrganization)
{
return Task.FromResult(0);
}
public Task SendNewDeviceLoggedInEmail(string email, string deviceType, DateTime timestamp, string ip)
{
return Task.FromResult(0);

View File

@ -16,6 +16,7 @@ namespace Bit.Core.Test.Services
private readonly IUserRepository _userRepository;
private readonly IOrganizationRepository _organizationRepository;
private readonly IOrganizationUserRepository _organizationUserRepository;
private readonly IMailService _mailService;
private readonly IWebHostEnvironment _hostingEnvironment;
private readonly ILogger<LicensingService> _logger;
@ -24,6 +25,7 @@ namespace Bit.Core.Test.Services
_userRepository = Substitute.For<IUserRepository>();
_organizationRepository = Substitute.For<IOrganizationRepository>();
_organizationUserRepository = Substitute.For<IOrganizationUserRepository>();
_mailService = Substitute.For<IMailService>();
_hostingEnvironment = Substitute.For<IWebHostEnvironment>();
_logger = Substitute.For<ILogger<LicensingService>>();
_globalSettings = new GlobalSettings();
@ -32,6 +34,7 @@ namespace Bit.Core.Test.Services
_userRepository,
_organizationRepository,
_organizationUserRepository,
_mailService,
_hostingEnvironment,
_logger,
_globalSettings