Skip to content

Commit 04e12d7

Browse files
committed
feat: lists handlers types that can be managed
1 parent e2d6996 commit 04e12d7

File tree

6 files changed

+75
-24
lines changed

6 files changed

+75
-24
lines changed

sample/Aguacongas.AspNetCore.Authentication.Sample/Startup.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public void ConfigureServices(IServiceCollection services)
4343
options.UseInMemoryDatabase(Guid.NewGuid().ToString());
4444
}, (context) =>
4545
{
46-
Debug.WriteLine($"{context.Scheme} has been {context.Action}");
46+
Debug.WriteLine($"The scheme {context.Scheme} has been {context.Action}");
4747
})
4848
.AddGoogle()
4949
.AddFacebook()

src/Aguacongas.AspNetCore.Authentication.TestBase/DynamicManagerTestBase.cs

+21
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ Task onSignId(CookieSignedInContext context)
6363
});
6464

6565
var sut = provider.GetRequiredService<DynamicManager<TSchemeDefinition>>();
66+
Assert.Contains(typeof(CookieAuthenticationHandler), sut.ManagedHandlerType);
67+
6668
var cookieOptions = new CookieAuthenticationOptions
6769
{
6870
Cookie = new CookieBuilder
@@ -115,6 +117,8 @@ Task onCreatingTicket(OAuthCreatingTicketContext context)
115117
});
116118

117119
var sut = provider.GetRequiredService<DynamicManager<TSchemeDefinition>>();
120+
Assert.Contains(typeof(FacebookHandler), sut.ManagedHandlerType);
121+
118122
var facebookOptions = new FacebookOptions
119123
{
120124
AppId = "test",
@@ -167,6 +171,8 @@ Task onCreatingTicket(OAuthCreatingTicketContext context)
167171
});
168172

169173
var sut = provider.GetRequiredService<DynamicManager<TSchemeDefinition>>();
174+
Assert.Contains(typeof(GoogleHandler), sut.ManagedHandlerType);
175+
170176
var googleOptions = new GoogleOptions
171177
{
172178
ClientId = "test",
@@ -233,6 +239,8 @@ Task onMessageReceived(Microsoft.AspNetCore.Authentication.JwtBearer.MessageRece
233239
};
234240

235241
var sut = provider.GetRequiredService<DynamicManager<TSchemeDefinition>>();
242+
Assert.Contains(typeof(JwtBearerHandler), sut.ManagedHandlerType);
243+
236244
await sut.AddAsync(definition);
237245
var state = await VerifyAddedAsync<JwtBearerOptions>("test", provider);
238246

@@ -282,6 +290,8 @@ Task onCreatingTicket(OAuthCreatingTicketContext context)
282290
};
283291

284292
var sut = provider.GetRequiredService<DynamicManager<TSchemeDefinition>>();
293+
Assert.Contains(typeof(MicrosoftAccountHandler), sut.ManagedHandlerType);
294+
285295
await sut.AddAsync(definition);
286296
var state = await VerifyAddedAsync<MicrosoftAccountOptions>("test", provider);
287297

@@ -335,6 +345,8 @@ Task onTicketReceived(TicketReceivedContext context)
335345
};
336346

337347
var sut = provider.GetRequiredService<DynamicManager<TSchemeDefinition>>();
348+
Assert.Contains(typeof(OpenIdConnectHandler), sut.ManagedHandlerType);
349+
338350
await sut.AddAsync(definition);
339351
var state = await VerifyAddedAsync<OpenIdConnectOptions>("test", provider);
340352

@@ -385,6 +397,8 @@ Task onTicketReceived(TicketReceivedContext context)
385397
};
386398

387399
var sut = provider.GetRequiredService<DynamicManager<TSchemeDefinition>>();
400+
Assert.Contains(typeof(TwitterHandler), sut.ManagedHandlerType);
401+
388402
await sut.AddAsync(definition);
389403
var state = await VerifyAddedAsync<TwitterOptions>("test", provider);
390404

@@ -437,6 +451,8 @@ Task onTicketReceived(TicketReceivedContext context)
437451
};
438452

439453
var sut = provider.GetRequiredService<DynamicManager<TSchemeDefinition>>();
454+
Assert.Contains(typeof(WsFederationHandler), sut.ManagedHandlerType);
455+
440456
await sut.AddAsync(definition);
441457
var state = await VerifyAddedAsync<WsFederationOptions>("test", provider);
442458

