diff --git a/ChangeLog b/ChangeLog index d53464c50e904e25d8776a43ca2e5f8a72775f5b..af3561ed7cd8f8b671182c7892d12d1e016af713 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,19 @@ -train-2012.03.14 (in progress): +train-2012.03.28 (in progress): + +train-2012.03.14: + * BrowserID now speaks Bulgarian + * Fix regressions related to ToS/PP feature (#841): #1303 + * Fix regressions related to improved email selection on iOS (#1133): #1304 + * "delegation of authority" implemented: #1271, #864 + * visual improvements: #403 + * improved algorithm for finding best language for a given user: #1128 + * frontend tests now run on every commit under travisci: #635 + * improve the way that .well-known/browserid is cached: #1205 + * l10n fixes: #1124, #1300 + * tools/build/dev env cleanup: #1235, #1234, #1257, #1245, #1055 + * improvements to developer tool for checking primary support - scripts/checks_primary_support + * documentation improvements: #1264, #1287, #1288 + * logging improvements: #1254, #1255, #1283, #1291 train-2012.03.01: * When the user authenticates log them in automatically without going to the email picker: #198 diff --git a/config/l10n-all.json b/config/l10n-all.json index 19ef4adfe56b8c873358010f79323af0562ff883..2d2b46ec5f8ebc49c92c1d1a0e3296cafc3cb7be 100644 --- a/config/l10n-all.json +++ b/config/l10n-all.json @@ -1,6 +1,6 @@ { "supported_languages": [ - "af", "ca", "cs", "da", "db-LB", "de", "el", "en-US", "eo", "es", + "af", "bg", "ca", "cs", "da", "db-LB", "de", "el", "en-US", "eo", "es", "es-MX", "et", "eu", "fi", "fr", "fy", "ga", "gd", "gl", "he", "hr", "hu", "it", "ja", "ko", "lij", "lt", "ml", "nl", "pa", "pl", "pt", "pt-BR", "rm", "ro", "ru", "sk", "sl", "son", "sq", "sr", "sv", "tr", diff --git a/resources/static/include_js/include.js b/resources/static/include_js/include.js index 75fdc53fec4ec7e51f493819773fc5dcec901c7d..d9dfc7821720c4b91c4617a2d85d7a3c2ee9b9e8 100644 --- a/resources/static/include_js/include.js +++ b/resources/static/include_js/include.js @@ -947,6 +947,19 @@ loginCanceled: [ ] }; + var compatMode = undefined; + function checkCompat(requiredMode) { + if (requiredMode === true) { + try { console.log("this site uses deprecated APIs (see documentation for navigator.id.request())"); } catch(e) { } + } + + if (compatMode === undefined) compatMode = requiredMode; + else if (compatMode != requiredMode) { + throw "you cannot combine browserid event APIs with navigator.id.getVerifiedEmail() or navigator.id.get()" + + "this site should instead use navigator.id.request() and the browserid event API"; + } + } + function emitEvent(type, params) { if (listeners[type]) { var evt = document.createEvent('Event'); @@ -1001,10 +1014,7 @@ } } - navigator.id.addEventListener = function(type, listener/*, useCapture */) { - // allocate iframe if it is not allocated - _open_hidden_iframe(); - + function internalAddEventListener(type, listener) { // add event to listeners table if it's not there already if (!listeners[type]) throw "unsupported event type: '" + type + "'"; @@ -1013,22 +1023,35 @@ if (listeners[type][i] === listener) return; } listeners[type].push(listener); - }; + } - navigator.id.removeEventListener = function(type, listener/*, useCapture */) { - if (!useCapture) useCapture = false; + navigator.id.addEventListener = function(type, listener) { + checkCompat(false); + + // allocate iframe if it is not allocated + _open_hidden_iframe(); + internalAddEventListener(type,listener); + }; + function internalRemoveEventListener(type, listener ) { // remove event from listeners table var i; for (i = 0; i < listeners[type].length; i++) { if (listeners[type][i] === listener) break; } - if (i < listeners[type][i] === listener) { + if (i < listeners[type][i].length) { listeners[type].splice(i, 1); } + } + + navigator.id.removeEventListener = function(type, listener/*, useCapture */) { + checkCompat(false); + internalRemoveEventListener(type, listener); }; navigator.id.logout = function() { + checkCompat(false); + // allocate iframe if it is not allocated _open_hidden_iframe(); @@ -1037,6 +1060,8 @@ }; navigator.id.setLoggedInUser = function(email) { + checkCompat(false); + // 1. allocate iframe if it is not allocated _open_hidden_iframe(); @@ -1044,11 +1069,34 @@ commChan.notify({ method: 'loggedInUser', params: email }); }; + // backwards compatibility function navigator.id.get = function(callback, options) { - // backwards compatibility function + checkCompat(true); + + if (options && options.silent) { + if (callback) setTimeout(function() { callback(null); }, 0); + } else { + function handleEvent(e) { + internalRemoveEventListener('login', handleEvent); + callback((e && e.assertion) ? e.assertion : null); + } + internalAddEventListener('login', handleEvent); + internalRequest(options); + } + }; + + // backwards compatibility function + navigator.id.getVerifiedEmail = function(callback) { + checkCompat(true); + navigator.id.get(callback); }; navigator.id.request = function(options) { + checkCompat(false); + return internalRequest(options); + }; + + function internalRequest(options) { // focus an existing window if (w) { try { diff --git a/scripts/browserid.spec b/scripts/browserid.spec index 6c891230e6540bbf3c7c23b66feb967c982d1327..b3690391a7cb1d00ad458972779f74314136f2cc 100644 --- a/scripts/browserid.spec +++ b/scripts/browserid.spec @@ -1,7 +1,7 @@ %define _rootdir /opt/browserid Name: browserid-server -Version: 0.2012.03.14 +Version: 0.2012.03.28 Release: 1%{?dist}_%{svnrev} Summary: BrowserID server Packager: Pete Fritchman <petef@mozilla.com> diff --git a/scripts/check_primary_support b/scripts/check_primary_support index fa0137afafc0edb21511a84df252ee27acd6badb..4861b74aa14ac6ac8ef4cb10eff60ffe986d558f 100755 --- a/scripts/check_primary_support +++ b/scripts/check_primary_support @@ -7,6 +7,7 @@ const https = require('https'), und = require('underscore'), +urlp = require('url'), util = require('util'), primary = require('../lib/primary'), @@ -29,8 +30,13 @@ primary.checkSupport(domain, function(err, urls, publicKey) { console.log('Priary domain: ', domain); console.log('Public Key: ', publicKey); - getResource('auth', urls.auth, urls, function () { - getResource('prov', urls.prov, urls); + var authopts = { + xframe: false + }; + getResource('auth', urls.auth, urls, authopts, function () { + getResource('prov', urls.prov, urls, { + xframe: true + }); }); }); @@ -38,14 +44,14 @@ primary.checkSupport(domain, function(err, urls, publicKey) { /** * Retrieve one of their urls and examine aspects of it for issues */ -function getResource(mode, url, urls, cb) { - console.log('Checking ', url); +function getResource(mode, url, urls, opts, cb) { + var path = urlp.parse(url).path; var body = "", r = https.request({ host: domain, - path: url, + path: path, method: 'GET' - }, checkResource(urls, body)); + }, checkResource(url, opts, body)); r.on('data', function (chunk) { body += chunk; }); @@ -74,20 +80,21 @@ function getResource(mode, url, urls, cb) { * * Do the provisioning and signin resources look kosher? */ -function checkResource (urls, body) { +function checkResource (url, opts, body) { return function (resp) { // Their are no X-Frame options if (resp.statusCode != 200) { - console.log("ERROR: HTTP status code=", resp.statusCode); + console.log("ERROR: HTTP status code=", resp.statusCode, url); } else { - var xframe = und.filter(Object.keys(resp.headers), function (header) { - return header.toLowerCase() == 'x-frame-options'; - }); - if (xframe.length == 1) { - console.log("ERROR: X-Frame-Options=", resp.headers[xframe[0]], ", BrowserID will not be able to communicate with your site." + - " Suppress X-Frame-Options for /.well-known/browserid, " + urls.auth + ' and ' + urls.prov); + if (opts.xframe === true) { + var xframe = und.filter(Object.keys(resp.headers), function (header) { + return header.toLowerCase() == 'x-frame-options'; + }); + if (xframe.length == 1) { + console.log("ERROR: X-Frame-Options=", resp.headers[xframe[0]], ", BrowserID will not be able to communicate with your site." + + " Suppress X-Frame-Options for ", url); + } } - resp.setEncoding('utf8'); } }; diff --git a/scripts/deploy/ssh.js b/scripts/deploy/ssh.js index 29c504ab24be86c8e8123d978c7ab8c7ab2dcf25..290abf1d322745ef8f4fbc17eac90345f289e606 100644 --- a/scripts/deploy/ssh.js +++ b/scripts/deploy/ssh.js @@ -36,3 +36,8 @@ exports.copySSL = function(host, pub, priv, cb) { }); }); }; + +exports.addSSHPubKey = function(host, pubkey, cb) { + var cmd = 'ssh -o "StrictHostKeyChecking no" ec2-user@' + host + " 'echo \'" + pubkey + "\' >> .ssh/authorized_keys'"; + child_process.exec(cmd, cb); +}; diff --git a/scripts/deploy_dev.js b/scripts/deploy_dev.js index f615705719ea99e2a8f7c75fc5fbdcd9a34dbb46..21c2308170cc8ca5a2ab8a2de76e4653575bdcc6 100755 --- a/scripts/deploy_dev.js +++ b/scripts/deploy_dev.js @@ -24,6 +24,10 @@ function DevDeployer() { this.sslpub = process.env['DEV_SSL_PUB']; this.sslpriv = process.env['DEV_SSL_PRIV']; + this.keypairs = []; + if (process.env['ADDITIONAL_KEYPAIRS']) { + this.keypairs = process.env['ADDITIONAL_KEYPAIRS'].split(','); + } if (!this.sslpub || !this.sslpriv) { throw("you must provide ssl cert paths via DEV_SSL_PUB & DEV_SSL_PRIV"); @@ -63,7 +67,21 @@ DevDeployer.prototype.configure = function(cb) { var config = { public_url: "https://dev.diresworb.org" }; ssh.copyUpConfig(self.deets.ipAddress, config, function (err) { if (err) return cb(err); - ssh.copySSL(self.deets.ipAddress, self.sslpub, self.sslpriv, cb); + ssh.copySSL(self.deets.ipAddress, self.sslpub, self.sslpriv, function(err) { + if (err) return cb(err); + + // now copy up addtional keypairs + var i = 0; + function copyNext() { + if (i == self.keypairs.length) return cb(null); + ssh.addSSHPubKey(self.deets.ipAddress, self.keypairs[i++], function(err) { + if (err) return cb(err); + self.emit('progress', "key added..."); + copyNext(); + }); + } + copyNext(); + }); }); } diff --git a/scripts/deploy_server.js b/scripts/deploy_server.js index 130bcd5ae06cb9276c2a0fa53343ddb0a9145036..f38338ee1bba2f6338472d75c2dd3a3385df2a97 100755 --- a/scripts/deploy_server.js +++ b/scripts/deploy_server.js @@ -176,7 +176,7 @@ Deployer.prototype.checkForUpdates = function() { var deployer = new Deployer(); var currentLogFile = null; -// a directory where we'll deployment logs +// a directory where we'll keep deployment logs var deployLogDir = process.env['DEPLOY_LOG_DIR'] || temp.mkdirSync(); var deployingSHA = null;