1
0
mirror of https://github.com/bitwarden/server.git synced 2024-11-21 12:05:42 +01:00

Add overriddable configuration (#4437)

* Add Overridable Configuration

* Add Remarks
This commit is contained in:
Justin Baur 2024-06-28 10:28:07 -04:00 committed by GitHub
parent 1ec2aae723
commit 84b18e9de7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 65 additions and 10 deletions

View File

@ -4,6 +4,8 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Data.Sqlite;
#nullable enable
namespace Bit.Api.IntegrationTest.Factories;
public class ApiApplicationFactory : WebApplicationFactoryBase<Startup>
@ -62,7 +64,7 @@ public class ApiApplicationFactory : WebApplicationFactoryBase<Startup>
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
SqliteConnection.Dispose();
SqliteConnection!.Dispose();
}
/// <summary>

View File

@ -16,6 +16,8 @@ using Microsoft.Extensions.Logging.Abstractions;
using NSubstitute;
using NoopRepos = Bit.Core.Repositories.Noop;
#nullable enable
namespace Bit.IntegrationTestCommon.Factories;
public static class FactoryConstants
@ -32,9 +34,11 @@ public abstract class WebApplicationFactoryBase<T> : WebApplicationFactory<T>
/// <remarks>
/// This will need to be set BEFORE using the <c>Server</c> property
/// </remarks>
public SqliteConnection SqliteConnection { get; set; }
public SqliteConnection? SqliteConnection { get; set; }
private readonly List<Action<IServiceCollection>> _configureTestServices = new();
private readonly List<Action<IConfigurationBuilder>> _configureAppConfiguration = new();
private bool _handleSqliteDisposal { get; set; }
@ -53,6 +57,50 @@ public abstract class WebApplicationFactoryBase<T> : WebApplicationFactory<T>
});
}
/// <summary>
/// Add your own configuration provider to the application.
/// </summary>
/// <param name="configure">The action adding your own providers.</param>
/// <remarks>This needs to be ran BEFORE making any calls through the factory to take effect.</remarks>
/// <example>
/// <code lang="C#">
/// factory.UpdateConfiguration(builder =&gt;
/// {
/// builder.AddInMemoryCollection(new Dictionary&lt;string, string?&gt;
/// {
/// { "globalSettings:attachment:connectionString", null},
/// { "globalSettings:events:connectionString", null},
/// })
/// })
/// </code>
/// </example>
public void UpdateConfiguration(Action<IConfigurationBuilder> configure)
{
_configureAppConfiguration.Add(configure);
}
/// <summary>
/// Updates a single configuration entry for multiple entries at once use <see cref="UpdateConfiguration(Action{IConfigurationBuilder})"/>.
/// </summary>
/// <param name="key">The fully qualified name of the setting, using <c>:</c> as delimiter between sections.</param>
/// <param name="value">The value of the setting.</param>
/// <remarks>This needs to be ran BEFORE making any calls through the factory to take effect.</remarks>
/// <example>
/// <code lang="C#">
/// factory.UpdateConfiguration("globalSettings:attachment:connectionString", null);
/// </code>
/// </example>
public void UpdateConfiguration(string key, string? value)
{
_configureAppConfiguration.Add(builder =>
{
builder.AddInMemoryCollection(new Dictionary<string, string?>
{
{ key, value },
});
});
}
/// <summary>
/// Configure the web host to use a SQLite in memory database
/// </summary>
@ -73,7 +121,7 @@ public abstract class WebApplicationFactoryBase<T> : WebApplicationFactory<T>
c.AddUserSecrets(typeof(Identity.Startup).Assembly, optional: true);
c.AddInMemoryCollection(new Dictionary<string, string>
c.AddInMemoryCollection(new Dictionary<string, string?>
{
// Manually insert a EF provider so that ConfigureServices will add EF repositories but we will override
// DbContextOptions to use an in memory database
@ -96,12 +144,16 @@ public abstract class WebApplicationFactoryBase<T> : WebApplicationFactory<T>
// Email Verification
{ "globalSettings:enableEmailVerification", "true" },
{"globalSettings:launchDarkly:flagValues:email-verification", "true" }
{ "globalSettings:launchDarkly:flagValues:email-verification", "true" }
});
});
// Run configured actions after defaults to allow them to take precedence
foreach (var configureAppConfiguration in _configureAppConfiguration)
{
builder.ConfigureAppConfiguration(configureAppConfiguration);
}
builder.ConfigureTestServices(services =>
{
var dbContextOptions = services.First(sd => sd.ServiceType == typeof(DbContextOptions<DatabaseContext>));
@ -193,10 +245,11 @@ public abstract class WebApplicationFactoryBase<T> : WebApplicationFactory<T>
return scope.ServiceProvider.GetRequiredService<DatabaseContext>();
}
public TS GetService<TS>()
public TService GetService<TService>()
where TService : notnull
{
var scope = Services.CreateScope();
return scope.ServiceProvider.GetRequiredService<TS>();
return scope.ServiceProvider.GetRequiredService<TService>();
}
protected override void Dispose(bool disposing)
@ -204,7 +257,7 @@ public abstract class WebApplicationFactoryBase<T> : WebApplicationFactory<T>
base.Dispose(disposing);
if (_handleSqliteDisposal)
{
SqliteConnection.Dispose();
SqliteConnection!.Dispose();
}
}
@ -213,7 +266,7 @@ public abstract class WebApplicationFactoryBase<T> : WebApplicationFactory<T>
var serviceProvider = serviceCollection.BuildServiceProvider();
using var scope = serviceProvider.CreateScope();
var services = scope.ServiceProvider;
var context = services.GetService<TContext>();
var context = services.GetRequiredService<TContext>();
if (_handleSqliteDisposal)
{
context.Database.EnsureDeleted();