Skip to content

Commit 1a046c1

Browse files
authored
Merge pull request #46 from raisely/fix-mfa-implementation
Update MFA handling as api now throws error
2 parents 332f55e + 49d0b20 commit 1a046c1

4 files changed

Lines changed: 60 additions & 26 deletions

File tree

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@raisely/cli",
3-
"version": "1.8.0",
3+
"version": "1.8.1",
44
"description": "Raisely CLI for local development",
55
"main": "./src/cli.js",
66
"type": "module",
@@ -61,4 +61,4 @@
6161
"quoteProps": "consistent",
6262
"bracketSpacing": true
6363
}
64-
}
64+
}

src/actions/api.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import fetch from 'node-fetch';
22
import https from 'https';
3+
import _ from 'lodash';
34
import { loadConfig, defaults } from '../config.js';
45

56
const devHttpsAgent = new https.Agent({
@@ -66,11 +67,25 @@ export default async function api(options) {
6667
status: response.status,
6768
};
6869

70+
if (responseIsJSON && formatted) {
71+
// if subcode, add this to error
72+
const subcode = _.get(formatted, 'errors[0].subcode');
73+
if (subcode) {
74+
error.subcode = subcode;
75+
}
76+
}
77+
6978
throw error;
7079
}
7180
return formatted;
7281
} catch (e) {
7382
retryConfig.retry--;
83+
84+
// Handle MFA error
85+
if (e.subcode && e.subcode.startsWith('MFA required')) {
86+
throw e;
87+
}
88+
7489
// Skip hard failures, except a timeout
7590
if (e.status <= 500 && e.status !== 408) {
7691
throw e.message;

src/helpers.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,7 @@ export function error(e, loader) {
127127
console.log(`${chalk.bgRed('Error:')} ${chalk.red(message)}`);
128128
}
129129
}
130+
131+
export function requiresMfa(e) {
132+
return e.subcode && e.subcode.startsWith('MFA required');
133+
}

src/login.js

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import ora from 'ora';
44
import { login } from './actions/auth.js';
55

66
import { updateConfig } from './config.js';
7-
import { log, error, informUpdate } from './helpers.js';
7+
import { log, error, informUpdate, requiresMfa } from './helpers.js';
88

99
export async function doLogin(message) {
1010
if (message) log(message, 'white');
@@ -35,37 +35,52 @@ export async function doLogin(message) {
3535
...credentials,
3636
requestAdminToken: true,
3737
});
38-
if (loginBody.data.requiresOtp) {
39-
loginLoader.info('Your account requires 2 factor authentication.');
40-
const response = await inquirer.prompt([
41-
{
42-
type: 'input',
43-
message: 'Please provide your one time password',
44-
name: 'otp',
45-
validate: (value) =>
46-
value.length
47-
? true
48-
: 'Please enter a one time password',
49-
},
50-
]);
38+
return loginSucceed(loginLoader, loginBody);
39+
} catch (e) {
40+
if (requiresMfa(e)) {
41+
return await loginWith2FA(loginLoader, credentials);
42+
} else {
43+
error(e, loginLoader);
44+
return false;
45+
}
46+
}
47+
}
5148

52-
loginLoader = ora('Logging you in...').start();
49+
async function loginWith2FA(loginLoader, credentials) {
50+
loginLoader.info('Your account requires 2 factor authentication.');
51+
try {
52+
const response = await inquirer.prompt([
53+
{
54+
type: 'input',
55+
message: 'Please provide your one time password',
56+
name: 'otp',
57+
validate: (value) =>
58+
value.length
59+
? true
60+
: 'Please enter a one time password',
61+
},
62+
]);
5363

54-
loginBody = await login({
55-
...credentials,
56-
otp: response.otp,
57-
requestAdminToken: true,
58-
});
59-
}
60-
const { token, data: user } = loginBody;
61-
loginLoader.succeed();
62-
return { user, token };
64+
loginLoader.info('Logging you in...');
65+
66+
const loginBody = await login({
67+
...credentials,
68+
otp: response.otp,
69+
requestAdminToken: true,
70+
});
71+
return loginSucceed(loginLoader, loginBody);
6372
} catch (e) {
6473
error(e, loginLoader);
6574
return false;
6675
}
6776
}
6877

78+
async function loginSucceed(loginLoader, loginBody) {
79+
const { token, data: user } = loginBody;
80+
loginLoader.succeed();
81+
return { user, token };
82+
}
83+
6984
export default async function loginAction() {
7085
const result = await doLogin();
7186
if (!result) return;

0 commit comments

Comments
 (0)