Skip to content

Commit

Permalink
add github authorization tools for jetpack-repo-watcher example
Browse files Browse the repository at this point in the history
  • Loading branch information
warner committed Oct 6, 2011
1 parent df80e24 commit d853b3e
Show file tree
Hide file tree
Showing 14 changed files with 381 additions and 0 deletions.
5 changes: 5 additions & 0 deletions modules/jetpack-repo-watcher/github-auth-tools/README.md
@@ -0,0 +1,5 @@
This is the jetpack-trunk add-on. It contains:

* A program (lib/main.js).
* A few tests.
* Some meager documentation.
2 changes: 2 additions & 0 deletions modules/jetpack-repo-watcher/github-auth-tools/doc/main.md
@@ -0,0 +1,2 @@
The main module is a program that creates a widget. When a user clicks on
the widget, the program loads the mozilla.org website in a new tab.
146 changes: 146 additions & 0 deletions modules/jetpack-repo-watcher/github-auth-tools/lib/base64.js
@@ -0,0 +1,146 @@
/**
*
* Base64 encode / decode
* http://www.webtoolkit.info/
*
**/

const _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

var Base64 = {

// private property

// public method for encoding
encode : function (input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;

input = Base64._utf8_encode(input);

while (i < input.length) {

chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);

enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;

if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}

output = output +
_keyStr.charAt(enc1) + _keyStr.charAt(enc2) +
_keyStr.charAt(enc3) + _keyStr.charAt(enc4);

}

return output;
},

// public method for decoding
decode : function (input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;

input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

while (i < input.length) {

enc1 = _keyStr.indexOf(input.charAt(i++));
enc2 = _keyStr.indexOf(input.charAt(i++));
enc3 = _keyStr.indexOf(input.charAt(i++));
enc4 = _keyStr.indexOf(input.charAt(i++));

chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;

output = output + String.fromCharCode(chr1);

if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}

}

output = Base64._utf8_decode(output);

return output;

},

// private method for UTF-8 encoding
_utf8_encode : function (string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";

for (var n = 0; n < string.length; n++) {

var c = string.charCodeAt(n);

if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}

}

return utftext;
},

// private method for UTF-8 decoding
_utf8_decode : function (utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;

while ( i < utftext.length ) {

c = utftext.charCodeAt(i);

if (c < 128) {
string += String.fromCharCode(c);
i++;
}
else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
}
else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}

}

return string;
}

}

exports.encode = Base64.encode;
exports.decode = Base64.decode;
@@ -0,0 +1,7 @@

const base64 = require("./base64");

exports.basic_auth_header = function(username, password) {
return "Basic "+base64.encode(username+":"+password);
}

@@ -0,0 +1,14 @@
const passwords = require("passwords");

exports.getGithubPassword = function(callback) {
passwords.search({url: "https://github.com",
onComplete: function(credentials) {
if (credentials.length == 0)
callback(undefined);
else
callback(credentials[0]);
}
});
}

// cred.username, cred.password
@@ -0,0 +1,21 @@

const request = require("request");

exports.GET = function(url, callback) {
request.Request({url: "https://api.github.com/"+url,
onComplete: callback}).get();
}

const auth = require("basic-auth");

exports.authorizedRequester = function(username, password) {
return {
GET: function(url, callback) {
var header = auth.basic_auth_header(username, password);
request.Request({url: "https://api.github.com/"+url,
headers: {Authorization: header},
onComplete: callback}
).get();
}
};
};
36 changes: 36 additions & 0 deletions modules/jetpack-repo-watcher/github-auth-tools/lib/github.js
@@ -0,0 +1,36 @@

const githubRequest = require("./github-request");

function checkRateLimiting(response) {
if (Number(response.headers["X-RateLimit-Remaining"]) == 0) {
console.log("Rate limited!");
throw new Error("Rate limited!");
}
}

function getCommitData(username, reponame, revid, callback) {
var url = "repos/"+username+"/"+reponame+"/git/commits/"+revid;
var gotResponse = function(response) {
checkRateLimiting(response);
callback(response.json);
};
githubRequest.GET(url, gotResponse);
}

exports.getReferenceData = function(username, reponame, branchname, callback) {
var url = "repos/"+username+"/"+reponame+"/git/refs/heads/"+branchname;
var gotResponse = function(response) {
checkRateLimiting(response);
var parsed = response.json;
//console.log("JSON is "+response.text);
//console.log("2 is "+JSON.stringify(response.json));
var revid = parsed.object.sha;
getCommitData(username, reponame, revid, callback);
};
githubRequest.GET(url, gotResponse);
}

