Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "chore: refactor auth to async await" #552

Merged
merged 1 commit into from
Jun 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 62 additions & 55 deletions src/cli/commands/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,56 +12,61 @@ 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): Promise<WebAuthResponse> {
async function webAuth(via: AuthCliCommands) {
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');
}

console.log(
const msg =
'\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');
urlStr + '\n';

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

const lbl = 'Waiting...';

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

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

debug(payload);
const callBackRes = await request(payload);
const {error, res, body} = callBackRes;
debug(error, (res || {}).statusCode, body);

if (error) {
throw error;
}

if (res.statusCode !== 200) {
throw AuthFailedError(body.message, res.statusCode);
}
return new Promise((resolve, reject) => {
debug(payload);
request(payload, (error, res, body) => {
debug(error, (res || {}).statusCode, body);
if (error) {
return reject(error);
}

if (!body.api) {
// retry request
setTimeout(() => {
attemptsLeft--;
if (attemptsLeft > 0) {
return testAuthComplete(token);
if (res.statusCode !== 200) {
return reject(AuthFailedError(body.message, res.statusCode));
}

throw TokenExpiredError();
}, 1000);
}
// we have success
if (body.api) {
return resolve({
res,
body,
});
}

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

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

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

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

if (!(res.statusCode === 200 || res.statusCode === 201)) {
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';
}
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: 17 additions & 14 deletions src/cli/commands/auth/is-authed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,33 @@ import * as snyk from '../../../lib';
import * as config from '../../../lib/config';
import * as request from '../../../lib/request';

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

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

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

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