1
0
mirror of https://github.com/bitwarden/server.git synced 2025-02-08 00:31:27 +01:00

Merge branch 'km/userkey-rotation-v2' of github.com:bitwarden/server into km/userkey-rotation-v2

This commit is contained in:
Bernd Schoolmann 2025-01-29 14:03:43 +01:00
commit b96bfadf38
No known key found for this signature in database
12 changed files with 34 additions and 135 deletions

View File

@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Version>2025.1.4</Version>
<Version>2025.1.5</Version>
<RootNamespace>Bit.$(MSBuildProjectName)</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>

View File

@ -5,7 +5,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="CsvHelper" Version="32.0.3" />
<PackageReference Include="CsvHelper" Version="33.0.1" />
</ItemGroup>
</Project>

View File

@ -37,11 +37,7 @@
// Premium
document.getElementById('@(nameof(Model.MaxStorageGb))').value = '1';
document.getElementById('@(nameof(Model.Premium))').checked = true;
using Stripe.Entitlements;
// Licensing
using Bit.Core;
using Stripe.Entitlements;
using Microsoft.Identity.Client.Extensibility;
document.getElementById('@(nameof(Model.LicenseKey))').value = '@Model.RandomLicenseKey';
document.getElementById('@(nameof(Model.PremiumExpirationDate))').value =
'@Model.OneYearExpirationDate';

View File

