Skip to content

Commit

Permalink
Pinless authentication. Finishes #1999
Browse files Browse the repository at this point in the history
  • Loading branch information
Scott Corgan committed Mar 26, 2014
1 parent 3a76374 commit 004fe50
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 32 deletions.
5 changes: 3 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ var semver = require('semver');
var format = require('chalk');

var API_HOST = process.env.API_HOST || 'https://api.divshot.com';
// var API_HOST = process.env.API_HOST || 'http://api.dev.divshot.com:9393';

var cliConfigDirectory = path.join(homeDir(), '.divshot');
var user = new User(cliConfigDirectory);
Expand All @@ -34,8 +33,10 @@ var cli = Nash.createCli({

api: Divshot.createClient({
token: user.get('token'),
host: API_HOST
host: API_HOST,
client_id: '526753cf2f55bd0002000006'
}),

user: user,
cwd: cwd,
package: new Package(user),
Expand Down
70 changes: 42 additions & 28 deletions lib/commands/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,60 @@ var request = require('request');
var url = require('url');
var format = require('chalk');
var open = require('open');
var read = require('read');

module.exports = function (cli) {
var POLL_TIMEOUT = 5000; // Poll api every 5 sedonds
var command = cli.command('login');

command.description('login to Divshot from the web');
command.handler(function (done) {
var host = cli.api.options.host;
var requestOptions = {};
var attempts = 0;

requestOptions.url = url.parse(host + '/access_token_request');
requestOptions.followRedirect = false;
request.post(requestOptions, function (err, response, body) {
var data = JSON.parse(body);
cli.api.user.generateTicket().then(function (res) {
if (!res.authorize_url) return done(cli.errors.DEFAULT);

if (err) return done(cli.errors.DEFAULT);
if (data.error) done(format.bold.red(data.statusCode) + ' ' + data.message);
if (response.headers.location) return confirmPin(response.headers.location);
});

function confirmPin (tokenLocation) {
cli.log('To Log-In, Visit: ' + format.bold.underline(tokenLocation));
open(res.authorize_url);

// Open browser for login
open(tokenLocation);
cli.log('Login here if browser doesn\'t open: ' + format.bold(res.authorize_url));

promptly.prompt('Enter PIN (you\'ll receive this upon login):', function (error, pin) {
request.get(tokenLocation + '/' + pin, function (err, response, body) {
var data = JSON.parse(body);

if (err) return done(cli.errors.DEFAULT);
if (data.error) return done(format.bold.red(response.statusCode) + ' ' + response.message);

if (+response.statusCode === 200) {
cli.user.set('token', JSON.parse(body));
read({silent: true, prompt: ''}, cli.log.bind(cli));

process.stdout.write('\nWaiting for authorization ...');

setTimeout(function () {
checkAuthStatus(res.ticket);
}, 3000); // check quick on the initial try

function checkAuthStatus (ticket) {
process.stdout.write('.');

cli.api.user.checkTicketStatus(ticket, function (err, res, body) {
if (res.statusCode == 200) {
var email = (body && body.user) ? body.user.email : 'a Divshot user';

cli.user.set('token', body.access_token);

cli.log('\n');
cli.log('You have successfully authenticated as ' + format.bold(email), {success:true});
cli.log();

cli.log('For more information about how to use the command-line interface, try divshot help or visit ' + format.bold('http://docs.divshot.com/guides/getting-started'));

cli.log('Authenticated!', {success:true});
done(null, JSON.parse(body));
done(null, body);
process.exit(0);
return;
}

if (res.statusCode == 404) done(cli.errors.INVALID_TICKET);
if (res.statusCode == 202) return setTimeout(function () { checkAuthStatus(ticket); }, POLL_TIMEOUT);
if (res.statusCode == 410) done(cli.errors.UNABLE_TO_AUTHENTICATE_TICKET);

process.exit(1);
});
});
}
}
});
});
};
};
2 changes: 2 additions & 0 deletions lib/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module.exports = {
DOMAIN_IN_USE: 'That domain is already in use.',
FILES_NOT_RELEASED: 'Not all files released.',
DIRECTORY_NOT_APP: 'The current directory is not an app.',
UNABLE_TO_AUTHENTICATE_TICKET: 'There was a problem authenticating. Please try again or contact [email protected]',

// missing
MISSING_CONFIG_KEY: 'Config key name required',
Expand All @@ -21,6 +22,7 @@ module.exports = {
INVALID_CREDENTIALS: 'Invalid credentials.',
INVALID_APP_NAME: 'Invalid app name.',
INVALID_ENVIRONMENT: 'Invalid environment.',
INVALID_TICKET: 'The authentication ticket is expired or invalid. Please try again.',

// Upgrad
UPGRADE_TO_USE_FEATURE: 'You must upgrade to a paid plain in order to use this feature.',
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "divshot-cli",
"description": "CLI for Divshot.io",
"version": "0.8.3",
"version": "0.9.0",
"dependencies": {
"regular": "~0.1.3",
"divshot-api": "0.6.x",
Expand All @@ -22,7 +22,8 @@
"nash": "0.2.x",
"semver": "2.2.x",
"mkdirp": "0.3.x",
"open": "0.0.4"
"open": "0.0.4",
"read": "1.0.x"
},
"devDependencies": {
"sinon": "~1.7.3",
Expand Down

0 comments on commit 004fe50

Please sign in to comment.