private static TokenOptions ValidateOptions(IOptions <TokenOptions> iOptions) { if (iOptions is null) { throw new ArgumentNullException(nameof(iOptions)); } var options = iOptions.Value; if (options is null) { throw new ArgumentNullException(nameof(iOptions.Value)); } if (options.Length <= 0) { throw new ArgumentException( "Length of token must be a positive integer", nameof(iOptions.Value.Length)); } if (options.Length < CharSetManager.GetSetsCount(options.CharSets)) { throw new ArgumentException( "Length of token must be greater or equal to count of character sets", nameof(iOptions.Value.Length)); } if (options.CharSets == CharSetOptions.None) { throw new ArgumentException( "No character set selected", nameof(iOptions.Value.CharSets)); } if (options.DistinctChars.Count != null && (options.DistinctChars.Count < 0 || options.DistinctChars.Count > options.Length)) { throw new ArgumentException( $"Count of distinct characters must be defined on range [0 - {options.DistinctChars.Count}]", nameof(iOptions.Value.DistinctChars.Count)); } return(options); }
/// <summary> /// Generates a new random token using specified options /// </summary> public static IRandomToken Generate(IOptions <TokenOptions> iOptions) { var options = ValidateOptions(iOptions); string tokenPayload; var token = new StringBuilder(); var rules = ResolveRules(options); var charSets = CharSetManager.BuildCharSets(options.CharSets); bool reRun; do { token.Clear(); tokenPayload = null; reRun = false; AppendConsecutivePart(token, charSets); AppendNonConsecutivePart(token, charSets, options.Length - charSets.Count); tokenPayload = Randomizer.Shuffle(token.ToString()); if (rules.Count > 0) { var failedRules = new List <ITokenRule>(rules.Where(rule => !rule.TryApply(tokenPayload))); if (failedRules.Count > 0) { reRun = !failedRules.TrueForAll(rule => rule.CanReApplyOnShuffledToken); if (!reRun) { tokenPayload = Randomizer.Shuffle(tokenPayload); while (!failedRules.TrueForAll(rule => rule.TryApply(tokenPayload))) { tokenPayload = Randomizer.Shuffle(tokenPayload); } } } } } while (reRun); return(new RandomToken(tokenPayload, options)); }