@ -17,7 +17,6 @@ public class FreshdeskController : Controller
private readonly BillingSettings _billingSettings;
private readonly IUserRepository _userRepository;
private readonly IOrganizationRepository _organizationRepository;
private readonly IOrganizationUserRepository _organizationUserRepository;
private readonly ILogger<FreshdeskController> _logger;
private readonly GlobalSettings _globalSettings;
private readonly IHttpClientFactory _httpClientFactory;
@ -25,7 +24,6 @@ public class FreshdeskController : Controller
public FreshdeskController(
IUserRepository userRepository,
IOrganizationRepository organizationRepository,
IOrganizationUserRepository organizationUserRepository,
IOptions<BillingSettings> billingSettings,
ILogger<FreshdeskController> logger,
GlobalSettings globalSettings,
@ -34,7 +32,6 @@ public class FreshdeskController : Controller
_billingSettings = billingSettings?.Value;
_userRepository = userRepository;
_organizationRepository = organizationRepository;
_organizationUserRepository = organizationUserRepository;
_logger = logger;
_globalSettings = globalSettings;
_httpClientFactory = httpClientFactory;

View File

@ -1,53 +0,0 @@
using Microsoft.AspNetCore.Mvc;
namespace Billing.Controllers;
public class LoginController : Controller
{
/*
private readonly PasswordlessSignInManager<IdentityUser> _signInManager;
public LoginController(
PasswordlessSignInManager<IdentityUser> signInManager)
{
_signInManager = signInManager;
}
public IActionResult Index()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Index(LoginModel model)
{
if (ModelState.IsValid)
{
var result = await _signInManager.PasswordlessSignInAsync(model.Email,
Url.Action("Confirm", "Login", null, Request.Scheme));
if (result.Succeeded)
{
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError(string.Empty, "Account not found.");
}
}
return View(model);
}
public async Task<IActionResult> Confirm(string email, string token)
{
var result = await _signInManager.PasswordlessSignInAsync(email, token, false);
if (!result.Succeeded)
{
return View("Error");
}
return RedirectToAction("Index", "Home");
}
*/
}

View File

@ -1,7 +1,6 @@
using Bit.Billing.Constants;
using Bit.Core.AdminConsole.Entities;
using Bit.Core.AdminConsole.Repositories;
using Bit.Core.Billing.Constants;
using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Interfaces;
using Bit.Core.Repositories;
using Bit.Core.Services;
@ -161,18 +160,13 @@ public class UpcomingInvoiceHandler : IUpcomingInvoiceHandler
private async Task<Subscription> TryEnableAutomaticTaxAsync(Subscription subscription)
{
var customerGetOptions = new CustomerGetOptions { Expand = ["tax"] };
var customer = await _stripeFacade.GetCustomer(subscription.CustomerId, customerGetOptions);
if (subscription.AutomaticTax.Enabled ||
customer.Tax?.AutomaticTax != StripeConstants.AutomaticTaxStatus.Supported)
if (subscription.AutomaticTax.Enabled)
{
return subscription;
}
var subscriptionUpdateOptions = new SubscriptionUpdateOptions
{
DefaultTaxRates = [],
AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true }
};

View File

@ -360,7 +360,7 @@ public class OrganizationBillingService(
{
AutomaticTax = new SubscriptionAutomaticTaxOptions
{
Enabled = customer.Tax?.AutomaticTax == StripeConstants.AutomaticTaxStatus.Supported
Enabled = true
},
CollectionMethod = StripeConstants.CollectionMethod.ChargeAutomatically,
Customer = customer.Id,

View File

@ -235,7 +235,7 @@ public class PremiumUserBillingService(
{
AutomaticTax = new SubscriptionAutomaticTaxOptions
{
Enabled = customer.Tax?.AutomaticTax == StripeConstants.AutomaticTaxStatus.Supported,
Enabled = true
},
CollectionMethod = StripeConstants.CollectionMethod.ChargeAutomatically,
Customer = customer.Id,

View File

@ -661,21 +661,11 @@ public class SubscriberService(
}
}
if (SubscriberIsEligibleForAutomaticTax(subscriber, customer))
{
await stripeAdapter.SubscriptionUpdateAsync(subscriber.GatewaySubscriptionId,
new SubscriptionUpdateOptions
{
AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true }
});
}
return;
bool SubscriberIsEligibleForAutomaticTax(ISubscriber localSubscriber, Customer localCustomer)
=> !string.IsNullOrEmpty(localSubscriber.GatewaySubscriptionId) &&
(localCustomer.Subscriptions?.Any(sub => sub.Id == localSubscriber.GatewaySubscriptionId && !sub.AutomaticTax.Enabled) ?? false) &&
localCustomer.Tax?.AutomaticTax == StripeConstants.AutomaticTaxStatus.Supported;
await stripeAdapter.SubscriptionUpdateAsync(subscriber.GatewaySubscriptionId,
new SubscriptionUpdateOptions
{
AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true },
});
}
public async Task VerifyBankAccount(

View File

@ -167,6 +167,7 @@ public static class FeatureFlagKeys
public const string UserkeyRotationV2 = "userkey-rotation-v2";
public const string EnablePasswordManagerSyncAndroid = "enable-password-manager-sync-android";
public const string EnablePasswordManagerSynciOS = "enable-password-manager-sync-ios";
public const string AccountDeprovisioningBanner = "pm-17120-account-deprovisioning-admin-console-banner";
public static List<string> GetAllKeys()
{

View File

@ -177,11 +177,7 @@ public class StripePaymentService : IPaymentService
customer = await _stripeAdapter.CustomerCreateAsync(customerCreateOptions);
subCreateOptions.AddExpand("latest_invoice.payment_intent");
subCreateOptions.Customer = customer.Id;
if (CustomerHasTaxLocationVerified(customer))
{
subCreateOptions.AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true };
}
subCreateOptions.AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true };
subscription = await _stripeAdapter.SubscriptionCreateAsync(subCreateOptions);
if (subscription.Status == "incomplete" && subscription.LatestInvoice?.PaymentIntent != null)
@ -362,13 +358,10 @@ public class StripePaymentService : IPaymentService
customer = await _stripeAdapter.CustomerUpdateAsync(org.GatewayCustomerId, customerUpdateOptions);
}
var subCreateOptions = new OrganizationUpgradeSubscriptionOptions(customer.Id, org, plan, upgrade);
if (CustomerHasTaxLocationVerified(customer))
var subCreateOptions = new OrganizationUpgradeSubscriptionOptions(customer.Id, org, plan, upgrade)
{
subCreateOptions.DefaultTaxRates = [];
subCreateOptions.AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true };
}
AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true }
};
var (stripePaymentMethod, paymentMethodType) = IdentifyPaymentMethod(customer, subCreateOptions);
@ -527,6 +520,10 @@ public class StripePaymentService : IPaymentService
var customerCreateOptions = new CustomerCreateOptions
{
Tax = new CustomerTaxOptions
{
ValidateLocation = StripeConstants.ValidateTaxLocationTiming.Immediately
},
Description = user.Name,
Email = user.Email,
Metadata = stripeCustomerMetadata,
@ -564,6 +561,7 @@ public class StripePaymentService : IPaymentService
var subCreateOptions = new SubscriptionCreateOptions
{
AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true },
Customer = customer.Id,
Items = [],
Metadata = new Dictionary<string, string>
@ -583,16 +581,10 @@ public class StripePaymentService : IPaymentService
subCreateOptions.Items.Add(new SubscriptionItemOptions
{
Plan = StoragePlanId,
Quantity = additionalStorageGb
Quantity = additionalStorageGb,
});
}
if (CustomerHasTaxLocationVerified(customer))
{
subCreateOptions.DefaultTaxRates = [];
subCreateOptions.AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true };
}
var subscription = await ChargeForNewSubscriptionAsync(user, customer, createdStripeCustomer,
stripePaymentMethod, paymentMethodType, subCreateOptions, braintreeCustomer);
@ -630,10 +622,7 @@ public class StripePaymentService : IPaymentService
SubscriptionItems = ToInvoiceSubscriptionItemOptions(subCreateOptions.Items)
});
if (CustomerHasTaxLocationVerified(customer))
{
previewInvoice.AutomaticTax = new InvoiceAutomaticTax { Enabled = true };
}
previewInvoice.AutomaticTax = new InvoiceAutomaticTax { Enabled = true };
if (previewInvoice.AmountDue > 0)
{
@ -691,14 +680,12 @@ public class StripePaymentService : IPaymentService
Customer = customer.Id,
SubscriptionItems = ToInvoiceSubscriptionItemOptions(subCreateOptions.Items),
SubscriptionDefaultTaxRates = subCreateOptions.DefaultTaxRates,
AutomaticTax = new InvoiceAutomaticTaxOptions
{
Enabled = true
}
};
if (CustomerHasTaxLocationVerified(customer))
{
upcomingInvoiceOptions.AutomaticTax = new InvoiceAutomaticTaxOptions { Enabled = true };
upcomingInvoiceOptions.SubscriptionDefaultTaxRates = [];
}
var previewInvoice = await _stripeAdapter.InvoiceUpcomingAsync(upcomingInvoiceOptions);
if (previewInvoice.AmountDue > 0)
@ -817,7 +804,11 @@ public class StripePaymentService : IPaymentService
Items = updatedItemOptions,
ProrationBehavior = invoiceNow ? Constants.AlwaysInvoice : Constants.CreateProrations,
DaysUntilDue = daysUntilDue ?? 1,
CollectionMethod = "send_invoice"
CollectionMethod = "send_invoice",
AutomaticTax = new SubscriptionAutomaticTaxOptions
{
Enabled = true
}
};
if (!invoiceNow && isAnnualPlan && sub.Status.Trim() != "trialing")
{
@ -825,13 +816,6 @@ public class StripePaymentService : IPaymentService
new SubscriptionPendingInvoiceItemIntervalOptions { Interval = "month" };
}
if (sub.AutomaticTax.Enabled != true &&
CustomerHasTaxLocationVerified(sub.Customer))
{
subUpdateOptions.DefaultTaxRates = [];
subUpdateOptions.AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true };
}
if (!subscriptionUpdate.UpdateNeeded(sub))
{
// No need to update subscription, quantity matches
@ -1516,13 +1500,11 @@ public class StripePaymentService : IPaymentService
if (!string.IsNullOrEmpty(subscriber.GatewaySubscriptionId) &&
customer.Subscriptions.Any(sub =>
sub.Id == subscriber.GatewaySubscriptionId &&
!sub.AutomaticTax.Enabled) &&
CustomerHasTaxLocationVerified(customer))
!sub.AutomaticTax.Enabled))
{
var subscriptionUpdateOptions = new SubscriptionUpdateOptions
{
AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true },
DefaultTaxRates = []
AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true }
};
_ = await _stripeAdapter.SubscriptionUpdateAsync(
@ -2280,14 +2262,6 @@ public class StripePaymentService : IPaymentService
}
}
/// <summary>
/// Determines if a Stripe customer supports automatic tax
/// </summary>
/// <param name="customer"></param>
/// <returns></returns>
private static bool CustomerHasTaxLocationVerified(Customer customer) =>
customer?.Tax?.AutomaticTax == StripeConstants.AutomaticTaxStatus.Supported;
// We are taking only first 30 characters of the SubscriberName because stripe provide
// for 30 characters for custom_fields,see the link: https://stripe.com/docs/api/invoices/create
private static string GetFirstThirtyCharacters(string subscriberName)

View File

@ -16,7 +16,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.2">
<PackageReference Include="coverlet.collector" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>