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) { } } }