Skip to content

Commit

Permalink
chore: refactor auth to async await
Browse files Browse the repository at this point in the history
  • Loading branch information
lili2311 committed Jun 3, 2019
1 parent 305ac09 commit 11b51f1
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 79 deletions.
117 changes: 55 additions & 62 deletions src/cli/commands/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,61 +12,56 @@ import { MisconfiguredAuthInCI } from '../../../lib/errors/misconfigured-auth-in
import { AuthFailedError } from '../../../lib/errors/authentication-failed-error';
import {verifyAPI} from './is-authed';

module.exports = auth;

const apiUrl = url.parse(config.API);
const authUrl = apiUrl.protocol + '//' + apiUrl.host;
const debug = Debug('snyk-auth');
let attemptsLeft = 0;

module.exports = auth;

function resetAttempts() {
attemptsLeft = 30;
}

type AuthCliCommands = 'wizard' | 'ignore';
interface WebAuthResponse {
res: object;
body: object;
}

async function webAuth(via: AuthCliCommands) {
async function webAuth(via: AuthCliCommands): Promise<WebAuthResponse> {
const token = uuid.v4(); // generate a random key
const redirects = {
wizard: '/authenticated',
};

if (isCI()) {
throw MisconfiguredAuthInCI();
}

let urlStr = authUrl + '/login?token=' + token;

// validate that via comes from our code, and not from user & CLI
if (redirects[via]) {
urlStr += '&redirectUri=' + new Buffer(redirects[via]).toString('base64');
}

const msg =
console.log(
'\nNow redirecting you to our auth page, go ahead and log in,\n' +
'and once the auth is complete, return to this prompt and you\'ll\n' +
'be ready to start using snyk.\n\nIf you can\'t wait use this url:\n' +
urlStr + '\n';

// suppress this message in CI
if (!isCI()) {
console.log(msg);
} else {
return Promise.reject(MisconfiguredAuthInCI());
}

const lbl = 'Waiting...';
urlStr + '\n');

return spinner(lbl).then(() => {
try {
setTimeout(() => {
open(urlStr, {wait: false});
}, 2000);
// start checking the token immediately in case they've already
// opened the url manually
return testAuthComplete(token);
})
// clear spinnger in case of success or failure
.then(spinner.clear(lbl))
.catch((error) => {
spinner.clear(lbl)();
throw error;
});
} catch (error) {
throw error;
}
}

async function testAuthComplete(token: string) {
Expand All @@ -79,59 +74,57 @@ async function testAuthComplete(token: string) {
method: 'post',
};

return new Promise((resolve, reject) => {
debug(payload);
request(payload, (error, res, body) => {
debug(error, (res || {}).statusCode, body);
if (error) {
return reject(error);
}
debug(payload);
const callBackRes = await request(payload);
const {error, res, body} = callBackRes;
debug(error, (res || {}).statusCode, body);

if (res.statusCode !== 200) {
return reject(AuthFailedError(body.message, res.statusCode));
}
if (error) {
throw error;
}

if (res.statusCode !== 200) {
throw AuthFailedError(body.message, res.statusCode);
}

// we have success
if (body.api) {
return resolve({
res,
body,
});
if (!body.api) {
// retry request
setTimeout(() => {
attemptsLeft--;
if (attemptsLeft > 0) {
return testAuthComplete(token);
}

// we need to wait and poll again in a moment
setTimeout(() => {
attemptsLeft--;
if (attemptsLeft > 0) {
return resolve(testAuthComplete(token));
}

reject(TokenExpiredError());
}, 1000);
});
});
throw TokenExpiredError();
}, 1000);
}

return {
res,
body,
};
}

async function auth(apiToken: string, via: AuthCliCommands) {
let promise;
let authPromise;
resetAttempts();
if (apiToken) {
// user is manually setting the API token on the CLI - let's trust them
promise = verifyAPI(apiToken);
authPromise = verifyAPI(apiToken);
} else {
promise = webAuth(via);
authPromise = webAuth(via);
}

return promise.then((data) => {
const res = data.res;
const body = res.body;
debug(body);
const authResponse = await authPromise;
const res = authResponse.res;
const body = res.body;
debug(body);

if (res.statusCode === 200 || res.statusCode === 201) {
snyk.config.set('api', body.api);
return '\nYour account has been authenticated. Snyk is now ready to ' +
'be used.\n';
}
if (!(res.statusCode === 200 || res.statusCode === 201)) {
throw AuthFailedError(body.message, res.statusCode);
});
}

snyk.config.set('api', body.api);
return '\nYour account has been authenticated. Snyk is now ready to ' +
'be used.\n';
}
31 changes: 14 additions & 17 deletions src/cli/commands/auth/is-authed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,30 @@ import * as snyk from '../../../lib';
import * as config from '../../../lib/config';
import * as request from '../../../lib/request';

export function isAuthed() {
export async function isAuthed() {
const token = snyk.config.get('api');
return verifyAPI(token).then((res: any) => {
return res.body.ok;
});
const res = await verifyAPI(token);
return res.body.ok;
}

export function verifyAPI(api) {
export async function verifyAPI(apiToken) {
const payload = {
body: {
api,
api: apiToken,
},
method: 'POST',
url: config.API + '/verify/token',
json: true,
};

return new Promise((resolve, reject) => {
request(payload, (error, res, body) => {
if (error) {
return reject(error);
}
const verifyTokenRes = await request(payload);
const {error, res, body} = verifyTokenRes;
if (error) {
throw error;
}

resolve({
res,
body,
});
});
});
return {
res,
body,
};
}

0 comments on commit 11b51f1

Please sign in to comment.