1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-30 15:42:48 -05:00

Turn on file scoped namespaces (#2225)

This commit is contained in:
Justin Baur
2022-08-29 14:53:16 -04:00
committed by GitHub
parent 7c4521e0b4
commit 34fb4cca2a
1206 changed files with 73816 additions and 75022 deletions

View File

@ -7,40 +7,39 @@ using Bit.Identity;
using Bit.Test.Common.Helpers;
using Microsoft.AspNetCore.Http;
namespace Bit.IntegrationTestCommon.Factories
namespace Bit.IntegrationTestCommon.Factories;
public class IdentityApplicationFactory : WebApplicationFactoryBase<Startup>
{
public class IdentityApplicationFactory : WebApplicationFactoryBase<Startup>
public const string DefaultDeviceIdentifier = "92b9d953-b9b6-4eaf-9d3e-11d57144dfeb";
public async Task<HttpContext> RegisterAsync(RegisterRequestModel model)
{
public const string DefaultDeviceIdentifier = "92b9d953-b9b6-4eaf-9d3e-11d57144dfeb";
return await Server.PostAsync("/accounts/register", JsonContent.Create(model));
}
public async Task<HttpContext> RegisterAsync(RegisterRequestModel model)
public async Task<(string Token, string RefreshToken)> TokenFromPasswordAsync(string username,
string password,
string deviceIdentifier = DefaultDeviceIdentifier,
string clientId = "web",
DeviceType deviceType = DeviceType.FirefoxBrowser,
string deviceName = "firefox")
{
var context = await Server.PostAsync("/connect/token", new FormUrlEncodedContent(new Dictionary<string, string>
{
return await Server.PostAsync("/accounts/register", JsonContent.Create(model));
}
{ "scope", "api offline_access" },
{ "client_id", clientId },
{ "deviceType", ((int)deviceType).ToString() },
{ "deviceIdentifier", deviceIdentifier },
{ "deviceName", deviceName },
{ "grant_type", "password" },
{ "username", username },
{ "password", password },
}), context => context.Request.Headers.Add("Auth-Email", CoreHelpers.Base64UrlEncodeString(username)));
public async Task<(string Token, string RefreshToken)> TokenFromPasswordAsync(string username,
string password,
string deviceIdentifier = DefaultDeviceIdentifier,
string clientId = "web",
DeviceType deviceType = DeviceType.FirefoxBrowser,
string deviceName = "firefox")
{
var context = await Server.PostAsync("/connect/token", new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "scope", "api offline_access" },
{ "client_id", clientId },
{ "deviceType", ((int)deviceType).ToString() },
{ "deviceIdentifier", deviceIdentifier },
{ "deviceName", deviceName },
{ "grant_type", "password" },
{ "username", username },
{ "password", password },
}), context => context.Request.Headers.Add("Auth-Email", CoreHelpers.Base64UrlEncodeString(username)));
using var body = await AssertHelper.AssertResponseTypeIs<JsonDocument>(context);
var root = body.RootElement;
using var body = await AssertHelper.AssertResponseTypeIs<JsonDocument>(context);
var root = body.RootElement;
return (root.GetProperty("access_token").GetString(), root.GetProperty("refresh_token").GetString());
}
return (root.GetProperty("access_token").GetString(), root.GetProperty("refresh_token").GetString());
}
}

View File

