diff --git a/resources/static/dialog/controllers/actions.js b/resources/static/dialog/controllers/actions.js index 98876183fcb6e4bb5499ac3986c1dbe1c32ae3f5..315b787cf5b8dc12d0b45261ed2b353ab339bc57 100644 --- a/resources/static/dialog/controllers/actions.js +++ b/resources/static/dialog/controllers/actions.js @@ -11,7 +11,7 @@ BrowserID.Modules.Actions = (function() { serviceManager = bid.module, user = bid.User, errors = bid.Errors, - wait = bid.Wait, + dialogHelpers = bid.Helpers.Dialog, runningService, onsuccess, onerror; @@ -113,12 +113,15 @@ BrowserID.Modules.Actions = (function() { }, self.getErrorDialog(errors.getAssertion)); }, - doAssertionGenerated: function(o) { + doAssertionGenerated: function(info) { // Clear onerror before the call to onsuccess - the code to onsuccess // calls window.close, which would trigger the onerror callback if we // tried this afterwards. - onerror = null; - if(onsuccess) onsuccess(o); + this.hideWait(); + dialogHelpers.animateClose(function() { + onerror = null; + if(onsuccess) onsuccess(info); + }); }, doNotMe: function() { diff --git a/resources/static/dialog/controllers/email_chosen.js b/resources/static/dialog/controllers/email_chosen.js index eee13a6f1590c02457639dbe5aeb198951898b16..8ce4747938702165bd391cb447fbc4176fa9e3fa 100644 --- a/resources/static/dialog/controllers/email_chosen.js +++ b/resources/static/dialog/controllers/email_chosen.js @@ -22,6 +22,7 @@ BrowserID.Modules.EmailChosen = (function() { } dialogHelpers.getAssertion.call(self, email, options.ready); + // TODO, this is not needed here, it is done in the state machine. storage.setLoggedIn(user.getOrigin(), options.email); sc.start.call(self, options); } diff --git a/resources/static/dialog/resources/helpers.js b/resources/static/dialog/resources/helpers.js index 50db742a114d042af9e667e4ecd9329e7fe1beb0..12029173c581474065a9f0cf4a895003673930cf 100644 --- a/resources/static/dialog/resources/helpers.js +++ b/resources/static/dialog/resources/helpers.js @@ -39,13 +39,11 @@ user.getAssertion(email, user.getOrigin(), function(assert) { assert = assert || null; wait.hide(); - animateClose(function() { - self.close("assertion_generated", { - assertion: assert - }); - - complete(callback, assert); + self.close("assertion_generated", { + assertion: assert }); + + complete(callback, assert); }, self.getErrorDialog(errors.getAssertion, complete)); } @@ -129,7 +127,8 @@ createUser: createUser, addEmail: addEmail, resetPassword: resetPassword, - cancelEvent: helpers.cancelEvent + cancelEvent: helpers.cancelEvent, + animateClose: animateClose }); }()); diff --git a/resources/static/dialog/resources/state.js b/resources/static/dialog/resources/state.js index 7a3e7d1d5915c195b0beada7fa180271985cde87..6dfa32485ce929e54ebfe992a0efdc95b4b0af00 100644 --- a/resources/static/dialog/resources/state.js +++ b/resources/static/dialog/resources/state.js @@ -84,11 +84,6 @@ BrowserID.State = (function() { } }); - handleState("is_this_your_computer", function(msg, info) { - startAction("doIsThisYourComputer", info); - }); - - handleState("authenticate", function(msg, info) { info = info || {}; info.privacyURL = self.privacyURL; @@ -198,16 +193,15 @@ BrowserID.State = (function() { // If the email is a primary, and their cert is not available, // throw the user down the primary flow. // Doing so will catch cases where the primary certificate is expired - // and the user must re-verify with their IdP. This flow will - // generate its own assertion when ready. + // and the user must re-verify with their IdP. redirectToState("primary_user", info); } } else { user.checkAuthentication(function(authentication) { if(authentication === "assertion") { - // user not authenticated, kick them over to the required email - // screen. + // user must authenticate with their password, kick them over to + // the required email screen to enter the password. startAction("doAuthenticateWithRequiredEmail", { email: email, secondary_auth: true, @@ -255,8 +249,8 @@ BrowserID.State = (function() { if (info.assertion !== null) { if (storage.usersComputer.shouldAsk(network.userid())) { // We have to confirm the user's status - redirectToState("is_this_your_computer", info); self.assertion_info = info; + redirectToState("is_this_your_computer", info); } else { storage.setLoggedIn(user.getOrigin(), self.email); @@ -268,6 +262,10 @@ BrowserID.State = (function() { } }); + handleState("is_this_your_computer", function(msg, info) { + startAction("doIsThisYourComputer", info); + }); + handleState("user_computer_status_set", function(msg, info) { // User's status has been confirmed, redirect them back to the // assertion_generated state with the stored assertion_info diff --git a/resources/static/test/cases/resources/state.js b/resources/static/test/cases/resources/state.js index 662de2576959644cacdeba517500c63621620c68..89594ef82af053fd95f83952296c288c90c22cd8 100644 --- a/resources/static/test/cases/resources/state.js +++ b/resources/static/test/cases/resources/state.js @@ -15,7 +15,8 @@ network = bid.Network, storage = bid.Storage, testHelpers = bid.TestHelpers, - xhr = bid.Mocks.xhr; + xhr = bid.Mocks.xhr, + TEST_EMAIL = "testuser@testuser.com"; var ActionsMock = function() { this.called = {}; @@ -79,15 +80,15 @@ test("user_staged - call doConfirmUser", function() { mediator.publish("user_staged", { - email: "testuser@testuser.com" + email: TEST_EMAIL }); - equal(actions.info.doConfirmUser.email, "testuser@testuser.com", "waiting for email confirmation for testuser@testuser.com"); + equal(actions.info.doConfirmUser.email, TEST_EMAIL, "waiting for email confirmation for testuser@testuser.com"); }); test("user_staged with required email - call doConfirmUser with required = true", function() { - mediator.publish("start", { requiredEmail: "testuser@testuser.com" }); - mediator.publish("user_staged", { email: "testuser@testuser.com" }); + mediator.publish("start", { requiredEmail: TEST_EMAIL }); + mediator.publish("user_staged", { email: TEST_EMAIL }); equal(actions.info.doConfirmUser.required, true, "doConfirmUser called with required flag"); }); @@ -99,31 +100,31 @@ }); test("email_staged - call doConfirmEmail", function() { - mediator.publish("email_staged", { email: "testuser@testuser.com" }); + mediator.publish("email_staged", { email: TEST_EMAIL }); equal(actions.info.doConfirmEmail.required, false, "doConfirmEmail called without required flag"); }); test("email_staged with required email - call doConfirmEmail with required = true", function() { - mediator.publish("start", { requiredEmail: "testuser@testuser.com" }); - mediator.publish("email_staged", { email: "testuser@testuser.com" }); + mediator.publish("start", { requiredEmail: TEST_EMAIL }); + mediator.publish("email_staged", { email: TEST_EMAIL }); equal(actions.info.doConfirmEmail.required, true, "doConfirmEmail called with required flag"); }); test("primary_user with already provisioned primary user - call doEmailChosen", function() { - storage.addEmail("testuser@testuser.com", { type: "primary", cert: "cert" }); - mediator.publish("primary_user", { email: "testuser@testuser.com" }); + storage.addEmail(TEST_EMAIL, { type: "primary", cert: "cert" }); + mediator.publish("primary_user", { email: TEST_EMAIL }); ok(actions.called.doEmailChosen, "doEmailChosen called"); }); test("primary_user with unprovisioned primary user - call doProvisionPrimaryUser", function() { - mediator.publish("primary_user", { email: "testuser@testuser.com" }); + mediator.publish("primary_user", { email: TEST_EMAIL }); ok(actions.called.doProvisionPrimaryUser, "doPrimaryUserProvisioned called"); }); test("primary_user_provisioned - call doEmailChosen", function() { - mediator.publish("primary_user_provisioned", { email: "testuser@testuser.com" }); + mediator.publish("primary_user_provisioned", { email: TEST_EMAIL }); ok(actions.called.doPrimaryUserProvisioned, "doPrimaryUserProvisioned called"); }); @@ -134,19 +135,19 @@ }); test("primary_user_unauthenticated after required email - call doCannotVerifyRequiredPrimary", function() { - mediator.publish("start", { requiredEmail: "testuser@testuser.com", type: "primary", add: false, email: "testuser@testuser.com" }); + mediator.publish("start", { requiredEmail: TEST_EMAIL, type: "primary", add: false, email: TEST_EMAIL }); mediator.publish("primary_user_unauthenticated"); ok(actions.called.doCannotVerifyRequiredPrimary, "doCannotVerifyRequiredPrimary called"); }); test("primary_user_unauthenticated after verification of new user - call doAuthenticate", function() { - mediator.publish("start", { email: "testuser@testuser.com", type: "primary", add: false }); + mediator.publish("start", { email: TEST_EMAIL, type: "primary", add: false }); mediator.publish("primary_user_unauthenticated"); ok(actions.called.doAuthenticate, "doAuthenticate called"); }); test("primary_user_unauthenticated after verification of additional email to current user - call doPickEmail and doAddEmail", function() { - mediator.publish("start", { email: "testuser@testuser.com", type: "primary", add: true }); + mediator.publish("start", { email: TEST_EMAIL, type: "primary", add: true }); mediator.publish("primary_user_unauthenticated"); ok(actions.called.doPickEmail, "doPickEmail called"); ok(actions.called.doAddEmail, "doAddEmail called"); @@ -163,46 +164,46 @@ }); test("primary_user - call doProvisionPrimaryUser", function() { - mediator.publish("primary_user", { email: "testuser@testuser.com", assertion: "assertion" }); + mediator.publish("primary_user", { email: TEST_EMAIL, assertion: "assertion" }); ok(actions.called.doProvisionPrimaryUser, "doProvisionPrimaryUser called"); }); asyncTest("primary_user_ready - redirect to `email_chosen`", function() { - storage.addEmail("testuser@testuser.com", {}); + storage.addEmail(TEST_EMAIL, {}); mediator.subscribe("email_chosen", function(msg, info) { - equal(info.email, "testuser@testuser.com", "correct email passed"); + equal(info.email, TEST_EMAIL, "correct email passed"); start(); }); - mediator.publish("primary_user_ready", { email: "testuser@testuser.com", assertion: "assertion" }); + mediator.publish("primary_user_ready", { email: TEST_EMAIL, assertion: "assertion" }); }); asyncTest("authenticated - redirect to `email_chosen`", function() { - storage.addEmail("testuser@testuser.com", {}); + storage.addEmail(TEST_EMAIL, {}); mediator.subscribe("email_chosen", function(msg, data) { - equal(data.email, "testuser@testuser.com"); + equal(data.email, TEST_EMAIL); start(); }); - mediator.publish("authenticated", { email: "testuser@testuser.com" }); + mediator.publish("authenticated", { email: TEST_EMAIL }); }); test("forgot_password", function() { mediator.publish("forgot_password", { - email: "testuser@testuser.com", + email: TEST_EMAIL, requiredEmail: true }); - equal(actions.info.doForgotPassword.email, "testuser@testuser.com", "correct email passed"); + equal(actions.info.doForgotPassword.email, TEST_EMAIL, "correct email passed"); equal(actions.info.doForgotPassword.requiredEmail, true, "correct requiredEmail passed"); }); test("reset_password - call doResetPassword", function() { // XXX how is this different from forgot_password? mediator.publish("reset_password", { - email: "testuser@testuser.com" + email: TEST_EMAIL }); - equal(actions.info.doResetPassword.email, "testuser@testuser.com", "reset password with the correct email"); + equal(actions.info.doResetPassword.email, TEST_EMAIL, "reset password with the correct email"); }); test("cancel reset_password flow - go two steps back", function() { @@ -210,11 +211,11 @@ // screens back. Do do this, we are simulating the steps necessary to get // to the reset_password flow. mediator.publish("authenticate"); - mediator.publish("forgot_password", undefined, { email: "testuser@testuser.com" }); + mediator.publish("forgot_password", undefined, { email: TEST_EMAIL }); mediator.publish("reset_password"); actions.info.doAuthenticate = {}; mediator.publish("cancel_state"); - equal(actions.info.doAuthenticate.email, "testuser@testuser.com", "authenticate called with the correct email"); + equal(actions.info.doAuthenticate.email, TEST_EMAIL, "authenticate called with the correct email"); }); asyncTest("assertion_generated with null assertion - redirect to pick_email", function() { @@ -243,11 +244,18 @@ test("assertion_generated with assertion, do not ask user whether it's their computer - doAssertionGenerated called", function() { setContextInfo("password"); + // First, set up the context info for the email. + + storage.addEmail(TEST_EMAIL, {}); + mediator.publish("email_chosen", { email: TEST_EMAIL }); mediator.publish("assertion_generated", { assertion: "assertion" }); - equal(actions.info.doAssertionGenerated, "assertion", "assertion generated with good assertion"); + equal(actions.info.doAssertionGenerated.assertion, "assertion", + "doAssertionGenerated called with assertion"); + equal(actions.info.doAssertionGenerated.email, TEST_EMAIL, + "doAssertionGenerated called with email"); }); test("email_confirmed", function() { @@ -274,10 +282,10 @@ test("authenticate", function() { mediator.publish("authenticate", { - email: "testuser@testuser.com" + email: TEST_EMAIL }); - equal(actions.info.doAuthenticate.email, "testuser@testuser.com", "authenticate with testuser@testuser.com"); + equal(actions.info.doAuthenticate.email, TEST_EMAIL, "authenticate with testuser@testuser.com"); }); test("start with no special parameters - go straight to checking auth", function() { @@ -303,19 +311,19 @@ }); test("start with valid requiredEmail - go to doCheckAuth", function() { - mediator.publish("start", { requiredEmail: "testuser@testuser.com" }); + mediator.publish("start", { requiredEmail: TEST_EMAIL }); equal(actions.called.doCheckAuth, true, "checking auth on start"); }); asyncTest("start to complete successful primary email verification - goto 'primary_user'", function() { mediator.subscribe("primary_user", function(msg, info) { - equal(info.email, "testuser@testuser.com", "correct email given"); + equal(info.email, TEST_EMAIL, "correct email given"); equal(info.add, true, "correct add flag"); start(); }); - mediator.publish("start", { email: "testuser@testuser.com", type: "primary", add: true }); + mediator.publish("start", { email: TEST_EMAIL, type: "primary", add: true }); }); test("cancel", function() { @@ -326,7 +334,7 @@ asyncTest("email_chosen with secondary email, user must authenticate - call doAuthenticateWithRequiredEmail", function() { - var email = "testuser@testuser.com"; + var email = TEST_EMAIL; storage.addEmail(email, { type: "secondary" }); xhr.setContextInfo("auth_level", "assertion"); @@ -341,7 +349,7 @@ }); asyncTest("email_chosen with secondary email, user authenticated to secondary - call doEmailChosen", function() { - var email = "testuser@testuser.com"; + var email = TEST_EMAIL; storage.addEmail(email, { type: "secondary" }); xhr.setContextInfo("auth_level", "password"); @@ -361,7 +369,7 @@ // generate its own assertion when ready. For efficiency, we could // check here whether the cert is ready, but it is early days yet and // the format may change. - var email = "testuser@testuser.com"; + var email = TEST_EMAIL; storage.addEmail(email, { type: "primary" }); mediator.publish("email_chosen", { email: email }); @@ -369,7 +377,7 @@ }); test("email_chosen with invalid email - throw exception", function() { - var email = "testuser@testuser.com", + var email = TEST_EMAIL, error; try { diff --git a/resources/static/test/mocks/xhr.js b/resources/static/test/mocks/xhr.js index 16c59dbcf5896e1e8427df3f36966be9ae3708ae..e33be1b0dfde34ddbf28f6dbdb0a896fb7a20e73 100644 --- a/resources/static/test/mocks/xhr.js +++ b/resources/static/test/mocks/xhr.js @@ -34,12 +34,12 @@ BrowserID.Mocks.xhr = (function() { "get /wsapi/email_for_token?token=token valid": { email: "testuser@testuser.com" }, "get /wsapi/email_for_token?token=token needsPassword": { email: "testuser@testuser.com", needs_password: true }, "get /wsapi/email_for_token?token=token invalid": { success: false }, - "post /wsapi/authenticate_user valid": { success: true }, + "post /wsapi/authenticate_user valid": { success: true, userid: 1 }, "post /wsapi/authenticate_user invalid": { success: false }, "post /wsapi/authenticate_user incorrectPassword": { success: false }, "post /wsapi/authenticate_user ajaxError": undefined, - "post /wsapi/auth_with_assertion primary": { success: true }, - "post /wsapi/auth_with_assertion valid": { success: true }, + "post /wsapi/auth_with_assertion primary": { success: true, userid: 1 }, + "post /wsapi/auth_with_assertion valid": { success: true, userid: 1 }, "post /wsapi/auth_with_assertion invalid": { success: false }, "post /wsapi/auth_with_assertion ajaxError": undefined, "post /wsapi/cert_key valid": random_cert,