Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/Core/Billing/Pricing/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ public static void AddPricingClient(this IServiceCollection services)
"Bitwarden-Region",
globalSettings.BaseServiceUri.CloudRegion?.ToLower(CultureInfo.InvariantCulture) ?? "us"
);
if (!string.IsNullOrEmpty(globalSettings.PricingApiKey))
{
httpClient.DefaultRequestHeaders.Add("X-Pricing-Api-Key", globalSettings.PricingApiKey);
}
});
}
}
1 change: 1 addition & 0 deletions src/Core/Settings/GlobalSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ public virtual string MailTemplateDirectory
/// </summary>
public virtual string SendDefaultHashKey { get; set; }
public virtual string PricingUri { get; set; }
public virtual string PricingApiKey { get; set; }
public virtual Fido2Settings Fido2 { get; set; } = new Fido2Settings();
public virtual ICommunicationSettings Communication { get; set; } = new CommunicationSettings();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
ο»Ώusing Bit.Core.Billing.Pricing;
using Bit.Core.Settings;
using Microsoft.Extensions.DependencyInjection;
using Xunit;

namespace Bit.Core.Test.Billing.Pricing;

public class ServiceCollectionExtensionsTests
{
private const string PricingApiKeyHeader = "X-Pricing-Api-Key";

// Obviously-synthetic test value; the server does not enforce the pricing
// service's >=32 character rule, so any non-empty value exercises the guard.
private const string ApiKey = "test-pricing-api-key-0123456789abcdef";

[Fact]
public void AddPricingClient_WhenApiKeyConfigured_SendsApiKeyHeader()
{
// Arrange
var services = new ServiceCollection();
services.AddSingleton(new GlobalSettings
{
PricingUri = "https://test.com/",
PricingApiKey = ApiKey
});
services.AddLogging();
services.AddPricingClient();

using var provider = services.BuildServiceProvider();

// Act
var httpClient = provider
.GetRequiredService<IHttpClientFactory>()
.CreateClient(nameof(IPricingClient));

// Assert
Assert.True(httpClient.DefaultRequestHeaders.Contains(PricingApiKeyHeader));
Assert.Equal(ApiKey, httpClient.DefaultRequestHeaders.GetValues(PricingApiKeyHeader).Single());
}

[Fact]
public void AddPricingClient_WhenApiKeyNotConfigured_DoesNotSendApiKeyHeader()
{
// Arrange
var services = new ServiceCollection();
services.AddSingleton(new GlobalSettings { PricingUri = "https://test.com/" });
services.AddLogging();
services.AddPricingClient();

using var provider = services.BuildServiceProvider();

// Act
var httpClient = provider
.GetRequiredService<IHttpClientFactory>()
.CreateClient(nameof(IPricingClient));

// Assert
Assert.False(httpClient.DefaultRequestHeaders.Contains(PricingApiKeyHeader));
}
}
Loading