diff --git a/src/Microsoft.AspNet.Identity/ClaimTypeOptions.cs b/src/Microsoft.AspNet.Identity/ClaimTypeOptions.cs index f84e4f18af..3216bae432 100644 --- a/src/Microsoft.AspNet.Identity/ClaimTypeOptions.cs +++ b/src/Microsoft.AspNet.Identity/ClaimTypeOptions.cs @@ -20,11 +20,6 @@ namespace Microsoft.AspNet.Identity UserName = ClaimTypes.Name; } - public ClaimTypeOptions(IConfiguration config) : this() - { - IdentityOptions.Read(this, config); - } - /// /// Claim type used for role claims /// diff --git a/src/Microsoft.AspNet.Identity/IdentityOptions.cs b/src/Microsoft.AspNet.Identity/IdentityOptions.cs index aeb4a9b4e4..d1063755ac 100644 --- a/src/Microsoft.AspNet.Identity/IdentityOptions.cs +++ b/src/Microsoft.AspNet.Identity/IdentityOptions.cs @@ -18,53 +18,6 @@ namespace Microsoft.AspNet.Identity 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 UserOptions User { get; set; } diff --git a/src/Microsoft.AspNet.Identity/IdentityOptionsSetup.cs b/src/Microsoft.AspNet.Identity/IdentityOptionsSetup.cs new file mode 100644 index 0000000000..580e137c1d --- /dev/null +++ b/src/Microsoft.AspNet.Identity/IdentityOptionsSetup.cs @@ -0,0 +1,64 @@ +using System; +using System.Reflection; +using Microsoft.AspNet.ConfigurationModel; +using Microsoft.AspNet.DependencyInjection; + +namespace Microsoft.AspNet.Identity +{ + /// + /// Configuration for lockout + /// + public class IdentityOptionsSetup : IOptionsSetup + { + 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? + } + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/IdentityServiceCollectionExtensions.cs b/src/Microsoft.AspNet.Identity/IdentityServiceCollectionExtensions.cs index 2b27706bc4..e41f552a47 100644 --- a/src/Microsoft.AspNet.Identity/IdentityServiceCollectionExtensions.cs +++ b/src/Microsoft.AspNet.Identity/IdentityServiceCollectionExtensions.cs @@ -28,6 +28,7 @@ namespace Microsoft.Framework.DependencyInjection { services.Add(IdentityServices.GetDefaultUserServices()); services.Add(IdentityServices.GetDefaultRoleServices()); + services.AddTransient, IdentityOptionsSetup>(); services.AddSingleton, OptionsAccessor>(); actionBuilder(new IdentityBuilder(services)); return services; diff --git a/src/Microsoft.AspNet.Identity/LockoutPolicy.cs b/src/Microsoft.AspNet.Identity/LockoutPolicy.cs deleted file mode 100644 index 98fdae5d17..0000000000 --- a/src/Microsoft.AspNet.Identity/LockoutPolicy.cs +++ /dev/null @@ -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 -{ - /// - /// Configuration for lockout - /// - public class LockoutPolicy - { - /// - /// If true, will enable user lockout when users are created - /// - public bool UserLockoutEnabledByDefault { get; set; } - - /// - /// Number of access attempts allowed for a user before lockout (if enabled) - /// - public int MaxFailedAccessAttemptsBeforeLockout { get; set; } - - /// - /// Default amount of time an user is locked out for after MaxFailedAccessAttempsBeforeLockout is reached - /// - public TimeSpan DefaultAccountLockoutTimeSpan { get; set; } - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/PasswordOptions.cs b/src/Microsoft.AspNet.Identity/PasswordOptions.cs index 3ba1bb77a1..63750523ec 100644 --- a/src/Microsoft.AspNet.Identity/PasswordOptions.cs +++ b/src/Microsoft.AspNet.Identity/PasswordOptions.cs @@ -13,11 +13,6 @@ namespace Microsoft.AspNet.Identity RequiredLength = 6; } - public PasswordOptions(IConfiguration config) : this() - { - IdentityOptions.Read(this, config); - } - /// /// Minimum required length /// diff --git a/src/Microsoft.AspNet.Identity/UserOptions.cs b/src/Microsoft.AspNet.Identity/UserOptions.cs index 0f3fef9280..75735645cc 100644 --- a/src/Microsoft.AspNet.Identity/UserOptions.cs +++ b/src/Microsoft.AspNet.Identity/UserOptions.cs @@ -10,11 +10,6 @@ namespace Microsoft.AspNet.Identity //User.RequireUniqueEmail = true; // TODO: app decision? } - public UserOptions(IConfiguration config) : this() - { - IdentityOptions.Read(this, config); - } - /// /// Only allow [A-Za-z0-9@_] in UserNames /// diff --git a/test/Microsoft.AspNet.Identity.Test/IdentityOptionsTest.cs b/test/Microsoft.AspNet.Identity.Test/IdentityOptionsTest.cs index c5f75f0eb4..af6c4af439 100644 --- a/test/Microsoft.AspNet.Identity.Test/IdentityOptionsTest.cs +++ b/test/Microsoft.AspNet.Identity.Test/IdentityOptionsTest.cs @@ -2,6 +2,9 @@ using System; using System.Collections.Generic; using System.Security.Claims; using Microsoft.Framework.ConfigurationModel; +using Microsoft.Framework.ConfigurationModel.Sources; +using Microsoft.Framework.DependencyInjection; +using Microsoft.Framework.DependencyInjection.Fallback; using Xunit; namespace Microsoft.AspNet.Identity.Test @@ -57,11 +60,21 @@ namespace Microsoft.AspNet.Identity.Test {"identity:password:RequireNonLetterOrDigit", "false"}, {"identity:password:RequireUpperCase", "false"}, {"identity:password:RequireDigit", "false"}, - {"identity:password:RequireLowerCase", "false"} + {"identity:password:RequireLowerCase", "false"}, + {"identity:lockout:EnabledByDefault", "TRUe"}, + {"identity:lockout:MaxFailedAccessAttempts", "1000"} }; var config = new Configuration { new MemoryConfigurationSource(dic) }; Assert.Equal(roleClaimType, config.Get("identity:claimtype:role")); - var options = new IdentityOptions(config); + + var setup = new IdentityOptionsSetup(config); + var services = new ServiceCollection(); + services.AddInstance(config); + services.AddTransient, IdentityOptionsSetup>(); + services.AddTransient, OptionsAccessor>(); + var accessor = services.BuildServiceProvider().GetService>(); + Assert.NotNull(accessor); + var options = accessor.Options; Assert.Equal(roleClaimType, options.ClaimType.Role); Assert.Equal(useridClaimType, options.ClaimType.UserId); Assert.Equal(usernameClaimType, options.ClaimType.UserName); @@ -74,16 +87,19 @@ namespace Microsoft.AspNet.Identity.Test Assert.False(options.Password.RequireNonLetterOrDigit); Assert.False(options.Password.RequireUppercase); Assert.Equal(10, options.Password.RequiredLength); + Assert.True(options.Lockout.EnabledByDefault); + Assert.Equal(1000, options.Lockout.MaxFailedAccessAttempts); } - [Fact] - public void ClaimTypeOptionsFromConfig() - { - const string roleClaimType = "rolez"; - const string usernameClaimType = "namez"; - const string useridClaimType = "idz"; - const string securityStampClaimType = "stampz"; + //[Fact] + //public void ClaimTypeOptionsFromConfig() + //{ + // const string roleClaimType = "rolez"; + // const string usernameClaimType = "namez"; + // const string useridClaimType = "idz"; + // const string securityStampClaimType = "stampz"; +<<<<<<< HEAD var dic = new Dictionary { {"role", roleClaimType}, @@ -119,6 +135,43 @@ namespace Microsoft.AspNet.Identity.Test Assert.False(options.RequireUppercase); Assert.Equal(10, options.RequiredLength); } +======= + // var dic = new Dictionary + // { + // {"role", roleClaimType}, + // {"username", usernameClaimType}, + // {"userid", useridClaimType}, + // {"securitystamp", securityStampClaimType} + // }; + // var config = new ConfigurationModel.Configuration {new MemoryConfigurationSource(dic)}; + // Assert.Equal(roleClaimType, config.Get("role")); + // var options = new ClaimTypeOptions(config); + // Assert.Equal(roleClaimType, options.Role); + // Assert.Equal(useridClaimType, options.UserId); + // Assert.Equal(usernameClaimType, options.UserName); + // Assert.Equal(securityStampClaimType, options.SecurityStamp); + //} + + //[Fact] + //public void PasswordOptionsFromConfig() + //{ + // var dic = new Dictionary + // { + // {"RequiredLength", "10"}, + // {"RequireNonLetterOrDigit", "false"}, + // {"RequireUpperCase", "false"}, + // {"RequireDigit", "false"}, + // {"RequireLowerCase", "false"} + // }; + // var config = new ConfigurationModel.Configuration { new MemoryConfigurationSource(dic) }; + // var options = new PasswordOptions(config); + // Assert.False(options.RequireDigit); + // Assert.False(options.RequireLowercase); + // Assert.False(options.RequireNonLetterOrDigit); + // Assert.False(options.RequireUppercase); + // Assert.Equal(10, options.RequiredLength); + //} +>>>>>>> Implement Config options } } \ No newline at end of file