Skip to content

Commit

Permalink
fixed all broken unit tests and additional tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrewTriesToCode committed Feb 6, 2024
1 parent 57021ee commit f029972
Show file tree
Hide file tree
Showing 10 changed files with 233 additions and 894 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public static FinbuckleMultiTenantBuilder<TTenantInfo> WithPerTenantAuthenticati
});

// Set per-tenant cookie options by convention.
builder.WithPerTenantOptions<CookieAuthenticationOptions>((options, tc) =>
builder.Services.ConfigureAllPerTenant<CookieAuthenticationOptions, TTenantInfo>((options, tc) =>
{
if (GetPropertyWithValidValue(tc, "CookieLoginPath") is string loginPath)
options.LoginPath = loginPath.Replace(Constants.TenantToken, tc.Identifier);
Expand All @@ -110,7 +110,7 @@ public static FinbuckleMultiTenantBuilder<TTenantInfo> WithPerTenantAuthenticati
});

// Set per-tenant OpenIdConnect options by convention.
builder.WithPerTenantOptions<OpenIdConnectOptions>((options, tc) =>
builder.Services.ConfigureAllPerTenant<OpenIdConnectOptions, TTenantInfo>((options, tc) =>
{
if (GetPropertyWithValidValue(tc, "OpenIdConnectAuthority") is string authority)
options.Authority = authority.Replace(Constants.TenantToken, tc.Identifier);
Expand All @@ -122,7 +122,7 @@ public static FinbuckleMultiTenantBuilder<TTenantInfo> WithPerTenantAuthenticati
options.ClientSecret = clientSecret.Replace(Constants.TenantToken, tc.Identifier);
});

builder.WithPerTenantOptions<AuthenticationOptions>((options, tc) =>
builder.Services.ConfigureAllPerTenant<AuthenticationOptions, TTenantInfo>((options, tc) =>
{
if (GetPropertyWithValidValue(tc, "ChallengeScheme") is string challengeScheme)
options.DefaultChallengeScheme = challengeScheme;
Expand Down Expand Up @@ -156,7 +156,7 @@ public static FinbuckleMultiTenantBuilder<TTenantInfo> WithPerTenantAuthenticati
// properties in the state parameter.
if (builder.Services.All(s => s.ServiceType != typeof(IAuthenticationService)))
throw new MultiTenantException(
"WithPerTenantAuthenticationCore() must be called after AddAuthentication() in ConfigureServices.");
"WithPerTenantAuthenticationCore() must be called after AddAuthentication().");
builder.Services.DecorateService<IAuthenticationService, MultiTenantAuthenticationService<TTenantInfo>>();

// We need to "decorate" IAuthenticationScheme provider.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ namespace Finbuckle.MultiTenant.AspNetCore
/// <summary>
/// Implements <see cref="IAuthenticationSchemeProvider"/>.
/// </summary>
// ReSharper disable once ClassWithVirtualMembersNeverInherited.Global
internal class MultiTenantAuthenticationSchemeProvider : IAuthenticationSchemeProvider
{
private readonly IAuthenticationSchemeProvider _inner;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
// ReSharper disable once CheckNamespace
namespace Microsoft.Extensions.DependencyInjection;

// TODO refactor methods into extensions
/// <summary>
/// Builder class for Finbuckle.MultiTenant configuration.
/// </summary>
Expand Down
810 changes: 131 additions & 679 deletions src/Finbuckle.MultiTenant/DependencyInjection/OptionsBuilderExtensions.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,12 @@ public static IServiceCollection ConfigurePerTenant<TOptions, TTenantInfo>(
ConfigurePerTenantReqs<TOptions>(services);

services.AddTransient<IConfigureOptions<TOptions>>(sp =>
new ConfigureNamedOptions<TOptions, TTenantInfo?>(
new ConfigureNamedOptions<TOptions, IMultiTenantContextAccessor<TTenantInfo>>(
name,
sp.GetService<TTenantInfo>(),
(options, tenantInfo) =>
sp.GetRequiredService<IMultiTenantContextAccessor<TTenantInfo>>(),
(options, mtcAccessor) =>
{
var tenantInfo = mtcAccessor.MultiTenantContext?.TenantInfo;
if (tenantInfo is not null)
configureOptions(options, tenantInfo);
}));
Expand Down Expand Up @@ -207,11 +208,12 @@ public static IServiceCollection PostConfigurePerTenant<TOptions, TTenantInfo>(
ConfigurePerTenantReqs<TOptions>(services);

services.AddTransient<IPostConfigureOptions<TOptions>>(sp =>
new PostConfigureOptions<TOptions, TTenantInfo?>(
new PostConfigureOptions<TOptions, IMultiTenantContextAccessor<TTenantInfo>>(
name,
sp.GetService<TTenantInfo>(),
(options, tenantInfo) =>
sp.GetRequiredService<IMultiTenantContextAccessor<TTenantInfo>>(),
(options, mtcAccessor) =>
{
var tenantInfo = mtcAccessor.MultiTenantContext?.TenantInfo;
if (tenantInfo is not null)
configureOptions(options, tenantInfo);
}));
Expand Down
117 changes: 4 additions & 113 deletions src/Finbuckle.MultiTenant/Options/MultiTenantOptionsCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,8 @@ public class MultiTenantOptionsCache<TOptions> : IOptionsMonitorCache<TOptions>
where TOptions : class
{
private readonly IMultiTenantContextAccessor multiTenantContextAccessor;

// The object is just a dummy because there is no ConcurrentSet<T> class.
//private readonly ConcurrentDictionary<string, ConcurrentDictionary<string, object>> _adjustedOptionsNames =
// new ConcurrentDictionary<string, ConcurrentDictionary<string, object>>();

private readonly ConcurrentDictionary<string, IOptionsMonitorCache<TOptions>> map = new ConcurrentDictionary<string, IOptionsMonitorCache<TOptions>>();

private readonly ConcurrentDictionary<string, IOptionsMonitorCache<TOptions>> map = new();

/// <summary>
/// Constructs a new instance of MultiTenantOptionsCache.
Expand All @@ -27,7 +23,8 @@ public class MultiTenantOptionsCache<TOptions> : IOptionsMonitorCache<TOptions>
/// <exception cref="ArgumentNullException"></exception>
public MultiTenantOptionsCache(IMultiTenantContextAccessor multiTenantContextAccessor)
{
this.multiTenantContextAccessor = multiTenantContextAccessor ?? throw new ArgumentNullException(nameof(multiTenantContextAccessor));
this.multiTenantContextAccessor = multiTenantContextAccessor ??
throw new ArgumentNullException(nameof(multiTenantContextAccessor));
}

/// <summary>
Expand Down Expand Up @@ -96,112 +93,6 @@ public bool TryAdd(string? name, TOptions options)
return cache.TryAdd(name, options);
}

/// <summary>
/// Try to remove an options instance for the current tenant.
/// </summary>
/// <param name="name">The options name.</param>
/// <returns>True if the options was removed from the cache for the current tenant.</returns>
public bool TryRemove(string? name)
{
name = name ?? Microsoft.Extensions.Options.Options.DefaultName;
var tenantId = multiTenantContextAccessor.MultiTenantContext?.TenantInfo?.Id ?? "";
var cache = map.GetOrAdd(tenantId, new OptionsCache<TOptions>());

return cache.TryRemove(name);
}
}

/// <summary>
/// Adds, retrieves, and removes instances of TOptions after adjusting them for the current TenantContext.
/// </summary>
public class MultiTenantOptionsCache<TOptions, TTenantInfo> : IOptionsMonitorCache<TOptions>
where TOptions : class
where TTenantInfo : class, ITenantInfo, new()
{
private readonly IMultiTenantContextAccessor<TTenantInfo> multiTenantContextAccessor;

// The object is just a dummy because there is no ConcurrentSet<T> class.
//private readonly ConcurrentDictionary<string, ConcurrentDictionary<string, object>> _adjustedOptionsNames =
// new ConcurrentDictionary<string, ConcurrentDictionary<string, object>>();

private readonly ConcurrentDictionary<string, IOptionsMonitorCache<TOptions>> map = new ConcurrentDictionary<string, IOptionsMonitorCache<TOptions>>();

/// <summary>
/// Constructs a new instance of MultiTenantOptionsCache.
/// </summary>
/// <param name="multiTenantContextAccessor"></param>
/// <exception cref="ArgumentNullException"></exception>
public MultiTenantOptionsCache(IMultiTenantContextAccessor<TTenantInfo> multiTenantContextAccessor)
{
this.multiTenantContextAccessor = multiTenantContextAccessor ?? throw new ArgumentNullException(nameof(multiTenantContextAccessor));
}

/// <summary>
/// Clears all cached options for the current tenant.
/// </summary>
public void Clear()
{
var tenantId = multiTenantContextAccessor.MultiTenantContext?.TenantInfo?.Id ?? "";
var cache = map.GetOrAdd(tenantId, new OptionsCache<TOptions>());

cache.Clear();
}

/// <summary>
/// Clears all cached options for the given tenant.
/// </summary>
/// <param name="tenantId">The Id of the tenant which will have its options cleared.</param>
public void Clear(string tenantId)
{
var cache = map.GetOrAdd(tenantId, new OptionsCache<TOptions>());

cache.Clear();
}

/// <summary>
/// Clears all cached options for all tenants and no tenant.
/// </summary>
public void ClearAll()
{
foreach (var cache in map.Values)
cache.Clear();
}

/// <summary>
/// Gets a named options instance for the current tenant, or adds a new instance created with createOptions.
/// </summary>
/// <param name="name">The options name.</param>
/// <param name="createOptions">The factory function for creating the options instance.</param>
/// <returns>The existing or new options instance.</returns>
public TOptions GetOrAdd(string? name, Func<TOptions> createOptions)
{
if (createOptions == null)
{
throw new ArgumentNullException(nameof(createOptions));
}

name = name ?? Microsoft.Extensions.Options.Options.DefaultName;
var tenantId = multiTenantContextAccessor.MultiTenantContext?.TenantInfo?.Id ?? "";
var cache = map.GetOrAdd(tenantId, new OptionsCache<TOptions>());

return cache.GetOrAdd(name, createOptions);
}

/// <summary>
/// Tries to adds a new option to the cache for the current tenant.
/// </summary>
/// <param name="name">The options name.</param>
/// <param name="options">The options instance.</param>
/// <returns>True if the options was added to the cache for the current tenant.</returns>
public bool TryAdd(string? name, TOptions options)
{
name = name ?? Microsoft.Extensions.Options.Options.DefaultName;
var tenantId = multiTenantContextAccessor.MultiTenantContext?.TenantInfo?.Id ?? "";
var cache = map.GetOrAdd(tenantId, new OptionsCache<TOptions>());

return cache.TryAdd(name, options);
}

/// <summary>
/// Try to remove an options instance for the current tenant.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,58 +14,59 @@ namespace Finbuckle.MultiTenant.AspNetCore.Test
{
public class MultiTenantAuthenticationSchemeProviderShould
{
private static IWebHostBuilder GetTestHostBuilder()
[Fact]
public async Task ReturnPerTenantAuthenticationOptions()

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (7.0.x, ubuntu-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (7.0.x, ubuntu-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (7.0.x, ubuntu-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (7.0.x, ubuntu-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (7.0.x, ubuntu-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (7.0.x, ubuntu-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (6.0.x, ubuntu-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (6.0.x, ubuntu-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (6.0.x, ubuntu-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (6.0.x, ubuntu-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (6.0.x, ubuntu-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (6.0.x, ubuntu-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (8.0.x, ubuntu-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (8.0.x, ubuntu-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (8.0.x, ubuntu-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (8.0.x, ubuntu-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (8.0.x, ubuntu-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (8.0.x, ubuntu-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (6.0.x, macos-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (6.0.x, macos-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (6.0.x, macos-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (6.0.x, macos-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (6.0.x, macos-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (6.0.x, macos-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (8.0.x, macos-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (8.0.x, macos-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (8.0.x, macos-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (8.0.x, macos-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (8.0.x, macos-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (8.0.x, macos-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (7.0.x, macos-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (7.0.x, macos-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (7.0.x, macos-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (7.0.x, macos-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (7.0.x, macos-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (7.0.x, macos-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (6.0.x, windows-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (6.0.x, windows-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (6.0.x, windows-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (6.0.x, windows-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (6.0.x, windows-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (6.0.x, windows-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (8.0.x, windows-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (8.0.x, windows-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (8.0.x, windows-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (8.0.x, windows-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (8.0.x, windows-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (8.0.x, windows-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (7.0.x, windows-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (7.0.x, windows-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (7.0.x, windows-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (7.0.x, windows-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (7.0.x, windows-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 18 in test/Finbuckle.MultiTenant.AspNetCore.Test/MultiTenantAuthenticationSchemeProviderShould.cs

View workflow job for this annotation

GitHub Actions / build-and-test (7.0.x, windows-latest)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
{
return new WebHostBuilder()
.ConfigureServices(services =>
{
services.AddAuthentication()
.AddCookie("tenant1Scheme")
.AddCookie("tenant2Scheme");
// var hostBuilder = GetTestHostBuilder();
//
// using (var server = new TestServer(hostBuilder))
// {
// var client = server.CreateClient();
// var response = await client.GetStringAsync("/tenant1");
// Assert.Equal("tenant1Scheme", response);
//
// response = await client.GetStringAsync("/tenant2");
// Assert.Equal("tenant2Scheme", response);
// }

services.AddMultiTenant<TenantInfo>()
.WithBasePathStrategy()
.WithPerTenantAuthentication()
.WithInMemoryStore()
.WithPerTenantOptions<AuthenticationOptions>((ao, ti) =>
{
ao.DefaultChallengeScheme = ti.Identifier + "Scheme";
});
var services = new ServiceCollection();
services.AddAuthentication()
.AddCookie("tenant1Scheme")
.AddCookie("tenant2Scheme");

services.AddMvc();
})
.Configure(app =>
{
app.UseMultiTenant();
app.Run(async context =>
{
if (context.GetMultiTenantContext<TenantInfo>()?.TenantInfo != null)
{
var schemeProvider = context.RequestServices.GetRequiredService<IAuthenticationSchemeProvider>();
await context.Response.WriteAsync((await schemeProvider.GetDefaultChallengeSchemeAsync())!.Name);
}
});
services.AddMultiTenant<TenantInfo>()
.WithPerTenantAuthentication();

var store = app.ApplicationServices.GetRequiredService<IMultiTenantStore<TenantInfo>>();
store.TryAddAsync(new TenantInfo { Id = "tenant1", Identifier = "tenant1" }).Wait();
store.TryAddAsync(new TenantInfo { Id = "tenant2", Identifier = "tenant2" }).Wait();
});
}
services.ConfigureAllPerTenant<AuthenticationOptions, TenantInfo>((ao, ti) =>
{
ao.DefaultChallengeScheme = ti.Identifier + "Scheme";
});

[Fact]
public async Task ReturnPerTenantAuthenticationOptions()
{
var hostBuilder = GetTestHostBuilder();
var sp = services.BuildServiceProvider();

using (var server = new TestServer(hostBuilder))
{
var client = server.CreateClient();
var response = await client.GetStringAsync("/tenant1");
Assert.Equal("tenant1Scheme", response);
var tenant1 = new TenantInfo{
Id = "tenant1",
Identifier = "tenant1"
};

var tenant2 = new TenantInfo{
Id = "tenant2",
Identifier = "tenant2"
};

var mtc = new MultiTenantContext<TenantInfo>();
var multiTenantContextAccessor = sp.GetRequiredService<IMultiTenantContextAccessor<TenantInfo>>();
multiTenantContextAccessor.MultiTenantContext = mtc;

mtc.TenantInfo = tenant1;
var schemeProvider = sp.GetRequiredService<IAuthenticationSchemeProvider>();

var option = schemeProvider.GetDefaultChallengeSchemeAsync().Result;
Assert.Equal("tenant1Scheme", option?.Name);

response = await client.GetStringAsync("/tenant2");
Assert.Equal("tenant2Scheme", response);
}
mtc.TenantInfo = tenant2;
option = schemeProvider.GetDefaultChallengeSchemeAsync().Result;
Assert.Equal("tenant2Scheme", option?.Name);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,21 +100,6 @@ public void RegisterIMultiTenantContextAccessorGenericInDi()
Assert.Equal(ServiceLifetime.Singleton, service!.Lifetime);
}

[Fact]
public void PreInitMultiTenantContextAccessorInDi()
{
var services = new ServiceCollection();
services.AddMultiTenant<TenantInfo>();

var service = services.SingleOrDefault(s => s.Lifetime == ServiceLifetime.Singleton &&
s.ServiceType ==
typeof(IMultiTenantContextAccessor<TenantInfo>) &&
s.ImplementationInstance is not null);

Assert.NotNull(service);
Assert.Equal(ServiceLifetime.Singleton, service!.Lifetime);
}

[Fact]
public void RegisterMultiTenantOptionsInDi()
{
Expand Down Expand Up @@ -143,10 +128,10 @@ public void RegisterNamedOptionsPerTenant()
var sp = services.BuildServiceProvider();

var configs = sp.GetRequiredService<IEnumerable<IConfigureOptions<TestOptions>>>();
var config = configs.Where(config => config is ConfigureNamedOptions<TestOptions> options).ToList();
var config = configs.Where(config => config is ConfigureNamedOptions<TestOptions, IMultiTenantContextAccessor<TenantInfo>> options).ToList();

Assert.Single(config);
Assert.Equal("name1", config.Select(c => (ConfigureNamedOptions<TestOptions>)c).Single().Name);
Assert.Equal("name1", config.Select(c => (ConfigureNamedOptions<TestOptions, IMultiTenantContextAccessor<TenantInfo>>)c).Single().Name);
}

[Fact]
Expand All @@ -158,11 +143,26 @@ public void RegisterUnnamedOptionsPerTenant()
var sp = services.BuildServiceProvider();

var configs = sp.GetRequiredService<IEnumerable<IConfigureOptions<TestOptions>>>();
var config = configs.Where(config => config is ConfigureNamedOptions<TestOptions> options).ToList();
var config = configs.Where(config => config is ConfigureNamedOptions<TestOptions, IMultiTenantContextAccessor<TenantInfo>> options).ToList();

Assert.Single(config);
Assert.Equal(Microsoft.Extensions.Options.Options.DefaultName,
config.Select(c => (ConfigureNamedOptions<TestOptions>)c).Single().Name);
config.Select(c => (ConfigureNamedOptions<TestOptions, IMultiTenantContextAccessor<TenantInfo>>)c).Single().Name);
}

[Fact]
public void RegisterAllOptionsPerTenant()
{
var services = new ServiceCollection();
services.AddMultiTenant<TenantInfo>();
services.ConfigureAllPerTenant<TestOptions, TenantInfo>((option, tenant) => option.Prop1 = tenant.Id);
var sp = services.BuildServiceProvider();

var configs = sp.GetRequiredService<IEnumerable<IConfigureOptions<TestOptions>>>();
var config = configs.Where(config => config is ConfigureNamedOptions<TestOptions, IMultiTenantContextAccessor<TenantInfo>> options).ToList();

Assert.Single(config);
Assert.Null(config.Select(c => (ConfigureNamedOptions<TestOptions, IMultiTenantContextAccessor<TenantInfo>>)c).Single().Name);
}
}
}
Loading

0 comments on commit f029972

Please sign in to comment.