Implement Config options
This commit is contained in:
parent
b623f725ba
commit
ab84228c37
|
|
@ -20,11 +20,6 @@ namespace Microsoft.AspNet.Identity
|
||||||
UserName = ClaimTypes.Name;
|
UserName = ClaimTypes.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClaimTypeOptions(IConfiguration config) : this()
|
|
||||||
{
|
|
||||||
IdentityOptions.Read(this, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Claim type used for role claims
|
/// Claim type used for role claims
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -18,53 +18,6 @@ namespace Microsoft.AspNet.Identity
|
||||||
Lockout = new LockoutOptions();
|
Lockout = new LockoutOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IdentityOptions(IConfiguration config)
|
|
||||||
{
|
|
||||||
ClaimType = new ClaimTypeOptions(config.GetSubKey("identity:claimtype"));
|
|
||||||
User = new UserOptions(config.GetSubKey("identity:user"));
|
|
||||||
Password = new PasswordOptions(config.GetSubKey("identity:password"));
|
|
||||||
//Lockout = new LockoutOptions(config.GetSubKey("identity:lockout"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Read(object obj, IConfiguration config)
|
|
||||||
{
|
|
||||||
var type = obj.GetType();
|
|
||||||
var props = type.GetTypeInfo().DeclaredProperties;
|
|
||||||
foreach (var prop in props)
|
|
||||||
{
|
|
||||||
// TODO: handle non string types?
|
|
||||||
if (!prop.CanWrite)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var configValue = config.Get(prop.Name);
|
|
||||||
if (configValue == null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (prop.PropertyType == typeof(string))
|
|
||||||
{
|
|
||||||
prop.SetValue(obj, configValue);
|
|
||||||
}
|
|
||||||
else if (prop.PropertyType == typeof(int))
|
|
||||||
{
|
|
||||||
// todo: TryParse/ errors?
|
|
||||||
prop.SetValue(obj, int.Parse(configValue));
|
|
||||||
}
|
|
||||||
else if (prop.PropertyType == typeof(bool))
|
|
||||||
{
|
|
||||||
// todo: TryParse/ errors?
|
|
||||||
prop.SetValue(obj, bool.Parse(configValue));
|
|
||||||
}
|
|
||||||
//else if (prop.PropertyType == typeof(TimeSpan))
|
|
||||||
//{
|
|
||||||
// // todo: TryParse/ errors?
|
|
||||||
// prop.SetValue(obj, TimeSpan.Parse(configValue));
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public ClaimTypeOptions ClaimType { get; set; }
|
public ClaimTypeOptions ClaimType { get; set; }
|
||||||
|
|
||||||
public UserOptions User { get; set; }
|
public UserOptions User { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using Microsoft.AspNet.ConfigurationModel;
|
||||||
|
using Microsoft.AspNet.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Identity
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Configuration for lockout
|
||||||
|
/// </summary>
|
||||||
|
public class IdentityOptionsSetup : IOptionsSetup<IdentityOptions>
|
||||||
|
{
|
||||||
|
private readonly IConfiguration _config;
|
||||||
|
|
||||||
|
public IdentityOptionsSetup(IConfiguration config)
|
||||||
|
{
|
||||||
|
_config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Order { get; set; }
|
||||||
|
|
||||||
|
public void Setup(IdentityOptions options)
|
||||||
|
{
|
||||||
|
ReadProperties(options.ClaimType, _config.GetSubKey("identity:claimtype"));
|
||||||
|
ReadProperties(options.User, _config.GetSubKey("identity:user"));
|
||||||
|
ReadProperties(options.Password, _config.GetSubKey("identity:password"));
|
||||||
|
ReadProperties(options.Lockout, _config.GetSubKey("identity:lockout"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Move this somewhere common (Config?)
|
||||||
|
public static void ReadProperties(object obj, IConfiguration config)
|
||||||
|
{
|
||||||
|
if (obj == null || config == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var props = obj.GetType().GetTypeInfo().DeclaredProperties;
|
||||||
|
foreach (var prop in props)
|
||||||
|
{
|
||||||
|
if (!prop.CanWrite)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var configValue = config.Get(prop.Name);
|
||||||
|
if (configValue == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// No convert on portable
|
||||||
|
#if NET45 || K10
|
||||||
|
prop.SetValue(obj, Convert.ChangeType(configValue, prop.PropertyType));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// TODO: what do we do about errors?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -28,6 +28,7 @@ namespace Microsoft.AspNet.DependencyInjection
|
||||||
{
|
{
|
||||||
services.Add(IdentityServices.GetDefaultUserServices<TUser>());
|
services.Add(IdentityServices.GetDefaultUserServices<TUser>());
|
||||||
services.Add(IdentityServices.GetDefaultRoleServices<TRole>());
|
services.Add(IdentityServices.GetDefaultRoleServices<TRole>());
|
||||||
|
services.AddTransient<IOptionsSetup<IdentityOptions>, IdentityOptionsSetup>();
|
||||||
services.AddSingleton<IOptionsAccessor<IdentityOptions>, OptionsAccessor<IdentityOptions>>();
|
services.AddSingleton<IOptionsAccessor<IdentityOptions>, OptionsAccessor<IdentityOptions>>();
|
||||||
actionBuilder(new IdentityBuilder<TUser, TRole>(services));
|
actionBuilder(new IdentityBuilder<TUser, TRole>(services));
|
||||||
return services;
|
return services;
|
||||||
|
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc.
|
|
||||||
// All Rights Reserved
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
|
|
||||||
// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
|
|
||||||
// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
|
|
||||||
// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
|
||||||
// NON-INFRINGEMENT.
|
|
||||||
// See the Apache 2 License for the specific language governing
|
|
||||||
// permissions and limitations under the License.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Identity
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Configuration for lockout
|
|
||||||
/// </summary>
|
|
||||||
public class LockoutPolicy
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// If true, will enable user lockout when users are created
|
|
||||||
/// </summary>
|
|
||||||
public bool UserLockoutEnabledByDefault { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Number of access attempts allowed for a user before lockout (if enabled)
|
|
||||||
/// </summary>
|
|
||||||
public int MaxFailedAccessAttemptsBeforeLockout { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default amount of time an user is locked out for after MaxFailedAccessAttempsBeforeLockout is reached
|
|
||||||
/// </summary>
|
|
||||||
public TimeSpan DefaultAccountLockoutTimeSpan { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -13,11 +13,6 @@ namespace Microsoft.AspNet.Identity
|
||||||
RequiredLength = 6;
|
RequiredLength = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PasswordOptions(IConfiguration config) : this()
|
|
||||||
{
|
|
||||||
IdentityOptions.Read(this, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Minimum required length
|
/// Minimum required length
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,6 @@ namespace Microsoft.AspNet.Identity
|
||||||
//User.RequireUniqueEmail = true; // TODO: app decision?
|
//User.RequireUniqueEmail = true; // TODO: app decision?
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserOptions(IConfiguration config) : this()
|
|
||||||
{
|
|
||||||
IdentityOptions.Read(this, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Only allow [A-Za-z0-9@_] in UserNames
|
/// Only allow [A-Za-z0-9@_] in UserNames
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ using System.Collections.Generic;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using Microsoft.AspNet.ConfigurationModel;
|
using Microsoft.AspNet.ConfigurationModel;
|
||||||
using Microsoft.AspNet.ConfigurationModel.Sources;
|
using Microsoft.AspNet.ConfigurationModel.Sources;
|
||||||
|
using Microsoft.AspNet.DependencyInjection;
|
||||||
|
using Microsoft.AspNet.DependencyInjection.Fallback;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Identity.Test
|
namespace Microsoft.AspNet.Identity.Test
|
||||||
|
|
@ -58,11 +60,21 @@ namespace Microsoft.AspNet.Identity.Test
|
||||||
{"identity:password:RequireNonLetterOrDigit", "false"},
|
{"identity:password:RequireNonLetterOrDigit", "false"},
|
||||||
{"identity:password:RequireUpperCase", "false"},
|
{"identity:password:RequireUpperCase", "false"},
|
||||||
{"identity:password:RequireDigit", "false"},
|
{"identity:password:RequireDigit", "false"},
|
||||||
{"identity:password:RequireLowerCase", "false"}
|
{"identity:password:RequireLowerCase", "false"},
|
||||||
|
{"identity:lockout:EnabledByDefault", "TRUe"},
|
||||||
|
{"identity:lockout:MaxFailedAccessAttempts", "1000"}
|
||||||
};
|
};
|
||||||
var config = new ConfigurationModel.Configuration { new MemoryConfigurationSource(dic) };
|
var config = new ConfigurationModel.Configuration { new MemoryConfigurationSource(dic) };
|
||||||
Assert.Equal(roleClaimType, config.Get("identity:claimtype:role"));
|
Assert.Equal(roleClaimType, config.Get("identity:claimtype:role"));
|
||||||
var options = new IdentityOptions(config);
|
|
||||||
|
var setup = new IdentityOptionsSetup(config);
|
||||||
|
var services = new ServiceCollection();
|
||||||
|
services.AddInstance<IConfiguration>(config);
|
||||||
|
services.AddTransient<IOptionsSetup<IdentityOptions>, IdentityOptionsSetup>();
|
||||||
|
services.AddTransient<IOptionsAccessor<IdentityOptions>, OptionsAccessor<IdentityOptions>>();
|
||||||
|
var accessor = services.BuildServiceProvider().GetService<IOptionsAccessor<IdentityOptions>>();
|
||||||
|
Assert.NotNull(accessor);
|
||||||
|
var options = accessor.Options;
|
||||||
Assert.Equal(roleClaimType, options.ClaimType.Role);
|
Assert.Equal(roleClaimType, options.ClaimType.Role);
|
||||||
Assert.Equal(useridClaimType, options.ClaimType.UserId);
|
Assert.Equal(useridClaimType, options.ClaimType.UserId);
|
||||||
Assert.Equal(usernameClaimType, options.ClaimType.UserName);
|
Assert.Equal(usernameClaimType, options.ClaimType.UserName);
|
||||||
|
|
@ -75,51 +87,53 @@ namespace Microsoft.AspNet.Identity.Test
|
||||||
Assert.False(options.Password.RequireNonLetterOrDigit);
|
Assert.False(options.Password.RequireNonLetterOrDigit);
|
||||||
Assert.False(options.Password.RequireUppercase);
|
Assert.False(options.Password.RequireUppercase);
|
||||||
Assert.Equal(10, options.Password.RequiredLength);
|
Assert.Equal(10, options.Password.RequiredLength);
|
||||||
|
Assert.True(options.Lockout.EnabledByDefault);
|
||||||
|
Assert.Equal(1000, options.Lockout.MaxFailedAccessAttempts);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
//[Fact]
|
||||||
public void ClaimTypeOptionsFromConfig()
|
//public void ClaimTypeOptionsFromConfig()
|
||||||
{
|
//{
|
||||||
const string roleClaimType = "rolez";
|
// const string roleClaimType = "rolez";
|
||||||
const string usernameClaimType = "namez";
|
// const string usernameClaimType = "namez";
|
||||||
const string useridClaimType = "idz";
|
// const string useridClaimType = "idz";
|
||||||
const string securityStampClaimType = "stampz";
|
// const string securityStampClaimType = "stampz";
|
||||||
|
|
||||||
var dic = new Dictionary<string, string>
|
// var dic = new Dictionary<string, string>
|
||||||
{
|
// {
|
||||||
{"role", roleClaimType},
|
// {"role", roleClaimType},
|
||||||
{"username", usernameClaimType},
|
// {"username", usernameClaimType},
|
||||||
{"userid", useridClaimType},
|
// {"userid", useridClaimType},
|
||||||
{"securitystamp", securityStampClaimType}
|
// {"securitystamp", securityStampClaimType}
|
||||||
};
|
// };
|
||||||
var config = new ConfigurationModel.Configuration {new MemoryConfigurationSource(dic)};
|
// var config = new ConfigurationModel.Configuration {new MemoryConfigurationSource(dic)};
|
||||||
Assert.Equal(roleClaimType, config.Get("role"));
|
// Assert.Equal(roleClaimType, config.Get("role"));
|
||||||
var options = new ClaimTypeOptions(config);
|
// var options = new ClaimTypeOptions(config);
|
||||||
Assert.Equal(roleClaimType, options.Role);
|
// Assert.Equal(roleClaimType, options.Role);
|
||||||
Assert.Equal(useridClaimType, options.UserId);
|
// Assert.Equal(useridClaimType, options.UserId);
|
||||||
Assert.Equal(usernameClaimType, options.UserName);
|
// Assert.Equal(usernameClaimType, options.UserName);
|
||||||
Assert.Equal(securityStampClaimType, options.SecurityStamp);
|
// Assert.Equal(securityStampClaimType, options.SecurityStamp);
|
||||||
}
|
//}
|
||||||
|
|
||||||
[Fact]
|
//[Fact]
|
||||||
public void PasswordOptionsFromConfig()
|
//public void PasswordOptionsFromConfig()
|
||||||
{
|
//{
|
||||||
var dic = new Dictionary<string, string>
|
// var dic = new Dictionary<string, string>
|
||||||
{
|
// {
|
||||||
{"RequiredLength", "10"},
|
// {"RequiredLength", "10"},
|
||||||
{"RequireNonLetterOrDigit", "false"},
|
// {"RequireNonLetterOrDigit", "false"},
|
||||||
{"RequireUpperCase", "false"},
|
// {"RequireUpperCase", "false"},
|
||||||
{"RequireDigit", "false"},
|
// {"RequireDigit", "false"},
|
||||||
{"RequireLowerCase", "false"}
|
// {"RequireLowerCase", "false"}
|
||||||
};
|
// };
|
||||||
var config = new ConfigurationModel.Configuration { new MemoryConfigurationSource(dic) };
|
// var config = new ConfigurationModel.Configuration { new MemoryConfigurationSource(dic) };
|
||||||
var options = new PasswordOptions(config);
|
// var options = new PasswordOptions(config);
|
||||||
Assert.False(options.RequireDigit);
|
// Assert.False(options.RequireDigit);
|
||||||
Assert.False(options.RequireLowercase);
|
// Assert.False(options.RequireLowercase);
|
||||||
Assert.False(options.RequireNonLetterOrDigit);
|
// Assert.False(options.RequireNonLetterOrDigit);
|
||||||
Assert.False(options.RequireUppercase);
|
// Assert.False(options.RequireUppercase);
|
||||||
Assert.Equal(10, options.RequiredLength);
|
// Assert.Equal(10, options.RequiredLength);
|
||||||
}
|
//}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue