diff --git a/resources/static/css/style.css b/resources/static/css/style.css index 35bfa524ab66efd353488ddd596061022bb3fc77..94aac066d5eea89dbaef6c4d9df944a96b34ffaa 100644 --- a/resources/static/css/style.css +++ b/resources/static/css/style.css @@ -515,30 +515,10 @@ button.delete:active { padding: 0; } -#signUpForm .red { - color: red; -} - #signUpForm .submit { height: 28px; } -#signUpForm .error { - margin-top: 20px; - color: red; - background-color: rgba(255,0,0,0.25); - -ms-filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#3fff0000,endColorstr=#3fff0000); - filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#3fff0000,endColorstr=#3fff0000); - zoom: 1; - padding: 5px; - line-height: 16px; - - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - -o-border-radius: 3px; - border-radius: 3px; -} - #signUpForm > .siteinfo { margin-bottom: 10px; } diff --git a/resources/static/dialog/views/error.ejs b/resources/static/dialog/views/error.ejs index 0b35cd680dc17fcb47e25adc6284ae7cce111b46..2a0ee0066700746b6c73e31818f4353ee1156976 100644 --- a/resources/static/dialog/views/error.ejs +++ b/resources/static/dialog/views/error.ejs @@ -14,6 +14,10 @@ <%= gettext("Persona requires cookies") %> </h2> <%= format(gettext("Please close this window, <a %s>enable cookies</a> and try again"), [" target='_blank' href='http://support.mozilla.org/en-US/kb/Websites%20say%20cookies%20are%20blocked'"]) %> + <% } else if(typeof title === "string") { %> + <h2> + <span class="emphasis"><%= title %></span> + </h2> <% } else { %> <h2 id="defaultError"> <%= gettext("We are very sorry.") %><span class="emphasis"> <%= gettext("There has been an error!") %></span> diff --git a/resources/static/pages/verify_secondary_address.js b/resources/static/pages/verify_secondary_address.js index df4561ec37b6707e3401afafd4f7c07225ba283a..5b2f7f20051e8bd9c3ce71c181ac75c2cc6c4c69 100644 --- a/resources/static/pages/verify_secondary_address.js +++ b/resources/static/pages/verify_secondary_address.js @@ -19,7 +19,6 @@ BrowserID.verifySecondaryAddress = (function() { tooltip = bid.Tooltip, token, sc, - needsPassword, mustAuth, verifyFunction, doc = document, @@ -29,11 +28,6 @@ BrowserID.verifySecondaryAddress = (function() { redirectTo, redirectTimeout; // set in config if available, use REDIRECT_SECONDS otw. - function showError(el, oncomplete) { - dom.hide(".hint,#signUpForm"); - $(el).fadeIn(ANIMATION_TIME, oncomplete); - } - function showRegistrationInfo(info) { dom.setInner("#email", info.email); @@ -55,38 +49,37 @@ BrowserID.verifySecondaryAddress = (function() { function submit(oncomplete) { var pass = dom.getInner("#password") || undefined, - vpass = dom.getInner("#vpassword") || undefined, - inputValid = (!needsPassword || - validation.passwordAndValidationPassword(pass, vpass)) - && (!mustAuth || - validation.password(pass)); + inputValid = !mustAuth || validation.password(pass); if (inputValid) { user[verifyFunction](token, pass, function(info) { dom.addClass("body", "complete"); - var verified = info.valid, - selector = verified ? "#congrats" : "#cannotcomplete"; - - pageHelpers.replaceFormWithNotice(selector, function() { - if (redirectTo && verified) { - - // set the loggedIn status for the site. This allows us to get - // a silent assertion without relying on the dialog to set the - // loggedIn status for the domain. This is useful when the user - // closes the dialog OR if redirection happens before the dialog - // has had a chance to finish its business. - storage.setLoggedIn(URLParse(redirectTo).originOnly(), email); - - setTimeout(function() { - doc.location.href = redirectTo; + var verified = info.valid; + + if (verified) { + pageHelpers.replaceFormWithNotice("#congrats", function() { + if (redirectTo) { + // set the loggedIn status for the site. This allows us to get + // a silent assertion without relying on the dialog to set the + // loggedIn status for the domain. This is useful when the user + // closes the dialog OR if redirection happens before the dialog + // has had a chance to finish its business. + storage.setLoggedIn(URLParse(redirectTo).originOnly(), email); + + setTimeout(function() { + doc.location.href = redirectTo; + complete(oncomplete, verified); + }, redirectTimeout); + } + else { complete(oncomplete, verified); - }, redirectTimeout); - } - else { - complete(oncomplete, verified); - } - }); + } + }); + } + else { + pageHelpers.showFailure(errors.cannotComplete, info, oncomplete); + } }, function(info) { if (info.network && info.network.status === 401) { tooltip.showTooltip("#cannot_authenticate"); @@ -103,36 +96,30 @@ BrowserID.verifySecondaryAddress = (function() { } function startVerification(oncomplete) { + var self=this; user.tokenInfo(token, function(info) { if (info) { redirectTo = info.returnTo; email = info.email; showRegistrationInfo(info); - needsPassword = info.needs_password; mustAuth = info.must_auth; - - if (needsPassword) { - // This is a fix for legacy users who started the user creation - // process without setting their password in the dialog. If the user - // needs a password, they must set it now. Once all legacy users are - // verified or their links invalidated, this flow can be removed. - dom.addClass("body", "enter_password"); - dom.addClass("body", "enter_verify_password"); - complete(oncomplete, true); - } - else if (mustAuth) { - // These are users who have set their passwords inside of the dialog. + if (mustAuth) { + // These are users who are authenticating in a different browser or + // session than the initiator. dom.addClass("body", "enter_password"); complete(oncomplete, true); } else { - // These are users who do not have to set their passwords at all. + // Easy case where user is in same browser and same session, just + // verify and be done with it all! submit(oncomplete); } } else { - showError("#cannotconfirm"); + // renderError is used directly instead of pageHelpers.showFailure + // because showFailure hides the title in the extended info. + self.renderError("error", errors.cannotConfirm); complete(oncomplete, false); } }, pageHelpers.getFailure(errors.getTokenInfo, oncomplete)); @@ -140,7 +127,8 @@ BrowserID.verifySecondaryAddress = (function() { var Module = bid.Modules.PageModule.extend({ start: function(options) { - this.checkRequired(options, "token", "verifyFunction"); + var self=this; + self.checkRequired(options, "token", "verifyFunction"); token = options.token; verifyFunction = options.verifyFunction; @@ -151,9 +139,9 @@ BrowserID.verifySecondaryAddress = (function() { redirectTimeout = REDIRECT_SECONDS * 1000; } - startVerification(options.ready); + startVerification.call(self, options.ready); - sc.start.call(this, options); + sc.start.call(self, options); }, submit: submit diff --git a/resources/static/shared/error-messages.js b/resources/static/shared/error-messages.js index 2ce74cfde884cc3adb5a4103cd12e30794f5be89..5b3530452890c3d112c358fdc92164a68bda9e85 100644 --- a/resources/static/shared/error-messages.js +++ b/resources/static/shared/error-messages.js @@ -35,6 +35,14 @@ BrowserID.Errors = (function(){ title: "Cancelling User Account" }, + cannotConfirm: { + title: gettext("There was a problem with your signup link. Has this address already been registered?") + }, + + cannotComplete: { + title: gettext("Error encountered trying to complete registration.") + }, + checkAuthentication: { title: "Checking Authentication" }, diff --git a/resources/static/test/cases/pages/verify_secondary_address.js b/resources/static/test/cases/pages/verify_secondary_address.js index 0d74afe90af7dc39c853bc3f8860a11adfbac517..538915443b4307122f9bc12d21bd78327c276492 100644 --- a/resources/static/test/cases/pages/verify_secondary_address.js +++ b/resources/static/test/cases/pages/verify_secondary_address.js @@ -13,6 +13,7 @@ dom = bid.DOM, testHelpers = bid.TestHelpers, testHasClass = testHelpers.testHasClass, + testVisible = testHelpers.testVisible, validToken = true, controller, config = { @@ -56,7 +57,7 @@ } function testCannotConfirm() { - ok($("#cannotconfirm").is(":visible"), "cannot confirm box is visible"); + testHelpers.testErrorVisible(); } test("start with missing token", function() { @@ -70,22 +71,21 @@ equal(error, "missing config option: token", "correct error thrown"); }); - asyncTest("no password: start with good token and site", function() { + asyncTest("valid token, no password necessary - verify user and show site info", function() { var returnTo = "https://test.domain/path"; storage.setReturnTo(returnTo); createController(config, function() { - testEmail(); - ok($(".siteinfo").is(":visible"), "siteinfo is visible when we say what it is"); - equal($(".website:nth(0)").text(), returnTo, "website is updated"); + testVisible("#congrats"); testHasClass("body", "complete"); + equal($("#congrats .website").text(), returnTo, "website is updated"); equal(doc.location.href, returnTo, "redirection occurred to correct URL"); equal(storage.getLoggedIn("https://test.domain"), "testuser@testuser.com", "logged in status set"); start(); }); }); - asyncTest("no password: start with good token and nosite", function() { + asyncTest("valid token, no password necessary, no saved site info - verify user but do not show site info", function() { createController(config, function() { testEmail(); equal($(".siteinfo").is(":visible"), false, "siteinfo is not visible without having it"); @@ -94,7 +94,7 @@ }); }); - asyncTest("no password: start with bad token", function() { + asyncTest("invalid token - show cannot confirm error", function() { xhr.useResult("invalid"); createController(config, function() { @@ -103,7 +103,7 @@ }); }); - asyncTest("no password: start with emailForVerficationToken XHR failure", function() { + asyncTest("valid token with xhr error - show error screen", function() { xhr.useResult("ajaxError"); createController(config, function() { testHelpers.testErrorVisible(); @@ -156,88 +156,4 @@ }); }); - asyncTest("must set password, successful login", function() { - xhr.useResult("needsPassword"); - createController(config, function() { - xhr.useResult("valid"); - - $("#password").val("password"); - $("#vpassword").val("password"); - - testHasClass("body", "enter_password"); - testHasClass("body", "enter_verify_password"); - - controller.submit(function(status) { - equal(status, true, "correct status"); - testHasClass("body", "complete"); - start(); - }); - }); - }); - - asyncTest("must set password, too short a password", function() { - xhr.useResult("needsPassword"); - createController(config, function() { - xhr.useResult("valid"); - - $("#password").val("pass"); - $("#vpassword").val("pass"); - - controller.submit(function(status) { - equal(status, false, "correct status"); - testHelpers.testTooltipVisible(); - start(); - }); - }); - }); - - asyncTest("must set password, too long a password", function() { - xhr.useResult("needsPassword"); - createController(config, function() { - xhr.useResult("valid"); - - var pass = testHelpers.generateString(81); - $("#password").val(pass); - $("#vpassword").val(pass); - - controller.submit(function(status) { - equal(status, false, "correct status"); - testHelpers.testTooltipVisible(); - start(); - }); - }); - }); - - asyncTest("must set password, missing verification password", function() { - xhr.useResult("needsPassword"); - createController(config, function() { - xhr.useResult("valid"); - - $("#password").val("password"); - $("#vpassword").val(""); - - controller.submit(function(status) { - equal(status, false, "correct status"); - testHelpers.testTooltipVisible(); - start(); - }); - }); - }); - - asyncTest("must set password, mismatched passwords", function() { - xhr.useResult("needsPassword"); - createController(config, function() { - xhr.useResult("valid"); - - $("#password").val("password"); - $("#vpassword").val("password1"); - - controller.submit(function(status) { - equal(status, false, "correct status"); - testHelpers.testTooltipVisible(); - start(); - }); - }); - }); - }()); diff --git a/resources/static/test/testHelpers/helpers.js b/resources/static/test/testHelpers/helpers.js index 0a7130ef5fc565d31ee50761f104cad7d28043d2..ed90066d39a1fdf4438117acbea6bcf7ce7f2823 100644 --- a/resources/static/test/testHelpers/helpers.js +++ b/resources/static/test/testHelpers/helpers.js @@ -221,8 +221,7 @@ BrowserID.TestHelpers = (function() { }, testHasClass: function(selector, className, msg) { - ok($(selector).hasClass(className), - selector + " has className " + className + " - " + msg); + ok($(selector).hasClass(className), msg || selector + " has className: " + className); }, testUndefined: function(toTest, msg) { @@ -231,6 +230,10 @@ BrowserID.TestHelpers = (function() { testNotUndefined: function(toTest, msg) { notEqual(typeof toTest, "undefined", msg || "object is defined"); + }, + + testVisible: function(selector, msg) { + ok($(selector).is(":visible"), msg || selector + " should be visible"); } }; diff --git a/resources/views/add_email_address.ejs b/resources/views/add_email_address.ejs index 9a4128aeee67fac5702ae45de569cd952d41fe4a..f56a6caf70bff61116465caf50941f13d20b2bec 100644 --- a/resources/views/add_email_address.ejs +++ b/resources/views/add_email_address.ejs @@ -2,15 +2,12 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -<div id="hAlign" class="display_always"> +<div id="hAlign"> <div id="vAlign"> - <ul class="notifications"> - <li class="notification error" id="cannotconfirm"><%= gettext('Error encountered while attempting to confirm your address. Have you previously verified this address?') %></li> - <li class="notification error" id="cannotcomplete"><%= gettext('Error encountered trying to complete registration.') %></li> - </ul> - - <form id="signUpForm" class="cf"> - <p class="hint siteinfo"><%= gettext('Finish signing into:') %> <strong><span class="website"></span></strong></p> + <form id="signUpForm" class="cf password_entry"> + <p class="hint siteinfo"> + <%= gettext('Finish signing into:') %> <strong class="website"></strong> + </p> <h1><%= gettext('Email Verification') %></h1> @@ -19,7 +16,8 @@ <label for="email"><%= gettext('Email Address') %></label> <input class="youraddress" id="email" placeholder="<%= gettext('Your Email') %>" type="email" value="" disabled="disabled" maxlength="254" /> </li> - <li class="password_entry"> + + <li> <label for="password"><%= gettext('Password') %></label> <input id="password" placeholder="<%= gettext('Your Password') %>" type="password" autofocus maxlength=80 /> @@ -27,35 +25,16 @@ <%= gettext('Password is required.') %> </div> - <div class="tooltip" id="password_length" for="password"> - <%= gettext('Password must be between 8 and 80 characters long.') %> - </div> - <div id="cannot_authenticate" class="tooltip" for="password"> <%= gettext('The account cannot be verified with this username and password.') %> </div> </li> - - <li class="password_entry" id="verify_password"> - <label for="vpassword"><%= gettext('Verify Password') %></label> - <input id="vpassword" placeholder="<%= gettext('Repeat Password') %>" type="password" maxlength="80"> - - <div id="vpassword_required" class="tooltip" for="vpassword"> - <%= gettext('Verification password is required.') %> - </div> - - <div class="tooltip" id="passwords_no_match" for="vpassword"> - <%= gettext ('Passwords do not match.') %> - </div> - - </li> </ul> <div class="submit cf password_entry"> <button><%= gettext('finish') %></button> </div> - </form> <div id="congrats"> diff --git a/resources/views/verify_email_address.ejs b/resources/views/verify_email_address.ejs index d033b9417e2b39158d875138bb6ec24aca1a0286..118c70df793807bfb6586e04eb955624061bbe5a 100644 --- a/resources/views/verify_email_address.ejs +++ b/resources/views/verify_email_address.ejs @@ -2,15 +2,13 @@ License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ %> -<div id="hAlign" class="display_always"> +<div id="hAlign"> <div id="vAlign"> - <ul class="notifications"> - <li class="notification error" id="cannotconfirm"><%= gettext('There was a problem with your signup link. Has this address already been registered?') %></li> - <li class="notification error" id="cannotcomplete"><%= gettext('Error encountered trying to complete registration.') %></li> - </ul> + <form id="signUpForm" class="cf password_entry"> + <p class="hint siteinfo"> + <%= gettext('Finish signing into:') %> <strong class="website"></strong> + </p> - <form id="signUpForm" class="cf"> - <p class="hint siteinfo"><%= gettext('Finish signing into:') %> <strong><span class="website"></span></strong></p> <h1><%= gettext('Last step!') %></h1> <ul class="inputs"> @@ -19,7 +17,7 @@ <input class="youraddress" id="email" placeholder="<%= gettext('Your Email') %>" type="email" value="" disabled="disabled" maxlength="254" /> </li> - <li class="password_entry"> + <li> <label for="password"><%= gettext('Password') %></label> <input id="password" placeholder="<%= gettext('Your Password') %>" type="password" autofocus maxlength=80 /> @@ -27,28 +25,10 @@ <%= gettext('Password is required.') %> </div> - <div class="tooltip" id="password_length" for="password"> - <%= gettext('Password must be between 8 and 80 characters long.') %> - </div> - <div id="cannot_authenticate" class="tooltip" for="password"> <%= gettext('The account cannot be verified with this username and password.') %> </div> </li> - - <li class="password_entry" id="verify_password"> - <label for="vpassword"><%= gettext('Verify Password') %></label> - <input id="vpassword" placeholder="<%= gettext('Repeat Password') %>" type="password" maxlength="80"> - - <div id="vpassword_required" class="tooltip" for="vpassword"> - <%= gettext('Verification password is required.') %> - </div> - - <div class="tooltip" id="passwords_no_match" for="vpassword"> - <%= gettext ('Passwords do not match.') %> - </div> - - </li> </ul> <div class="submit cf password_entry">