From 8ac2dc50afbfea2e0cccf7df08ef21b2cc36bdb5 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 15 Jul 2021 16:37:16 +0200 Subject: [PATCH] [Provider] Send email on removal (#1463) --- .../src/CommCore/Services/ProviderService.cs | 19 ++++++++++++++++++- .../Services/ProviderServiceTests.cs | 6 ++++-- .../Provider/ProviderUserRemoved.html.hbs | 9 +++++++++ .../Provider/ProviderUserRemoved.text.hbs | 4 ++++ .../Provider/ProviderUserRemovedViewModel.cs | 7 +++++++ src/Core/Services/IMailService.cs | 1 + .../Implementations/HandlebarsMailService.cs | 14 ++++++++++++++ .../NoopImplementations/NoopMailService.cs | 5 +++++ 8 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 src/Core/MailTemplates/Handlebars/Provider/ProviderUserRemoved.html.hbs create mode 100644 src/Core/MailTemplates/Handlebars/Provider/ProviderUserRemoved.text.hbs create mode 100644 src/Core/Models/Mail/Provider/ProviderUserRemovedViewModel.cs diff --git a/bitwarden_license/src/CommCore/Services/ProviderService.cs b/bitwarden_license/src/CommCore/Services/ProviderService.cs index 973cb05e7..cc08b210b 100644 --- a/bitwarden_license/src/CommCore/Services/ProviderService.cs +++ b/bitwarden_license/src/CommCore/Services/ProviderService.cs @@ -259,7 +259,7 @@ namespace Bit.CommCore.Services await _providerUserRepository.ReplaceAsync(providerUser); events.Add((providerUser, EventType.ProviderUser_Confirmed, null)); - await _mailService.SendOrganizationConfirmedEmailAsync(provider.Name, user.Email); + await _mailService.SendProviderConfirmedEmailAsync(provider.Name, user.Email); result.Add(Tuple.Create(providerUser, "")); } catch (BadRequestException e) @@ -293,7 +293,17 @@ namespace Bit.CommCore.Services public async Task>> DeleteUsersAsync(Guid providerId, IEnumerable providerUserIds, Guid deletingUserId) { + var provider = await _providerRepository.GetByIdAsync(providerId); + + if (provider == null) + { + throw new NotFoundException(); + } + var providerUsers = await _providerUserRepository.GetManyAsync(providerUserIds); + var users = await _userRepository.GetManyAsync(providerUsers.Where(pu => pu.UserId.HasValue) + .Select(pu => pu.UserId.Value)); + var keyedUsers = users.ToDictionary(u => u.Id); if (!await HasConfirmedProviderAdminExceptAsync(providerId, providerUserIds)) { @@ -319,6 +329,13 @@ namespace Bit.CommCore.Services events.Add((providerUser, EventType.ProviderUser_Removed, null)); + var user = keyedUsers.GetValueOrDefault(providerUser.UserId.GetValueOrDefault()); + var email = user == null ? providerUser.Email : user.Email; + if (!string.IsNullOrWhiteSpace(email)) + { + await _mailService.SendProviderUserRemoved(provider.Name, email); + } + result.Add(Tuple.Create(providerUser, "")); deletedUserIds.Add(providerUser.Id); } diff --git a/bitwarden_license/test/CmmCore.Test/Services/ProviderServiceTests.cs b/bitwarden_license/test/CmmCore.Test/Services/ProviderServiceTests.cs index 1ec208dc0..d8443cd26 100644 --- a/bitwarden_license/test/CmmCore.Test/Services/ProviderServiceTests.cs +++ b/bitwarden_license/test/CmmCore.Test/Services/ProviderServiceTests.cs @@ -360,7 +360,8 @@ namespace Bit.CommCore.Test.Services providerUser.ProviderId = provider.Id; } providerUsers.Last().ProviderId = default; - + + sutProvider.GetDependency().GetByIdAsync(provider.Id).Returns(provider); var providerUserRepository = sutProvider.GetDependency(); providerUserRepository.GetManyAsync(default).ReturnsForAnyArgs(providerUsers); providerUserRepository.GetManyByProviderAsync(default, default).ReturnsForAnyArgs(new ProviderUser[] {}); @@ -383,7 +384,8 @@ namespace Bit.CommCore.Test.Services providerUser.ProviderId = provider.Id; } providerUsers.Last().ProviderId = default; - + + sutProvider.GetDependency().GetByIdAsync(provider.Id).Returns(provider); var providerUserRepository = sutProvider.GetDependency(); providerUserRepository.GetManyAsync(default).ReturnsForAnyArgs(providerUsers); providerUserRepository.GetManyByProviderAsync(default, default).ReturnsForAnyArgs(new[] {remainingOwner}); diff --git a/src/Core/MailTemplates/Handlebars/Provider/ProviderUserRemoved.html.hbs b/src/Core/MailTemplates/Handlebars/Provider/ProviderUserRemoved.html.hbs new file mode 100644 index 000000000..028d53c13 --- /dev/null +++ b/src/Core/MailTemplates/Handlebars/Provider/ProviderUserRemoved.html.hbs @@ -0,0 +1,9 @@ +{{#>FullHtmlLayout}} + + + + +
+ You have been removed from {{ProviderName}}. You will no longer have access to the Provider Portal. If you have an existing Bitwarden account, your account is unaffected. +
+{{/FullHtmlLayout}} diff --git a/src/Core/MailTemplates/Handlebars/Provider/ProviderUserRemoved.text.hbs b/src/Core/MailTemplates/Handlebars/Provider/ProviderUserRemoved.text.hbs new file mode 100644 index 000000000..ec1d7976c --- /dev/null +++ b/src/Core/MailTemplates/Handlebars/Provider/ProviderUserRemoved.text.hbs @@ -0,0 +1,4 @@ +{{#>BasicTextLayout}} +You have been removed from {{ProviderName}}. You will no longer have access to the Provider Portal. +If you have an existing Bitwarden account, your account is unaffected. +{{/BasicTextLayout}} diff --git a/src/Core/Models/Mail/Provider/ProviderUserRemovedViewModel.cs b/src/Core/Models/Mail/Provider/ProviderUserRemovedViewModel.cs new file mode 100644 index 000000000..4d64ed3d7 --- /dev/null +++ b/src/Core/Models/Mail/Provider/ProviderUserRemovedViewModel.cs @@ -0,0 +1,7 @@ +namespace Bit.Core.Models.Mail.Provider +{ + public class ProviderUserRemovedViewModel : BaseMailModel + { + public string ProviderName { get; set; } + } +} diff --git a/src/Core/Services/IMailService.cs b/src/Core/Services/IMailService.cs index e2071b5eb..afbae18a7 100644 --- a/src/Core/Services/IMailService.cs +++ b/src/Core/Services/IMailService.cs @@ -45,5 +45,6 @@ namespace Bit.Core.Services Task SendProviderSetupInviteEmailAsync(Provider provider, string token, string email); Task SendProviderInviteEmailAsync(string providerName, ProviderUser providerUser, string token, string email); Task SendProviderConfirmedEmailAsync(string providerName, string email); + Task SendProviderUserRemoved(string providerName, string email); } } diff --git a/src/Core/Services/Implementations/HandlebarsMailService.cs b/src/Core/Services/Implementations/HandlebarsMailService.cs index 92b5e678c..409dcb562 100644 --- a/src/Core/Services/Implementations/HandlebarsMailService.cs +++ b/src/Core/Services/Implementations/HandlebarsMailService.cs @@ -697,5 +697,19 @@ namespace Bit.Core.Services message.Category = "ProviderUserConfirmed"; await _mailDeliveryService.SendEmailAsync(message); } + + public async Task SendProviderUserRemoved(string providerName, string email) + { + var message = CreateDefaultMessage($"You Have Been Removed from {providerName}", email); + var model = new ProviderUserRemovedViewModel + { + ProviderName = CoreHelpers.SanitizeForEmail(providerName), + WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash, + SiteName = _globalSettings.SiteName + }; + await AddMessageContentAsync(message, "Provider.ProviderUserRemoved", model); + message.Category = "ProviderUserRemoved"; + await _mailDeliveryService.SendEmailAsync(message); + } } } diff --git a/src/Core/Services/NoopImplementations/NoopMailService.cs b/src/Core/Services/NoopImplementations/NoopMailService.cs index 144077c26..d7b17e78b 100644 --- a/src/Core/Services/NoopImplementations/NoopMailService.cs +++ b/src/Core/Services/NoopImplementations/NoopMailService.cs @@ -179,5 +179,10 @@ namespace Bit.Core.Services { return Task.FromResult(0); } + + public Task SendProviderUserRemoved(string providerName, string email) + { + return Task.FromResult(0); + } } }