diff --git a/src/BuildingBlocks/BuildingBlocks.csproj b/src/BuildingBlocks/BuildingBlocks.csproj index 252ed49..8944ac0 100644 --- a/src/BuildingBlocks/BuildingBlocks.csproj +++ b/src/BuildingBlocks/BuildingBlocks.csproj @@ -102,6 +102,7 @@ + diff --git a/src/BuildingBlocks/TestBase/Auth/AuthServiceCollectionExtensions.cs b/src/BuildingBlocks/TestBase/Auth/AuthServiceCollectionExtensions.cs deleted file mode 100644 index 21e7d68..0000000 --- a/src/BuildingBlocks/TestBase/Auth/AuthServiceCollectionExtensions.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Security.Claims; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authorization; -using Microsoft.Extensions.DependencyInjection; - -namespace BuildingBlocks.TestBase.Auth; - -//ref: https://blog.joaograssi.com/posts/2021/asp-net-core-testing-permission-protected-api-endpoints/ -public static class AuthServiceCollectionExtensions -{ - private static MockAuthUser GetMockUser() => - new MockAuthUser(new Claim("sub", Guid.NewGuid().ToString()), - new Claim("email", "sam@test.com")); - - public static AuthenticationBuilder AddTestAuthentication(this IServiceCollection services) - { - services.AddAuthorization(options => - { - // AuthConstants.Scheme is just a scheme we define. I called it "TestAuth" - options.DefaultPolicy = new AuthorizationPolicyBuilder("Test") - .RequireAuthenticatedUser() - .Build(); - }); - - // Register a default user, so all requests have it by default - services.AddScoped(_ => GetMockUser()); - - // Register our custom authentication handler - return services.AddAuthentication("Test") - .AddScheme("Test", options => { }); - } -} diff --git a/src/BuildingBlocks/TestBase/Auth/MockAuthUser.cs b/src/BuildingBlocks/TestBase/Auth/MockAuthUser.cs deleted file mode 100644 index e261174..0000000 --- a/src/BuildingBlocks/TestBase/Auth/MockAuthUser.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Security.Claims; - -namespace BuildingBlocks.TestBase.Auth; - -public class MockAuthUser -{ - public List Claims { get; } - public MockAuthUser(params Claim[] claims) => Claims = claims.ToList(); -} diff --git a/src/BuildingBlocks/TestBase/Auth/TestAuthHandler.cs b/src/BuildingBlocks/TestBase/Auth/TestAuthHandler.cs deleted file mode 100644 index e5a168f..0000000 --- a/src/BuildingBlocks/TestBase/Auth/TestAuthHandler.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Security.Claims; -using System.Text.Encodings.Web; -using Microsoft.AspNetCore.Authentication; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; - -namespace BuildingBlocks.TestBase.Auth; - -//ref: https://blog.joaograssi.com/posts/2021/asp-net-core-testing-permission-protected-api-endpoints/ -public class TestAuthHandler : AuthenticationHandler -{ - - - private readonly MockAuthUser _mockAuthUser; - - public TestAuthHandler( - IOptionsMonitor options, - ILoggerFactory logger, - UrlEncoder encoder, - ISystemClock clock, - MockAuthUser mockAuthUser) - : base(options, logger, encoder, clock) - { - // 1. We get a "mock" user instance here via DI. - // we'll see how this work later, don't worry - _mockAuthUser = mockAuthUser; - } - - protected override Task HandleAuthenticateAsync() - { - if (_mockAuthUser.Claims.Count == 0) - return Task.FromResult(AuthenticateResult.Fail("Mock auth user not configured.")); - - // 2. Create the principal and the ticket - var identity = new ClaimsIdentity(_mockAuthUser.Claims, "Test"); - var principal = new ClaimsPrincipal(identity); - var ticket = new AuthenticationTicket(principal, "Test"); - - // 3. Authenticate the request - var result = AuthenticateResult.Success(ticket); - return Task.FromResult(result); - } -} diff --git a/src/BuildingBlocks/TestBase/TestBase.cs b/src/BuildingBlocks/TestBase/TestBase.cs index e874a2a..935698f 100644 --- a/src/BuildingBlocks/TestBase/TestBase.cs +++ b/src/BuildingBlocks/TestBase/TestBase.cs @@ -5,7 +5,6 @@ using BuildingBlocks.EFCore; using BuildingBlocks.MassTransit; using BuildingBlocks.Mongo; using BuildingBlocks.PersistMessageProcessor; -using BuildingBlocks.TestBase.Auth; using BuildingBlocks.Web; using DotNet.Testcontainers.Containers; using EasyNetQ.Management.Client; @@ -32,6 +31,10 @@ using ILogger = Serilog.ILogger; namespace BuildingBlocks.TestBase; +using System.Net; +using System.Security.Claims; +using WebMotions.Fake.Authentication.JwtBearer; + public class TestFixture : IAsyncLifetime where TEntryPoint : class { @@ -44,7 +47,18 @@ public class TestFixture : IAsyncLifetime public MongoDbTestcontainer MongoDbTestContainer; private ITestHarness TestHarness => ServiceProvider?.GetTestHarness(); - public HttpClient HttpClient => _factory?.CreateClient(); + + public HttpClient HttpClient + { + get + { + var claims = new Dictionary { { ClaimTypes.Name, "test@sample.com" }, { ClaimTypes.Role, "admin" }, }; + var httpClient = _factory?.CreateClient(); + httpClient.SetFakeBearerToken(claims); + return httpClient; + } + } + public GrpcChannel Channel => GrpcChannel.ForAddress(HttpClient.BaseAddress!, new GrpcChannelOptions { HttpClient = HttpClient }); public Action TestRegistrationServices { get; set; } public IServiceProvider ServiceProvider => _factory?.Services; @@ -63,7 +77,15 @@ public class TestFixture : IAsyncLifetime { TestRegistrationServices?.Invoke(services); services.ReplaceSingleton(AddHttpContextAccessorMock); - services.AddTestAuthentication(); + + // add authentication using a fake jwt bearer - we can use SetAdminUser method to set authenticate user to existing HttContextAccessor + // https://github.com/webmotions/fake-authentication-jwtbearer + // https://github.com/webmotions/fake-authentication-jwtbearer/issues/14 + services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = FakeJwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = FakeJwtBearerDefaults.AuthenticationScheme; + }).AddFakeJwtBearer(); }); }); } @@ -235,13 +257,9 @@ public class TestFixture : IAsyncLifetime configuration.AddInMemoryCollection(new KeyValuePair[] { new("DatabaseOptions:DefaultConnection", MsSqlTestContainer.ConnectionString + "TrustServerCertificate=True"), - new("PersistMessageOptions:ConnectionString", MsSqlPersistTestContainer.ConnectionString + "TrustServerCertificate=True"), - new("RabbitMqOptions:HostName", RabbitMqTestContainer.Hostname), - new("RabbitMqOptions:UserName", RabbitMqTestContainer.Username), - new("RabbitMqOptions:Password", RabbitMqTestContainer.Password), - new("RabbitMqOptions:Port", RabbitMqTestContainer.Port.ToString()), - new("MongoOptions:ConnectionString", MongoDbTestContainer.ConnectionString), - new("MongoOptions:DatabaseName", MongoDbTestContainer.Database) + new("PersistMessageOptions:ConnectionString", MsSqlPersistTestContainer.ConnectionString + "TrustServerCertificate=True"), new("RabbitMqOptions:HostName", RabbitMqTestContainer.Hostname), + new("RabbitMqOptions:UserName", RabbitMqTestContainer.Username), new("RabbitMqOptions:Password", RabbitMqTestContainer.Password), new("RabbitMqOptions:Port", RabbitMqTestContainer.Port.ToString()), + new("MongoOptions:ConnectionString", MongoDbTestContainer.ConnectionString), new("MongoOptions:DatabaseName", MongoDbTestContainer.Database) }); } @@ -365,7 +383,6 @@ public class TestWriteFixture : TestFixture } } - public class TestReadFixture : TestFixture where TEntryPoint : class where TRContext : MongoDbContext @@ -428,7 +445,6 @@ public class TestFixtureCore : IAsyncLifetime _reSpawnerPersistDb = await Respawner.CreateAsync(PersistDbConnection, new RespawnerOptions { TablesToIgnore = new Table[] { "__EFMigrationsHistory" }, }); - await _reSpawnerPersistDb.ResetAsync(PersistDbConnection); } if (!string.IsNullOrEmpty(databaseOptions?.DefaultConnection)) @@ -439,18 +455,25 @@ public class TestFixtureCore : IAsyncLifetime _reSpawnerDefaultDb = await Respawner.CreateAsync(DefaultDbConnection, new RespawnerOptions { TablesToIgnore = new Table[] { "__EFMigrationsHistory" }, }); - await _reSpawnerDefaultDb.ResetAsync(DefaultDbConnection); - await SeedDataAsync(); } } public async Task DisposeAsync() { + await ResetSqlAsync(); await ResetMongoAsync(); await ResetRabbitMqAsync(); } + private async Task ResetSqlAsync() + { + if (PersistDbConnection is not null) + await _reSpawnerPersistDb.ResetAsync(PersistDbConnection); + if (DefaultDbConnection is not null) + await _reSpawnerDefaultDb.ResetAsync(DefaultDbConnection); + } + private async Task ResetMongoAsync(CancellationToken cancellationToken = default) { //https://stackoverflow.com/questions/3366397/delete-everything-in-a-mongodb-database @@ -517,7 +540,6 @@ public abstract class TestReadBase : TestFixtureCore Fixture { get; } } - public abstract class TestWriteBase : TestFixtureCore //,IClassFixture> where TEntryPoint : class diff --git a/src/Services/Booking/src/Booking.Api/Program.cs b/src/Services/Booking/src/Booking.Api/Program.cs index 4e36300..ad0f0ce 100644 --- a/src/Services/Booking/src/Booking.Api/Program.cs +++ b/src/Services/Booking/src/Booking.Api/Program.cs @@ -20,7 +20,6 @@ var app = builder.Build(); app.MapMinimalEndpoints(); app.UseAuthentication(); app.UseAuthorization(); -app.UseRouting(); app.UseHttpsRedirection(); app.UseInfrastructure(); diff --git a/src/Services/Flight/src/Flight.Api/Program.cs b/src/Services/Flight/src/Flight.Api/Program.cs index fff475e..001e913 100644 --- a/src/Services/Flight/src/Flight.Api/Program.cs +++ b/src/Services/Flight/src/Flight.Api/Program.cs @@ -21,7 +21,6 @@ var app = builder.Build(); app.MapMinimalEndpoints(); app.UseAuthentication(); app.UseAuthorization(); -app.UseRouting(); app.UseHttpsRedirection(); app.UseInfrastructure(); diff --git a/src/Services/Flight/tests/EndToEndTest/Flight/Features/GetFlightByIdTests.cs b/src/Services/Flight/tests/EndToEndTest/Flight/Features/GetFlightByIdTests.cs index 72d27f0..e4a0e9a 100644 --- a/src/Services/Flight/tests/EndToEndTest/Flight/Features/GetFlightByIdTests.cs +++ b/src/Services/Flight/tests/EndToEndTest/Flight/Features/GetFlightByIdTests.cs @@ -10,6 +10,8 @@ using Xunit; namespace EndToEnd.Test.Flight.Features; +using BuildingBlocks.Contracts.EventBus.Messages; + public class GetFlightByIdTests: FlightEndToEndTestBase { public GetFlightByIdTests(TestFixture integrationTestFixture) : base(integrationTestFixture) @@ -23,6 +25,8 @@ public class GetFlightByIdTests: FlightEndToEndTestBase //Arrange var command = new FakeCreateFlightCommand().Generate(); await Fixture.SendAsync(command); + (await Fixture.WaitForPublishing()).Should().Be(true); + (await Fixture.WaitForConsuming()).Should().Be(true); (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); // Act diff --git a/src/Services/Flight/tests/EndToEndTest/FlightTestBase.cs b/src/Services/Flight/tests/EndToEndTest/FlightEndToEndTestBase.cs similarity index 100% rename from src/Services/Flight/tests/EndToEndTest/FlightTestBase.cs rename to src/Services/Flight/tests/EndToEndTest/FlightEndToEndTestBase.cs diff --git a/src/Services/Identity/src/Identity.Api/Program.cs b/src/Services/Identity/src/Identity.Api/Program.cs index de125f5..459d4ee 100644 --- a/src/Services/Identity/src/Identity.Api/Program.cs +++ b/src/Services/Identity/src/Identity.Api/Program.cs @@ -20,7 +20,6 @@ var app = builder.Build(); app.MapMinimalEndpoints(); app.UseAuthentication(); app.UseAuthorization(); -app.UseRouting(); app.UseHttpsRedirection(); app.UseInfrastructure(); diff --git a/src/Services/Passenger/src/Passenger.Api/Program.cs b/src/Services/Passenger/src/Passenger.Api/Program.cs index 81bfe00..7f85306 100644 --- a/src/Services/Passenger/src/Passenger.Api/Program.cs +++ b/src/Services/Passenger/src/Passenger.Api/Program.cs @@ -20,7 +20,6 @@ var app = builder.Build(); app.MapMinimalEndpoints(); app.UseAuthentication(); app.UseAuthorization(); -app.UseRouting(); app.UseHttpsRedirection(); app.UseInfrastructure();