@ -9,103 +9,102 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace Bit.IntegrationTestCommon.Factories
namespace Bit.IntegrationTestCommon.Factories;
public static class FactoryConstants
{
public static class FactoryConstants
public const string DefaultDatabaseName = "test_database";
public const string WhitelistedIp = "1.1.1.1";
}
public abstract class WebApplicationFactoryBase<T> : WebApplicationFactory<T>
where T : class
{
/// <summary>
/// The database name to use for this instance of the factory. By default it will use a shared database name so all instances will connect to the same database during it's lifetime.
/// </summary>
/// <remarks>
/// This will need to be set BEFORE using the <c>Server</c> property
/// </remarks>
public string DatabaseName { get; set; } = FactoryConstants.DefaultDatabaseName;
/// <summary>
/// Configure the web host to use an EF in memory database
/// </summary>
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
public const string DefaultDatabaseName = "test_database";
public const string WhitelistedIp = "1.1.1.1";
builder.ConfigureAppConfiguration(c =>
{
c.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json")
.AddJsonFile("appsettings.Development.json");
c.AddUserSecrets(typeof(Identity.Startup).Assembly, optional: true);
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
{ "globalSettings:databaseProvider", "postgres" },
{ "globalSettings:postgreSql:connectionString", "Host=localhost;Username=test;Password=test;Database=test" },
// Clear the redis connection string for distributed caching, forcing an in-memory implementation
{ "globalSettings:redis:connectionString", ""}
});
});
builder.ConfigureTestServices(services =>
{
var dbContextOptions = services.First(sd => sd.ServiceType == typeof(DbContextOptions<DatabaseContext>));
services.Remove(dbContextOptions);
services.AddScoped(_ =>
{
return new DbContextOptionsBuilder<DatabaseContext>()
.UseInMemoryDatabase(DatabaseName)
.Options;
});
// QUESTION: The normal licensing service should run fine on developer machines but not in CI
// should we have a fork here to leave the normal service for developers?
// TODO: Eventually add the license file to CI
var licensingService = services.First(sd => sd.ServiceType == typeof(ILicensingService));
services.Remove(licensingService);
services.AddSingleton<ILicensingService, NoopLicensingService>();
// FUTURE CONSIDERATION: Add way to run this self hosted/cloud, for now it is cloud only
var pushRegistrationService = services.First(sd => sd.ServiceType == typeof(IPushRegistrationService));
services.Remove(pushRegistrationService);
services.AddSingleton<IPushRegistrationService, NoopPushRegistrationService>();
// Even though we are cloud we currently set this up as cloud, we can use the EF/selfhosted service
// instead of using Noop for this service
// TODO: Install and use azurite in CI pipeline
var eventWriteService = services.First(sd => sd.ServiceType == typeof(IEventWriteService));
services.Remove(eventWriteService);
services.AddSingleton<IEventWriteService, RepositoryEventWriteService>();
var eventRepositoryService = services.First(sd => sd.ServiceType == typeof(IEventRepository));
services.Remove(eventRepositoryService);
services.AddSingleton<IEventRepository, EventRepository>();
// Our Rate limiter works so well that it begins to fail tests unless we carve out
// one whitelisted ip. We should still test the rate limiter though and they should change the Ip
// to something that is NOT whitelisted
services.Configure<IpRateLimitOptions>(options =>
{
options.IpWhitelist = new List<string>
{
FactoryConstants.WhitelistedIp,
};
});
// Fix IP Rate Limiting
services.AddSingleton<IStartupFilter, CustomStartupFilter>();
});
}
public abstract class WebApplicationFactoryBase<T> : WebApplicationFactory<T>
where T : class
public DatabaseContext GetDatabaseContext()
{
/// <summary>
/// The database name to use for this instance of the factory. By default it will use a shared database name so all instances will connect to the same database during it's lifetime.
/// </summary>
/// <remarks>
/// This will need to be set BEFORE using the <c>Server</c> property
/// </remarks>
public string DatabaseName { get; set; } = FactoryConstants.DefaultDatabaseName;
/// <summary>
/// Configure the web host to use an EF in memory database
/// </summary>
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureAppConfiguration(c =>
{
c.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json")
.AddJsonFile("appsettings.Development.json");
c.AddUserSecrets(typeof(Identity.Startup).Assembly, optional: true);
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
{ "globalSettings:databaseProvider", "postgres" },
{ "globalSettings:postgreSql:connectionString", "Host=localhost;Username=test;Password=test;Database=test" },
// Clear the redis connection string for distributed caching, forcing an in-memory implementation
{ "globalSettings:redis:connectionString", ""}
});
});
builder.ConfigureTestServices(services =>
{
var dbContextOptions = services.First(sd => sd.ServiceType == typeof(DbContextOptions<DatabaseContext>));
services.Remove(dbContextOptions);
services.AddScoped(_ =>
{
return new DbContextOptionsBuilder<DatabaseContext>()
.UseInMemoryDatabase(DatabaseName)
.Options;
});
// QUESTION: The normal licensing service should run fine on developer machines but not in CI
// should we have a fork here to leave the normal service for developers?
// TODO: Eventually add the license file to CI
var licensingService = services.First(sd => sd.ServiceType == typeof(ILicensingService));
services.Remove(licensingService);
services.AddSingleton<ILicensingService, NoopLicensingService>();
// FUTURE CONSIDERATION: Add way to run this self hosted/cloud, for now it is cloud only
var pushRegistrationService = services.First(sd => sd.ServiceType == typeof(IPushRegistrationService));
services.Remove(pushRegistrationService);
services.AddSingleton<IPushRegistrationService, NoopPushRegistrationService>();
// Even though we are cloud we currently set this up as cloud, we can use the EF/selfhosted service
// instead of using Noop for this service
// TODO: Install and use azurite in CI pipeline
var eventWriteService = services.First(sd => sd.ServiceType == typeof(IEventWriteService));
services.Remove(eventWriteService);
services.AddSingleton<IEventWriteService, RepositoryEventWriteService>();
var eventRepositoryService = services.First(sd => sd.ServiceType == typeof(IEventRepository));
services.Remove(eventRepositoryService);
services.AddSingleton<IEventRepository, EventRepository>();
// Our Rate limiter works so well that it begins to fail tests unless we carve out
// one whitelisted ip. We should still test the rate limiter though and they should change the Ip
// to something that is NOT whitelisted
services.Configure<IpRateLimitOptions>(options =>
{
options.IpWhitelist = new List<string>
{
FactoryConstants.WhitelistedIp,
};
});
// Fix IP Rate Limiting
services.AddSingleton<IStartupFilter, CustomStartupFilter>();
});
}
public DatabaseContext GetDatabaseContext()
{
var scope = Services.CreateScope();
return scope.ServiceProvider.GetRequiredService<DatabaseContext>();
}
var scope = Services.CreateScope();
return scope.ServiceProvider.GetRequiredService<DatabaseContext>();
}
}

