Skip to content

Commit 2c94c69

Browse files
committed
feat: dynamicallly update authentication provider
1 parent 94e4d23 commit 2c94c69

File tree

1 file changed

+70
-47
lines changed

1 file changed

+70
-47
lines changed

src/Aguacongas.AspNetCore.Authentication/DynamicManager.cs

+70-47
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,48 @@
11
using Microsoft.AspNetCore.Authentication;
2+
using Microsoft.Extensions.DependencyModel;
23
using Microsoft.Extensions.Logging;
34
using Newtonsoft.Json;
45
using System;
6+
using System.Linq;
7+
using System.Reflection;
58
using System.Threading;
69
using System.Threading.Tasks;
710

811
namespace Aguacongas.AspNetCore.Authentication
912
{
10-
public class DynamicManager : DynamicManager<ProviderDefinition>
11-
{
12-
/// <summary>
13-
/// Initializes a new instance of the <see cref="DynamicManager"/> class.
14-
/// </summary>
15-
/// <param name="schemeProvider">The scheme provider.</param>
16-
/// <param name="wrapperFactory">The wrapper factory.</param>
17-
/// <param name="store">The store.</param>
18-
/// <param name="logger">The logger.</param>
19-
public DynamicManager(IAuthenticationSchemeProvider schemeProvider,
20-
OptionsMonitorCacheWrapperFactory wrapperFactory,
21-
IDynamicProviderStore<ProviderDefinition> store,
22-
ILogger<DynamicManager<ProviderDefinition>> logger)
23-
: base(schemeProvider, wrapperFactory, store, logger)
24-
{
25-
}
26-
}
27-
2813
public class DynamicManager<TDefinition>
2914
where TDefinition: ProviderDefinition, new()
3015
{
31-
private static readonly JsonSerializerSettings _jsonSerializerSettings = new JsonSerializerSettings
32-
{
33-
NullValueHandling = NullValueHandling.Ignore,
34-
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
35-
Formatting = Formatting.None,
36-
DefaultValueHandling = DefaultValueHandling.Ignore,
37-
ContractResolver = new ContractResolver()
38-
};
39-
4016
private readonly IDynamicProviderStore<TDefinition>_store;
4117
private readonly ILogger<DynamicManager<TDefinition>> _logger;
4218
private readonly IAuthenticationSchemeProvider _schemeProvider;
4319
private readonly OptionsMonitorCacheWrapperFactory _wrapperFactory;
4420

21+
/// <summary>
22+
/// Gets or sets the json serializer settings.
23+
/// </summary>
24+
/// <value>
25+
/// The json serializer settings.
26+
/// </value>
27+
public static JsonSerializerSettings JsonSerializerSettings { get; } = new JsonSerializerSettings
28+
{
29+
NullValueHandling = NullValueHandling.Ignore,
30+
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
31+
Formatting = Formatting.None,
32+
DefaultValueHandling = DefaultValueHandling.Ignore,
33+
ContractResolver = new ContractResolver()
34+
};
35+
36+
/// <summary>
37+
/// Gets or sets the function to serialize the provider definition.
38+
/// </summary>
39+
/// <value>
40+
/// The serialize function.
41+
/// </value>
4542
public Func<AuthenticationSchemeOptions, Type, string> Serialize { get; set; } = SerializeOptions;
4643

44+
public Func<string, Type, AuthenticationSchemeOptions> Deserialize { get; set; } = DeserializeOptions;
45+
4746
/// <summary>
4847
/// Initializes a new instance of the <see cref="DynamicManager{TDefinition}"/> class.
4948
/// </summary>
@@ -55,10 +54,10 @@ public DynamicManager(IAuthenticationSchemeProvider schemeProvider,
5554
OptionsMonitorCacheWrapperFactory wrapperFactory,
5655
IDynamicProviderStore<TDefinition> store, ILogger<DynamicManager<TDefinition>> logger)
5756
{
58-
_schemeProvider = schemeProvider;
59-
_wrapperFactory = wrapperFactory;
60-
_store = store;
61-
_logger = logger;
57+
_schemeProvider = schemeProvider ?? throw new ArgumentNullException(nameof(schemeProvider));
58+
_wrapperFactory = wrapperFactory ?? throw new ArgumentNullException(nameof(wrapperFactory));
59+
_store = store ?? throw new ArgumentNullException(nameof(store));
60+
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
6261
}
6362

6463
/// <summary>
@@ -75,7 +74,7 @@ public DynamicManager(IAuthenticationSchemeProvider schemeProvider,
7574
where THandler : AuthenticationHandler<TOptions>
7675
where TOptions : AuthenticationSchemeOptions, new()
7776
{
78-
return AddAsync(scheme, displayName, typeof(THandler), (AuthenticationSchemeOptions)options, cancellationToken);
77+
return AddAsync(scheme, displayName, typeof(THandler), options, cancellationToken);
7978
}
8079

8180
/// <summary>
@@ -123,6 +122,22 @@ await _store.AddAsync(new TDefinition
123122
_logger.LogInformation("Scheme {scheme} added with name {displayName} for {handlerType} with options {options}", scheme, displayName, handlerType, serializerOptions);
124123
}
125124

125+
/// <summary>
126+
/// Updates the scheme asynchronously.
127+
/// </summary>
128+
/// <typeparam name="THandler">The type of the handler.</typeparam>
129+
/// <typeparam name="TOptions">The type of the options.</typeparam>
130+
/// <param name="scheme">The scheme.</param>
131+
/// <param name="displayName">The display name.</param>
132+
/// <param name="options">The options.</param>
133+
/// <param name="cancellationToken">The cancellation token.</param>
134+
/// <returns></returns>
135+
public Task UpdateAsync<THandler, TOptions>(string scheme, string displayName, TOptions options, CancellationToken cancellationToken = default(CancellationToken))
136+
where THandler : AuthenticationHandler<TOptions>
137+
where TOptions : AuthenticationSchemeOptions, new()
138+
{
139+
return UpdateAsync(scheme, displayName, typeof(THandler), options, cancellationToken);
140+
}
126141
/// <summary>
127142
/// Updates the scheme asynchronously.
128143
/// </summary>
@@ -139,7 +154,7 @@ await _store.AddAsync(new TDefinition
139154
public async Task UpdateAsync(string scheme, string displayName, Type handlerType, AuthenticationSchemeOptions options, CancellationToken cancellationToken = default(CancellationToken))
140155
{
141156
var genericTypeArguments = GetGenericTypeArguments(handlerType);
142-
if (handlerType.GetInterface(nameof(IAuthenticationHandler)) == null || handlerType.GenericTypeArguments.Length == 0)
157+
if (handlerType.GetInterface(nameof(IAuthenticationHandler)) == null || genericTypeArguments.Length == 0)
143158
{
144159
throw new ArgumentException($"Parameter {nameof(handlerType)} should be a {nameof(AuthenticationHandler<AuthenticationSchemeOptions>)}");
145160
}
@@ -171,6 +186,8 @@ await _store.AddAsync(new TDefinition
171186

172187
_schemeProvider.AddScheme(new AuthenticationScheme(scheme, displayName, handlerType));
173188
optionsMonitorCache.TryAdd(scheme, options);
189+
190+
_logger.LogInformation("Scheme {scheme} updated with name {displayName} for {handlerType} with options {options}", scheme, displayName, handlerType, serializerOptions);
174191
}
175192

176193
/// <summary>
@@ -191,6 +208,8 @@ await _store.AddAsync(new TDefinition
191208
await _store.RemoveAsync(definition, cancellationToken);
192209
_schemeProvider.RemoveScheme(scheme);
193210
optionsMonitorCache.TryRemove(scheme);
211+
212+
_logger.LogInformation("Scheme {scheme} removed for handler type {handlerType}", scheme, handlerType);
194213
}
195214
}
196215

@@ -199,22 +218,34 @@ await _store.AddAsync(new TDefinition
199218
/// </summary>
200219
public void Load()
201220
{
202-
foreach(var definition in _store.ProviderDefinitions)
221+
var platform = Environment.OSVersion.Platform.ToString();
222+
var runtimeAssemblyNames = DependencyContext.Default.GetRuntimeAssemblyNames(platform);
223+
224+
foreach (var definition in _store.ProviderDefinitions)
203225
{
204226
var scheme = definition.Id;
205-
var handlerType = Type.GetType(definition.HandlerTypeName);
206-
var optionsType = handlerType.GenericTypeArguments[0];
227+
var handlerType = runtimeAssemblyNames
228+
.Select(Assembly.Load)
229+
.SelectMany(a => a.ExportedTypes)
230+
.First(t => t.FullName == definition.HandlerTypeName);
231+
232+
var optionsType = GetGenericTypeArguments(handlerType)[0];
207233
var optionsMonitorCache = _wrapperFactory.Get(optionsType);
208-
var options = JsonConvert.DeserializeObject(definition.SerializedOptions, optionsType) as AuthenticationSchemeOptions;
234+
var options = Deserialize(definition.SerializedOptions, optionsType);
209235

210236
_schemeProvider.AddScheme(new AuthenticationScheme(scheme, definition.DisplayName, handlerType));
211237
optionsMonitorCache.TryAdd(scheme, options);
212238
}
213239
}
214240

215-
protected static string SerializeOptions(AuthenticationSchemeOptions options, Type optionsType)
241+
private static string SerializeOptions(AuthenticationSchemeOptions options, Type optionsType)
242+
{
243+
return JsonConvert.SerializeObject(options, optionsType, JsonSerializerSettings);
244+
}
245+
246+
private static AuthenticationSchemeOptions DeserializeOptions(string value, Type optionsType)
216247
{
217-
return JsonConvert.SerializeObject(options, optionsType, _jsonSerializerSettings);
248+
return JsonConvert.DeserializeObject(value, optionsType) as AuthenticationSchemeOptions;
218249
}
219250

220251
private Type[] GetGenericTypeArguments(Type type)
@@ -231,13 +262,5 @@ private Type[] GetGenericTypeArguments(Type type)
231262

232263
return GetGenericTypeArguments(type.BaseType);
233264
}
234-
235-
class OptionsMonitorCacheWrapper
236-
{
237-
public OptionsMonitorCacheWrapper(Type optionsType)
238-
{
239-
240-
}
241-
}
242265
}
243266
}

0 commit comments

Comments
 (0)