using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Developpez.Dotnet.Security
{
///
/// Password
///
public class Password
{
///
/// Value of the password
///
public string Value { get; set; }
///
/// Validate a password
///
/// Rule applying to the validation
public void Validate(PasswordSecurityRule rule)
{
rule.Validate(this);
}
}
///
/// Password strategy
///
public class PasswordSecurityRule
{
///
/// Minimal number of digits
///
public int? MinNbDigits { get; set; }
///
/// Minimal number of letters
///
public int? MinNbLetters { get; set; }
///
/// Minimal number of special characters
///
public int? MinNbSpecialChars { get; set; }
///
/// Minimal number of lowercase
///
public int? MinNbLowerCase { get; set; }
///
/// Minimal number of uppercase
///
public int? MinNbUpperCase { get; set; }
///
/// Minimal number of characters
///
public int? MinTotalLength { get; set; }
///
/// Maximal number of characters
///
public int? MaxTotalLength { get; set; }
///
/// Validate the rule
///
internal void Validate(Password password)
{
var errors = new StringBuilder();
// Digits
if (MinNbDigits.IsApplicable() && password.Value.ToCharArray().Count(i => char.IsDigit(i)) < MinNbDigits)
errors.AppendLine(string.Format("\t- Minimum {0} digits.", MinNbDigits));
// Letters
if (MinNbLetters.IsApplicable() && password.Value.ToCharArray().Count(i => char.IsLetter(i)) < MinNbLetters)
errors.AppendLine(string.Format("\t- Minimum {0} letters.", MinNbLetters));
// Special chars
if (MinNbSpecialChars.IsApplicable() && password.Value.ToCharArray().Count(i => !char.IsLetterOrDigit(i)) < MinNbSpecialChars)
errors.AppendLine(string.Format("\t- Minimum {0} special characters.", MinNbSpecialChars));
// Lower case
if (MinNbLowerCase.IsApplicable() && password.Value.ToCharArray().Count(i => char.IsLower(i)) < MinNbLowerCase)
errors.AppendLine(string.Format("\t- Minimum {0} lowercase characters.", MinNbLowerCase));
// Upper case
if (MinNbUpperCase.IsApplicable() && password.Value.ToCharArray().Count(i => char.IsUpper(i)) < MinNbUpperCase)
errors.AppendLine(string.Format("\t- Minimum {0} uppercase characters.", MinNbUpperCase));
// Min length
if (MinTotalLength.IsApplicable() && password.Value.Length < MinTotalLength)
errors.AppendLine(string.Format("\t- The length must be minimum {0}.", MinTotalLength));
// Max length
if (MaxTotalLength.IsApplicable() && password.Value.Length > MaxTotalLength)
errors.AppendLine(string.Format("\t- The length must be maximum {0}.", MaxTotalLength));
if (errors.Length > 0)
{
errors.Insert(0, "Your password is not valid, please corect the following:");
throw new PasswordValidationException(errors.ToString());
}
}
}
///
/// Extensions for password strategy
///
internal static class PasswordRuleExtensions
{
///
/// Check if the parameter is applicable to the rule
///
public static bool IsApplicable(this int? nb)
{
if (nb == null) return false;
if (nb == 0) return false;
return true;
}
}
///
/// Exception thrown by a password validation
///
public class PasswordValidationException : Exception
{
///
/// Constructor for PasswordValidationException
///
public PasswordValidationException(string exeption)
: base(exeption)
{
}
}
}