-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
160 lines (125 loc) · 4.68 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
'use strict';
const PasswordGenerator = {
numbersChars: '0123456789',
alphabetChars: 'abcdefghijklmnopqrstuvwxyz',
symbolsChars: '!@#$%&*()_+-={}[]:;<>?,./|',
/**
* Generate a random password given the params
* @param {Number} size - the total length of the password
* @param {Object} options - Object with the options of configuration
* @return {String} The generated password
*/
generate() {
const options = PasswordGenerator.mergeOptions(arguments);
let finalPassword = '';
let numberPassword = '';
let symbolsPassword = '';
let possibleChars = PasswordGenerator.alphabetChars;
if(options.allowUppercase) {
possibleChars += PasswordGenerator.alphabetChars.toUpperCase();
}
for(let i = 0; i < options.size; i++) {
finalPassword += PasswordGenerator.generateNextChar(possibleChars, finalPassword, options);
}
if(options.numbers > 0) {
finalPassword = finalPassword.substring(0, (finalPassword.length - options.numbers));
for(let i = 0; i < options.numbers; i++) {
numberPassword += PasswordGenerator.generateNextChar(PasswordGenerator.numbersChars, numberPassword, options);
}
finalPassword = numberPassword + finalPassword;
}
if(options.symbols > 0) {
finalPassword = finalPassword.substring(0, (finalPassword.length - options.symbols));
for(let i = 0; i < options.symbols; i++) {
symbolsPassword += PasswordGenerator.generateNextChar(PasswordGenerator.symbolsChars, symbolsPassword, options);
}
finalPassword = finalPassword + symbolsPassword;
}
finalPassword = PasswordGenerator.shuffleString(finalPassword);
return finalPassword;
},
/**
* Merge default options with Users options
* @param {(Number|Object)} userOptions Arguments passing in the function generate
* @return {Object} Object with the final options
*/
mergeOptions(userOptions) {
let userObjOptions = userOptions[0];
let defaultValues = {
size: 16,
numbers: 5,
symbols: 5,
allowUppercase: true,
allowRepetintion: false
};
if(typeof userObjOptions === 'number') {
defaultValues.size = userObjOptions;
}
if(userOptions[1] && userOptions[1] === Object(userOptions[1])) {
userObjOptions = userOptions[1];
}
if( userObjOptions === Object(userObjOptions) ) {
if(userObjOptions.hasOwnProperty('size')) {
defaultValues.size = userObjOptions.size;
}
if(userObjOptions.hasOwnProperty('numbers')) {
defaultValues.numbers = userObjOptions.numbers;
if(defaultValues.size < defaultValues.numbers) {
defaultValues.numbers = defaultValues.size;
}
}
if(userObjOptions.hasOwnProperty('symbols')) {
defaultValues.symbols = userObjOptions.symbols;
if(defaultValues.size < defaultValues.symbols) {
defaultValues.symbols = defaultValues.size;
}
}
if(userObjOptions.hasOwnProperty('allowUppercase')) {
defaultValues.allowUppercase = userObjOptions.allowUppercase;
}
if(userObjOptions.hasOwnProperty('allowRepetintion')) {
defaultValues.allowRepetintion = userObjOptions.allowRepetintion;
}
}
return defaultValues;
},
/**
* Generate the next char for the password string
* @param {String} possibleChars - A string containing all the chars allowed in the password
* @param {String} hash - The actual password
* @param {Object} options - Object with the module configuration
* @return {String} The next char for the password
*/
generateNextChar(possibleChars, hash, options) {
const nextChar = possibleChars.charAt(Math.floor(Math.random() * possibleChars.length));
if(!options.allowRepetintion && PasswordGenerator.checkForRepetintion(hash, nextChar) && (options.numbers <= PasswordGenerator.numbersChars.length && options.symbols <= PasswordGenerator.symbolsChars.length)) {
return PasswordGenerator.generateNextChar(possibleChars, hash, options);
}
return nextChar;
},
/**
* Check if chars exist at given string
* @param {String} hash - The string to check
* @param {String} nextChar - the char that can't be in the string
* @return {Boolean} true if exist and false if doesn't
*/
checkForRepetintion(hash, nextChar) {
return (hash.indexOf(nextChar) !== -1);
},
/**
* Shuffle the String with all the chars for the password, that way we have the exact amount of each type of chars in the password
* @param {String} finalPassword - the string to be suffled
* @return {String} shuffled string
*/
shuffleString(finalPassword) {
const shuffledString = finalPassword
.split('')
.sort(() => 0.5 - Math.random()) // eslint-disable-line no-magic-numbers
.join('');
if(shuffledString === finalPassword) {
return PasswordGenerator.shuffleString(finalPassword);
}
return shuffledString;
}
};
module.exports = Object.create(PasswordGenerator);