parse-dashboard 4.2.0-beta.1 → 4.2.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30,13 +30,13 @@ function initialize(app, options) {
30
30
  otpCode: req.body.otpCode
31
31
  });
32
32
  if (!match.matchingUsername) {
33
- return cb(null, false, { message: 'Invalid username or password' });
34
- }
35
- if (match.otpMissing) {
36
- return cb(null, false, { message: 'Please enter your one-time password.' });
33
+ return cb(null, false, { message: JSON.stringify({ text: 'Invalid username or password' }) });
37
34
  }
38
35
  if (!match.otpValid) {
39
- return cb(null, false, { message: 'Invalid one-time password.' });
36
+ return cb(null, false, { message: JSON.stringify({ text: 'Invalid one-time password.', otpLength: match.otpMissingLength || 6}) });
37
+ }
38
+ if (match.otpMissingLength) {
39
+ return cb(null, false, { message: JSON.stringify({ text: 'Please enter your one-time password.', otpLength: match.otpMissingLength || 6 })});
40
40
  }
41
41
  cb(null, match.matchingUsername);
42
42
  })
@@ -91,7 +91,7 @@ function authenticate(userToTest, usernameOnly) {
91
91
  let appsUserHasAccessTo = null;
92
92
  let matchingUsername = null;
93
93
  let isReadOnly = false;
94
- let otpMissing = false;
94
+ let otpMissingLength = false;
95
95
  let otpValid = true;
96
96
 
97
97
  //they provided auth
@@ -104,17 +104,20 @@ function authenticate(userToTest, usernameOnly) {
104
104
  let usernameMatches = userToTest.name == user.user;
105
105
  if (usernameMatches && user.mfa && !usernameOnly) {
106
106
  if (!userToTest.otpCode) {
107
- otpMissing = true;
107
+ otpMissingLength = user.mfaDigits || 6;
108
108
  } else {
109
109
  const totp = new OTPAuth.TOTP({
110
110
  algorithm: user.mfaAlgorithm || 'SHA1',
111
- secret: OTPAuth.Secret.fromBase32(user.mfa)
111
+ secret: OTPAuth.Secret.fromBase32(user.mfa),
112
+ digits: user.mfaDigits,
113
+ period: user.mfaPeriod,
112
114
  });
113
115
  const valid = totp.validate({
114
116
  token: userToTest.otpCode
115
117
  });
116
118
  if (valid === null) {
117
119
  otpValid = false;
120
+ otpMissingLength = user.mfaDigits || 6;
118
121
  }
119
122
  }
120
123
  }
@@ -132,7 +135,7 @@ function authenticate(userToTest, usernameOnly) {
132
135
  return {
133
136
  isAuthenticated,
134
137
  matchingUsername,
135
- otpMissing,
138
+ otpMissingLength,
136
139
  otpValid,
137
140
  appsUserHasAccessTo,
138
141
  isReadOnly,
@@ -65,7 +65,19 @@ const generateSecret = ({ app, username, algorithm, digits, period }) => {
65
65
  secret
66
66
  });
67
67
  const url = totp.toString();
68
- return { secret: secret.base32, url };
68
+ const config = { mfa: secret.base32 };
69
+ config.app = app;
70
+ config.url = url;
71
+ if (algorithm !== 'SHA1') {
72
+ config.mfaAlgorithm = algorithm;
73
+ }
74
+ if (digits != 6) {
75
+ config.mfaDigits = digits;
76
+ }
77
+ if (period != 30) {
78
+ config.mfaPeriod = period;
79
+ }
80
+ return { config };
69
81
  };
70
82
  const showQR = text => {
71
83
  const QRCode = require('qrcode');
@@ -77,7 +89,10 @@ const showQR = text => {
77
89
  });
78
90
  };
79
91
 
80
- const showInstructions = ({ app, username, passwordCopied, secret, url, encrypt, config }) => {
92
+ const showInstructions = ({ app, username, passwordCopied, encrypt, config }) => {
93
+ const {secret, url} = config;
94
+ const mfaJSON = {...config};
95
+ delete mfaJSON.url;
81
96
  let orderCounter = 0;
82
97
  const getOrder = () => {
83
98
  orderCounter++;
@@ -90,7 +105,7 @@ const showInstructions = ({ app, username, passwordCopied, secret, url, encrypt,
90
105
 
91
106
  console.log(
92
107
  `\n${getOrder()}. Add the following settings for user "${username}" ${app ? `in app "${app}" ` : '' }to the Parse Dashboard configuration.` +
93
- `\n\n ${JSON.stringify(config)}`
108
+ `\n\n ${JSON.stringify(mfaJSON)}`
94
109
  );
95
110
 
96
111
  if (passwordCopied) {
@@ -101,14 +116,14 @@ const showInstructions = ({ app, username, passwordCopied, secret, url, encrypt,
101
116
 
102
117
  if (secret) {
103
118
  console.log(
104
- `\n${getOrder()}. Open the authenticator app to scan the QR code above or enter this secret code:` +
105
- `\n\n ${secret}` +
119
+ `\n${getOrder()}. Open the authenticator app to scan the QR code above or enter this secret code:` +
120
+ `\n\n ${secret}` +
106
121
  '\n\n If the secret code generates incorrect one-time passwords, try this alternative:' +
107
- `\n\n ${url}` +
122
+ `\n\n ${url}` +
108
123
  `\n\n${getOrder()}. Destroy any records of the QR code and the secret code to secure the account.`
109
124
  );
110
125
  }
111
-
126
+
112
127
  if (encrypt) {
113
128
  console.log(
114
129
  `\n${getOrder()}. Make sure that "useEncryptedPasswords" is set to "true" in your dashboard configuration.` +
@@ -173,6 +188,7 @@ module.exports = {
173
188
  const salt = bcrypt.genSaltSync(10);
174
189
  data.pass = bcrypt.hashSync(data.pass, salt);
175
190
  }
191
+ const config = {};
176
192
  if (mfa) {
177
193
  const { app } = await inquirer.prompt([
178
194
  {
@@ -182,18 +198,13 @@ module.exports = {
182
198
  }
183
199
  ]);
184
200
  const { algorithm, digits, period } = await getAlgorithm();
185
- const { secret, url } = generateSecret({ app, username, algorithm, digits, period });
186
- data.mfa = secret;
187
- data.app = app;
188
- data.url = url;
189
- if (algorithm !== 'SHA1') {
190
- data.mfaAlgorithm = algorithm;
191
- }
192
- showQR(data.url);
201
+ const secret =generateSecret({ app, username, algorithm, digits, period });
202
+ Object.assign(config, secret.config);
203
+ showQR(secret.config.url);
193
204
  }
194
-
195
- const config = { mfa: data.mfa, user: data.user, pass: data.pass };
196
- showInstructions({ app: data.app, username, passwordCopied: true, secret: data.mfa, url: data.url, encrypt, config });
205
+ config.user = data.user;
206
+ config.pass = data.pass ;
207
+ showInstructions({ app: data.app, username, passwordCopied: true, encrypt, config });
197
208
  },
198
209
  async createMFA() {
199
210
  console.log('');
@@ -212,14 +223,9 @@ module.exports = {
212
223
  ]);
213
224
  const { algorithm, digits, period } = await getAlgorithm();
214
225
 
215
- const { url, secret } = generateSecret({ app, username, algorithm, digits, period });
216
- showQR(url);
217
-
226
+ const { config } = generateSecret({ app, username, algorithm, digits, period });
227
+ showQR(config.url);
218
228
  // Compose config
219
- const config = { mfa: secret };
220
- if (algorithm !== 'SHA1') {
221
- config.mfaAlgorithm = algorithm;
222
- }
223
- showInstructions({ app, username, secret, url, config });
229
+ showInstructions({ app, username, config });
224
230
  }
225
231
  };
@@ -184,22 +184,22 @@ module.exports = function(config, options) {
184
184
  </div>`
185
185
  }
186
186
  res.send(`<!DOCTYPE html>
187
+ <html>
187
188
  <head>
188
189
  <link rel="shortcut icon" type="image/x-icon" href="${mountPath}favicon.ico" />
189
190
  <base href="${mountPath}"/>
190
191
  <script>
191
192
  PARSE_DASHBOARD_PATH = "${mountPath}";
192
193
  </script>
193
- </head>
194
- <html>
195
194
  <title>Parse Dashboard</title>
196
- <body>
197
- <div id="login_mount"></div>
198
- ${errors}
199
- <script id="csrf" type="application/json">"${req.csrfToken()}"</script>
200
- <script src="${mountPath}bundles/login.bundle.js"></script>
201
- </body>
202
- </html>
195
+ </head>
196
+ <body>
197
+ <div id="login_mount"></div>
198
+ ${errors}
199
+ <script id="csrf" type="application/json">"${req.csrfToken()}"</script>
200
+ <script src="${mountPath}bundles/login.bundle.js"></script>
201
+ </body>
202
+ </html>
203
203
  `);
204
204
  });
205
205
 
@@ -212,20 +212,20 @@ module.exports = function(config, options) {
212
212
  res.append('username', req.user.matchingUsername);
213
213
  }
214
214
  res.send(`<!DOCTYPE html>
215
+ <html>
215
216
  <head>
216
217
  <link rel="shortcut icon" type="image/x-icon" href="${mountPath}favicon.ico" />
217
218
  <base href="${mountPath}"/>
218
219
  <script>
219
220
  PARSE_DASHBOARD_PATH = "${mountPath}";
220
221
  </script>
221
- </head>
222
- <html>
223
222
  <title>Parse Dashboard</title>
224
- <body>
225
- <div id="browser_mount"></div>
226
- <script src="${mountPath}bundles/dashboard.bundle.js"></script>
227
- </body>
228
- </html>
223
+ </head>
224
+ <body>
225
+ <div id="browser_mount"></div>
226
+ <script src="${mountPath}bundles/dashboard.bundle.js"></script>
227
+ </body>
228
+ </html>
229
229
  `);
230
230
  });
231
231
  });