Last active
November 16, 2018 14:23
-
-
Save preetpalS/b502659b9cb2ddd80fce33932c5dd047 to your computer and use it in GitHub Desktop.
Simple command line random password generator (Ruby)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'optparse' | |
require 'ostruct' | |
class RandomPasswordGenerator | |
VERSION = %w(0.1.0) | |
CORE_CHARACTER_SET = [('a'..'z').to_a, | |
('A'..'Z').to_a, | |
(0..9).map(&:to_s)].flatten.freeze | |
BASIC_SYMBOL_SET = ['$', '_', '-', '+', '='].freeze | |
BASIC_SYMBOL_SET_KEY = 'basic' | |
EMPTY_SYMBOL_SET = [].freeze | |
EMPTY_SYMBOL_SET_KEY = 'empty' | |
FULL_SYMBOL_SET = # Higher chance of experiencing compatibility issues | |
['`', '~', '!', '@', '#', '$', '%', '^', | |
'&', '*', '(', ')', '_', '-', '=', '+', | |
'[', ']', '{', '}', '\\', '|', ':', ';', | |
'\'', '"', ',', '.', '<', '>', '/', '?'].freeze | |
FULL_SYMBOL_SET_KEY = 'full' | |
SYMBOL_SETS = [BASIC_SYMBOL_SET_KEY, EMPTY_SYMBOL_SET_KEY, FULL_SYMBOL_SET_KEY].freeze | |
SYMBOL_SET_ALIASES = SYMBOL_SETS.map { |s| [s[0], s] }.to_h.freeze | |
SYMBOL_SET_MAX_KEY_LENGTH = SYMBOL_SETS.map(&:length).max | |
DEFAULT_SYMBOL_SET_KEY = BASIC_SYMBOL_SET_KEY | |
DEFAULT_MINIMUM_LENGTH = 12 | |
DEFAULT_MAXIMUM_LENGTH = 25 | |
def initialize | |
# Note that the standard library OptionParser library invoked in the following method has access | |
# to ARGV and removes any options that it found and parsed in ARGV (argument vector). | |
@options = parse_command_line_arguments | |
puts generate_random_password | |
end | |
private | |
def parse_command_line_arguments | |
options = OpenStruct.new | |
options.symbol_set = DEFAULT_SYMBOL_SET_KEY | |
options.minimum_length = DEFAULT_MINIMUM_LENGTH | |
options.maximum_length = DEFAULT_MAXIMUM_LENGTH | |
OptionParser.new do |opts| | |
opts.banner = 'Usage: random_password_generator [options]' | |
opts.separator '' | |
opts.separator 'Specific options:' | |
opts.on('-sSYMBOL_SET', '--symbol-set=SYMBOL_SET', SYMBOL_SETS, SYMBOL_SET_ALIASES, | |
<<MESSAGE) do |symbol_set| | |
Select which symbol-set to use from the following (default=#{DEFAULT_SYMBOL_SET_KEY}): | |
#{BASIC_SYMBOL_SET_KEY.ljust(SYMBOL_SET_MAX_KEY_LENGTH)}\t\t#{BASIC_SYMBOL_SET.join(' ')} | |
#{EMPTY_SYMBOL_SET_KEY} | |
#{FULL_SYMBOL_SET_KEY.ljust(SYMBOL_SET_MAX_KEY_LENGTH)}\t\t#{FULL_SYMBOL_SET.join(' ')} | |
MESSAGE | |
options.symbol_set = symbol_set | |
end | |
opts.on('--minimum-length=MIN', | |
"Set minimum length of generated random password (default=#{DEFAULT_MINIMUM_LENGTH})") do |minimum_length| | |
options.minimum_length = Integer(minimum_length) | |
end | |
opts.on('--maximum-length=MAX', | |
"Set maximum length of generated random password (default=#{DEFAULT_MAXIMUM_LENGTH})") do |maximum_length| | |
options.maximum_length = Integer(maximum_length) | |
end | |
opts.separator '' | |
opts.separator 'Common options:' | |
opts.on_tail('-h', '--help', 'Show this message') do | |
puts opts | |
exit | |
end | |
opts.on_tail('-v', '--version', 'Show version') do | |
puts "Version: #{VERSION.join('.')}" | |
exit | |
end | |
end.parse! | |
check_option_invariants(options) | |
options | |
end | |
def check_option_invariants(options) | |
fail "Program invariant violated (maximum_length cannot be less than minimum length)" if options.maximum_length < options.minimum_length | |
end | |
def symbol_set | |
case @options.symbol_set | |
when BASIC_SYMBOL_SET_KEY | |
BASIC_SYMBOL_SET | |
when EMPTY_SYMBOL_SET_KEY | |
EMPTY_SYMBOL_SET | |
when FULL_SYMBOL_SET_KEY | |
FULL_SYMBOL_SET | |
else | |
fail "Program invariant violated (unknown symbol set: ). GUID: e9ab3fd0-c17e-41da-a72a-a68855a253a0" | |
end | |
end | |
def acceptable_characters | |
@acceptable_characters ||= [ | |
CORE_CHARACTER_SET, | |
symbol_set | |
].flatten.freeze | |
end | |
def generate_random_password | |
password_length = ((@options.minimum_length)..(@options.maximum_length)).to_a.sample | |
Array.new(password_length, nil).to_a.map { |_| acceptable_characters.sample }.join('') | |
end | |
end | |
RandomPasswordGenerator.new |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment