mirror of
https://github.com/bitwarden/server.git
synced 2025-05-20 11:04:31 -05:00
[SG-72] Sync changed email address with stripe (#2042)
* sync changed email address with strip * sync changed email address with strip * fixed formatting * throw exception if not successful * Added revert if stripe sync fails * Added revert if stripe sync fails * Added revert if stripe sync fails * created stripe sync service * fixed lint issue * reverted to use stripe exception message * added null checks to customer id and email address * added braces * removed empty email
This commit is contained in:
parent
b39a43210d
commit
8e79c20dce
13
src/Core/Exceptions/InvalidEmailException.cs
Normal file
13
src/Core/Exceptions/InvalidEmailException.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Bit.Core.Exceptions
|
||||||
|
{
|
||||||
|
public class InvalidEmailException : Exception
|
||||||
|
{
|
||||||
|
public InvalidEmailException()
|
||||||
|
: base("Invalid email.")
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
src/Core/Exceptions/InvalidGatewayCustomerIdException.cs
Normal file
13
src/Core/Exceptions/InvalidGatewayCustomerIdException.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Bit.Core.Exceptions
|
||||||
|
{
|
||||||
|
public class InvalidGatewayCustomerIdException : Exception
|
||||||
|
{
|
||||||
|
public InvalidGatewayCustomerIdException()
|
||||||
|
: base("Invalid gateway customerId.")
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
src/Core/Services/IStripeSyncService.cs
Normal file
9
src/Core/Services/IStripeSyncService.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Bit.Core.Services
|
||||||
|
{
|
||||||
|
public interface IStripeSyncService
|
||||||
|
{
|
||||||
|
Task UpdateCustomerEmailAddress(string gatewayCustomerId, string emailAddress);
|
||||||
|
}
|
||||||
|
}
|
33
src/Core/Services/Implementations/StripeSyncService.cs
Normal file
33
src/Core/Services/Implementations/StripeSyncService.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Bit.Core.Exceptions;
|
||||||
|
|
||||||
|
namespace Bit.Core.Services
|
||||||
|
{
|
||||||
|
public class StripeSyncService : IStripeSyncService
|
||||||
|
{
|
||||||
|
private readonly IStripeAdapter _stripeAdapter;
|
||||||
|
|
||||||
|
public StripeSyncService(IStripeAdapter stripeAdapter)
|
||||||
|
{
|
||||||
|
_stripeAdapter = stripeAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UpdateCustomerEmailAddress(string gatewayCustomerId, string emailAddress)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(gatewayCustomerId))
|
||||||
|
{
|
||||||
|
throw new InvalidGatewayCustomerIdException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(emailAddress))
|
||||||
|
{
|
||||||
|
throw new InvalidEmailException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var customer = await _stripeAdapter.CustomerGetAsync(gatewayCustomerId);
|
||||||
|
|
||||||
|
await _stripeAdapter.CustomerUpdateAsync(customer.Id,
|
||||||
|
new Stripe.CustomerUpdateOptions { Email = emailAddress });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -52,6 +52,7 @@ namespace Bit.Core.Services
|
|||||||
private readonly IOrganizationService _organizationService;
|
private readonly IOrganizationService _organizationService;
|
||||||
private readonly IProviderUserRepository _providerUserRepository;
|
private readonly IProviderUserRepository _providerUserRepository;
|
||||||
private readonly IDeviceRepository _deviceRepository;
|
private readonly IDeviceRepository _deviceRepository;
|
||||||
|
private readonly IStripeSyncService _stripeSyncService;
|
||||||
|
|
||||||
public UserService(
|
public UserService(
|
||||||
IUserRepository userRepository,
|
IUserRepository userRepository,
|
||||||
@ -81,7 +82,8 @@ namespace Bit.Core.Services
|
|||||||
IGlobalSettings globalSettings,
|
IGlobalSettings globalSettings,
|
||||||
IOrganizationService organizationService,
|
IOrganizationService organizationService,
|
||||||
IProviderUserRepository providerUserRepository,
|
IProviderUserRepository providerUserRepository,
|
||||||
IDeviceRepository deviceRepository)
|
IDeviceRepository deviceRepository,
|
||||||
|
IStripeSyncService stripeSyncService)
|
||||||
: base(
|
: base(
|
||||||
store,
|
store,
|
||||||
optionsAccessor,
|
optionsAccessor,
|
||||||
@ -117,6 +119,7 @@ namespace Bit.Core.Services
|
|||||||
_organizationService = organizationService;
|
_organizationService = organizationService;
|
||||||
_providerUserRepository = providerUserRepository;
|
_providerUserRepository = providerUserRepository;
|
||||||
_deviceRepository = deviceRepository;
|
_deviceRepository = deviceRepository;
|
||||||
|
_stripeSyncService = stripeSyncService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Guid? GetProperUserId(ClaimsPrincipal principal)
|
public Guid? GetProperUserId(ClaimsPrincipal principal)
|
||||||
@ -543,6 +546,14 @@ namespace Bit.Core.Services
|
|||||||
return IdentityResult.Failed(_identityErrorDescriber.DuplicateEmail(newEmail));
|
return IdentityResult.Failed(_identityErrorDescriber.DuplicateEmail(newEmail));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var previousState = new
|
||||||
|
{
|
||||||
|
Key = user.Key,
|
||||||
|
MasterPassword = user.MasterPassword,
|
||||||
|
SecurityStamp = user.SecurityStamp,
|
||||||
|
Email = user.Email
|
||||||
|
};
|
||||||
|
|
||||||
var result = await UpdatePasswordHash(user, newMasterPassword);
|
var result = await UpdatePasswordHash(user, newMasterPassword);
|
||||||
if (!result.Succeeded)
|
if (!result.Succeeded)
|
||||||
{
|
{
|
||||||
@ -554,6 +565,32 @@ namespace Bit.Core.Services
|
|||||||
user.EmailVerified = true;
|
user.EmailVerified = true;
|
||||||
user.RevisionDate = user.AccountRevisionDate = DateTime.UtcNow;
|
user.RevisionDate = user.AccountRevisionDate = DateTime.UtcNow;
|
||||||
await _userRepository.ReplaceAsync(user);
|
await _userRepository.ReplaceAsync(user);
|
||||||
|
|
||||||
|
if (user.Gateway == GatewayType.Stripe)
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _stripeSyncService.UpdateCustomerEmailAddress(user.GatewayCustomerId,
|
||||||
|
user.BillingEmailAddress());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
//if sync to strip fails, update email and securityStamp to previous
|
||||||
|
user.Key = previousState.Key;
|
||||||
|
user.Email = previousState.Email;
|
||||||
|
user.RevisionDate = user.AccountRevisionDate = DateTime.UtcNow;
|
||||||
|
user.MasterPassword = previousState.MasterPassword;
|
||||||
|
user.SecurityStamp = previousState.SecurityStamp;
|
||||||
|
|
||||||
|
await _userRepository.ReplaceAsync(user);
|
||||||
|
return IdentityResult.Failed(new IdentityError
|
||||||
|
{
|
||||||
|
Description = ex.Message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await _pushService.PushLogOutAsync(user.Id);
|
await _pushService.PushLogOutAsync(user.Id);
|
||||||
|
|
||||||
return IdentityResult.Success;
|
return IdentityResult.Success;
|
||||||
|
@ -148,6 +148,7 @@ namespace Bit.SharedWeb.Utilities
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
services.AddSingleton<IPaymentService, StripePaymentService>();
|
services.AddSingleton<IPaymentService, StripePaymentService>();
|
||||||
|
services.AddSingleton<IStripeSyncService, StripeSyncService>();
|
||||||
services.AddSingleton<IMailService, HandlebarsMailService>();
|
services.AddSingleton<IMailService, HandlebarsMailService>();
|
||||||
services.AddSingleton<ILicensingService, LicensingService>();
|
services.AddSingleton<ILicensingService, LicensingService>();
|
||||||
services.AddTokenizers();
|
services.AddTokenizers();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user