Skip to content

Commit

Permalink
Merge branch 'main' into ac/pm-14026/fix-endpoint-doc
Browse files Browse the repository at this point in the history
  • Loading branch information
JimmyVo16 authored Jan 6, 2025
2 parents 7f23917 + cd7c4bf commit c53e96f
Show file tree
Hide file tree
Showing 138 changed files with 2,641 additions and 956 deletions.
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ src/Admin/Views/Tools @bitwarden/team-billing-dev
.github/workflows/repository-management.yml @bitwarden/team-platform-dev
.github/workflows/test-database.yml @bitwarden/team-platform-dev
.github/workflows/test.yml @bitwarden/team-platform-dev
**/*Platform* @bitwarden/team-platform-dev

# Multiple owners - DO NOT REMOVE (BRE)
**/packages.lock.json
Expand Down
17 changes: 16 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ jobs:
- name: Scan Docker image
id: container-scan
uses: anchore/scan-action@5ed195cc06065322983cae4bb31e2a751feb86fd # v5.2.0
uses: anchore/scan-action@abae793926ec39a78ab18002bc7fc45bbbd94342 # v6.0.0
with:
image: ${{ steps.image-tags.outputs.primary_tag }}
fail-build: false
Expand Down Expand Up @@ -654,6 +654,21 @@ jobs:
}
})
trigger-ephemeral-environment-sync:
name: Trigger Ephemeral Environment Sync
needs: trigger-ee-updates
if: |
github.event_name == 'pull_request_target'
&& contains(github.event.pull_request.labels.*.name, 'ephemeral-environment')
uses: bitwarden/gh-actions/.github/workflows/_ephemeral_environment_manager.yml@main
with:
ephemeral_env_branch: process.env.GITHUB_HEAD_REF
project: server
sync_environment: true
pull_request_number: ${{ github.event.number }}
secrets: inherit


check-failures:
name: Check for failures
if: always()
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/repository-management.yml
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ jobs:
git cherry-pick --strategy-option=theirs -x $SOURCE_COMMIT
git push -u origin $destination_branch
fi
}
# If we are cutting 'hotfix-rc':
if [[ "$CUT_BRANCH" == "hotfix-rc" ]]; then
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ jobs:
fail-on-error: true

- name: Upload to codecov.io
uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4.6.0
uses: codecov/codecov-action@1e68e06f1dbfde0e4cefc87efeba9e4643565303 # v5.1.2
if: ${{ needs.check-test-secrets.outputs.available == 'true' }}
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
4 changes: 2 additions & 2 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>

<Version>2024.12.1</Version>
<Version>2025.1.0</Version>

<RootNamespace>Bit.$(MSBuildProjectName)</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
Expand Down Expand Up @@ -64,4 +64,4 @@
</ItemGroup>
</Target>

</Project>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ public class ProviderBillingService(
IProviderOrganizationRepository providerOrganizationRepository,
IProviderPlanRepository providerPlanRepository,
IStripeAdapter stripeAdapter,
ISubscriberService subscriberService) : IProviderBillingService
ISubscriberService subscriberService,
ITaxService taxService) : IProviderBillingService
{
public async Task ChangePlan(ChangeProviderPlanCommand command)
{
Expand Down Expand Up @@ -335,13 +336,29 @@ public async Task<Customer> SetupCustomer(
Metadata = new Dictionary<string, string>
{
{ "region", globalSettings.BaseServiceUri.CloudRegion }
},
TaxIdData = taxInfo.HasTaxId ?
}
};

if (!string.IsNullOrEmpty(taxInfo.TaxIdNumber))
{
var taxIdType = taxService.GetStripeTaxCode(taxInfo.BillingAddressCountry,
taxInfo.TaxIdNumber);

if (taxIdType == null)
{
logger.LogWarning("Could not infer tax ID type in country '{Country}' with tax ID '{TaxID}'.",
taxInfo.BillingAddressCountry,
taxInfo.TaxIdNumber);
throw new BadRequestException("billingTaxIdTypeInferenceError");
}

customerCreateOptions.TaxIdData = taxInfo.HasTaxId
?
[
new CustomerTaxIdDataOptions { Type = taxInfo.TaxIdType, Value = taxInfo.TaxIdNumber }
new CustomerTaxIdDataOptions { Type = taxIdType, Value = taxInfo.TaxIdNumber }
]
: null
};
: null;
}

