diff --git a/bin/browserid b/bin/browserid index d69fe6767558d96e9b15a8cbfa9360c435873269..32cca02f7f9656f22e46ae55c3ad5d3cb9913121 100755 --- a/bin/browserid +++ b/bin/browserid @@ -213,7 +213,7 @@ function router(app) { // request to logger, dev formatted which omits personal data in the requests app.use(express.logger({ - format: 'dev', + format: config.get('express_log_format'), stream: { write: function(x) { logger.info(typeof x === 'string' ? x.trim() : x); diff --git a/bin/keysigner b/bin/keysigner index ac5fa7f249bec8a734f218e5c2597338e239e538..211cf1c19b1bc563e6f207cbd8d9acc675ca448a 100755 --- a/bin/keysigner +++ b/bin/keysigner @@ -57,7 +57,7 @@ var app = express.createServer(); // our server will log app.use(express.logger({ - format: 'dev', + format: config.get('express_log_format'), stream: { write: function(x) { logger.info(typeof x === 'string' ? x.trim() : x); diff --git a/bin/verifier b/bin/verifier index 8da38a12f39c7d57a035635a3e1271360376af46..de9740281dbafe04f826282e17e7411e1d1c2bcb 100755 --- a/bin/verifier +++ b/bin/verifier @@ -54,6 +54,7 @@ var app = express.createServer(); // request to logger, dev formatted which omits personal data in the requests app.use(express.logger({ + format: config.get('express_log_format'), stream: { write: function(x) { logger.info(typeof x === 'string' ? x.trim() : x); diff --git a/lib/configuration.js b/lib/configuration.js index a71fc10d6312e51971130f5955f23badc99591a4..da7982c4415a1a4518d97c51965927241305cc92 100644 --- a/lib/configuration.js +++ b/lib/configuration.js @@ -202,6 +202,8 @@ exports.performSubstitution = function(app) { } }; +g_config['express_log_format'] = (exports.get('env') === 'production' ? 'default' : 'dev'); + // At the time this file is required, we'll determine the "process name" for this proc // if we can determine what type of process it is (browserid or verifier) based // on the path, we'll use that, otherwise we'll name it 'ephemeral'. diff --git a/lib/logging.js b/lib/logging.js index 3e7feb5a1a7d7e972f572b5c4923aaf205c4471f..6382a9030096f2e1515d48e4122f7fef0e8ed132 100644 --- a/lib/logging.js +++ b/lib/logging.js @@ -38,7 +38,7 @@ * A very thin wrapper around winston for general server logging. * Exports a winston Logger instance in exports.logger with several functions * corresponding to different log levels. use it like this: - * + * * const logger = require('../libs/logging.js').logger; * logger.debug("you can probably ignore this. just for debugging."); * logger.info("something happened, here's info about it!"); diff --git a/resources/static/css/style.css b/resources/static/css/style.css index 64e8c5f177abf5758169124608e60b5de50d8b5f..69a40d3e13e57527a1f83c9fe6315070ecc16d12 100644 --- a/resources/static/css/style.css +++ b/resources/static/css/style.css @@ -736,16 +736,20 @@ h1 { } -#congrats #siteinfo, #congrats { +.siteinfo, #congrats { display: none; } #congrats p { color: #62615F; - display: block; + /*display: block;*/ text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.5); } +#congrats .siteinfo { + margin-top: 10px; +} + #congrats .website { display: block; text-align: center; diff --git a/resources/static/dialog/css/m.css b/resources/static/dialog/css/m.css index 303557e63d05233aeb9c500c04c35878a6b64f2e..416ad1d2536465d9a71a7455c558475629977eb4 100644 --- a/resources/static/dialog/css/m.css +++ b/resources/static/dialog/css/m.css @@ -74,6 +74,11 @@ vertical-align: middle; } + #favicon .vertical { + height: auto; + line-height: 20px; + } + #formWrap { background-color: transparent; } diff --git a/resources/static/dialog/css/popup.css b/resources/static/dialog/css/popup.css index fb43054b98e7ff5cbcac496726a0ffd0f5378cc1..9318251411c775fb6b9bfe8e603d0002387785c3 100644 --- a/resources/static/dialog/css/popup.css +++ b/resources/static/dialog/css/popup.css @@ -18,6 +18,7 @@ body { font-size: 13px; line-height: 21px; background-image: url('/i/bg.png'); + color: #000; } @@ -221,8 +222,9 @@ section > .contents { #favicon { position: absolute; - left: 450px; + left: 375px; top: 0; + right: 0; z-index: 10; } @@ -235,6 +237,14 @@ section > .contents { margin: 0 auto 10px; } +#favicon .vertical { + display: block; + line-height: 250px; + text-align: center; + overflow: hidden; + text-overflow: ellipsis; +} + #signIn .vertical { padding: 15px 20px 20px 20px; } diff --git a/resources/static/dialog/qunit.html b/resources/static/dialog/qunit.html index 0236807217744451277741940817a7f083dcc48c..17d4b0b53ea6fe60227513bef3e727515ea92545 100644 --- a/resources/static/dialog/qunit.html +++ b/resources/static/dialog/qunit.html @@ -33,10 +33,13 @@ </div> <input id="email" /> + <input id="password" /> + <input id="vpassword" /> + <div id="congrats">Congrats!</div> <span id="cannotconfirm" class="error">Cannot confirm</span> <span id="cannotcommunicate" class="error">Cannot communicate</span> - <span id="siteinfo" class="error"><span class="website"></span></span> - <span class=".hint">Hint</span> + <span class="siteinfo" class="error"><span class="website"></span></span> + <span class="hint">Hint</span> </div> <div id="needsTooltip">Tooltip Anchor</div> diff --git a/resources/static/dialog/resources/validation.js b/resources/static/dialog/resources/validation.js index 15b98c1b7a6bf3b1837f97f8cec72ec541bb4dea..341f4349b020a8091d64e9de231d21f354407df8 100644 --- a/resources/static/dialog/resources/validation.js +++ b/resources/static/dialog/resources/validation.js @@ -38,12 +38,12 @@ BrowserID.Validation = (function() { tooltip = bid.Tooltip; bid.verifyEmail = function(address) { - // gotten from http://blog.gerv.net/2011/05/html5_email_address_regexp/ + // Original gotten from http://blog.gerv.net/2011/05/html5_email_address_regexp/ // changed the requirement that there must be a ldh-str because BrowserID - // is only used on internet based networks. + // is only used on internet based networks. var parts = address.split("@"); - return /^[\w.!#$%&'*+\-/=?\^`{|}~]+@[a-z0-9-]+(\.[a-z0-9-]+)+$/.test(address) + return /^[\w.!#$%&'*+\-/=?\^`{|}~]+@[a-z\d-]+(\.[a-z\d-]+)+$/i.test(address) // total address allwed to be 254 bytes long && address.length <= 254 // local side only allowed to be 64 bytes long diff --git a/resources/static/dialog/test/qunit/pages/add_email_address_test.js b/resources/static/dialog/test/qunit/pages/add_email_address_test.js index d353a848f9b27f4357411ab19c8dd400339453ae..f457a7425db4fc60b12fccc56aaa9e7996fdbb89 100644 --- a/resources/static/dialog/test/qunit/pages/add_email_address_test.js +++ b/resources/static/dialog/test/qunit/pages/add_email_address_test.js @@ -64,8 +64,8 @@ steal.plugins("jquery").then("/dialog/test/qunit/mocks/xhr", "/dialog/resources/ setTimeout(function() { equal($("#email").text(), "testuser@testuser.com", "email set"); - ok($("#siteinfo").is(":visible"), "siteinfo is visible when we say what it is"); - equal($("#siteinfo .website").text(), "browserid.org", "origin is updated"); + ok($(".siteinfo").is(":visible"), "siteinfo is visible when we say what it is"); + equal($(".website").text(), "browserid.org", "origin is updated"); start(); }, 500); stop(); @@ -76,8 +76,8 @@ steal.plugins("jquery").then("/dialog/test/qunit/mocks/xhr", "/dialog/resources/ setTimeout(function() { equal($("#email").text(), "testuser@testuser.com", "email set"); - equal($("#siteinfo").is(":visible"), false, "siteinfo is not visible without having it"); - equal($("#siteinfo .website").text(), "", "origin is not updated"); + equal($(".siteinfo").is(":visible"), false, "siteinfo is not visible without having it"); + equal($(".siteinfo .website").text(), "", "origin is not updated"); start(); }, 500); stop(); @@ -105,14 +105,4 @@ steal.plugins("jquery").then("/dialog/test/qunit/mocks/xhr", "/dialog/resources/ stop(); }); - test("addEmailAddress with completeEmailRegistration XHR failure", function() { - xhr.useResult("ajaxError"); - bid.addEmailAddress("token"); - - setTimeout(function() { - ok($("#cannotcommunicate").is(":visible"), "cannot communicate box is visible"); - start(); - }, 500); - stop(); - }); }); diff --git a/resources/static/dialog/test/qunit/pages/verify_email_address_test.js b/resources/static/dialog/test/qunit/pages/verify_email_address_test.js new file mode 100644 index 0000000000000000000000000000000000000000..306540fbd8a5ccb37050543520c9a1bc26430049 --- /dev/null +++ b/resources/static/dialog/test/qunit/pages/verify_email_address_test.js @@ -0,0 +1,174 @@ +/*jshint browsers:true, forin: true, laxbreak: true */ +/*global steal: true, test: true, start: true, stop: true, module: true, ok: true, equal: true, BrowserID:true */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla BrowserID. + * + * The Initial Developer of the Original Code is Mozilla. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +steal.plugins("jquery").then("/dialog/test/qunit/mocks/xhr", "/dialog/resources/network", "/js/pages/verify_email_address", function() { + "use strict"; + + var bid = BrowserID, + network = bid.Network, + storage = bid.Storage, + xhr = bid.Mocks.xhr, + validToken = true; + + module("pages/verify_email_address", { + setup: function() { + network.setXHR(xhr); + xhr.useResult("valid"); + $(".error").stop().hide(); + $(".website").text(""); + }, + teardown: function() { + network.setXHR($); + $(".error").stop().hide(); + $(".website").text(""); + } + }); + + test("verifyEmailAddress with good token and site", function() { + storage.setStagedOnBehalfOf("browserid.org"); + + bid.verifyEmailAddress("token"); + + setTimeout(function() { + equal($("#email").val(), "testuser@testuser.com", "email set"); + ok($(".siteinfo").is(":visible"), "siteinfo is visible when we say what it is"); + equal($(".website").text(), "browserid.org", "origin is updated"); + start(); + }, 500); + stop(); + }); + + test("verifyEmailAddress with good token and nosite", function() { + $(".siteinfo").hide(); + storage.setStagedOnBehalfOf(""); + + bid.verifyEmailAddress("token"); + + + setTimeout(function() { + equal($("#email").val(), "testuser@testuser.com", "email set"); + equal($(".siteinfo").is(":visible"), false, "siteinfo is not visible without having it"); + equal($(".siteinfo .website").text(), "", "origin is not updated"); + start(); + }, 500); + stop(); + }); + + test("verifyEmailAddress with bad token", function() { + xhr.useResult("invalid"); + + bid.verifyEmailAddress("token"); + setTimeout(function() { + ok($("#cannotconfirm").is(":visible"), "cannot confirm box is visible"); + start(); + }, 500); + stop(); + }); + + test("verifyEmailAddress with emailForVerficationToken XHR failure", function() { + xhr.useResult("ajaxError"); + bid.verifyEmailAddress("token"); + + setTimeout(function() { + ok($("#cannotcommunicate").is(":visible"), "cannot communicate box is visible"); + start(); + }, 500); + stop(); + }); + + test("submit with good token, both passwords", function() { + bid.verifyEmailAddress("token"); + + + $("#password").val("password"); + $("#vpassword").val("password"); + + bid.verifyEmailAddress.submit(); + + setTimeout(function() { + equal($("#congrats").is(":visible"), true, "congrats is visible, we are complete"); + start(); + }, 500); + stop(); + }); + + test("submit with good token, missing password", function() { + bid.verifyEmailAddress("token"); + + + $("#password").val(""); + $("#vpassword").val("password"); + + bid.verifyEmailAddress.submit(); + + setTimeout(function() { + equal($("#congrats").is(":visible"), false, "congrats is not visible, missing password"); + start(); + }, 500); + stop(); + }); + + test("submit with good token, missing verification password", function() { + bid.verifyEmailAddress("token"); + + + $("#password").val("password"); + $("#vpassword").val(""); + + bid.verifyEmailAddress.submit(); + + setTimeout(function() { + equal($("#congrats").is(":visible"), false, "congrats is not visible, missing verification password"); + start(); + }, 500); + stop(); + }); + + test("submit with good token, different passwords", function() { + bid.verifyEmailAddress("token"); + + $("#password").val("password"); + $("#vpassword").val("pass"); + + bid.verifyEmailAddress.submit(); + + setTimeout(function() { + equal($("#congrats").is(":visible"), false, "congrats is not visible, different passwords"); + start(); + }, 500); + stop(); + }); +}); diff --git a/resources/static/dialog/test/qunit/qunit.js b/resources/static/dialog/test/qunit/qunit.js index 414860785aafa74b1a0bd39c40630e57ed9fb2d4..a0eb186337863c4843cd0c773c69f2ab92408082 100644 --- a/resources/static/dialog/test/qunit/qunit.js +++ b/resources/static/dialog/test/qunit/qunit.js @@ -24,6 +24,7 @@ steal("/dialog/resources/browserid.js", .then("include_unit_test") .then("relay/relay_unit_test") .then("pages/add_email_address_test") + .then("pages/verify_email_address_test") .then("pages/forgot_unit_test") .then("resources/tooltip_unit_test") .then("resources/channel_unit_test") diff --git a/resources/static/dialog/test/qunit/resources/validation_unit_test.js b/resources/static/dialog/test/qunit/resources/validation_unit_test.js index 37925f8174bb184647f14f600f12e729707fe60c..7b7c532a331a55f06f09522d5a9d07dbc098a463 100644 --- a/resources/static/dialog/test/qunit/resources/validation_unit_test.js +++ b/resources/static/dialog/test/qunit/resources/validation_unit_test.js @@ -112,8 +112,15 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid", fu test("email with Capital Letters in domain side", function() { var valid = validation.email("x@Y.z"); - equal(valid, false, "capital letters not allowed in domain side"); - equal(tooltipShown, true, "missing email shows no tooltip"); + equal(valid, true, "capital letters are allowed in domain side"); + equal(tooltipShown, false, "capital letters in domain side causes no tooltip"); + }); + + test("email with numbers in domain side", function() { + var valid = validation.email("x@0.Z"); + + equal(valid, true, "numbers are allowed in domain side"); + equal(tooltipShown, false, "numbers in domain side causes no tooltip"); }); diff --git a/resources/static/js/pages/add_email_address.js b/resources/static/js/pages/add_email_address.js index 58b4198f68713ab968032690e692679406b54f1e..0faff6d6cb66ffae21e5d0429bf20aae7d9aff86 100644 --- a/resources/static/js/pages/add_email_address.js +++ b/resources/static/js/pages/add_email_address.js @@ -43,8 +43,8 @@ $("#email").text(info.email); if (info.origin) { - $("#siteinfo .website").html(info.origin); - $("#siteinfo").show(); + $(".website").html(info.origin); + $(".siteinfo").show(); } $("#signUpForm").delay(2000).fadeOut(ANIMATION_TIME, function() { diff --git a/resources/static/js/pages/verify_email_address.js b/resources/static/js/pages/verify_email_address.js index 6c97f534739ff52494eaab9f051991526c3891ac..5d3002a606d8d05e6fa05e7a7236e47f60c76344 100644 --- a/resources/static/js/pages/verify_email_address.js +++ b/resources/static/js/pages/verify_email_address.js @@ -1,4 +1,4 @@ -/*globals BrowserID:true, $:true */ +/*globals BrowserID: true, $:true */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -37,43 +37,47 @@ (function() { "use strict"; - var bid = BrowserID; + var bid = BrowserID, + token; function showError(el) { $(el).fadeIn(250); $("#signUpForm").remove(); } - bid.verifyEmailAddress = function(token) { - $("#signUpForm").submit(function(event) { - event.preventDefault(); + function submit(event) { + if (event) event.preventDefault(); - var pass = $("#password").val(), - vpass = $("#vpassword").val(); + var pass = $("#password").val(), + vpass = $("#vpassword").val(); - var valid = bid.Validation.passwordAndValidationPassword(pass, vpass); + var valid = bid.Validation.passwordAndValidationPassword(pass, vpass); - if (valid) { - bid.Network.completeUserRegistration(token, pass, function onSuccess(registered) { - if (registered) { - $("#signUpForm").hide(); - $("#congrats").fadeIn(250); - } - else { - showError("#cannotcomplete"); - } - }, function onFailure() { - showError("#cannotconnect"); - }); - } - }); + if (valid) { + bid.Network.completeUserRegistration(token, pass, function onSuccess(registered) { + if (registered) { + $("#signUpForm").hide(); + $("#congrats").fadeIn(250); + } + else { + showError("#cannotcomplete"); + } + }, function onFailure() { + showError("#cannotcommunicate"); + }); + } + } + + function init(tok) { + $("#signUpForm").bind("submit", submit); + $(".siteinfo").hide(); + $("#congrats").hide(); + token = tok; var staged = bid.Storage.getStagedOnBehalfOf(); if (staged) { $('.website').html(staged); - } - else { - $('.hint').hide(); + $('.siteinfo').show(); } // go get the email address @@ -82,9 +86,20 @@ $('#email').val(email); } else { - showError("#badtoken"); + showError("#cannotconfirm"); } + }, function() { + showError("#cannotcommunicate"); }); + } + + function reset() { + $("#signUpForm").unbind("submit", submit); + } + + init.submit = submit; + init.reset = reset; + + bid.verifyEmailAddress = init; - }; }()); diff --git a/resources/views/signin.ejs b/resources/views/signin.ejs index 9c4a90874ac5ec267182e9152746cf911e3ed1be..b4623d8ebb13156d9855ad81d15b0bbd93a381c0 100644 --- a/resources/views/signin.ejs +++ b/resources/views/signin.ejs @@ -36,12 +36,12 @@ </ul> <div class="submit cf"> - <div class="remember cf"> + <!--div class="remember cf"> <div class="checkAlign"> <input id="memorize" type="checkbox" tabindex="3"> </div> <label for="memorize">remember me</label> - </div> + </div--> <input type="submit" class="create" value="Sign In" tabindex="5"/> </div> </form> diff --git a/resources/views/verifyemail.ejs b/resources/views/verifyemail.ejs index d9ee49385494c4069cba00874bbe0023e661a419..ffaf2540dfe3fb18e1bb66fa1ef96b2ce706c198 100644 --- a/resources/views/verifyemail.ejs +++ b/resources/views/verifyemail.ejs @@ -4,8 +4,9 @@ <h1 class="serif">Email Verification</h1> <ul class="notifications"> - <li class="notification error" id="cannotconnect">Error comunicating with server.</li> + <li class="notification error" id="cannotcommunicate">Error comunicating with server.</li> <li class="notification error" id="cannotconfirm">Error encountered while attempting to confirm your address. Have you previously verified this address?</li> + <li class="notification error" id="cannotcomplete">Error encountered trying to complete registration.</li> </ul> <p class="hint">One moment while we attempt to confirm your email address...</p> @@ -16,11 +17,11 @@ <p class="serif"> <strong id="email">Your address</strong> has been verified! - <span id="siteinfo"> + <p class="siteinfo"> Your new address is set up and you should now be signed in. You may now close this window and go back to <strong class="website"></strong> - </span> + </p> </p> </div> </div> diff --git a/resources/views/verifyuser.ejs b/resources/views/verifyuser.ejs index b173f3580063d842a085e950083669dabf57a4d5..dbc34d5011f9614afa7edeb5a5e99334a12a309d 100644 --- a/resources/views/verifyuser.ejs +++ b/resources/views/verifyuser.ejs @@ -1,13 +1,13 @@ <div id="vAlign" class="display_always"> <div id="signUpFormWrap"> <ul class="notifications"> - <li class="notification error" id="badtoken">There was a problem with your signup link. Has this address already been registered?</li> - <li class="notification error" id="cannotconnect">Error comunicating with server.</li> + <li class="notification error" id="cannotconfirm">There was a problem with your signup link. Has this address already been registered?</li> + <li class="notification error" id="cannotcommunicate">Error comunicating with server.</li> <li class="notification error" id="cannotcomplete">Error encountered trying to complete registration.</li> </ul> <form id="signUpForm" class="cf"> - <p class="hint">Finish signing into: <strong><span class="website"></span></strong></p> + <p class="hint siteinfo">Finish signing into: <strong><span class="website"></span></strong></p> <h1 class="serif">Last step!</h1> @@ -49,7 +49,14 @@ </form> <div id="congrats"> - <p class="serif">Thank you for signing up with <strong>BrowserID</strong>. You can now use your <strong>BrowserID</strong> account to <em>Sign In</em> or <em>Sign Up</em> to websites all across the web!</p> + <p class="serif">Thank you for signing up with <strong>BrowserID</strong>. You can now use your <strong>BrowserID</strong> account to <em>Sign In</em> or <em>Sign Up</em> to websites all across the web! + </p> + + <p class="serif siteinfo"> + Your new address is set up and you should now be signed in. + You may now close this window and go back to + <strong class="website"></strong> + </p> </div> </div>