mirror of
https://github.com/bitwarden/server
synced 2025-12-26 21:23:39 +00:00
Merge branch 'main' into billing/PM-24964/msp-unable-verfy-bank-account
This commit is contained in:
@@ -51,6 +51,7 @@ public class WebhookIntegrationHandlerTests
|
||||
|
||||
Assert.True(result.Success);
|
||||
Assert.Equal(result.Message, message);
|
||||
Assert.Empty(result.FailureReason);
|
||||
|
||||
sutProvider.GetDependency<IHttpClientFactory>().Received(1).CreateClient(
|
||||
Arg.Is(AssertHelper.AssertPropertyEqual(WebhookIntegrationHandler.HttpClientName))
|
||||
@@ -59,6 +60,7 @@ public class WebhookIntegrationHandlerTests
|
||||
Assert.Single(_handler.CapturedRequests);
|
||||
var request = _handler.CapturedRequests[0];
|
||||
Assert.NotNull(request);
|
||||
Assert.NotNull(request.Content);
|
||||
var returned = await request.Content.ReadAsStringAsync();
|
||||
|
||||
Assert.Equal(HttpMethod.Post, request.Method);
|
||||
@@ -77,6 +79,7 @@ public class WebhookIntegrationHandlerTests
|
||||
|
||||
Assert.True(result.Success);
|
||||
Assert.Equal(result.Message, message);
|
||||
Assert.Empty(result.FailureReason);
|
||||
|
||||
sutProvider.GetDependency<IHttpClientFactory>().Received(1).CreateClient(
|
||||
Arg.Is(AssertHelper.AssertPropertyEqual(WebhookIntegrationHandler.HttpClientName))
|
||||
@@ -85,6 +88,7 @@ public class WebhookIntegrationHandlerTests
|
||||
Assert.Single(_handler.CapturedRequests);
|
||||
var request = _handler.CapturedRequests[0];
|
||||
Assert.NotNull(request);
|
||||
Assert.NotNull(request.Content);
|
||||
var returned = await request.Content.ReadAsStringAsync();
|
||||
|
||||
Assert.Equal(HttpMethod.Post, request.Method);
|
||||
|
||||
@@ -329,13 +329,165 @@ public class SubscriberServiceTests
|
||||
#endregion
|
||||
|
||||
#region GetPaymentMethod
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task GetPaymentMethod_NullSubscriber_ThrowsArgumentNullException(
|
||||
SutProvider<SubscriberService> sutProvider) =>
|
||||
await Assert.ThrowsAsync<ArgumentNullException>(() => sutProvider.Sut.GetPaymentSource(null));
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task GetPaymentMethod_Braintree_NoDefaultPaymentMethod_ReturnsNull(
|
||||
public async Task GetPaymentMethod_WithNegativeStripeAccountBalance_ReturnsCorrectAccountCreditAmount(Organization organization,
|
||||
SutProvider<SubscriberService> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
// Stripe reports balance in cents as a negative number for credit
|
||||
const int stripeAccountBalance = -593; // $5.93 credit (negative cents)
|
||||
const decimal creditAmount = 5.93M; // Same value in dollars
|
||||
|
||||
|
||||
var customer = new Customer
|
||||
{
|
||||
Balance = stripeAccountBalance,
|
||||
Subscriptions = new StripeList<Subscription>()
|
||||
{
|
||||
Data =
|
||||
[new Subscription { Id = organization.GatewaySubscriptionId, Status = "active" }]
|
||||
},
|
||||
InvoiceSettings = new CustomerInvoiceSettings
|
||||
{
|
||||
DefaultPaymentMethod = new PaymentMethod
|
||||
{
|
||||
Type = StripeConstants.PaymentMethodTypes.USBankAccount,
|
||||
UsBankAccount = new PaymentMethodUsBankAccount { BankName = "Chase", Last4 = "9999" }
|
||||
}
|
||||
}
|
||||
};
|
||||
sutProvider.GetDependency<IStripeAdapter>().CustomerGetAsync(organization.GatewayCustomerId,
|
||||
Arg.Is<CustomerGetOptions>(options => options.Expand.Contains("default_source") &&
|
||||
options.Expand.Contains("invoice_settings.default_payment_method")
|
||||
&& options.Expand.Contains("subscriptions")
|
||||
&& options.Expand.Contains("tax_ids")))
|
||||
.Returns(customer);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.GetPaymentMethod(organization);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal(creditAmount, result.AccountCredit);
|
||||
await sutProvider.GetDependency<IStripeAdapter>().Received(1).CustomerGetAsync(
|
||||
organization.GatewayCustomerId,
|
||||
Arg.Is<CustomerGetOptions>(options =>
|
||||
options.Expand.Contains("default_source") &&
|
||||
options.Expand.Contains("invoice_settings.default_payment_method") &&
|
||||
options.Expand.Contains("subscriptions") &&
|
||||
options.Expand.Contains("tax_ids")));
|
||||
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task GetPaymentMethod_WithZeroStripeAccountBalance_ReturnsCorrectAccountCreditAmount(
|
||||
Organization organization, SutProvider<SubscriberService> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
const int stripeAccountBalance = 0;
|
||||
|
||||
var customer = new Customer
|
||||
{
|
||||
Balance = stripeAccountBalance,
|
||||
Subscriptions = new StripeList<Subscription>()
|
||||
{
|
||||
Data =
|
||||
[new Subscription { Id = organization.GatewaySubscriptionId, Status = "active" }]
|
||||
},
|
||||
InvoiceSettings = new CustomerInvoiceSettings
|
||||
{
|
||||
DefaultPaymentMethod = new PaymentMethod
|
||||
{
|
||||
Type = StripeConstants.PaymentMethodTypes.USBankAccount,
|
||||
UsBankAccount = new PaymentMethodUsBankAccount { BankName = "Chase", Last4 = "9999" }
|
||||
}
|
||||
}
|
||||
};
|
||||
sutProvider.GetDependency<IStripeAdapter>().CustomerGetAsync(organization.GatewayCustomerId,
|
||||
Arg.Is<CustomerGetOptions>(options => options.Expand.Contains("default_source") &&
|
||||
options.Expand.Contains("invoice_settings.default_payment_method")
|
||||
&& options.Expand.Contains("subscriptions")
|
||||
&& options.Expand.Contains("tax_ids")))
|
||||
.Returns(customer);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.GetPaymentMethod(organization);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal(0, result.AccountCredit);
|
||||
await sutProvider.GetDependency<IStripeAdapter>().Received(1).CustomerGetAsync(
|
||||
organization.GatewayCustomerId,
|
||||
Arg.Is<CustomerGetOptions>(options =>
|
||||
options.Expand.Contains("default_source") &&
|
||||
options.Expand.Contains("invoice_settings.default_payment_method") &&
|
||||
options.Expand.Contains("subscriptions") &&
|
||||
options.Expand.Contains("tax_ids")));
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task GetPaymentMethod_WithPositiveStripeAccountBalance_ReturnsCorrectAccountCreditAmount(
|
||||
Organization organization, SutProvider<SubscriberService> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
const int stripeAccountBalance = 593; // $5.93 charge balance
|
||||
const decimal accountBalance = -5.93M; // account balance
|
||||
var customer = new Customer
|
||||
{
|
||||
Balance = stripeAccountBalance,
|
||||
Subscriptions = new StripeList<Subscription>()
|
||||
{
|
||||
Data =
|
||||
[new Subscription { Id = organization.GatewaySubscriptionId, Status = "active" }]
|
||||
},
|
||||
InvoiceSettings = new CustomerInvoiceSettings
|
||||
{
|
||||
DefaultPaymentMethod = new PaymentMethod
|
||||
{
|
||||
Type = StripeConstants.PaymentMethodTypes.USBankAccount,
|
||||
UsBankAccount = new PaymentMethodUsBankAccount { BankName = "Chase", Last4 = "9999" }
|
||||
}
|
||||
}
|
||||
};
|
||||
sutProvider.GetDependency<IStripeAdapter>().CustomerGetAsync(organization.GatewayCustomerId,
|
||||
Arg.Is<CustomerGetOptions>(options => options.Expand.Contains("default_source") &&
|
||||
options.Expand.Contains("invoice_settings.default_payment_method")
|
||||
&& options.Expand.Contains("subscriptions")
|
||||
&& options.Expand.Contains("tax_ids")))
|
||||
.Returns(customer);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.GetPaymentMethod(organization);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal(accountBalance, result.AccountCredit);
|
||||
await sutProvider.GetDependency<IStripeAdapter>().Received(1).CustomerGetAsync(
|
||||
organization.GatewayCustomerId,
|
||||
Arg.Is<CustomerGetOptions>(options =>
|
||||
options.Expand.Contains("default_source") &&
|
||||
options.Expand.Contains("invoice_settings.default_payment_method") &&
|
||||
options.Expand.Contains("subscriptions") &&
|
||||
options.Expand.Contains("tax_ids")));
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetPaymentSource
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task GetPaymentSource_NullSubscriber_ThrowsArgumentNullException(
|
||||
SutProvider<SubscriberService> sutProvider) =>
|
||||
await Assert.ThrowsAsync<ArgumentNullException>(() => sutProvider.Sut.GetPaymentSource(null));
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task GetPaymentSource_Braintree_NoDefaultPaymentMethod_ReturnsNull(
|
||||
Provider provider,
|
||||
SutProvider<SubscriberService> sutProvider)
|
||||
{
|
||||
@@ -372,7 +524,7 @@ public class SubscriberServiceTests
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task GetPaymentMethod_Braintree_PayPalAccount_Succeeds(
|
||||
public async Task GetPaymentSource_Braintree_PayPalAccount_Succeeds(
|
||||
Provider provider,
|
||||
SutProvider<SubscriberService> sutProvider)
|
||||
{
|
||||
@@ -421,7 +573,7 @@ public class SubscriberServiceTests
|
||||
// TODO: Determine if we need to test Braintree.UsBankAccount
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task GetPaymentMethod_Stripe_BankAccountPaymentMethod_Succeeds(
|
||||
public async Task GetPaymentSource_Stripe_BankAccountPaymentMethod_Succeeds(
|
||||
Provider provider,
|
||||
SutProvider<SubscriberService> sutProvider)
|
||||
{
|
||||
@@ -455,7 +607,7 @@ public class SubscriberServiceTests
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task GetPaymentMethod_Stripe_CardPaymentMethod_Succeeds(
|
||||
public async Task GetPaymentSource_Stripe_CardPaymentMethod_Succeeds(
|
||||
Provider provider,
|
||||
SutProvider<SubscriberService> sutProvider)
|
||||
{
|
||||
@@ -491,43 +643,37 @@ public class SubscriberServiceTests
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task GetPaymentMethod_Stripe_SetupIntentForBankAccount_Succeeds(
|
||||
public async Task GetPaymentSource_Stripe_SetupIntentForBankAccount_Succeeds(
|
||||
Provider provider,
|
||||
SutProvider<SubscriberService> sutProvider)
|
||||
{
|
||||
var customer = new Customer
|
||||
{
|
||||
Id = provider.GatewayCustomerId
|
||||
};
|
||||
var customer = new Customer { Id = provider.GatewayCustomerId };
|
||||
|
||||
sutProvider.GetDependency<IStripeAdapter>().CustomerGetAsync(provider.GatewayCustomerId,
|
||||
Arg.Is<CustomerGetOptions>(
|
||||
options => options.Expand.Contains("default_source") &&
|
||||
options.Expand.Contains("invoice_settings.default_payment_method")))
|
||||
Arg.Is<CustomerGetOptions>(options => options.Expand.Contains("default_source") &&
|
||||
options.Expand.Contains(
|
||||
"invoice_settings.default_payment_method")))
|
||||
.Returns(customer);
|
||||
|
||||
var setupIntent = new SetupIntent
|
||||
{
|
||||
Id = "setup_intent_id",
|
||||
Status = "requires_action",
|
||||
NextAction = new SetupIntentNextAction
|
||||
{
|
||||
VerifyWithMicrodeposits = new SetupIntentNextActionVerifyWithMicrodeposits()
|
||||
},
|
||||
NextAction =
|
||||
new SetupIntentNextAction
|
||||
{
|
||||
VerifyWithMicrodeposits = new SetupIntentNextActionVerifyWithMicrodeposits()
|
||||
},
|
||||
PaymentMethod = new PaymentMethod
|
||||
{
|
||||
UsBankAccount = new PaymentMethodUsBankAccount
|
||||
{
|
||||
BankName = "Chase",
|
||||
Last4 = "9999"
|
||||
}
|
||||
UsBankAccount = new PaymentMethodUsBankAccount { BankName = "Chase", Last4 = "9999" }
|
||||
}
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<ISetupIntentCache>().GetSetupIntentIdForSubscriber(provider.Id).Returns(setupIntent.Id);
|
||||
|
||||
sutProvider.GetDependency<IStripeAdapter>().SetupIntentGet(setupIntent.Id, Arg.Is<SetupIntentGetOptions>(
|
||||
options => options.Expand.Contains("payment_method"))).Returns(setupIntent);
|
||||
sutProvider.GetDependency<IStripeAdapter>().SetupIntentGet(setupIntent.Id,
|
||||
Arg.Is<SetupIntentGetOptions>(options => options.Expand.Contains("payment_method"))).Returns(setupIntent);
|
||||
|
||||
var paymentMethod = await sutProvider.Sut.GetPaymentSource(provider);
|
||||
|
||||
@@ -537,24 +683,19 @@ public class SubscriberServiceTests
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task GetPaymentMethod_Stripe_LegacyBankAccount_Succeeds(
|
||||
public async Task GetPaymentSource_Stripe_LegacyBankAccount_Succeeds(
|
||||
Provider provider,
|
||||
SutProvider<SubscriberService> sutProvider)
|
||||
{
|
||||
var customer = new Customer
|
||||
{
|
||||
DefaultSource = new BankAccount
|
||||
{
|
||||
Status = "verified",
|
||||
BankName = "Chase",
|
||||
Last4 = "9999"
|
||||
}
|
||||
DefaultSource = new BankAccount { Status = "verified", BankName = "Chase", Last4 = "9999" }
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IStripeAdapter>().CustomerGetAsync(provider.GatewayCustomerId,
|
||||
Arg.Is<CustomerGetOptions>(
|
||||
options => options.Expand.Contains("default_source") &&
|
||||
options.Expand.Contains("invoice_settings.default_payment_method")))
|
||||
Arg.Is<CustomerGetOptions>(options => options.Expand.Contains("default_source") &&
|
||||
options.Expand.Contains(
|
||||
"invoice_settings.default_payment_method")))
|
||||
.Returns(customer);
|
||||
|
||||
var paymentMethod = await sutProvider.Sut.GetPaymentSource(provider);
|
||||
@@ -565,25 +706,19 @@ public class SubscriberServiceTests
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task GetPaymentMethod_Stripe_LegacyCard_Succeeds(
|
||||
public async Task GetPaymentSource_Stripe_LegacyCard_Succeeds(
|
||||
Provider provider,
|
||||
SutProvider<SubscriberService> sutProvider)
|
||||
{
|
||||
var customer = new Customer
|
||||
{
|
||||
DefaultSource = new Card
|
||||
{
|
||||
Brand = "Visa",
|
||||
Last4 = "9999",
|
||||
ExpMonth = 9,
|
||||
ExpYear = 2028
|
||||
}
|
||||
DefaultSource = new Card { Brand = "Visa", Last4 = "9999", ExpMonth = 9, ExpYear = 2028 }
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IStripeAdapter>().CustomerGetAsync(provider.GatewayCustomerId,
|
||||
Arg.Is<CustomerGetOptions>(
|
||||
options => options.Expand.Contains("default_source") &&
|
||||
options.Expand.Contains("invoice_settings.default_payment_method")))
|
||||
Arg.Is<CustomerGetOptions>(options => options.Expand.Contains("default_source") &&
|
||||
options.Expand.Contains(
|
||||
"invoice_settings.default_payment_method")))
|
||||
.Returns(customer);
|
||||
|
||||
var paymentMethod = await sutProvider.Sut.GetPaymentSource(provider);
|
||||
@@ -594,7 +729,7 @@ public class SubscriberServiceTests
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task GetPaymentMethod_Stripe_LegacySourceCard_Succeeds(
|
||||
public async Task GetPaymentSource_Stripe_LegacySourceCard_Succeeds(
|
||||
Provider provider,
|
||||
SutProvider<SubscriberService> sutProvider)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
using Bit.Identity.IdentityServer.RequestValidators.SendAccess;
|
||||
using Xunit;
|
||||
|
||||
namespace Bit.Identity.Test.IdentityServer.SendAccess;
|
||||
|
||||
/// <summary>
|
||||
/// Snapshot tests to ensure the string constants in <see cref="SendAccessConstants"/> do not change unintentionally.
|
||||
/// If you change any of these values, please ensure you understand the impact and update the SDK accordingly.
|
||||
/// If you intentionally change any of these values, please update the tests to reflect the new expected values.
|
||||
/// </summary>
|
||||
public class SendConstantsSnapshotTests
|
||||
{
|
||||
[Fact]
|
||||
public void SendAccessError_Constant_HasCorrectValue()
|
||||
{
|
||||
// Assert
|
||||
Assert.Equal("send_access_error_type", SendAccessConstants.SendAccessError);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TokenRequest_Constants_HaveCorrectValues()
|
||||
{
|
||||
// Assert
|
||||
Assert.Equal("send_id", SendAccessConstants.TokenRequest.SendId);
|
||||
Assert.Equal("password_hash_b64", SendAccessConstants.TokenRequest.ClientB64HashedPassword);
|
||||
Assert.Equal("email", SendAccessConstants.TokenRequest.Email);
|
||||
Assert.Equal("otp", SendAccessConstants.TokenRequest.Otp);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GrantValidatorResults_Constants_HaveCorrectValues()
|
||||
{
|
||||
// Assert
|
||||
Assert.Equal("valid_send_guid", SendAccessConstants.GrantValidatorResults.ValidSendGuid);
|
||||
Assert.Equal("send_id_required", SendAccessConstants.GrantValidatorResults.SendIdRequired);
|
||||
Assert.Equal("send_id_invalid", SendAccessConstants.GrantValidatorResults.InvalidSendId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PasswordValidatorResults_Constants_HaveCorrectValues()
|
||||
{
|
||||
// Assert
|
||||
Assert.Equal("password_hash_b64_invalid", SendAccessConstants.PasswordValidatorResults.RequestPasswordDoesNotMatch);
|
||||
Assert.Equal("password_hash_b64_required", SendAccessConstants.PasswordValidatorResults.RequestPasswordIsRequired);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmailOtpValidatorResults_Constants_HaveCorrectValues()
|
||||
{
|
||||
// Assert
|
||||
Assert.Equal("email_invalid", SendAccessConstants.EmailOtpValidatorResults.EmailInvalid);
|
||||
Assert.Equal("email_required", SendAccessConstants.EmailOtpValidatorResults.EmailRequired);
|
||||
Assert.Equal("email_and_otp_required_otp_sent", SendAccessConstants.EmailOtpValidatorResults.EmailOtpSent);
|
||||
Assert.Equal("otp_invalid", SendAccessConstants.EmailOtpValidatorResults.EmailOtpInvalid);
|
||||
Assert.Equal("otp_generation_failed", SendAccessConstants.EmailOtpValidatorResults.OtpGenerationFailed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OtpToken_Constants_HaveCorrectValues()
|
||||
{
|
||||
// Assert
|
||||
Assert.Equal("send_access", SendAccessConstants.OtpToken.TokenProviderName);
|
||||
Assert.Equal("email_otp", SendAccessConstants.OtpToken.Purpose);
|
||||
Assert.Equal("{0}_{1}", SendAccessConstants.OtpToken.TokenUniqueIdentifier);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OtpEmail_Constants_HaveCorrectValues()
|
||||
{
|
||||
// Assert
|
||||
Assert.Equal("Your Bitwarden Send verification code is {0}", SendAccessConstants.OtpEmail.Subject);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user