View File

@ -4,65 +4,64 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Primitives;
namespace Bit.IntegrationTestCommon.Factories
namespace Bit.IntegrationTestCommon.Factories;
public static class WebApplicationFactoryExtensions
{
public static class WebApplicationFactoryExtensions
private static async Task<HttpContext> SendAsync(this TestServer server,
HttpMethod method,
string requestUri,
HttpContent content = null,
Action<HttpContext> extraConfiguration = null)
{
private static async Task<HttpContext> SendAsync(this TestServer server,
HttpMethod method,
string requestUri,
HttpContent content = null,
Action<HttpContext> extraConfiguration = null)
return await server.SendAsync(httpContext =>
{
return await server.SendAsync(httpContext =>
// Automatically set the whitelisted IP so normal tests do not run into rate limit issues
// to test rate limiter, use the extraConfiguration parameter to set Connection.RemoteIpAddress
// it runs after this so it will take precedence.
httpContext.Connection.RemoteIpAddress = IPAddress.Parse(FactoryConstants.WhitelistedIp);
httpContext.Request.Path = new PathString(requestUri);
httpContext.Request.Method = method.Method;
if (content != null)
{
// Automatically set the whitelisted IP so normal tests do not run into rate limit issues
// to test rate limiter, use the extraConfiguration parameter to set Connection.RemoteIpAddress
// it runs after this so it will take precedence.
httpContext.Connection.RemoteIpAddress = IPAddress.Parse(FactoryConstants.WhitelistedIp);
httpContext.Request.Path = new PathString(requestUri);
httpContext.Request.Method = method.Method;
if (content != null)
foreach (var header in content.Headers)
{
foreach (var header in content.Headers)
{
httpContext.Request.Headers.Add(header.Key, new StringValues(header.Value.ToArray()));
}
httpContext.Request.Body = content.ReadAsStream();
httpContext.Request.Headers.Add(header.Key, new StringValues(header.Value.ToArray()));
}
extraConfiguration?.Invoke(httpContext);
});
}
public static Task<HttpContext> PostAsync(this TestServer server,
string requestUri,
HttpContent content,
Action<HttpContext> extraConfiguration = null)
=> SendAsync(server, HttpMethod.Post, requestUri, content, extraConfiguration);
public static Task<HttpContext> GetAsync(this TestServer server,
string requestUri,
Action<HttpContext> extraConfiguration = null)
=> SendAsync(server, HttpMethod.Get, requestUri, content: null, extraConfiguration);
httpContext.Request.Body = content.ReadAsStream();
}
public static HttpContext SetAuthEmail(this HttpContext context, string username)
{
context.Request.Headers.Add("Auth-Email", CoreHelpers.Base64UrlEncodeString(username));
return context;
}
extraConfiguration?.Invoke(httpContext);
});
}
public static Task<HttpContext> PostAsync(this TestServer server,
string requestUri,
HttpContent content,
Action<HttpContext> extraConfiguration = null)
=> SendAsync(server, HttpMethod.Post, requestUri, content, extraConfiguration);
public static Task<HttpContext> GetAsync(this TestServer server,
string requestUri,
Action<HttpContext> extraConfiguration = null)
=> SendAsync(server, HttpMethod.Get, requestUri, content: null, extraConfiguration);
public static HttpContext SetIp(this HttpContext context, string ip)
{
context.Connection.RemoteIpAddress = IPAddress.Parse(ip);
return context;
}
public static HttpContext SetAuthEmail(this HttpContext context, string username)
{
context.Request.Headers.Add("Auth-Email", CoreHelpers.Base64UrlEncodeString(username));
return context;
}
public static async Task<string> ReadBodyAsStringAsync(this HttpContext context)
{
using var sr = new StreamReader(context.Response.Body);
return await sr.ReadToEndAsync();
}
public static HttpContext SetIp(this HttpContext context, string ip)
{
context.Connection.RemoteIpAddress = IPAddress.Parse(ip);
return context;
}
public static async Task<string> ReadBodyAsStringAsync(this HttpContext context)
{
using var sr = new StreamReader(context.Response.Body);
return await sr.ReadToEndAsync();
}
}