@@ -489,6 +505,9 @@ Task onTicketReceived(TicketReceivedContext context)
489505
};
490506

491507
var sut = provider.GetRequiredService<DynamicManager<TSchemeDefinition>>();
508+
Assert.Contains(typeof(CookieAuthenticationHandler), sut.ManagedHandlerType);
509+
Assert.Contains(typeof(WsFederationHandler), sut.ManagedHandlerType);
510+
492511
await Assert.ThrowsAsync<InvalidOperationException>(() => sut.UpdateAsync(definition));
493512

494513
await sut.AddAsync(definition);
@@ -550,6 +569,8 @@ public async Task RemoveAsync_should_remove_handler()
550569
};
551570

552571
var sut = provider.GetRequiredService<DynamicManager<TSchemeDefinition>>();
572+
Assert.Contains(typeof(CookieAuthenticationHandler), sut.ManagedHandlerType);
573+
553574
await sut.AddAsync(definition);
554575
await VerifyAddedAsync<CookieAuthenticationOptions>("test", provider);
555576

src/Aguacongas.AspNetCore.Authentication/AuthenticationBuilderExtensions.cs

+13-5
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,25 @@ public static class AuthenticationBuilderExtensions
1414
/// <summary>
1515
/// Configures the DI for dynamic scheme management.
1616
/// </summary>
17-
/// <typeparam name="TDefinition">The type of the definition.</typeparam>
17+
/// <typeparam name="TSchemeDefinition">The type of the definition.</typeparam>
1818
/// <param name="builder">The builder.</param>
1919
/// <param name="notify">The action to call on scheme added or removed.</param>
2020
/// <returns></returns>
21-
public static DynamicAuthenticationBuilder AddDynamic<TDefinition>(this AuthenticationBuilder builder, Action<NotificationContext> notify = null)
22-
where TDefinition: SchemeDefinitionBase, new()
21+
public static DynamicAuthenticationBuilder AddDynamic<TSchemeDefinition>(this AuthenticationBuilder builder, Action<NotificationContext> notify = null)
22+
where TSchemeDefinition: SchemeDefinitionBase, new()
2323
{
24+
var dynamicBuilder = new DynamicAuthenticationBuilder(builder.Services, notify);
2425
builder.Services
2526
.AddSingleton<OptionsMonitorCacheWrapperFactory>()
26-
.AddTransient<DynamicManager<TDefinition>>();
27-
return new DynamicAuthenticationBuilder(builder.Services, notify);
27+
.AddTransient(provider => new DynamicManager<TSchemeDefinition>
28+
(
29+
provider.GetRequiredService<IAuthenticationSchemeProvider>(),
30+
provider.GetRequiredService<OptionsMonitorCacheWrapperFactory>(),
31+
provider.GetRequiredService<IDynamicProviderStore<TSchemeDefinition>>(),
32+
dynamicBuilder.HandlerTypes
33+
)
34+
);
35+
return dynamicBuilder;
2836
}
2937
}
3038
}

src/Aguacongas.AspNetCore.Authentication/DynamicAuthenticationBuilder.cs

+24-8
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using Microsoft.Extensions.DependencyInjection;
55
using Microsoft.Extensions.Options;
66
using System;
7+
using System.Collections.Generic;
78