try
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,12 @@ public async Task SetupCustomer_Success(
{
provider.Name = "MSP";

sutProvider.GetDependency<ITaxService>()
.GetStripeTaxCode(Arg.Is<string>(
p => p == taxInfo.BillingAddressCountry),
Arg.Is<string>(p => p == taxInfo.TaxIdNumber))
.Returns(taxInfo.TaxIdType);

taxInfo.BillingAddressCountry = "AD";

var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
Expand Down Expand Up @@ -777,6 +783,29 @@ public async Task SetupCustomer_Success(
Assert.Equivalent(expected, actual);
}

[Theory, BitAutoData]
public async Task SetupCustomer_Throws_BadRequestException_WhenTaxIdIsInvalid(
SutProvider<ProviderBillingService> sutProvider,
Provider provider,
TaxInfo taxInfo)
{
provider.Name = "MSP";

taxInfo.BillingAddressCountry = "AD";

sutProvider.GetDependency<ITaxService>()
.GetStripeTaxCode(Arg.Is<string>(
p => p == taxInfo.BillingAddressCountry),
Arg.Is<string>(p => p == taxInfo.TaxIdNumber))
.Returns((string)null);

var actual = await Assert.ThrowsAsync<BadRequestException>(async () =>
await sutProvider.Sut.SetupCustomer(provider, taxInfo));

Assert.IsType<BadRequestException>(actual);
Assert.Equal("billingTaxIdTypeInferenceError", actual.Message);
}

#endregion

#region SetupSubscription
Expand Down
151 changes: 151 additions & 0 deletions bitwarden_license/test/Commercial.Core.Test/Billing/TaxServiceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
using Bit.Core.Billing.Services;
using Bit.Test.Common.AutoFixture;
using Bit.Test.Common.AutoFixture.Attributes;
using Xunit;

namespace Bit.Commercial.Core.Test.Billing;

[SutProviderCustomize]
public class TaxServiceTests
{
[Theory]
[BitAutoData("AD", "A-123456-Z", "ad_nrt")]
[BitAutoData("AD", "A123456Z", "ad_nrt")]
[BitAutoData("AR", "20-12345678-9", "ar_cuit")]
[BitAutoData("AR", "20123456789", "ar_cuit")]
[BitAutoData("AU", "01259983598", "au_abn")]
[BitAutoData("AU", "123456789123", "au_arn")]
[BitAutoData("AT", "ATU12345678", "eu_vat")]
[BitAutoData("BH", "123456789012345", "bh_vat")]
[BitAutoData("BY", "123456789", "by_tin")]
[BitAutoData("BE", "BE0123456789", "eu_vat")]
[BitAutoData("BO", "123456789", "bo_tin")]
[BitAutoData("BR", "01.234.456/5432-10", "br_cnpj")]
[BitAutoData("BR", "01234456543210", "br_cnpj")]
[BitAutoData("BR", "123.456.789-87", "br_cpf")]
[BitAutoData("BR", "12345678987", "br_cpf")]
[BitAutoData("BG", "123456789", "bg_uic")]
[BitAutoData("BG", "BG012100705", "eu_vat")]
[BitAutoData("CA", "100728494", "ca_bn")]
[BitAutoData("CA", "123456789RT0001", "ca_gst_hst")]
[BitAutoData("CA", "PST-1234-1234", "ca_pst_bc")]
[BitAutoData("CA", "123456-7", "ca_pst_mb")]
[BitAutoData("CA", "1234567", "ca_pst_sk")]
[BitAutoData("CA", "1234567890TQ1234", "ca_qst")]
[BitAutoData("CL", "11.121.326-1", "cl_tin")]
[BitAutoData("CL", "11121326-1", "cl_tin")]
[BitAutoData("CL", "23.121.326-K", "cl_tin")]
[BitAutoData("CL", "43651326-K", "cl_tin")]
[BitAutoData("CN", "123456789012345678", "cn_tin")]
[BitAutoData("CN", "123456789012345", "cn_tin")]
[BitAutoData("CO", "123.456.789-0", "co_nit")]
[BitAutoData("CO", "1234567890", "co_nit")]
[BitAutoData("CR", "1-234-567890", "cr_tin")]
[BitAutoData("CR", "1234567890", "cr_tin")]
[BitAutoData("HR", "HR12345678912", "eu_vat")]
[BitAutoData("HR", "12345678901", "hr_oib")]
[BitAutoData("CY", "CY12345678X", "eu_vat")]
[BitAutoData("CZ", "CZ12345678", "eu_vat")]
[BitAutoData("DK", "DK12345678", "eu_vat")]
[BitAutoData("DO", "123-4567890-1", "do_rcn")]
[BitAutoData("DO", "12345678901", "do_rcn")]
[BitAutoData("EC", "1234567890001", "ec_ruc")]
[BitAutoData("EG", "123456789", "eg_tin")]
[BitAutoData("SV", "1234-567890-123-4", "sv_nit")]
[BitAutoData("SV", "12345678901234", "sv_nit")]
[BitAutoData("EE", "EE123456789", "eu_vat")]
[BitAutoData("EU", "EU123456789", "eu_oss_vat")]
[BitAutoData("FI", "FI12345678", "eu_vat")]
[BitAutoData("FR", "FR12345678901", "eu_vat")]
[BitAutoData("GE", "123456789", "ge_vat")]
[BitAutoData("DE", "1234567890", "de_stn")]
[BitAutoData("DE", "DE123456789", "eu_vat")]
[BitAutoData("GR", "EL123456789", "eu_vat")]
[BitAutoData("HK", "12345678", "hk_br")]
[BitAutoData("HU", "HU12345678", "eu_vat")]
[BitAutoData("HU", "12345678-1-23", "hu_tin")]
[BitAutoData("HU", "12345678123", "hu_tin")]
[BitAutoData("IS", "123456", "is_vat")]
[BitAutoData("IN", "12ABCDE1234F1Z5", "in_gst")]
[BitAutoData("IN", "12ABCDE3456FGZH", "in_gst")]
[BitAutoData("ID", "012.345.678.9-012.345", "id_npwp")]
[BitAutoData("ID", "0123456789012345", "id_npwp")]
[BitAutoData("IE", "IE1234567A", "eu_vat")]
[BitAutoData("IE", "IE1234567AB", "eu_vat")]
[BitAutoData("IL", "000012345", "il_vat")]
[BitAutoData("IL", "123456789", "il_vat")]
[BitAutoData("IT", "IT12345678901", "eu_vat")]
[BitAutoData("JP", "1234567890123", "jp_cn")]
[BitAutoData("JP", "12345", "jp_rn")]
[BitAutoData("KZ", "123456789012", "kz_bin")]
[BitAutoData("KE", "P000111111A", "ke_pin")]
[BitAutoData("LV", "LV12345678912", "eu_vat")]
[BitAutoData("LI", "CHE123456789", "li_uid")]
[BitAutoData("LI", "12345", "li_vat")]
[BitAutoData("LT", "LT123456789123", "eu_vat")]
[BitAutoData("LU", "LU12345678", "eu_vat")]
[BitAutoData("MY", "12345678", "my_frp")]
[BitAutoData("MY", "C 1234567890", "my_itn")]
[BitAutoData("MY", "C1234567890", "my_itn")]
[BitAutoData("MY", "A12-3456-78912345", "my_sst")]
[BitAutoData("MY", "A12345678912345", "my_sst")]
[BitAutoData("MT", "MT12345678", "eu_vat")]
[BitAutoData("MX", "ABC010203AB9", "mx_rfc")]
[BitAutoData("MD", "1003600", "md_vat")]
[BitAutoData("MA", "12345678", "ma_vat")]
[BitAutoData("NL", "NL123456789B12", "eu_vat")]
[BitAutoData("NZ", "123456789", "nz_gst")]
[BitAutoData("NG", "12345678-0001", "ng_tin")]
[BitAutoData("NO", "123456789MVA", "no_vat")]
[BitAutoData("NO", "1234567", "no_voec")]
[BitAutoData("OM", "OM1234567890", "om_vat")]
[BitAutoData("PE", "12345678901", "pe_ruc")]
[BitAutoData("PH", "123456789012", "ph_tin")]
[BitAutoData("PL", "PL1234567890", "eu_vat")]
[BitAutoData("PT", "PT123456789", "eu_vat")]
[BitAutoData("RO", "RO1234567891", "eu_vat")]
[BitAutoData("RO", "1234567890123", "ro_tin")]
[BitAutoData("RU", "1234567891", "ru_inn")]
[BitAutoData("RU", "123456789", "ru_kpp")]
[BitAutoData("SA", "123456789012345", "sa_vat")]
[BitAutoData("RS", "123456789", "rs_pib")]
[BitAutoData("SG", "M12345678X", "sg_gst")]
[BitAutoData("SG", "123456789F", "sg_uen")]
[BitAutoData("SK", "SK1234567891", "eu_vat")]
[BitAutoData("SI", "SI12345678", "eu_vat")]
[BitAutoData("SI", "12345678", "si_tin")]
[BitAutoData("ZA", "4123456789", "za_vat")]
[BitAutoData("KR", "123-45-67890", "kr_brn")]
[BitAutoData("KR", "1234567890", "kr_brn")]
[BitAutoData("ES", "A12345678", "es_cif")]
[BitAutoData("ES", "ESX1234567X", "eu_vat")]
[BitAutoData("SE", "SE123456789012", "eu_vat")]
[BitAutoData("CH", "CHE-123.456.789 HR", "ch_uid")]
[BitAutoData("CH", "CHE123456789HR", "ch_uid")]
[BitAutoData("CH", "CHE-123.456.789 MWST", "ch_vat")]
[BitAutoData("CH", "CHE123456789MWST", "ch_vat")]
[BitAutoData("TW", "12345678", "tw_vat")]
[BitAutoData("TH", "1234567890123", "th_vat")]
[BitAutoData("TR", "0123456789", "tr_tin")]
[BitAutoData("UA", "123456789", "ua_vat")]
[BitAutoData("AE", "123456789012345", "ae_trn")]
[BitAutoData("GB", "XI123456789", "eu_vat")]
[BitAutoData("GB", "GB123456789", "gb_vat")]
[BitAutoData("US", "12-3456789", "us_ein")]
[BitAutoData("UY", "123456789012", "uy_ruc")]
[BitAutoData("UZ", "123456789", "uz_tin")]
[BitAutoData("UZ", "123456789012", "uz_vat")]
[BitAutoData("VE", "A-12345678-9", "ve_rif")]
[BitAutoData("VE", "A123456789", "ve_rif")]
[BitAutoData("VN", "1234567890", "vn_tin")]
public void GetStripeTaxCode_WithValidCountryAndTaxId_ReturnsExpectedTaxIdType(
string country,
string taxId,
string expected,
SutProvider<TaxService> sutProvider)
{
var result = sutProvider.Sut.GetStripeTaxCode(country, taxId);

Assert.Equal(expected, result);
}
}
3 changes: 0 additions & 3 deletions scripts/bitwarden.ps1

This file was deleted.

31 changes: 0 additions & 31 deletions scripts/bitwarden.sh

This file was deleted.

47 changes: 0 additions & 47 deletions scripts/build

This file was deleted.

Loading

0 comments on commit c53e96f

Please sign in to comment.