exports.getEmails = function(requester, callback) {
var url = "user/emails";
requester.GET(url, function(response) { callback(response.json); });
};
36 changes: 36 additions & 0 deletions modules/jetpack-repo-watcher/github-auth-tools/lib/main.js
@@ -0,0 +1,36 @@
const github = require("./github");
const ui = require("./ui");

var latest;

function doUpdate() {
console.log("doing update");
function gotResponse(data) {
latest = data;
var msg = "Latest Jetpack: "+data.author.name;
ui.setStatus(msg);
}
github.getReferenceData("mozilla", "addon-sdk", "master", gotResponse);
}

function openCommitPage() {
// assume 'latest' is filled in
var viewURL = "https://github.com/mozilla/addon-sdk/commit/"+latest.sha;
ui.openPage(viewURL);
};

exports.main = function() {
doUpdate();
ui.everyMinute(doUpdate);
ui.onClick(openCommitPage);
require("get-github-password").getGithubPassword(
function(cred) {
var requester = require("github-request").authorizedRequester(cred.username, cred.password);
github.getEmails(requester, function(emails) {
console.log("emails: "+JSON.stringify(emails));
});
});
};


console.log("The add-on is running.");
41 changes: 41 additions & 0 deletions modules/jetpack-repo-watcher/github-auth-tools/lib/ui.js
@@ -0,0 +1,41 @@

const widget = require("widget");
const timer = require("timer");
const tabs = require("tabs");

exports.everyMinute = function(callback) {
timer.setInterval(callback, 60*1000);
};

var myWidget;
var clickHandler;

function clicked() {
console.log("clickclick: "+clickHandler);
if (clickHandler)
clickHandler();
}

exports.setStatus = function(string) {
if (!myWidget) {
// first time: must create the widget
myWidget = widget.Widget(
{
id: "jetpack-trunk",
label: "Current Jetpack Trunk",
content: "Jetpack Trunk: ...",
width: 200,
onClick: clicked,
allow: {script: false}
});
}
myWidget.content = string;
};

exports.onClick = function(handler) {
clickHandler = handler;
}

exports.openPage = function(url) {
tabs.open(url);
}
9 changes: 9 additions & 0 deletions modules/jetpack-repo-watcher/github-auth-tools/package.json
@@ -0,0 +1,9 @@
{
"name": "jetpack-trunk",
"license": "MPL 1.1/GPL 2.0/LGPL 2.1",
"author": "",
"version": "0.1",
"fullName": "jetpack-trunk",
"id": "jid1-3NQXWA5DrkivKg",
"description": "a basic add-on"
}
@@ -0,0 +1,9 @@

const auth = require("basic-auth");

exports.test_auth = function(test) {
var username = "alice";
var password = "yaycookies";
test.assertEqual(auth.basic_auth_header(username, password),
"YWxpY2U6eWF5Y29va2llcw==");
}
14 changes: 14 additions & 0 deletions modules/jetpack-repo-watcher/github-auth-tools/test/test-github.js
@@ -0,0 +1,14 @@

const github = require("github");

exports.test_github = function(test) {
function gotResponse(data) {
console.log("last commit was created at "+data.author.date);
console.log("by "+data.author.name);
console.log("message: "+data.message);
test.pass();
test.done();
}
github.getReferenceData("mozilla", "addon-sdk", "master", gotResponse);
test.waitUntilDone(20000);
}
32 changes: 32 additions & 0 deletions modules/jetpack-repo-watcher/github-auth-tools/test/test-main.js
@@ -0,0 +1,32 @@
const main = require("main");

exports.test_test_run = function(test) {
test.pass("Unit test running!");
};

exports.test_id = function(test) {
test.assert(require("self").id.length > 0);
};

exports.test_url = function(test) {
require("request").Request({
url: "http://www.mozilla.org/",
onComplete: function(response) {
test.assertEqual(response.statusText, "OK");
test.done();
}
}).get();
test.waitUntilDone(20000);
};

exports.test_open_tab = function(test) {
const tabs = require("tabs");
tabs.open({
url: "http://www.mozilla.org/",
onReady: function(tab) {
test.assertEqual(tab.url, "http://www.mozilla.org/");
test.done();
}
});
test.waitUntilDone(20000);
};
@@ -0,0 +1,9 @@

const ui = require("ui");
const timers = require("timers");

exports.test_ui = function(test) {
ui.setStatus("status yay!");
timers.setTimeout(function(){test.pass(); test.done();}, 3*1000);
test.waitUntilDone();
}

0 comments on commit d853b3e

Please sign in to comment.