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

Add two-factor authentication support #5

Merged
merged 2 commits into from
Nov 25, 2014
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
72 changes: 63 additions & 9 deletions lib/api/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,18 @@ var schema = {
}
};

// 2FA OTP Scheme
var otpScheme = {
properties: {
otp: {
required: true
, message: "Invalid 2FA authentication code."
, description: "2FA Authentication Code:"
, type: "number"
}
}
}

/**
* Login
* Asks the user for username and password. Then authenticates the user.
Expand All @@ -28,8 +40,7 @@ var schema = {
* @return {undefined}
*/
var login = module.exports = function (callback) {

if (!CONFIG.username || !CONFIG.password) {
if (!CONFIG.username) {
return CONFIG.prompt.get(schema, function (err, result) {
if (err) { return callback(err); }
CONFIG.username = result.username;
Expand All @@ -39,23 +50,66 @@ var login = module.exports = function (callback) {
// TODO
}

CONFIG._github.authenticate({
type: "basic",
username: CONFIG.username,
password: CONFIG.password
});
if (CONFIG.token) {
CONFIG._github.authenticate({
type: "oauth",
token: CONFIG.token
});
} else {
CONFIG._github.authenticate({
type: "basic",
username: CONFIG.username,
password: CONFIG.password
});

CONFIG._github.user.get({}, function (err, user) {
var opts = {
note: "CLI GitHub",
note_url: "https://github.com/IonicaBizau/cli-github"
}

if (CONFIG.otp) {
opts.headers = {
"X-GitHub-OTP": CONFIG.otp
}
}

return CONFIG._github.authorization.create(opts, function (err, res) {
if (err) {
var error;
try {
error = JSON.parse(err.message).message;
} catch (e) {
error = err.toString();
}

if (error.indexOf("Must specify two-factor authentication OTP code.") !== -1 && !CONFIG.otp) {
return CONFIG.prompt.get(otpScheme, function (err, result) {
if (err) { return callback(err); }
CONFIG.otp = result.otp;
login(callback);
});
} else {
return callback(err);
}
}

CONFIG.token = res.token;
login(callback);
});
}

CONFIG._github.user.get({}, function (err, user) {
if (err) {
delete CONFIG.username;
delete CONFIG.password;
delete CONFIG.otp;
delete CONFIG.token;
return callback(err);
}

Fs.writeFileSync(CONFIG.CONFIG_PATH, JSON.stringify({
username: CONFIG.username
, password: CONFIG.password
, token: CONFIG.token
}));

callback(null, user);
Expand Down
7 changes: 2 additions & 5 deletions lib/api/profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,9 @@ module.exports = function (options, progress, callback) {
// TODO use github library
var user = options.username || options;
Request.get({
auth: {
username: CONFIG.username
, password: CONFIG.password
}
, headers: {
headers: {
"user-agent": "GitHub - CLI"
, "Authorization": "token " + CONFIG.token
}
, url: "https://api.github.com/users/" + user
, json: true
Expand Down
74 changes: 52 additions & 22 deletions lib/api/stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
var Request = require("request")
, Couleurs = require("couleurs")
, Moment = require("moment")
, ParseXML = require('xml2js').parseString
;

// Icons! :-)
Expand All @@ -14,9 +13,46 @@ var icons = {
, "PullRequestEvent": "⇑"
, "DeleteEvent": "⊗"
, "ReleaseEvent": "⌗"
, "IssueEvent": "⚠"
, "IssuesEvent": "⚠"
};

// Event descriptions
var createDescription = function (event) {
var msg = "";

var actor = event.actor;
var repo = event.repo;
var payload = event.payload
switch (event.type) {
case "CreateEvent":
msg = actor.login + " created " + repo.name;
break;
case "WatchEvent":
msg = actor.login + " starred " + repo.name;
break;
case "PushEvent":
msg = actor.login + " pushed to " + payload.ref.replace("refs/heads/", "") + " at " + repo.name;
break;
case "ForkEvent":
msg = actor.login + " forked " + repo.name + " to " + payload.forkee.full_name;
break;
case "PullRequestEvent":
msg = actor.login + " " + payload.action + " pull request " + repo.name + "#" + payload.number;
break;
case "DeleteEvent":
msg = actor.login + " deleted " + payload.ref_type + " " + payload.ref + " at " + repo.name;
break;
case "ReleaseEvent":
msg = actor.login + " published " + repo.name + " " + payload.release.tag_name;
break;
case "IssuesEvent":
msg = actor.login + " " + payload.action + " issue " + repo.name + "#" + payload.issue.number;
break;
}

return msg;
}

/**
* NewsFeed
* Fetches the latest events from news feed.
Expand All @@ -28,32 +64,26 @@ var icons = {
*/
module.exports = function (callback) {
Request.get({
auth: {
username: CONFIG.username
, password: CONFIG.password
}
, headers: {
headers: {
"user-agent": "GitHub - CLI"
, "Authorization": "token " + CONFIG.token
}
, url: "https://github.com/IonicaBizau.private.atom"
, url: "https://api.github.com/users/" + CONFIG.username + "/received_events"
}, function (err, status, body) {
if (err || body.error) { return callback(err || body.error); }

ParseXML(body, function (err, result) {
if (err) { return callback(err); }
var streamData = [];

for (var i = 0; i < result.feed.entry.length; ++i) {
var cEv = result.feed.entry[i];
var streamData = [];
var events = JSON.parse(body);
for (var i = 0; i < events.length; ++i) {
var cEv = events[i];

streamData.push({
icon: icons[cEv.id[0].split(/:|\//)[2]] || " "
, description: cEv.title[0]._
, time: Moment(cEv.updated[0]).fromNow()
});
}
streamData.push({
icon: icons[cEv.type] || " "
, description: createDescription(cEv)
, time: Moment(cEv.created_at).fromNow()
});
}

callback(null, streamData);
});
callback(null, streamData);
});
};
7 changes: 2 additions & 5 deletions lib/api/user-issues.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,9 @@ function getAll(url, callback, progress, i, data) {
data = data || [];
i = i || 1;
Request.get({
auth: {
username: CONFIG.username
, password: CONFIG.password
}
, headers: {
headers: {
"user-agent": "GitHub - CLI"
, "Authorization": "token " + CONFIG.token
}
, json: true
, url: url + "&page=" + i
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Ionică Bizău <bizauionica@gmail.com>",
"contributors": [ "Zach Bruggeman <mail@bruggie.com>" ],
"license": "MIT",
"dependencies": {
"cli-update": "0.0.1",
Expand All @@ -20,7 +21,6 @@
"overlap": "0.1.0",
"image-to-ascii": "0.1.1",
"request": "2.40.0",
"xml2js": "0.4.4",
"keypress": "0.2.1",
"prompt": "0.2.13",
"moment": "2.8.1",
Expand Down