89
namespace Aguacongas.AspNetCore.Authentication
910
{
@@ -19,6 +20,15 @@ public enum SchemeAction
1920
public class DynamicAuthenticationBuilder : AuthenticationBuilder
2021
{
2122
private readonly Action<NotificationContext> _notify;
23+
private readonly List<Type> _handlerTypes = new List<Type>();
24+
25+
/// <summary>
26+
/// Gets the handler types managed by this instance.
27+
/// </summary>
28+
/// <value>
29+
/// The handler types.
30+
/// </value>
31+
public IEnumerable<Type> HandlerTypes { get; }
2232

2333
/// <summary>
2434
/// Initializes a new instance of the <see cref="DynamicAuthenticationBuilder"/> class.
@@ -28,6 +38,7 @@ public class DynamicAuthenticationBuilder : AuthenticationBuilder
2838
public DynamicAuthenticationBuilder(IServiceCollection services, Action<NotificationContext> notify): base(services)
2939
{
3040
_notify = notify;
41+
HandlerTypes = _handlerTypes;
3142
}
3243

3344
/// <summary>
@@ -43,14 +54,19 @@ public DynamicAuthenticationBuilder(IServiceCollection services, Action<Notifica
4354
/// </returns>
4455
public override AuthenticationBuilder AddScheme<TOptions, THandler>(string authenticationScheme, string displayName, Action<TOptions> configureOptions)
4556
{
46-
Services.AddSingleton(provider => new OptionsMonitorCacheWrapper<TOptions>(
47-
provider.GetRequiredService<IOptionsMonitorCache<TOptions>>(),
48-
(name, configure) =>
49-
{
50-
configureOptions?.Invoke((TOptions)configure);
51-
_notify?.Invoke(new NotificationContext(provider, name, SchemeAction.Added));
52-
},
53-
name => _notify?.Invoke(new NotificationContext(provider, name, SchemeAction.Removed))));
57+
_handlerTypes.Add(typeof(THandler));
58+
Services.AddSingleton(provider =>
59+
new OptionsMonitorCacheWrapper<TOptions>
60+
(
61+
provider.GetRequiredService<IOptionsMonitorCache<TOptions>>(),
62+
(name, configure) =>
63+
{
64+
configureOptions?.Invoke((TOptions)configure);
65+
_notify?.Invoke(new NotificationContext(provider, name, SchemeAction.Added));
66+
},
67+
name => _notify?.Invoke(new NotificationContext(provider, name, SchemeAction.Removed))
68+
)
69+
);
5470
base.AddScheme<TOptions, THandler>(authenticationScheme, displayName, configureOptions);
5571
return this;
5672
}

src/Aguacongas.AspNetCore.Authentication/DynamicManager.cs

+11-6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using Microsoft.Extensions.DependencyModel;
55
using Microsoft.Extensions.Logging;
66
using System;
7+
using System.Collections.Generic;
78
using System.Linq;
89
using System.Reflection;
910
using System.Threading;
@@ -23,6 +24,8 @@ public class DynamicManager<TSchemeDefinition>
2324
private readonly IAuthenticationSchemeProvider _schemeProvider;
2425
private readonly OptionsMonitorCacheWrapperFactory _wrapperFactory;
2526

27+
public virtual IEnumerable<Type> ManagedHandlerType { get; }
28+
2629
/// <summary>
2730
/// Initializes a new instance of the <see cref="DynamicManager{TSchemeDefinition}"/> class.
2831
/// </summary>
@@ -38,11 +41,13 @@ public class DynamicManager<TSchemeDefinition>
3841
/// </exception>
3942
public DynamicManager(IAuthenticationSchemeProvider schemeProvider,
4043
OptionsMonitorCacheWrapperFactory wrapperFactory,
41-
IDynamicProviderStore<TSchemeDefinition> store)
44+
IDynamicProviderStore<TSchemeDefinition> store,
45+
IEnumerable<Type> managedTypes)
4246
{
4347
_schemeProvider = schemeProvider ?? throw new ArgumentNullException(nameof(schemeProvider));
4448
_wrapperFactory = wrapperFactory ?? throw new ArgumentNullException(nameof(wrapperFactory));
4549
_store = store ?? throw new ArgumentNullException(nameof(store));
50+
ManagedHandlerType = managedTypes ?? throw new ArgumentNullException(nameof(managedTypes));
4651
}
4752

4853
/// <summary>
@@ -52,7 +57,7 @@ public DynamicManager(IAuthenticationSchemeProvider schemeProvider,
5257
/// <param name="cancellationToken">The cancellation token.</param>
5358
/// <returns></returns>
5459
/// <exception cref="ArgumentNullException">definition</exception>
55-
public async Task AddAsync(TSchemeDefinition definition, CancellationToken cancellationToken = default(CancellationToken))
60+
public virtual async Task AddAsync(TSchemeDefinition definition, CancellationToken cancellationToken = default(CancellationToken))
5661
{
5762
if (definition == null)
5863
{
@@ -82,7 +87,7 @@ public DynamicManager(IAuthenticationSchemeProvider schemeProvider,
8287
/// <returns></returns>
8388
/// <exception cref="ArgumentNullException">definition</exception>
8489
/// <exception cref="InvalidOperationException">The scheme does not exist.</exception>
85-
public async Task UpdateAsync(TSchemeDefinition definition, CancellationToken cancellationToken = default(CancellationToken))
90+
public virtual async Task UpdateAsync(TSchemeDefinition definition, CancellationToken cancellationToken = default(CancellationToken))
8691
{
8792
if (definition == null)
8893
{
@@ -115,7 +120,7 @@ public DynamicManager(IAuthenticationSchemeProvider schemeProvider,
115120
/// <param name="cancellationToken">The cancellation token.</param>
116121
/// <returns></returns>
117122
/// <exception cref="ArgumentException">scheme cannot be null or white space.</exception>
118-
public async Task RemoveAsync(string scheme, CancellationToken cancellationToken = default(CancellationToken))
123+
public virtual async Task RemoveAsync(string scheme, CancellationToken cancellationToken = default(CancellationToken))
119124
{
120125
if (string.IsNullOrWhiteSpace(scheme))
121126
{
@@ -139,7 +144,7 @@ public DynamicManager(IAuthenticationSchemeProvider schemeProvider,
139144
/// <param name="scheme">The scheme.</param>
140145
/// <returns>The scheme definition or null.</returns>
141146
/// <exception cref="ArgumentException">scheme cannot be null or white space.</exception>
142-
public Task<TSchemeDefinition> FindBySchemeAsync(string scheme)
147+
public virtual Task<TSchemeDefinition> FindBySchemeAsync(string scheme)
143148
{
144149
if (string.IsNullOrWhiteSpace(scheme))
145150
{
@@ -151,7 +156,7 @@ public Task<TSchemeDefinition> FindBySchemeAsync(string scheme)
151156
/// <summary>
152157
/// Loads the configuration.
153158
/// </summary>
154-
public void Load()
159+
public virtual void Load()
155160
{
156161
var platform = Environment.OSVersion.Platform.ToString();
157162
var runtimeAssemblyNames = DependencyContext.Default.GetRuntimeAssemblyNames(platform);

test/Aguacongas.AspNetCore.Authentication.Test/DynamicManagerTest.cs

+5-4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Microsoft.AspNetCore.Authentication;
44
using Moq;
55
using System;
6+
using System.Collections.Generic;
67
using System.Threading.Tasks;
78
using Xunit;
89

@@ -13,14 +14,14 @@ public class DynamicManagerTest
1314
[Fact]
1415
public async Task Assertions()
1516
{
16-
Assert.Throws<ArgumentNullException>(() => new DynamicManager<FakeSchemeDefinition>(null, null, null));
17+
Assert.Throws<ArgumentNullException>(() => new DynamicManager<FakeSchemeDefinition>(null, null, null, null));
1718
var schemeProviderMock = new Mock<IAuthenticationSchemeProvider>().Object;
18-
Assert.Throws<ArgumentNullException>(() => new DynamicManager<FakeSchemeDefinition>(schemeProviderMock, null, null));
19+
Assert.Throws<ArgumentNullException>(() => new DynamicManager<FakeSchemeDefinition>(schemeProviderMock, null, null, null));
1920
var serviceProviderMock = new Mock<IServiceProvider>().Object;
2021
var factory = new OptionsMonitorCacheWrapperFactory(serviceProviderMock);
21-
Assert.Throws<ArgumentNullException>(() => new DynamicManager<FakeSchemeDefinition>(schemeProviderMock, factory, null));
22+
Assert.Throws<ArgumentNullException>(() => new DynamicManager<FakeSchemeDefinition>(schemeProviderMock, factory, null, null));
2223
var storeMock = new Mock<IDynamicProviderStore<FakeSchemeDefinition>>().Object;
23-
var manager = new DynamicManager<FakeSchemeDefinition>(schemeProviderMock, factory, storeMock);
24+
var manager = new DynamicManager<FakeSchemeDefinition>(schemeProviderMock, factory, storeMock, new List<Type>());
2425
await Assert.ThrowsAsync<ArgumentNullException>(() => manager.AddAsync(null));
2526
await Assert.ThrowsAsync<ArgumentNullException>(() => manager.UpdateAsync(null));
2627
await Assert.ThrowsAsync<ArgumentException>(() => manager.RemoveAsync(null));

0 commit comments

Comments
 (0)